diff --git a/package.json b/package.json index d5177b49..db60e9ac 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "test": "jest", "mac": "cross-env NODE_ENV=production yarn run build && electron-builder build -m --publish never", "mas": "cross-env NODE_ENV=production yarn run build && electron-builder build -m mas --universal --publish never", + "masDev": "cross-env NODE_ENV=production yarn run build && electron-builder build -m mas-dev --universal --publish never", "dir": "cross-env NODE_ENV=production yarn run build && electron-builder --dir --publish never", "peggy": "peggy --format es --output ./src/main/modules/FilterLang/FilterLang.js ./src/main/modules/FilterLang/FilterLang.pegjs", "depcheck": "depcheck" diff --git a/release/app/package.json b/release/app/package.json index bf9f1a05..4ccac288 100644 --- a/release/app/package.json +++ b/release/app/package.json @@ -1,6 +1,6 @@ { "name": "sleek", - "version": "2.0.3-rc.3", + "version": "2.0.3-rc.4", "description": "todo.txt manager for Linux, Windows and MacOS, free and open-source (FOSS)", "synopsis": "todo.txt manager for Linux, Windows and MacOS, free and open-source (FOSS)", "keywords": [ diff --git a/src/__tests__/__mock__/recurrence.txt b/src/__tests__/__mock__/recurrence.txt index e44a79cb..be4c0b43 100644 --- a/src/__tests__/__mock__/recurrence.txt +++ b/src/__tests__/__mock__/recurrence.txt @@ -1,11 +1,12 @@ -2023-11-26 Line 1 rec:1d due:2023-11-27 -2023-11-26 Line 1 rec:w due:2023-12-03 -2023-11-26 Line 1 rec:2m due:2024-01-26 -2023-11-26 Line 1 rec:+1d due:2023-11-28 -2023-11-26 Line 1 rec:7w due:2024-01-14 +2023-11-28 Line 1 rec:1d due:2023-11-29 +2023-11-28 Line 1 rec:w due:2023-12-05 +2023-11-28 Line 1 rec:2m due:2024-01-28 +2023-11-28 Line 1 rec:+1d due:2023-11-30 +2023-11-28 Line 1 rec:7w due:2024-01-16 2023-07-21 Line 1 due:2023-07-24 rec:+1b 2021-01-01 taxes are due in one year t:2022-03-30 due:2022-04-30 rec:+1y -2023-11-26 Water plants @home +quick due:2023-12-03 t:2023-11-23 rec:1w -2023-11-26 Line 1 rec:+1d t:2023-09-20 due:2023-11-27 -(A) 2023-11-26 Line 1 rec:1d pri:A due:2023-11-27 \ No newline at end of file +2023-11-28 Water plants @home +quick due:2023-12-05 t:2023-11-25 rec:1w +2023-11-28 Line 1 rec:+1d t:2023-09-20 +2023-11-28 Line 1 rec:1d pri:A due:2023-11-29 +2023-11-28 (A) Do something rec:d t:2023-11-29 @SomeContext \ No newline at end of file diff --git a/src/__tests__/main/Dialog.tsx b/src/__tests__/main/Dialog.tsx index b33aadeb..f1bc8949 100644 --- a/src/__tests__/main/Dialog.tsx +++ b/src/__tests__/main/Dialog.tsx @@ -47,7 +47,7 @@ describe('openFile', () => { }); it('should call addFile when a file is selected', async () => { - await openFile(); + await openFile(false); expect(dialog.showOpenDialog).toHaveBeenCalledWith({ properties: ['openFile'], @@ -65,7 +65,7 @@ describe('openFile', () => { securityScopedBookmarks: true, }); - await openFile(); + await openFile(false); expect(addFile).not.toHaveBeenCalled(); }); @@ -83,7 +83,7 @@ describe('createFile', () => { securityScopedBookmarks: true, }); - await createFile(); + await createFile(false); expect(dialog.showSaveDialog).toHaveBeenCalledWith({ defaultPath: expect.any(String), @@ -102,7 +102,7 @@ describe('createFile', () => { securityScopedBookmarks: true, }); - await createFile(); + await createFile(false); expect(addFile).not.toHaveBeenCalled(); }); diff --git a/src/__tests__/main/File.tsx b/src/__tests__/main/File.tsx index 58067935..eefc2239 100644 --- a/src/__tests__/main/File.tsx +++ b/src/__tests__/main/File.tsx @@ -2,12 +2,20 @@ import path from 'path' import { configStorage } from '../../main/config'; import { addFile, removeFile, setFile } from '../../main/modules/File/File'; +jest.mock('../../main/main', () => ({ + mainWindow: { + webContents: { + send: jest.fn(), + }, + }, +})); + jest.mock('../../main/config', () => ({ configStorage: { get: jest.fn().mockReturnValue([ - { active: false, todoFileName: 'test1.txt', todoFilePath: path.join('/', 'path', 'to', 'test1.txt'), todoFileBookmark: null, doneFilePath: path.join('/', 'path', 'to', 'done.txt'), doneFileBookmark: null }, - { active: true, todoFileName: 'test2.txt', todoFilePath: path.join('/', 'path', 'to', 'test2.txt'), todoFileBookmark: null, doneFilePath: path.join('/', 'path', 'to', 'done.txt'), doneFileBookmark: null }, - { active: false, todoFileName: 'test3.txt', todoFilePath: path.join('/', 'path', 'to', 'test3.txt'), todoFileBookmark: null, doneFilePath: path.join('/', 'path', 'to', 'done.txt'), doneFileBookmark: null }, + { active: false, todoFileName: 'test1.txt', todoFilePath: path.join('/', 'path', 'to', 'test1.txt'), todoFileBookmark: null, doneFilePath: null, doneFileBookmark: null }, + { active: true, todoFileName: 'test2.txt', todoFilePath: path.join('/', 'path', 'to', 'test2.txt'), todoFileBookmark: null, doneFilePath: null, doneFileBookmark: null }, + { active: false, todoFileName: 'test3.txt', todoFilePath: path.join('/', 'path', 'to', 'test3.txt'), todoFileBookmark: null, doneFilePath: null, doneFileBookmark: null }, ]), set: jest.fn(), }, @@ -29,7 +37,7 @@ describe('File functions', () => { todoFileName: 'test1.txt', todoFilePath: path.join('/', 'path', 'to', 'test1.txt'), todoFileBookmark: null, - doneFilePath: path.join('/', 'path', 'to', 'done.txt'), + doneFilePath: null, doneFileBookmark: null }, { @@ -37,7 +45,7 @@ describe('File functions', () => { todoFileName: 'test2.txt', todoFilePath: path.join('/', 'path', 'to', 'test2.txt'), todoFileBookmark: null, - doneFilePath: path.join('/', 'path', 'to', 'done.txt'), + doneFilePath: null, doneFileBookmark: null }, { @@ -45,7 +53,7 @@ describe('File functions', () => { todoFileName: 'test3.txt', todoFilePath: path.join('/', 'path', 'to', 'test3.txt'), todoFileBookmark: null, - doneFilePath: path.join('/', 'path', 'to', 'done.txt'), + doneFilePath: null, doneFileBookmark: null }, { @@ -53,7 +61,7 @@ describe('File functions', () => { todoFileName: 'test4.txt', todoFilePath: path.join('/', 'path', 'to', 'test4.txt'), todoFileBookmark: null, - doneFilePath: path.join('/', 'path', 'to', 'done.txt'), + doneFilePath: null, doneFileBookmark: null }, ]); @@ -67,7 +75,7 @@ describe('File functions', () => { todoFileName: 'test1.txt', todoFilePath: path.join('/', 'path', 'to', 'test1.txt'), todoFileBookmark: null, - doneFilePath: path.join('/', 'path', 'to', 'done.txt'), + doneFilePath: null, doneFileBookmark: null }, { @@ -75,7 +83,7 @@ describe('File functions', () => { todoFileName: 'test3.txt', todoFilePath: path.join('/', 'path', 'to', 'test3.txt'), todoFileBookmark: null, - doneFilePath: path.join('/', 'path', 'to', 'done.txt'), + doneFilePath: null, doneFileBookmark: null }, { @@ -83,7 +91,7 @@ describe('File functions', () => { todoFileName: 'test4.txt', todoFilePath: path.join('/', 'path', 'to', 'test4.txt'), todoFileBookmark: null, - doneFilePath: path.join('/', 'path', 'to', 'done.txt'), + doneFilePath: null, doneFileBookmark: null }, ]); @@ -97,7 +105,7 @@ describe('File functions', () => { todoFileName: 'test1.txt', todoFilePath: path.join('/', 'path', 'to', 'test1.txt'), todoFileBookmark: null, - doneFilePath: path.join('/', 'path', 'to', 'done.txt'), + doneFilePath: null, doneFileBookmark: null }, { @@ -105,7 +113,7 @@ describe('File functions', () => { todoFileName: 'test3.txt', todoFilePath: path.join('/', 'path', 'to', 'test3.txt'), todoFileBookmark: null, - doneFilePath: path.join('/', 'path', 'to', 'done.txt'), + doneFilePath: null, doneFileBookmark: null }, ]); @@ -119,7 +127,7 @@ describe('File functions', () => { todoFileName: 'test1.txt', todoFilePath: path.join('/', 'path', 'to', 'test1.txt'), todoFileBookmark: null, - doneFilePath: path.join('/', 'path', 'to', 'done.txt'), + doneFilePath: null, doneFileBookmark: null }, { @@ -127,7 +135,7 @@ describe('File functions', () => { todoFileName: 'test3.txt', todoFilePath: path.join('/', 'path', 'to', 'test3.txt'), todoFileBookmark: null, - doneFilePath: path.join('/', 'path', 'to', 'done.txt'), + doneFilePath: null, doneFileBookmark: null }, ]); diff --git a/src/locales/cs.json b/src/locales/cs.json index c1cd2be1..a377cc11 100644 --- a/src/locales/cs.json +++ b/src/locales/cs.json @@ -2,7 +2,9 @@ "copy": "Kopírovat", "delete": "Smazat", "cancel": "Zrušit", - "fileTabs.changeLocation": "Změnit umístění souboru done.txt", + "openFile": "Otevřít soubor", + "createFile": "Vytvořit soubor", + "fileTabs.changeLocation": "Změnit soubor pro archivaci", "fileTabs.revealFile": "Zobrazit v správci souborů", "fileTabs.removeFileHeadline": "Odstranit soubor ze sleek?", "fileTabs.removeFileText": "Nebude smazán z pevného disku.", @@ -40,8 +42,6 @@ "shared.attributeMapping.created": "Datum vytvoření", "shared.attributeMapping.completed": "Datum dokončení", "splashscreen.noFiles.text": "Přetáhněte sem soubor todo.txt nebo použijte tlačítka", - "splashscreen.noFiles.open": "Otevřít soubor todo.txt", - "splashscreen.noFiles.create": "Vytvořit soubor todo.txt", "splashscreen.noTodosAvailable.text": "V tomto souboru nejsou žádné úkoly", "splashscreen.noTodosAvailable.create": "Vytvořit úkol", "splashscreen.noTodosVisible.text": "Žádné výsledky nejsou viditelné.", @@ -66,6 +66,8 @@ "prompt.delete.headline": "Smazat úkol?", "prompt.delete.text": "Úkol bude trvale odstraněn ze souboru", "prompt.archive.headline": "Archivovat dokončené úkoly?", - "prompt.archive.text": "Tímto se přesunou všechny dokončené úkoly do vašeho určeného souboru done", - "prompt.archive.button": "Archivovat" + "prompt.archive.text": "Tímto se přesunou všechny dokončené úkoly do vašeho určeného archivačního souboru", + "prompt.archive.button": "Archivovat", + "prompt.archive.changeFile.headline": "Vyberte soubor pro archivaci", + "prompt.archive.changeFile.text": "Pro archivaci dokončených úkolů je nutné nejprve vybrat archivační soubor." } diff --git a/src/locales/de.json b/src/locales/de.json index 22c60e3d..efb15a7c 100644 --- a/src/locales/de.json +++ b/src/locales/de.json @@ -2,7 +2,9 @@ "copy": "Kopieren", "delete": "Löschen", "cancel": "Abbrechen", - "fileTabs.changeLocation": "Speicherort der done.txt-Datei ändern", + "openFile": "Datei öffnen", + "createFile": "Datei erstellen", + "fileTabs.changeLocation": "Datei für die Archivierung ändern", "fileTabs.revealFile": "Im Dateimanager anzeigen", "fileTabs.removeFileHeadline": "Datei aus sleek entfernen?", "fileTabs.removeFileText": "Die Datei wird nicht von Ihrer Festplatte gelöscht.", @@ -40,8 +42,6 @@ "shared.attributeMapping.created": "Erstellungsdatum", "shared.attributeMapping.completed": "Abschlussdatum", "splashscreen.noFiles.text": "Ziehen Sie Ihre todo.txt-Datei hierher oder verwenden Sie die Schaltflächen", - "splashscreen.noFiles.open": "todo.txt-Datei öffnen", - "splashscreen.noFiles.create": "todo.txt-Datei erstellen", "splashscreen.noTodosAvailable.text": "Keine Aufgaben in dieser Datei", "splashscreen.noTodosAvailable.create": "Eine Aufgabe erstellen", "splashscreen.noTodosVisible.text": "Keine sichtbaren Ergebnisse.", @@ -66,6 +66,8 @@ "prompt.delete.headline": "Aufgabe löschen?", "prompt.delete.text": "Die Aufgabe wird dauerhaft aus der Datei entfernt", "prompt.archive.headline": "Abgeschlossene Aufgaben archivieren?", - "prompt.archive.text": "Dadurch werden alle abgeschlossenen Aufgaben in Ihre angegebene 'erledigt'-Datei verschoben", - "prompt.archive.button": "Archivieren" + "prompt.archive.text": "Dadurch werden alle abgeschlossenen Aufgaben in Ihre angegebene Archivdatei verschoben", + "prompt.archive.button": "Archivieren", + "prompt.archive.changeFile.headline": "Datei für Archivierung auswählen", + "prompt.archive.changeFile.text": "Um abgeschlossene Aufgaben zu archivieren, musst du zuerst eine Archivdatei auswählen" } \ No newline at end of file diff --git a/src/locales/en-gb.json b/src/locales/en-gb.json index 7e895419..6ce7dbb5 100644 --- a/src/locales/en-gb.json +++ b/src/locales/en-gb.json @@ -2,7 +2,9 @@ "copy": "Copy", "delete": "Delete", "cancel": "Cancel", - "fileTabs.changeLocation": "Change location of done.txt file", + "openFile": "Open file", + "createFile": "Create file", + "fileTabs.changeLocation": "Change file for archiving", "fileTabs.revealFile": "Reveal in file manager", "fileTabs.removeFileHeadline": "Remove file from sleek?", "fileTabs.removeFileText": "It will not be deleted from your hard drive.", @@ -40,8 +42,6 @@ "shared.attributeMapping.created": "Creation date", "shared.attributeMapping.completed": "Completion date", "splashscreen.noFiles.text": "Drop your todo.txt file here or use the buttons", - "splashscreen.noFiles.open": "Open todo.txt file", - "splashscreen.noFiles.create": "Create todo.txt file", "splashscreen.noTodosAvailable.text": "No todos in this file", "splashscreen.noTodosAvailable.create": "Create a todo", "splashscreen.noTodosVisible.text": "No results visible.", @@ -66,6 +66,8 @@ "prompt.delete.headline": "Delete todo?", "prompt.delete.text": "The todo will be permanently removed from the file", "prompt.archive.headline": "Archive completed todos?", - "prompt.archive.text": "This will move all completed todos to your specified done file", - "prompt.archive.button": "Archive" + "prompt.archive.text": "This will move all completed todos to your specified archiving file", + "prompt.archive.button": "Archive", + "prompt.archive.changeFile.headline": "Choose a File for Archiving", + "prompt.archive.changeFile.text": "To archive completed todos, you need to choose an archive file first" } diff --git a/src/locales/en.json b/src/locales/en.json index 7e895419..6ce7dbb5 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -2,7 +2,9 @@ "copy": "Copy", "delete": "Delete", "cancel": "Cancel", - "fileTabs.changeLocation": "Change location of done.txt file", + "openFile": "Open file", + "createFile": "Create file", + "fileTabs.changeLocation": "Change file for archiving", "fileTabs.revealFile": "Reveal in file manager", "fileTabs.removeFileHeadline": "Remove file from sleek?", "fileTabs.removeFileText": "It will not be deleted from your hard drive.", @@ -40,8 +42,6 @@ "shared.attributeMapping.created": "Creation date", "shared.attributeMapping.completed": "Completion date", "splashscreen.noFiles.text": "Drop your todo.txt file here or use the buttons", - "splashscreen.noFiles.open": "Open todo.txt file", - "splashscreen.noFiles.create": "Create todo.txt file", "splashscreen.noTodosAvailable.text": "No todos in this file", "splashscreen.noTodosAvailable.create": "Create a todo", "splashscreen.noTodosVisible.text": "No results visible.", @@ -66,6 +66,8 @@ "prompt.delete.headline": "Delete todo?", "prompt.delete.text": "The todo will be permanently removed from the file", "prompt.archive.headline": "Archive completed todos?", - "prompt.archive.text": "This will move all completed todos to your specified done file", - "prompt.archive.button": "Archive" + "prompt.archive.text": "This will move all completed todos to your specified archiving file", + "prompt.archive.button": "Archive", + "prompt.archive.changeFile.headline": "Choose a File for Archiving", + "prompt.archive.changeFile.text": "To archive completed todos, you need to choose an archive file first" } diff --git a/src/locales/es.json b/src/locales/es.json index 561a1420..376e9e35 100644 --- a/src/locales/es.json +++ b/src/locales/es.json @@ -2,7 +2,9 @@ "copy": "Copiar", "delete": "Eliminar", "cancel": "Cancelar", - "fileTabs.changeLocation": "Cambiar la ubicación del archivo done.txt", + "openFile": "Abrir archivo", + "createFile": "Crear archivo", + "fileTabs.changeLocation": "Cambiar archivo para archivar", "fileTabs.revealFile": "Mostrar en el administrador de archivos", "fileTabs.removeFileHeadline": "¿Eliminar archivo de sleek?", "fileTabs.removeFileText": "No se eliminará de su disco duro.", @@ -40,8 +42,6 @@ "shared.attributeMapping.created": "Fecha de creación", "shared.attributeMapping.completed": "Fecha de finalización", "splashscreen.noFiles.text": "Arrastre su archivo todo.txt aquí o use los botones", - "splashscreen.noFiles.open": "Abrir archivo todo.txt", - "splashscreen.noFiles.create": "Crear archivo todo.txt", "splashscreen.noTodosAvailable.text": "No hay tareas en este archivo", "splashscreen.noTodosAvailable.create": "Crear una tarea", "splashscreen.noTodosVisible.text": "No se ven resultados.", @@ -66,6 +66,8 @@ "prompt.delete.headline": "¿Eliminar tarea?", "prompt.delete.text": "La tarea se eliminará permanentemente del archivo", "prompt.archive.headline": "¿Archivar tareas completadas?", - "prompt.archive.text": "Esto moverá todas las tareas completadas a su archivo done especificado", - "prompt.archive.button": "Archivar" + "prompt.archive.text": "Esto moverá todas las tareas completadas a tu archivo de archivado especificado", + "prompt.archive.button": "Archivar", + "prompt.archive.changeFile.headline": "Selecciona un archivo para archivar", + "prompt.archive.changeFile.text": "Para archivar tareas completadas, primero debes elegir un archivo de archivo." } diff --git a/src/locales/fr.json b/src/locales/fr.json index c002cabe..22c04396 100644 --- a/src/locales/fr.json +++ b/src/locales/fr.json @@ -2,7 +2,9 @@ "copy": "Copier", "delete": "Supprimer", "cancel": "Annuler", - "fileTabs.changeLocation": "Changer l'emplacement du fichier done.txt", + "openFile": "Ouvrir un fichier", + "createFile": "Créer un fichier", + "fileTabs.changeLocation": "Changer le fichier pour archiver", "fileTabs.revealFile": "Révéler dans le gestionnaire de fichiers", "fileTabs.removeFileHeadline": "Supprimer le fichier de sleek?", "fileTabs.removeFileText": "Il ne sera pas supprimé de votre disque dur.", @@ -40,8 +42,6 @@ "shared.attributeMapping.created": "Date de création", "shared.attributeMapping.completed": "Date de réalisation", "splashscreen.noFiles.text": "Déposez votre fichier todo.txt ici ou utilisez les boutons", - "splashscreen.noFiles.open": "Ouvrir le fichier todo.txt", - "splashscreen.noFiles.create": "Créer un fichier todo.txt", "splashscreen.noTodosAvailable.text": "Aucune tâche dans ce fichier", "splashscreen.noTodosAvailable.create": "Créer une tâche", "splashscreen.noTodosVisible.text": "Aucun résultat visible.", @@ -66,6 +66,8 @@ "prompt.delete.headline": "Supprimer la tâche?", "prompt.delete.text": "La tâche sera définitivement supprimée du fichier", "prompt.archive.headline": "Archiver les tâches terminées?", - "prompt.archive.text": "Cela déplacera toutes les tâches terminées vers votre fichier done spécifié", - "prompt.archive.button": "Archiver" -} + "prompt.archive.text": "Cela déplacera toutes les tâches terminées vers votre fichier d'archivage spécifié", + "prompt.archive.button": "Archiver", + "prompt.archive.changeFile.headline": "Choisissez un fichier pour archiver", + "prompt.archive.changeFile.text": "Pour archiver les tâches terminées, vous devez d'abord choisir un fichier d'archivage." +} \ No newline at end of file diff --git a/src/locales/hi.json b/src/locales/hi.json index 23c8c582..02174aae 100644 --- a/src/locales/hi.json +++ b/src/locales/hi.json @@ -2,7 +2,9 @@ "copy": "कॉपी करें", "delete": "हटाएं", "cancel": "रद्द करें", - "fileTabs.changeLocation": "done.txt फ़ाइल का स्थान बदलें", + "openFile": "फ़ाइल खोलें", + "createFile": "फ़ाइल बनाएं", + "fileTabs.changeLocation": "आर्काइव के लिए फ़ाइल बदलें", "fileTabs.revealFile": "फ़ाइल प्रबंधक में दिखाएँ", "fileTabs.removeFileHeadline": "sleek से फ़ाइल हटाएं?", "fileTabs.removeFileText": "यह आपके हार्ड ड्राइव से हटाएं नहीं होगा।", @@ -40,8 +42,6 @@ "shared.attributeMapping.created": "निर्माण तिथि", "shared.attributeMapping.completed": "पूर्ण तिथि", "splashscreen.noFiles.text": "अपनी todo.txt फ़ाइल यहाँ ड्रैग करें या बटन का उपयोग करें", - "splashscreen.noFiles.open": "todo.txt फ़ाइल खोलें", - "splashscreen.noFiles.create": "todo.txt फ़ाइल बनाएं", "splashscreen.noTodosAvailable.text": "इस फ़ाइल में कोई कार्य नहीं हैं", "splashscreen.noTodosAvailable.create": "कार्य बनाएं", "splashscreen.noTodosVisible.text": "कोई दिखाई देने वाला परिणाम नहीं है।", @@ -66,6 +66,8 @@ "prompt.delete.headline": "कार्य हटाएं?", "prompt.delete.text": "कार्य फ़ाइल से स्थायी रूप से हटा दिया जाएगा", "prompt.archive.headline": "पूर्ण किए गए कार्यों को संग्रहित करें?", - "prompt.archive.text": "यह सभी पूर्ण किए गए कार्यों को आपके निर्दिष्ट संपन्न फ़ाइल में ले जाएगा", - "prompt.archive.button": "संग्रहित करें" -} + "prompt.archive.text": "इससे सभी पूर्ण हुई कार्यों को आपके निर्दिष्ट आर्काइव फ़ाइल में मूव किया जाएगा", + "prompt.archive.button": "संग्रहित करें", + "prompt.archive.changeFile.headline": "आर्काइव के लिए एक फ़ाइल चुनें", + "prompt.archive.changeFile.text": "पूर्ण हुए कार्यों को आर्काइव करने के लिए, आपको पहले एक आर्काइव फ़ाइल चुननी होगी।" +} \ No newline at end of file diff --git a/src/locales/hu.json b/src/locales/hu.json index 86fbed56..742e275f 100644 --- a/src/locales/hu.json +++ b/src/locales/hu.json @@ -2,7 +2,9 @@ "copy": "Másolás", "delete": "Törlés", "cancel": "Mégse", - "fileTabs.changeLocation": "Fájl done.txt helyének megváltoztatása", + "openFile": "Fájl megnyitása", + "createFile": "Fájl létrehozása", + "fileTabs.changeLocation": "Fájl megváltoztatása az archiváláshoz", "fileTabs.revealFile": "Megmutatás a fájlkezelőben", "fileTabs.removeFileHeadline": "Fájl eltávolítása a sleek?", "fileTabs.removeFileText": "Nem kerül törlésre a merevlemezről.", @@ -40,8 +42,6 @@ "shared.attributeMapping.created": "Létrehozás dátuma", "shared.attributeMapping.completed": "Befejezés dátuma", "splashscreen.noFiles.text": "Húzza ide a todo.txt fájlt, vagy használja a gombokat", - "splashscreen.noFiles.open": "Todo.txt fájl megnyitása", - "splashscreen.noFiles.create": "Todo.txt fájl létrehozása", "splashscreen.noTodosAvailable.text": "Nincsenek feladatok ebben a fájlban", "splashscreen.noTodosAvailable.create": "Feladat létrehozása", "splashscreen.noTodosVisible.text": "Nincs látható eredmény.", @@ -66,6 +66,8 @@ "prompt.delete.headline": "Feladat törlése?", "prompt.delete.text": "A feladat véglegesen törlődik a fájlból", "prompt.archive.headline": "Befejezett feladatok archiválása?", - "prompt.archive.text": "Ez az összes befejezett feladatot áthelyezi a meghatározott done fájlba", - "prompt.archive.button": "Archiválás" + "prompt.archive.text": "Ez az összes befejezett teendőt a megadott archiválási fájlba fogja áthelyezni", + "prompt.archive.button": "Archiválás", + "prompt.archive.changeFile.headline": "Válassz fájlt az archiváláshoz", + "prompt.archive.changeFile.text": "A befejezett teendők archiválásához először válaszd ki az archív fájlt." } diff --git a/src/locales/it.json b/src/locales/it.json index 4a8ed394..62d23ebe 100644 --- a/src/locales/it.json +++ b/src/locales/it.json @@ -2,7 +2,9 @@ "copy": "Copia", "delete": "Elimina", "cancel": "Annulla", - "fileTabs.changeLocation": "Cambia posizione del file done.txt", + "openFile": "Apri file", + "createFile": "Crea file", + "fileTabs.changeLocation": "Cambia file per l'archiviazione", "fileTabs.revealFile": "Mostra nel gestore di file", "fileTabs.removeFileHeadline": "Rimuovi il file da sleek?", "fileTabs.removeFileText": "Non verrà eliminato dal tuo disco rigido.", @@ -40,8 +42,6 @@ "shared.attributeMapping.created": "Data di creazione", "shared.attributeMapping.completed": "Data di completamento", "splashscreen.noFiles.text": "Trascina il tuo file todo.txt qui o usa i pulsanti", - "splashscreen.noFiles.open": "Apri file todo.txt", - "splashscreen.noFiles.create": "Crea file todo.txt", "splashscreen.noTodosAvailable.text": "Nessun compito in questo file", "splashscreen.noTodosAvailable.create": "Crea un compito", "splashscreen.noTodosVisible.text": "Nessun risultato visibile.", @@ -66,6 +66,8 @@ "prompt.delete.headline": "Eliminare il compito?", "prompt.delete.text": "Il compito verrà eliminato definitivamente dal file", "prompt.archive.headline": "Archiviare i compiti completati?", - "prompt.archive.text": "Ciò sposterà tutti i compiti completati nel tuo file done specificato", - "prompt.archive.button": "Archivia" + "prompt.archive.text": "Questo sposterà tutti i compiti completati nel tuo file di archiviazione specificato", + "prompt.archive.button": "Archivia", + "prompt.archive.changeFile.headline": "Scegli un file da archiviare", + "prompt.archive.changeFile.text": "Per archiviare i compiti completati, devi prima scegliere un file di archiviazione." } diff --git a/src/locales/jp.json b/src/locales/jp.json index 45a23519..95bcfb17 100644 --- a/src/locales/jp.json +++ b/src/locales/jp.json @@ -2,7 +2,9 @@ "copy": "コピー", "delete": "削除", "cancel": "キャンセル", - "fileTabs.changeLocation": "done.txt ファイルの場所を変更", + "openFile": "ファイルを開く", + "createFile": "ファイルを作成", + "fileTabs.changeLocation": "アーカイブ用のファイルを変更", "fileTabs.revealFile": "ファイルマネージャーで表示", "fileTabs.removeFileHeadline": "sleek からファイルを削除しますか?", "fileTabs.removeFileText": "ハードディスクからは削除されません。", @@ -40,8 +42,6 @@ "shared.attributeMapping.created": "作成日", "shared.attributeMapping.completed": "完了日", "splashscreen.noFiles.text": "todo.txt ファイルをここにドラッグ&ドロップするか、ボタンを使用してください", - "splashscreen.noFiles.open": "todo.txt ファイルを開く", - "splashscreen.noFiles.create": "todo.txt ファイルを作成", "splashscreen.noTodosAvailable.text": "このファイルにはタスクがありません", "splashscreen.noTodosAvailable.create": "タスクを作成", "splashscreen.noTodosVisible.text": "表示できる結果はありません。", @@ -66,6 +66,8 @@ "prompt.delete.headline": "タスクを削除しますか?", "prompt.delete.text": "タスクはファイルから永久に削除されます", "prompt.archive.headline": "完了したタスクをアーカイブしますか?", - "prompt.archive.text": "これにより、すべての完了したタスクが指定した done ファイルに移動されます", - "prompt.archive.button": "アーカイブ" + "prompt.archive.text": "これにより、すべての完了したタスクが指定されたアーカイブファイルに移動されます", + "prompt.archive.button": "アーカイブ", + "prompt.archive.changeFile.headline": "アーカイブ用のファイルを選択", + "prompt.archive.changeFile.text": "完了したタスクをアーカイブするには、まずアーカイブ用のファイルを選択する必要があります。" } diff --git a/src/locales/ko.json b/src/locales/ko.json index 10abc521..77e713b9 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -2,7 +2,9 @@ "copy": "복사", "delete": "삭제", "cancel": "취소", - "fileTabs.changeLocation": "done.txt 파일 위치 변경", + "openFile": "파일 열기", + "createFile": "파일 생성", + "fileTabs.changeLocation": "아카이브를 위한 파일 변경", "fileTabs.revealFile": "파일 매니저에서 보기", "fileTabs.removeFileHeadline": "sleek에서 파일 삭제?", "fileTabs.removeFileText": "하드 드라이브에서는 삭제되지 않습니다.", @@ -40,8 +42,6 @@ "shared.attributeMapping.created": "생성일", "shared.attributeMapping.completed": "완료일", "splashscreen.noFiles.text": "todo.txt 파일을 여기로 끌어오거나 버튼을 사용하세요", - "splashscreen.noFiles.open": "todo.txt 파일 열기", - "splashscreen.noFiles.create": "todo.txt 파일 생성", "splashscreen.noTodosAvailable.text": "이 파일에 작업이 없습니다", "splashscreen.noTodosAvailable.create": "작업 생성", "splashscreen.noTodosVisible.text": "표시할 결과 없음.", @@ -66,6 +66,8 @@ "prompt.delete.headline": "작업 삭제?", "prompt.delete.text": "작업은 파일에서 영구적으로 삭제됩니다", "prompt.archive.headline": "완료된 작업 아카이브?", - "prompt.archive.text": "이 작업은 모든 완료된 작업을 지정한 완료 파일로 이동시킵니다", - "prompt.archive.button": "아카이브" + "prompt.archive.text": "이로써 완료된 모든 할 일이 지정한 아카이브 파일로 이동됩니다", + "prompt.archive.button": "아카이브", + "prompt.archive.changeFile.headline": "아카이브할 파일 선택", + "prompt.archive.changeFile.text": "완료된 할 일을 아카이브하려면 먼저 아카이브 파일을 선택해야 합니다." } diff --git a/src/locales/pl.json b/src/locales/pl.json index c5bfa16a..8dda7261 100644 --- a/src/locales/pl.json +++ b/src/locales/pl.json @@ -2,7 +2,9 @@ "copy": "Kopiuj", "delete": "Usuń", "cancel": "Anuluj", - "fileTabs.changeLocation": "Zmień lokalizację pliku done.txt", + "openFile": "Otwórz plik", + "createFile": "Utwórz plik", + "fileTabs.changeLocation": "Zmień plik do archiwizacji", "fileTabs.revealFile": "Pokaż w menedżerze plików", "fileTabs.removeFileHeadline": "Usunąć plik z sleek?", "fileTabs.removeFileText": "Nie zostanie usunięty z dysku twardego.", @@ -40,8 +42,6 @@ "shared.attributeMapping.created": "Data utworzenia", "shared.attributeMapping.completed": "Data ukończenia", "splashscreen.noFiles.text": "Przeciągnij tutaj plik todo.txt lub użyj przycisków", - "splashscreen.noFiles.open": "Otwórz plik todo.txt", - "splashscreen.noFiles.create": "Utwórz plik todo.txt", "splashscreen.noTodosAvailable.text": "Brak zadań w tym pliku", "splashscreen.noTodosAvailable.create": "Utwórz zadanie", "splashscreen.noTodosVisible.text": "Brak widocznych wyników.", @@ -66,6 +66,8 @@ "prompt.delete.headline": "Usunąć zadanie?", "prompt.delete.text": "Zadanie zostanie trwale usunięte z pliku", "prompt.archive.headline": "Zarchiwizować ukończone zadania?", - "prompt.archive.text": "To przeniesie wszystkie ukończone zadania do wskazanego pliku done", - "prompt.archive.button": "Archiwizuj" + "prompt.archive.text": "To spowoduje przeniesienie wszystkich ukończonych zadań do określonego pliku archiwizacji", + "prompt.archive.button": "Archiwizuj", + "prompt.archive.changeFile.headline": "Wybierz plik do archiwizacji", + "prompt.archive.changeFile.text": "Aby zarchiwizować ukończone zadania, musisz najpierw wybrać plik archiwizacyjny." } diff --git a/src/locales/pt.json b/src/locales/pt.json index 321b5c5f..b4dcebfb 100644 --- a/src/locales/pt.json +++ b/src/locales/pt.json @@ -2,7 +2,9 @@ "copy": "Copiar", "delete": "Eliminar", "cancel": "Cancelar", - "fileTabs.changeLocation": "Alterar localização do ficheiro done.txt", + "openFile": "Abrir ficheiro", + "createFile": "Criar ficheiro", + "fileTabs.changeLocation": "Alterar arquivo para arquivamento", "fileTabs.revealFile": "Revelar no gerenciador de arquivos", "fileTabs.removeFileHeadline": "Remover ficheiro do sleek?", "fileTabs.removeFileText": "Não será eliminado do seu disco rígido.", @@ -40,8 +42,6 @@ "shared.attributeMapping.created": "Data de criação", "shared.attributeMapping.completed": "Data de conclusão", "splashscreen.noFiles.text": "Arraste o seu ficheiro todo.txt para aqui ou utilize os botões", - "splashscreen.noFiles.open": "Abrir ficheiro todo.txt", - "splashscreen.noFiles.create": "Criar ficheiro todo.txt", "splashscreen.noTodosAvailable.text": "Sem tarefas neste ficheiro", "splashscreen.noTodosAvailable.create": "Criar uma tarefa", "splashscreen.noTodosVisible.text": "Sem resultados visíveis.", @@ -66,6 +66,8 @@ "prompt.delete.headline": "Eliminar tarefa?", "prompt.delete.text": "A tarefa será eliminada permanentemente do ficheiro", "prompt.archive.headline": "Arquivar tarefas concluídas?", - "prompt.archive.text": "Isto moverá todas as tarefas concluídas para o seu ficheiro de conclusões especificado", - "prompt.archive.button": "Arquivar" -} + "prompt.archive.text": "Isso moverá todas as tarefas concluídas para o seu arquivo de arquivamento especificado", + "prompt.archive.button": "Arquivar", + "prompt.archive.changeFile.headline": "Escolha um arquivo para arquivar", + "prompt.archive.changeFile.text": "Para arquivar tarefas concluídas, é necessário escolher um arquivo de arquivamento primeiro." +} \ No newline at end of file diff --git a/src/locales/ru.json b/src/locales/ru.json index af4d18c5..c6f88b06 100644 --- a/src/locales/ru.json +++ b/src/locales/ru.json @@ -2,7 +2,9 @@ "copy": "Копировать", "delete": "Удалить", "cancel": "Отменить", - "fileTabs.changeLocation": "Изменить местоположение файла done.txt", + "openFile": "Открыть файл", + "createFile": "Создать файл", + "fileTabs.changeLocation": "Изменить файл для архивации", "fileTabs.revealFile": "Показать в файловом менеджере", "fileTabs.removeFileHeadline": "Удалить файл из sleek?", "fileTabs.removeFileText": "Он не будет удален с вашего жесткого диска.", @@ -40,8 +42,6 @@ "shared.attributeMapping.created": "Дата создания", "shared.attributeMapping.completed": "Дата завершения", "splashscreen.noFiles.text": "Перетащите ваш файл todo.txt сюда или используйте кнопки", - "splashscreen.noFiles.open": "Открыть файл todo.txt", - "splashscreen.noFiles.create": "Создать файл todo.txt", "splashscreen.noTodosAvailable.text": "Нет задач в этом файле", "splashscreen.noTodosAvailable.create": "Создать задачу", "splashscreen.noTodosVisible.text": "Нет видимых результатов.", @@ -66,6 +66,8 @@ "prompt.delete.headline": "Удалить задачу?", "prompt.delete.text": "Задача будет удалена навсегда из файла", "prompt.archive.headline": "Архивировать завершенные задачи?", - "prompt.archive.text": "Это переместит все завершенные задачи в указанный файл done", - "prompt.archive.button": "Архивировать" + "prompt.archive.text": "Это переместит все завершенные задачи в указанный вами файл архивации", + "prompt.archive.button": "Архивировать", + "prompt.archive.changeFile.headline": "Выберите файл для архивации", + "prompt.archive.changeFile.text": "Чтобы архивировать завершенные задачи, сначала выберите файл для архивации." } \ No newline at end of file diff --git a/src/locales/tr.json b/src/locales/tr.json index 0e11cb0c..d033e695 100644 --- a/src/locales/tr.json +++ b/src/locales/tr.json @@ -2,7 +2,9 @@ "copy": "Kopyala", "delete": "Sil", "cancel": "İptal", - "fileTabs.changeLocation": "done.txt dosyasının konumunu değiştir", + "openFile": "Dosyasını aç", + "createFile": "Dosyası oluştur", + "fileTabs.changeLocation": "Arşivleme için dosya değiştir", "fileTabs.revealFile": "Dosya yöneticisinde göster", "fileTabs.removeFileHeadline": "Dosyayı sleek'ten kaldırmak istiyor musunuz?", "fileTabs.removeFileText": "Sabit diskinizden silinmeyecektir.", @@ -40,8 +42,6 @@ "shared.attributeMapping.created": "Oluşturma tarihi", "shared.attributeMapping.completed": "Tamamlanma tarihi", "splashscreen.noFiles.text": "Todo.txt dosyanızı buraya sürükleyin veya düğmeleri kullanın", - "splashscreen.noFiles.open": "Todo.txt dosyasını aç", - "splashscreen.noFiles.create": "Todo.txt dosyası oluştur", "splashscreen.noTodosAvailable.text": "Bu dosyada görev yok", "splashscreen.noTodosAvailable.create": "Görev oluştur", "splashscreen.noTodosVisible.text": "Görünen sonuç yok.", @@ -66,6 +66,8 @@ "prompt.delete.headline": "Görevi silmek istiyor musunuz?", "prompt.delete.text": "Görev dosyadan kalıcı olarak silinecektir", "prompt.archive.headline": "Tamamlanan görevleri arşivlemek istiyor musunuz?", - "prompt.archive.text": "Bu, tüm tamamlanan görevleri belirttiğiniz tamamlandı dosyasına taşıyacaktır", - "prompt.archive.button": "Arşivle" + "prompt.archive.text": "Bu, tüm tamamlanan görevleri belirttiğiniz arşiv dosyanıza taşıyacaktır", + "prompt.archive.button": "Arşivle", + "prompt.archive.changeFile.headline": "Arşivlemek için bir dosya seçin", + "prompt.archive.changeFile.text": "Tamamlanan görevleri arşivlemek için önce bir arşiv dosyası seçmeniz gerekiyor." } \ No newline at end of file diff --git a/src/locales/zh.json b/src/locales/zh.json index cab4e395..144c3f5d 100644 --- a/src/locales/zh.json +++ b/src/locales/zh.json @@ -2,7 +2,9 @@ "copy": "复制", "delete": "删除", "cancel": "取消", - "fileTabs.changeLocation": "更改 done.txt 文件位置", + "openFile": "打开 文件", + "createFile": "创建 文件", + "fileTabs.changeLocation": "更改文件以进行归档", "fileTabs.revealFile": "在文件管理器中显示", "fileTabs.removeFileHeadline": "从 sleek 中删除文件?", "fileTabs.removeFileText": "它不会从您的硬盘驱动器中删除。", @@ -40,8 +42,6 @@ "shared.attributeMapping.created": "创建日期", "shared.attributeMapping.completed": "完成日期", "splashscreen.noFiles.text": "将您的 todo.txt 文件拖到此处或使用按钮", - "splashscreen.noFiles.open": "打开 todo.txt 文件", - "splashscreen.noFiles.create": "创建 todo.txt 文件", "splashscreen.noTodosAvailable.text": "此文件中没有任务", "splashscreen.noTodosAvailable.create": "创建任务", "splashscreen.noTodosVisible.text": "没有可见的结果。", @@ -66,6 +66,8 @@ "prompt.delete.headline": "删除任务?", "prompt.delete.text": "任务将永久从文件中删除", "prompt.archive.headline": "归档已完成的任务?", - "prompt.archive.text": "这将将所有已完成的任务移动到指定的已完成文件", - "prompt.archive.button": "归档" -} + "prompt.archive.text": "这将把所有已完成的待办事项移动到您指定的归档文件中", + "prompt.archive.button": "归档", + "prompt.archive.changeFile.headline": "选择一个文件进行归档", + "prompt.archive.changeFile.text": "要归档已完成的任务,您需要首先选择一个归档文件。" +} \ No newline at end of file diff --git a/src/main/main.ts b/src/main/main.ts index b35861bb..d0be948a 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -4,7 +4,7 @@ import fs from 'fs'; import { configStorage } from './config'; import createMenu from './modules/Menu'; import { resolveHtmlPath, getAssetPath, File } from './util'; -import createFileWatcher from './modules/File/Watcher'; +import { createFileWatcher, watcher } from './modules/File/Watcher'; import createTray from './modules/Tray'; import './modules/Ipc'; import handleTheme from './modules/Theme'; @@ -30,9 +30,11 @@ const handleCreateWindow = () => { } } -const handleClosed = () => { +const handleClosed = async () => { + if(watcher) await watcher.close(); + mainWindow = null; - + delete eventListeners.handleReadyToShow; delete eventListeners.handleClosed; delete eventListeners.handleResize; diff --git a/src/main/modules/File/Archive.tsx b/src/main/modules/File/Archive.tsx index 8cf1bab1..058fff7f 100644 --- a/src/main/modules/File/Archive.tsx +++ b/src/main/modules/File/Archive.tsx @@ -5,8 +5,9 @@ import { configStorage } from '../../config'; import { writeStringToFile } from './Write'; import { createTodoObjects } from '../TodoObject/CreateTodoObjects'; -async function extractTodosFromFile(filePath: string, complete: boolean): Promise { +async function extractTodosFromFile(filePath: string | null, complete: boolean): Promise { try { + if(!filePath) throw new Error; const content = await fs.readFile(filePath, 'utf8'); const todoObjects = createTodoObjects(content); const validTodoStrings = todoObjects @@ -29,8 +30,12 @@ async function archiveTodos(): Promise { } const todoFilePath = activeFile.todoFilePath; const doneFilePath = activeFile.doneFilePath; + + if(!doneFilePath) return; + const completedTodos = await extractTodosFromFile(todoFilePath, true); const uncompletedTodos = await extractTodosFromFile(todoFilePath, false); + const todosFromDoneFile = await extractTodosFromFile(doneFilePath, true); const stringDoneFile = todosFromDoneFile.length === 0 ? completedTodos.join('\n') : todosFromDoneFile.join('\n') + '\n' + completedTodos.join('\n'); const stringTodoFile = uncompletedTodos.join('\n'); diff --git a/src/main/modules/File/Dialog.tsx b/src/main/modules/File/Dialog.tsx index d7abe466..d8a7f139 100644 --- a/src/main/modules/File/Dialog.tsx +++ b/src/main/modules/File/Dialog.tsx @@ -2,7 +2,7 @@ import { app, dialog, OpenDialogReturnValue, SaveDialogReturnValue } from 'elect import path from 'path'; import fs from 'fs/promises'; import { configStorage } from '../../config'; -import { addFile } from './File'; +import { addFile, addDoneFile } from './File'; import { File } from '../../util'; const dialogFilters = [ @@ -16,7 +16,7 @@ const dialogFilters = [ } ] -async function openFile(): Promise { +async function openFile(setDoneFile: boolean): Promise { try { const result: OpenDialogReturnValue = await dialog.showOpenDialog({ properties: ['openFile'], @@ -27,7 +27,11 @@ async function openFile(): Promise { const filePath: string = result.filePaths[0]; const securityScopedBookmark: string | null = result.bookmarks?.[0] || null; - addFile(filePath, securityScopedBookmark); + if(setDoneFile) { + addDoneFile(filePath, securityScopedBookmark); + } else { + addFile(filePath, securityScopedBookmark); + } } return; } catch (error: any) { @@ -35,31 +39,7 @@ async function openFile(): Promise { } } -async function changeDoneFilePath(index: number): Promise { - try { - const files: File[] = (configStorage.get('files') as File[]) || []; - const currentPath = path.dirname(files[index].todoFilePath); - const result: OpenDialogReturnValue = await dialog.showOpenDialog({ - properties: ['openFile'], - filters: dialogFilters, - defaultPath: currentPath, - securityScopedBookmarks: true, - }); - if (!result.canceled && result.filePaths.length > 0) { - const filePath: string = result.filePaths[0]; - const securityScopedBookmarks: string[] | null = result.bookmarks || null; - - if(filePath) files[index].doneFilePath = filePath; - if(securityScopedBookmarks) files[index].doneFileBookmark = securityScopedBookmarks[0]; - configStorage.set('files', files) - } - return; - } catch (error: any) { - console.error('FileDialog.ts:', error); - } -} - -async function createFile(): Promise { +async function createFile(setDoneFile: boolean): Promise { try { const result: SaveDialogReturnValue = await dialog.showSaveDialog({ defaultPath: path.join(app.getPath('documents'), 'todo.txt'), @@ -72,7 +52,12 @@ async function createFile(): Promise { const securityScopedBookmark: string | null = result.bookmark || null; await fs.writeFile(filePath, ''); - addFile(filePath, securityScopedBookmark); + + if(setDoneFile) { + addDoneFile(filePath, securityScopedBookmark); + } else { + addFile(filePath, securityScopedBookmark); + } } return; } catch (error: any) { @@ -82,6 +67,5 @@ async function createFile(): Promise { export { createFile, - openFile, - changeDoneFilePath + openFile }; diff --git a/src/main/modules/File/File.tsx b/src/main/modules/File/File.tsx index 7428b970..cf2b0559 100644 --- a/src/main/modules/File/File.tsx +++ b/src/main/modules/File/File.tsx @@ -3,6 +3,7 @@ import { configStorage } from '../../config'; import createFileWatcher from './Watcher'; import path from 'path'; import { File } from '../../util'; +import { mainWindow } from '../../main'; function addFile(filePath: string, bookmark: string | null) { try { @@ -17,7 +18,7 @@ function addFile(filePath: string, bookmark: string | null) { todoFileName: path.basename(filePath), todoFilePath: filePath, todoFileBookmark: bookmark, - doneFilePath: path.join(path.dirname(filePath), 'done.txt'), + doneFilePath: null, doneFileBookmark: null }); } else { @@ -35,6 +36,28 @@ function addFile(filePath: string, bookmark: string | null) { } } +function addDoneFile(filePath: string, bookmark: string | null) { + try { + const files: File[] = configStorage.get('files') || []; + const activeIndex: number = files.findIndex((file) => file.active); + + if(activeIndex === -1) return false; + + files[activeIndex].doneFilePath = filePath; + files[activeIndex].doneFileBookmark = bookmark; + + configStorage.set('files', files); + + mainWindow!.webContents.send('archiveTodos'); + + console.info(`File.ts: Done file added for ${files[activeIndex].todoFileName}`); + + } catch (error: any) { + console.error('File.ts:', error); + throw error; + } +} + async function removeFile(index: number): Promise { try { let files: File[] = configStorage.get('files') as File[]; @@ -98,4 +121,4 @@ function revealFile(index: number): void { } } -export { setFile, removeFile, addFile, revealFile }; +export { setFile, removeFile, addFile, addDoneFile, revealFile }; diff --git a/src/main/modules/File/Watcher.tsx b/src/main/modules/File/Watcher.tsx index d19a3d64..3d28d8c9 100644 --- a/src/main/modules/File/Watcher.tsx +++ b/src/main/modules/File/Watcher.tsx @@ -51,4 +51,4 @@ function createFileWatcher(files: File[]): string { } } -export default createFileWatcher; +export { createFileWatcher, watcher }; diff --git a/src/main/modules/Ipc.tsx b/src/main/modules/Ipc.tsx index a53ccf71..2d61cb84 100644 --- a/src/main/modules/Ipc.tsx +++ b/src/main/modules/Ipc.tsx @@ -5,7 +5,7 @@ import { writeTodoObjectToFile, removeLineFromFile } from './File/Write'; import archiveTodos from './File/Archive'; import { configStorage, filterStorage, notifiedTodoObjectsStorage } from '../config'; import { addFile, setFile, removeFile, revealFile } from './File/File'; -import { openFile, createFile, changeDoneFilePath } from './File/Dialog'; +import { openFile, createFile } from './File/Dialog'; async function handleDataRequest(event: IpcMainEvent, searchString: string): Promise { const [todoObjects, attributes, headers, filters] = await processDataRequest(searchString); @@ -110,6 +110,22 @@ function handleRevealFile(event: IpcMainEvent, index: number): void { } } +function handleOpenFile(event: IpcMainEvent, setDoneFile: boolean): void { + try { + openFile(setDoneFile); + } catch (error: any) { + console.error('ipcEvents.ts:', error); + } +} + +function handleCreateFile(event: IpcMainEvent, setDoneFile: boolean): void { + try { + createFile(setDoneFile); + } catch (error: any) { + console.error('ipcEvents.ts:', error); + } +} + function handleChangeDoneFilePath(event: IpcMainEvent, index: number): void { try { changeDoneFilePath(index); @@ -146,8 +162,8 @@ function removeEventListeners(): void { ipcMain.off('storeSetNotifiedTodoObjects', handleStoreSetNotifiedTodoObjects); ipcMain.off('setFile', handleSetFile); ipcMain.off('removeFile', handleRemoveFile); - ipcMain.off('openFile', openFile); - ipcMain.off('createFile', createFile); + ipcMain.off('openFile', handleOpenFile); + ipcMain.off('createFile', handleCreateFile); ipcMain.off('requestData', handleDataRequest); ipcMain.off('writeTodoToFile', handleWriteTodoToFile); ipcMain.off('archiveTodos', archiveTodos); @@ -167,8 +183,8 @@ ipcMain.on('storeSetFilters', handleStoreSetFilters); ipcMain.on('storeSetNotifiedTodoObjects', handleStoreSetNotifiedTodoObjects); ipcMain.on('setFile', handleSetFile); ipcMain.on('removeFile', handleRemoveFile); -ipcMain.on('openFile', openFile); -ipcMain.on('createFile', createFile); +ipcMain.on('openFile', handleOpenFile); +ipcMain.on('createFile', handleCreateFile); ipcMain.on('requestData', handleDataRequest); ipcMain.on('writeTodoToFile', handleWriteTodoToFile); ipcMain.on('archiveTodos', archiveTodos); @@ -177,4 +193,4 @@ ipcMain.on('droppedFile', handleDroppedFile); ipcMain.on('saveToClipboard', handleSaveToClipboard); ipcMain.on('revealFile', handleRevealFile); ipcMain.on('changeDoneFilePath', handleChangeDoneFilePath); -ipcMain.on('removeLineFromFile', handleRemoveLineFromFile); +ipcMain.on('removeLineFromFile', handleRemoveLineFromFile); \ No newline at end of file diff --git a/src/main/modules/Menu.tsx b/src/main/modules/Menu.tsx index 73f58b40..c897592f 100644 --- a/src/main/modules/Menu.tsx +++ b/src/main/modules/Menu.tsx @@ -61,13 +61,17 @@ function createMenu(files: File[]) { submenu: [ { type: 'separator' }, { - label: 'Open todo.txt file', + label: 'Open file', accelerator: 'CmdOrCtrl+O', - click: openFile, + click: () => { + openFile(false); + }, }, { - label: 'Create todo.txt file', - click: createFile, + label: 'Create file', + click: () => { + createFile(false); + }, }, { type: 'separator' }, ...(files?.length > 0 diff --git a/src/main/modules/TodoObject/ChangeCompleteState.tsx b/src/main/modules/TodoObject/ChangeCompleteState.tsx index ed4f8dbf..ffa80744 100644 --- a/src/main/modules/TodoObject/ChangeCompleteState.tsx +++ b/src/main/modules/TodoObject/ChangeCompleteState.tsx @@ -36,4 +36,4 @@ async function changeCompleteState(todoString: string, state: boolean): Promise< return Promise.resolve(updatedTodoString); } -export { changeCompleteState }; +export { changeCompleteState }; \ No newline at end of file diff --git a/src/main/util.tsx b/src/main/util.tsx index 46391ddc..09183583 100644 --- a/src/main/util.tsx +++ b/src/main/util.tsx @@ -66,7 +66,7 @@ export interface File { todoFileName: string; todoFilePath: string; todoFileBookmark: string | null; - doneFilePath: string; + doneFilePath: string | null; doneFileBookmark: string | null; } diff --git a/src/renderer/App.tsx b/src/renderer/App.tsx index 10a8eb2f..97204084 100644 --- a/src/renderer/App.tsx +++ b/src/renderer/App.tsx @@ -50,6 +50,8 @@ const App = () => { const [textFieldValue, setTextFieldValue] = useState(null); const [promptItem, setPromptItem] = useState(null); const [matomo, setMatomo] = useState(store.get('matomo') || false); + const [showPromptArchive, setShowPromptArchive] = useState(false); + const [showPromptDoneFile, setShowPromptDoneFile] = useState(false); const searchFieldRef = useRef(null); @@ -175,7 +177,7 @@ const App = () => { }, [promptItem]); useEffect(() => { - store.set('', isNavigationOpen) + store.set('isNavigationOpen', isNavigationOpen) }, [isNavigationOpen]); useEffect(() => { @@ -244,6 +246,7 @@ const App = () => { setIsNavigationOpen={setIsNavigationOpen} setIsSettingsOpen={setIsSettingsOpen} setTodoObject={setTodoObject} + setShowPromptArchive={setShowPromptArchive} /> {files?.length > 0 && ( <> @@ -336,6 +339,7 @@ const App = () => { setSnackBarSeverity={setSnackBarSeverity} setSnackBarContent={setSnackBarContent} setPromptItem={setPromptItem} + setShowPromptDoneFile={setShowPromptDoneFile} /> )} { {promptItem && ( { onConfirm={() => handlePromptConfirm(promptItem)} headline={promptItem.headline || ''} text={promptItem.text || ''} - buttonText={promptItem.label} + confirmButton={promptItem.label} /> )} diff --git a/src/renderer/Archive.tsx b/src/renderer/Archive.tsx index 9180c9bb..7c743f8f 100644 --- a/src/renderer/Archive.tsx +++ b/src/renderer/Archive.tsx @@ -2,44 +2,66 @@ import React, { useState, useEffect } from 'react'; import { withTranslation, WithTranslation } from 'react-i18next'; import Prompt from './Prompt'; import { i18n } from './LanguageSelector'; +import { File } from '../main/util'; -const { ipcRenderer } = window.api; +const { ipcRenderer, store } = window.api; interface Props extends WithTranslation { setSnackBarContent: React.Dispatch>; setSnackBarSeverity: React.Dispatch>; + showPromptArchive: boolean; + setShowPromptArchive: React.Dispatch>, + showPromptDoneFile: boolean; + setShowPromptDoneFile: React.Dispatch>, t: typeof i18n.t; } const Archive: React.FC = ({ setSnackBarContent, setSnackBarSeverity, + showPromptArchive, + setShowPromptArchive, + showPromptDoneFile, + setShowPromptDoneFile, t }) => { - const [showPrompt, setShowPrompt] = useState(false); - const handleArchiveTodos = (response: string | Error) => { + setShowPromptDoneFile(false); if (typeof response === 'string') { setSnackBarSeverity('success'); setSnackBarContent(response); - setShowPrompt(false); + setShowPromptArchive(false); } else if (response instanceof Error) { setSnackBarSeverity('error'); setSnackBarContent(response.message); - setShowPrompt(true); + setShowPromptArchive(true); } else { - setShowPrompt(true); + setShowPromptArchive(true); } }; - const handlePromptClose = () => { - setShowPrompt(false); + const handlePromptArchiveConfirm = () => { + ipcRenderer.send('archiveTodos'); }; - const handlePromptConfirm = () => { - ipcRenderer.send('archiveTodos'); + const handleOpenDoneFile = () => { + ipcRenderer.send('openFile', true); + }; + + const handleCreateDoneFile = () => { + ipcRenderer.send('createFile', true); }; + useEffect(() => { + const files: File[] = store.get('files'); + const index = files.findIndex((file) => file.active); + + if(showPromptArchive && !files[index].doneFilePath) { + setShowPromptArchive(false); + setShowPromptDoneFile(true); + } + }, [showPromptArchive]); + useEffect(() => { ipcRenderer.on('archiveTodos', handleArchiveTodos); }, []); @@ -47,12 +69,22 @@ const Archive: React.FC = ({ return ( <> setShowPromptDoneFile(false)} + headline={t('prompt.archive.changeFile.headline')} + text={t('prompt.archive.changeFile.text')} + button1={t('openFile')} + onButton1={handleOpenDoneFile} + button2={t('createFile')} + onButton2={handleCreateDoneFile} + /> + setShowPromptArchive(false)} headline={t('prompt.archive.headline')} text={t('prompt.archive.text')} - buttonText={t('prompt.archive.button')} + confirmButton={t('prompt.archive.button')} + onConfirm={handlePromptArchiveConfirm} /> ); diff --git a/src/renderer/ContextMenu.tsx b/src/renderer/ContextMenu.tsx index 2eaa00cb..4d09944a 100644 --- a/src/renderer/ContextMenu.tsx +++ b/src/renderer/ContextMenu.tsx @@ -14,6 +14,7 @@ interface Props { setSnackBarSeverity: React.Dispatch>; setSnackBarContent: React.Dispatch>; setPromptItem: React.Dispatch>; + setShowPromptDoneFile: React.Dispatch>; } const { ipcRenderer } = window.api; @@ -26,6 +27,7 @@ const ContextMenu: React.FC = memo(({ setSnackBarSeverity, setSnackBarContent, setPromptItem, + setShowPromptDoneFile, }) => { const handleContextMenuClick = (item: ContextMenuItem) => { const { id, todoObject, index} = item; @@ -50,7 +52,8 @@ const ContextMenu: React.FC = memo(({ }; const handleChangeDoneFilePath = (index: number | undefined) => { - ipcRenderer.send('changeDoneFilePath', index); + //ipcRenderer.send('changeDoneFilePath', index); + setShowPromptDoneFile(true); }; const handleSaveToClipboard = function (response: Error | string) { diff --git a/src/renderer/Navigation.tsx b/src/renderer/Navigation.tsx index f1fcb652..5e1f7d54 100644 --- a/src/renderer/Navigation.tsx +++ b/src/renderer/Navigation.tsx @@ -1,6 +1,7 @@ import React, { useEffect, memo } from 'react'; import AddIcon from '@mui/icons-material/Add'; import FilterAltIcon from '@mui/icons-material/FilterAlt'; +import InventoryIcon from '@mui/icons-material/Inventory'; import FileOpenIcon from '@mui/icons-material/FileOpen'; import SettingsIcon from '@mui/icons-material/Settings'; import KeyboardArrowLeftIcon from '@mui/icons-material/KeyboardArrowLeft'; @@ -18,6 +19,7 @@ interface Props { setDialogOpen: React.Dispatch>; files: File[]; setIsNavigationOpen: React.Dispatch>; + setShowPromptArchive: React.Dispatch>; } const NavigationComponent: React.FC = memo(({ @@ -27,6 +29,7 @@ const NavigationComponent: React.FC = memo(({ setDialogOpen, files, setIsNavigationOpen, + setShowPromptArchive, }) => { useEffect(() => { const handleKeyDown = (event: KeyboardEvent) => { @@ -52,9 +55,12 @@ const NavigationComponent: React.FC = memo(({ + )} - - + + + {button1 && } + {button2 && } + {confirmButton && } + ); }; -export default Prompt; +export default withTranslation()(Prompt); diff --git a/src/renderer/SplashScreen.tsx b/src/renderer/SplashScreen.tsx index 3baf4980..82eceec8 100644 --- a/src/renderer/SplashScreen.tsx +++ b/src/renderer/SplashScreen.tsx @@ -32,11 +32,11 @@ const SplashScreen: FC = memo(({ }; const handleOpenFile = () => { - ipcRenderer.send('openFile'); + ipcRenderer.send('openFile', false); }; const handleCreateFile = () => { - ipcRenderer.send('createFile'); + ipcRenderer.send('createFile', false); }; return ( @@ -69,10 +69,10 @@ const SplashScreen: FC = memo(({

{t('splashscreen.noFiles.text')}