diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 4a7ea303..00000000 --- a/.editorconfig +++ /dev/null @@ -1,12 +0,0 @@ -root = true - -[*] -indent_style = space -indent_size = 2 -end_of_line = lf -charset = utf-8 -trim_trailing_whitespace = true -insert_final_newline = true - -[*.md] -trim_trailing_whitespace = false diff --git a/.erb/configs/.eslintrc b/.erb/configs/.eslintrc deleted file mode 100644 index 83dd1e44..00000000 --- a/.erb/configs/.eslintrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "rules": { - "no-console": "off", - "global-require": "off", - "import/no-dynamic-require": "off" - } -} \ No newline at end of file diff --git a/.erb/configs/webpack.config.eslint.ts b/.erb/configs/webpack.config.eslint.ts deleted file mode 100644 index af7ab2a9..00000000 --- a/.erb/configs/webpack.config.eslint.ts +++ /dev/null @@ -1,3 +0,0 @@ -/* eslint import/no-unresolved: off, import/no-self-import: off */ - -module.exports = require('./webpack.config.renderer.dev').default; \ No newline at end of file diff --git a/.erb/configs/webpack.config.main.prod.ts b/.erb/configs/webpack.config.main.prod.ts index 747c1513..e4309c99 100644 --- a/.erb/configs/webpack.config.main.prod.ts +++ b/.erb/configs/webpack.config.main.prod.ts @@ -35,6 +35,10 @@ const configuration: webpack.Configuration = { }, }, + resolve: { + extensions: ['.tsx', '.ts', '.js'], + }, + optimization: { minimizer: [ new TerserPlugin({ diff --git a/.erb/scripts/.eslintrc b/.erb/scripts/.eslintrc deleted file mode 100644 index 35dc618d..00000000 --- a/.erb/scripts/.eslintrc +++ /dev/null @@ -1,8 +0,0 @@ -{ - "rules": { - "no-console": "off", - "global-require": "off", - "import/no-dynamic-require": "off", - "import/no-extraneous-dependencies": "off" - } -} diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 16585b65..00000000 --- a/.eslintignore +++ /dev/null @@ -1,33 +0,0 @@ -# Logs -logs -*.log - -# Runtime data -pids -*.pid -*.seed - -# Coverage directory used by tools like istanbul -coverage -.eslintcache - -# Dependency directory -# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git -node_modules - -# OSX -.DS_Store - -release/app/dist -release/build -.erb/dll - -.idea -npm-debug.log.* -*.css.d.ts -*.sass.d.ts -*.scss.d.ts - -# eslint ignores hidden directories by default: -# https://github.com/eslint/eslint/issues/8429 -!.erb \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index aa8d5860..00000000 --- a/.eslintrc.js +++ /dev/null @@ -1,37 +0,0 @@ -module.exports = { - extends: 'erb', - plugins: ['@typescript-eslint'], - rules: { - // A temporary hack related to IDE not resolving correct package.json - 'import/no-extraneous-dependencies': 'off', - 'react/react-in-jsx-scope': 'off', - 'react/jsx-filename-extension': 'off', - 'import/extensions': 'off', - 'import/no-unresolved': 'off', - 'import/no-import-module-exports': 'off', - 'no-shadow': 'off', - '@typescript-eslint/no-shadow': 'error', - 'no-unused-vars': 'off', - '@typescript-eslint/no-unused-vars': 'error', - }, - parserOptions: { - ecmaVersion: 2020, - sourceType: 'module', - project: './tsconfig.json', - tsconfigRootDir: __dirname, - createDefaultProgram: true, - }, - settings: { - 'import/resolver': { - // See https://github.com/benmosher/eslint-plugin-import/issues/1396#issuecomment-575727774 for line below - node: {}, - webpack: { - config: require.resolve('./.erb/configs/webpack.config.eslint.ts'), - }, - typescript: {}, - }, - 'import/parsers': { - '@typescript-eslint/parser': ['.ts', '.tsx'], - }, - }, -}; diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 20570f2f..00000000 --- a/.gitattributes +++ /dev/null @@ -1,12 +0,0 @@ -* text eol=lf -*.exe binary -*.png binary -*.jpg binary -*.jpeg binary -*.ico binary -*.icns binary -*.eot binary -*.otf binary -*.ttf binary -*.woff binary -*.woff2 binary diff --git a/SECURITY.md b/SECURITY.md index e109eda5..61e61692 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -12,4 +12,4 @@ The following versions of sleek are provided with security updates. ## Reporting a Vulnerability -If you find a vulnerability in sleek, please send as much detail as possible to ransome@duck.com. \ No newline at end of file +If you find a vulnerability in sleek, please send as much detail as possible to ransome@mailbox.org. \ No newline at end of file diff --git a/assets/architecture.drawio b/assets/architecture.drawio deleted file mode 100644 index 9295c7f5..00000000 --- a/assets/architecture.drawio +++ /dev/null @@ -1,154 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/flatpak/com.github.ransome1.sleek.appdata.xml b/flatpak/com.github.ransome1.sleek.appdata.xml index 10594c3e..b111a764 100755 --- a/flatpak/com.github.ransome1.sleek.appdata.xml +++ b/flatpak/com.github.ransome1.sleek.appdata.xml @@ -9,7 +9,7 @@ Robin Ahle - + https://github.com/ransome1/sleek https://github.com/ransome1/sleek/issues diff --git a/flatpak/com.github.ransome1.sleek.desktop b/flatpak/com.github.ransome1.sleek.desktop index 02ea2f5e..36569b08 100755 --- a/flatpak/com.github.ransome1.sleek.desktop +++ b/flatpak/com.github.ransome1.sleek.desktop @@ -1,5 +1,5 @@ [Desktop Entry] -Version=2.0.4-rc.3 +Version=2.0.4-rc.4 Name=sleek Exec=sleek Type=Application diff --git a/package.json b/package.json index 23b59a9b..f740f7ca 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "sleek", - "version": "2.0.4-rc.3", + "version": "2.0.4-rc.4", "main": "./src/main/main.tsx", "scripts": { "build": "concurrently \"yarn run peggy\" \"yarn run build:main\" \"yarn run build:renderer\"", @@ -90,15 +90,15 @@ "sugar": "^2.0.6" }, "devDependencies": { - "@electron/notarize": "^1.2.3", + "@electron/notarize": "^2.2.0", "@electron/rebuild": "^3.2.13", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.10", "@svgr/webpack": "^8.0.1", "@teamsupercell/typings-for-css-modules-loader": "^2.5.2", - "@testing-library/jest-dom": "^5.16.5", + "@testing-library/jest-dom": "^6.1.5", "@testing-library/react": "^14.0.0", "@types/jest": "^29.5.2", - "@types/node": "20.2.5", + "@types/node": "20.10.5", "@types/react": "^18.2.8", "@types/react-dom": "^18.2.4", "@types/react-test-renderer": "^18.0.0", @@ -119,7 +119,7 @@ "jest": "^29.5.0", "jest-environment-jsdom": "^29.5.0", "mini-css-extract-plugin": "^2.7.6", - "prettier": "^2.8.8", + "prettier": "^3.1.1", "react-refresh": "^0.14.0", "react-test-renderer": "^18.2.0", "rimraf": "^5.0.1", diff --git a/release/app/package.json b/release/app/package.json index 975f2371..567d46d1 100644 --- a/release/app/package.json +++ b/release/app/package.json @@ -1,6 +1,6 @@ { "name": "sleek", - "version": "2.0.4-rc.3", + "version": "2.0.4-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": [ @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/ransome1/sleek.git" }, - "author": "Robin Ahle ", + "author": "Robin Ahle ", "copyright": "Copyright © 2023 ${author}", "license": "MIT", "main": "./dist/main/main.js", diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index ca62142c..1f38ecaf 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -1,6 +1,6 @@ name: sleek base: core20 -version: "2.0.4-rc.3" +version: "2.0.4-rc.4" summary: todo.txt manager for Linux, free and open-source (FOSS) description: | sleek is an open-source (FOSS) todo manager based on the todo.txt syntax. Stripped down to only the most necessary features, and with a clean and simple interface, sleek aims to help you focus on getting things done. diff --git a/src/__tests__/__mock__/recurrence.txt b/src/__tests__/__mock__/recurrence.txt index c3b5fbdc..9da1efd0 100644 --- a/src/__tests__/__mock__/recurrence.txt +++ b/src/__tests__/__mock__/recurrence.txt @@ -1,15 +1,15 @@ -2023-12-19 Line 1 rec:1d due:2023-12-20 -2023-12-19 Line 1 rec:w due:2023-12-26 -2023-12-19 Line 1 rec:2m due:2024-02-19 -2023-12-19 Line 1 rec:+1d due:2023-12-21 -2023-12-19 Line 1 rec:7w due:2024-02-06 -2023-12-19 Line 1 due:2023-07-24 rec:+1b -2023-12-19 taxes are due in one year t:2022-03-30 due:2022-04-30 rec:+1y -2023-12-19 Water plants @home +quick due:2023-12-26 t:2023-12-16 rec:1w -2023-12-19 Line 1 rec:+1d t:2023-09-20 -2023-12-19 Line 1 rec:1d pri:A due:2023-12-20 -2023-12-19 (A) Do something rec:d t:2023-12-20 @SomeContext -2023-12-19 Do something rec:0d -2023-12-19 Do something rec:0d due:2023-12-19 -2023-12-19 Do something rec:0d due:2023-12-19 t:2023-12-19 \ No newline at end of file +2023-12-23 Line 1 rec:1d due:2023-12-24 +2023-12-23 Line 1 rec:w due:2023-12-30 +2023-12-23 Line 1 rec:2m due:2024-02-23 +2023-12-23 Line 1 rec:+1d due:2023-12-25 +2023-12-23 Line 1 rec:7w due:2024-02-10 +2023-12-23 Line 1 due:2023-07-24 rec:+1b +2023-12-23 taxes are due in one year t:2022-03-30 due:2022-04-30 rec:+1y +2023-12-23 Water plants @home +quick due:2023-12-30 t:2023-12-20 rec:1w +2023-12-23 Line 1 rec:+1d t:2023-09-20 +2023-12-23 Line 1 rec:1d pri:A due:2023-12-24 +2023-12-23 (A) Do something rec:d t:2023-12-24 @SomeContext +2023-12-23 Do something rec:0d +2023-12-23 Do something rec:0d due:2023-12-23 +2023-12-23 Do something rec:0d due:2023-12-23 t:2023-12-23 \ No newline at end of file diff --git a/src/__tests__/main/Write.tsx b/src/__tests__/main/Write.tsx index 61680548..5603bbdf 100644 --- a/src/__tests__/main/Write.tsx +++ b/src/__tests__/main/Write.tsx @@ -98,9 +98,7 @@ describe('Writing to file', () => { test('should append 3 new lines at the end of the file', async () => { const originalGet = configStorage.get; configStorage.get = (key: string) => { - if(key === 'multilineTextField') { - return true; - } else if(key === 'useMultilineForBulkTodoCreation') { + if(key === 'bulkTodoCreation') { return true; } return originalGet.call(configStorage, key); @@ -117,9 +115,7 @@ describe('Writing to file', () => { test('should update a specific line and append 2 lines to the updated line', async () => { const originalGet = configStorage.get; configStorage.get = (key: string) => { - if(key === 'multilineTextField') { - return true; - } else if(key === 'useMultilineForBulkTodoCreation') { + if(key === 'bulkTodoCreation') { return true; } return originalGet.call(configStorage, key); @@ -136,9 +132,7 @@ describe('Writing to file', () => { test('should append a multi line todo', async () => { const originalGet = configStorage.get; configStorage.get = (key: string) => { - if(key === 'multilineTextField') { - return true; - } else if(key === 'useMultilineForBulkTodoCreation') { + if(key === 'bulkTodoCreation') { return false; } return originalGet.call(configStorage, key); @@ -155,9 +149,7 @@ describe('Writing to file', () => { test('should update line with a multi line todo', async () => { const originalGet = configStorage.get; configStorage.get = (key: string) => { - if(key === 'multilineTextField') { - return true; - } else if(key === 'useMultilineForBulkTodoCreation') { + if(key === 'bulkTodoCreation') { return false; } return originalGet.call(configStorage, key); diff --git a/src/locales/cs.json b/src/locales/cs.json index 50d5efdc..ca6a6015 100644 --- a/src/locales/cs.json +++ b/src/locales/cs.json @@ -21,7 +21,7 @@ "settings.dark": "Tmavé", "settings.language": "Jazyk", "settings.notificationThreshold": "Hranice oznámení", - "settings.useMultilineForBulkTodoCreation": "Každý řádek v textovém poli vytvoří samostatnou položku úkolu", + "settings.bulkTodoCreation": "Každý řádek v textovém poli vytvoří samostatnou položku úkolu", "settings.matomo": "Povolit analýzu Matomo", "drawer.tabs.attributes": "Atributy", "drawer.tabs.filters": "Filtry", diff --git a/src/locales/de.json b/src/locales/de.json index d4c6ee00..feda98c1 100644 --- a/src/locales/de.json +++ b/src/locales/de.json @@ -21,7 +21,7 @@ "settings.dark": "Dunkel", "settings.language": "Sprache", "settings.notificationThreshold": "Benachrichtigungsschwelle", - "settings.useMultilineForBulkTodoCreation": "Jede Zeile im Textfeld erstellt eine separate Todo", + "settings.bulkTodoCreation": "Jede Zeile im Textfeld erstellt eine separate Todo", "settings.matomo": "Matomo-Analyse erlauben", "drawer.tabs.attributes": "Attribute", "drawer.tabs.filters": "Filter", diff --git a/src/locales/en-gb.json b/src/locales/en-gb.json index a02c588e..3648d754 100644 --- a/src/locales/en-gb.json +++ b/src/locales/en-gb.json @@ -21,7 +21,7 @@ "settings.dark": "Dark", "settings.language": "Language", "settings.notificationThreshold": "Notification threshold", - "settings.useMultilineForBulkTodoCreation": "Each row in the text field creates a separate to-do item", + "settings.bulkTodoCreation": "Each row in the text field creates a separate to-do item", "settings.matomo": "Allow Matomo Analysis", "drawer.tabs.attributes": "Attributes", "drawer.tabs.filters": "Filters", diff --git a/src/locales/en.json b/src/locales/en.json index a02c588e..3648d754 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -21,7 +21,7 @@ "settings.dark": "Dark", "settings.language": "Language", "settings.notificationThreshold": "Notification threshold", - "settings.useMultilineForBulkTodoCreation": "Each row in the text field creates a separate to-do item", + "settings.bulkTodoCreation": "Each row in the text field creates a separate to-do item", "settings.matomo": "Allow Matomo Analysis", "drawer.tabs.attributes": "Attributes", "drawer.tabs.filters": "Filters", diff --git a/src/locales/es.json b/src/locales/es.json index 3ed6c50d..3132b3f3 100644 --- a/src/locales/es.json +++ b/src/locales/es.json @@ -21,7 +21,7 @@ "settings.dark": "Oscuro", "settings.language": "Idioma", "settings.notificationThreshold": "Umbral de notificación", - "settings.useMultilineForBulkTodoCreation": "Cada línea en el campo de texto crea un elemento de tarea separado", + "settings.bulkTodoCreation": "Cada línea en el campo de texto crea un elemento de tarea separado", "settings.matomo": "Permitir análisis de Matomo", "drawer.tabs.attributes": "Atributos", "drawer.tabs.filters": "Filtros", diff --git a/src/locales/fr.json b/src/locales/fr.json index eb448a16..2c35edbd 100644 --- a/src/locales/fr.json +++ b/src/locales/fr.json @@ -21,7 +21,7 @@ "settings.dark": "Sombre", "settings.language": "Langue", "settings.notificationThreshold": "Umbral de notificación", - "settings.useMultilineForBulkTodoCreation": "Chaque ligne dans le champ de texte crée un élément de tâche séparé", + "settings.bulkTodoCreation": "Chaque ligne dans le champ de texte crée un élément de tâche séparé", "settings.matomo": "Autoriser l'analyse Matomo", "drawer.tabs.attributes": "Attributs", "drawer.tabs.filters": "Filtres", diff --git a/src/locales/hi.json b/src/locales/hi.json index dd386b7b..cae1c53c 100644 --- a/src/locales/hi.json +++ b/src/locales/hi.json @@ -21,7 +21,7 @@ "settings.dark": "डार्क", "settings.language": "भाषा", "settings.notificationThreshold": "सूचना सीमा", - "settings.useMultilineForBulkTodoCreation": "पाठ क्षेत्र में प्रत्येक पंक्ति स्वतंत्र टूडू आइटम बनाती है", + "settings.bulkTodoCreation": "पाठ क्षेत्र में प्रत्येक पंक्ति स्वतंत्र टूडू आइटम बनाती है", "settings.matomo": "मैटोमो विश्लेषण की अनुमति दें", "drawer.tabs.attributes": "गुण", "drawer.tabs.filters": "फ़िल्टर", diff --git a/src/locales/hu.json b/src/locales/hu.json index 9faa2d2c..a4b51c0f 100644 --- a/src/locales/hu.json +++ b/src/locales/hu.json @@ -21,7 +21,7 @@ "settings.dark": "Sötét", "settings.language": "Nyelv", "settings.notificationThreshold": "Értesítés küszöbérték", - "settings.useMultilineForBulkTodoCreation": "Minden sor külön teendőelemet hoz létre a szövegmezőben", + "settings.bulkTodoCreation": "Minden sor külön teendőelemet hoz létre a szövegmezőben", "settings.matomo": "Matomo elemzés engedélyezése", "drawer.tabs.attributes": "Tulajdonságok", "drawer.tabs.filters": "Szűrők", diff --git a/src/locales/it.json b/src/locales/it.json index 4f438e7e..7bb74cc8 100644 --- a/src/locales/it.json +++ b/src/locales/it.json @@ -21,7 +21,7 @@ "settings.dark": "Scuro", "settings.language": "Lingua", "settings.notificationThreshold": "Soglia di notifica", - "settings.useMultilineForBulkTodoCreation": "Ogni riga nel campo di testo crea un'attività separata", + "settings.bulkTodoCreation": "Ogni riga nel campo di testo crea un'attività separata", "settings.matomo": "Consenti l'analisi di Matomo", "drawer.tabs.attributes": "Attributi", "drawer.tabs.filters": "Filtri", diff --git a/src/locales/jp.json b/src/locales/jp.json index 6f20488d..6c973c6b 100644 --- a/src/locales/jp.json +++ b/src/locales/jp.json @@ -21,7 +21,7 @@ "settings.dark": "ダーク", "settings.language": "言語", "settings.notificationThreshold": "通知しきい値", - "settings.useMultilineForBulkTodoCreation": "テキストフィールド内の各行は別々のタスクを作成します", + "settings.bulkTodoCreation": "テキストフィールド内の各行は別々のタスクを作成します", "settings.matomo": "Matomoの分析を許可", "drawer.tabs.attributes": "属性", "drawer.tabs.filters": "フィルター", diff --git a/src/locales/ko.json b/src/locales/ko.json index 3d253b45..23ac5199 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -21,7 +21,7 @@ "settings.dark": "다크", "settings.language": "언어", "settings.notificationThreshold": "알림 임계값", - "settings.useMultilineForBulkTodoCreation": "텍스트 필드의 각 줄은 별도의 할 일 항목을 생성합니다", + "settings.bulkTodoCreation": "텍스트 필드의 각 줄은 별도의 할 일 항목을 생성합니다", "settings.matomo": "Matomo 분석 허용", "drawer.tabs.attributes": "속성", "drawer.tabs.filters": "필터", diff --git a/src/locales/pl.json b/src/locales/pl.json index 8e61c9a4..289ec71e 100644 --- a/src/locales/pl.json +++ b/src/locales/pl.json @@ -21,7 +21,7 @@ "settings.dark": "Ciemny", "settings.language": "Język", "settings.notificationThreshold": "Prog powiadomień", - "settings.useMultilineForBulkTodoCreation": "Każdy wiersz w polu tekstowym tworzy oddzielną pozycję na liście zadań", + "settings.bulkTodoCreation": "Każdy wiersz w polu tekstowym tworzy oddzielną pozycję na liście zadań", "settings.matomo": "Zezwalaj na analizę Matomo", "drawer.tabs.attributes": "Atrybuty", "drawer.tabs.filters": "Filtry", diff --git a/src/locales/pt.json b/src/locales/pt.json index 220076d8..de8a8e0e 100644 --- a/src/locales/pt.json +++ b/src/locales/pt.json @@ -21,7 +21,7 @@ "settings.dark": "Escuro", "settings.language": "Idioma", "settings.notificationThreshold": "Prog powiadomień", - "settings.useMultilineForBulkTodoCreation": "Cada linha no campo de texto cria um item de tarefa separado", + "settings.bulkTodoCreation": "Cada linha no campo de texto cria um item de tarefa separado", "settings.matomo": "Permitir Análise do Matomo", "drawer.tabs.attributes": "Atributos", "drawer.tabs.filters": "Filtros", diff --git a/src/locales/ru.json b/src/locales/ru.json index 66a2d074..d9e5a723 100644 --- a/src/locales/ru.json +++ b/src/locales/ru.json @@ -21,7 +21,7 @@ "settings.dark": "Темная", "settings.language": "Язык", "settings.notificationThreshold": "Порог уведомлений", - "settings.useMultilineForBulkTodoCreation": "Каждая строка в текстовом поле создает отдельную задачу", + "settings.bulkTodoCreation": "Каждая строка в текстовом поле создает отдельную задачу", "settings.matomo": "Разрешить анализ Matomo", "drawer.tabs.attributes": "Атрибуты", "drawer.tabs.filters": "Фильтры", diff --git a/src/locales/tr.json b/src/locales/tr.json index 591acc29..4d8eef0d 100644 --- a/src/locales/tr.json +++ b/src/locales/tr.json @@ -21,7 +21,7 @@ "settings.dark": "Koyu", "settings.language": "Dil", "settings.notificationThreshold": "Bildirim Eşik Değeri", - "settings.useMultilineForBulkTodoCreation": "Metin alanındaki her satır ayrı bir görev oluşturur", + "settings.bulkTodoCreation": "Metin alanındaki her satır ayrı bir görev oluşturur", "settings.matomo": "Matomo Analizine İzin Ver", "drawer.tabs.attributes": "Özellikler", "drawer.tabs.filters": "Filtreler", diff --git a/src/locales/zh.json b/src/locales/zh.json index 1d1f9446..c3f43f2a 100644 --- a/src/locales/zh.json +++ b/src/locales/zh.json @@ -21,7 +21,7 @@ "settings.dark": "暗黑", "settings.language": "语言", "settings.notificationThreshold": "通知阈值", - "settings.useMultilineForBulkTodoCreation": "文本字段中的每一行都创建一个单独的待办事项", + "settings.bulkTodoCreation": "文本字段中的每一行都创建一个单独的待办事项", "settings.matomo": "允许Matomo分析", "drawer.tabs.attributes": "属性", "drawer.tabs.filters": "过滤器", diff --git a/src/main/config.tsx b/src/main/config.tsx index dac2917c..442a511a 100644 --- a/src/main/config.tsx +++ b/src/main/config.tsx @@ -74,6 +74,12 @@ const configStorage = new Store({ '2.0.2': store => { store.set('dueDateInTheFuture', true); }, + '2.0.4': store => { + store.delete('multilineTextField'); + store.delete('isDrawerOpen'); + store.delete('useMultilineForBulkTodoCreation'); + store.set('bulkTodoCreation', false); + }, } }); diff --git a/src/main/modules/File/Write.tsx b/src/main/modules/File/Write.tsx index b50aaa23..89816d49 100644 --- a/src/main/modules/File/Write.tsx +++ b/src/main/modules/File/Write.tsx @@ -28,12 +28,23 @@ async function removeLineFromFile(id: number): Promise { return `Line ${id} removed from file`; } -async function writeTodoObjectToFile(id: number, inputString: string): Promise { - const multilineTextField: boolean = configStorage.get('multilineTextField'); - const useMultilineForBulkTodoCreation: boolean = configStorage.get('useMultilineForBulkTodoCreation'); +async function writeTodoObjectToFile(id: number, string: string): Promise { + const activeFile: FileObject | null = getActiveFile(); + if(!activeFile) { + throw new Error('Todo file is not defined'); + } + const bookmark = activeFile.todoFileBookmark; + const todoFilePath = activeFile.todoFilePath; + + const bulkTodoCreation: boolean = configStorage.get('bulkTodoCreation'); const convertRelativeToAbsoluteDates = configStorage.get('convertRelativeToAbsoluteDates'); const appendCreationDate = configStorage.get('appendCreationDate'); - const content = (multilineTextField && useMultilineForBulkTodoCreation) ? inputString : inputString.replaceAll(/\n/g, String.fromCharCode(16)); + + const content = + (bulkTodoCreation) + ? string.replaceAll(String.fromCharCode(16), '\n') + : string.replaceAll(/\n/g, String.fromCharCode(16)); + const linesToWrite = content.split('\n').filter(line => line.trim() !== ''); if(linesToWrite.length === 0 && id < 1) { @@ -57,25 +68,11 @@ async function writeTodoObjectToFile(id: number, inputString: string): Promise { try { @@ -17,6 +18,16 @@ async function handleDataRequest(event: IpcMainEvent, searchString: string): Pro } } +async function handleCreateTodoObject(event: IpcMainEvent, string: string, index: number, refreshTextField: boolean): Promise { + try { + const todoObject = await createTodoObject(string, index); + event.reply('createTodoObject', todoObject, refreshTextField); + } catch(error) { + console.error(error); + event.reply('handleError', error); + } +} + async function handleWriteTodoToFile(event: IpcMainEvent, id: number, string: string, state: boolean): Promise { try { let updatedString: string | null = string; @@ -173,6 +184,7 @@ function removeEventListeners(): void { ipcMain.off('removeFile', handleRemoveFile); ipcMain.off('openFile', handleOpenFile); ipcMain.off('createFile', handleCreateFile); + ipcMain.off('createTodoObject', handleCreateTodoObject); ipcMain.off('requestData', handleDataRequest); ipcMain.off('writeTodoToFile', handleWriteTodoToFile); ipcMain.off('archiveTodos', handleArchiveTodos); @@ -193,6 +205,7 @@ ipcMain.on('setFile', handleSetFile); ipcMain.on('removeFile', handleRemoveFile); ipcMain.on('openFile', handleOpenFile); ipcMain.on('createFile', handleCreateFile); +ipcMain.on('createTodoObject', handleCreateTodoObject); ipcMain.on('requestData', handleDataRequest); ipcMain.on('writeTodoToFile', handleWriteTodoToFile); ipcMain.on('archiveTodos', handleArchiveTodos); diff --git a/src/main/modules/Menu.tsx b/src/main/modules/Menu.tsx index ee846e25..255b819a 100644 --- a/src/main/modules/Menu.tsx +++ b/src/main/modules/Menu.tsx @@ -9,6 +9,10 @@ const isMac: boolean = process.platform === 'darwin'; const description = appPackage.description; function createMenu(files: FileObject[]) { + // @ts-ignore + // @ts-ignore + // @ts-ignore + // @ts-ignore const template: Electron.MenuItemConstructorOptions[] = [ { label: 'sleek', diff --git a/src/main/modules/ProcessDataRequest/CreateRecurringTodo.tsx b/src/main/modules/ProcessDataRequest/CreateRecurringTodo.tsx index 25f3317f..cd47b884 100644 --- a/src/main/modules/ProcessDataRequest/CreateRecurringTodo.tsx +++ b/src/main/modules/ProcessDataRequest/CreateRecurringTodo.tsx @@ -49,9 +49,9 @@ const createRecurringTodo = async (todoString: string, recurrence: string): Prom if(recurrence) { const strictRecurrence: boolean = recurrence.startsWith('+'); - const temp: any = strictRecurrence ? recurrence.slice(1) : recurrence; - const recurrenceInterval = temp.slice(-1) as RecurrenceInterval; - const recurrenceValue = parseInt(temp.slice(0, -1)); + const updatedRecurrence: any = strictRecurrence ? recurrence.slice(1) : recurrence; + const recurrenceInterval = updatedRecurrence.slice(-1) as RecurrenceInterval; + const recurrenceValue = parseInt(updatedRecurrence.slice(0, -1)); const oldDueDate: any = JsTodoTxtObject?.extensions()?.find((item) => item.key === 'due')?.value; const oldThresholdDate: any = JsTodoTxtObject?.extensions()?.find((item) => item.key === 't')?.value; diff --git a/src/main/modules/ProcessDataRequest/CreateTodoObjects.tsx b/src/main/modules/ProcessDataRequest/CreateTodoObjects.tsx index 67fe5b4f..9b81ecdd 100644 --- a/src/main/modules/ProcessDataRequest/CreateTodoObjects.tsx +++ b/src/main/modules/ProcessDataRequest/CreateTodoObjects.tsx @@ -1,12 +1,50 @@ import { app } from 'electron'; import { Item } from 'jstodotxt'; -import dayjs from 'dayjs'; import { handleNotification } from '../Notifications'; import { extractSpeakingDates } from '../Date'; +import { configStorage } from '../../config'; +import dayjs from 'dayjs'; let lines: string[]; export const badge: Badge = { count: 0 }; +function createTodoObject(string: string, index: number): TodoObject { + const content = string.replaceAll(/[\x10\r\n]/g, ' '); + const JsTodoTxtObject = new Item(content); + const body = JsTodoTxtObject.body(); + const speakingDates: DateAttributes = extractSpeakingDates(body); + const due = speakingDates['due:']?.date || null; + const dueString = speakingDates['due:']?.string || null; + const notify = speakingDates['due:']?.notify || false; + const t = speakingDates['t:']?.date || null; + const tString = speakingDates['t:']?.string || null; + const extensions = JsTodoTxtObject.extensions(); + const hidden = extensions.some(extension => extension.key === 'h' && extension.value === '1'); + const pm = extensions.find(extension => extension.key === 'pm')?.value || null; + const rec = extensions.find(extension => extension.key === 'rec')?.value || null; + const creation = dayjs(JsTodoTxtObject.created()).isValid() ? dayjs(JsTodoTxtObject.created()).format('YYYY-MM-DD') : null; + const completed = dayjs(JsTodoTxtObject.completed()).isValid() ? dayjs(JsTodoTxtObject.completed()).format('YYYY-MM-DD') : null; + return { + id: index, + body, + created: creation, + complete: JsTodoTxtObject.complete(), + completed: completed, + priority: JsTodoTxtObject.priority(), + contexts: JsTodoTxtObject.contexts(), + projects: JsTodoTxtObject.projects(), + due, + dueString, + notify, + t, + tString, + rec, + hidden, + pm, + string: string, + }; +} + async function createTodoObjects(fileContent: string | null): Promise { if(!fileContent) { lines = []; @@ -14,47 +52,12 @@ async function createTodoObjects(fileContent: string | null): Promise line.trim() !== ''); - const items: Item[] = lines.map(line => new Item(line.replaceAll(String.fromCharCode(16), ' '))); - - const todoObjects: TodoObject[] = await Promise.all(items.map(async (JsTodoTxtObject, i) => { - const body = JsTodoTxtObject.body(); - const speakingDates: DateAttributes = extractSpeakingDates(body); - const due = speakingDates['due:']?.date || null; - const dueString = speakingDates['due:']?.string || null; - const notify = speakingDates['due:']?.notify || false; - const t = speakingDates['t:']?.date || null; - const tString = speakingDates['t:']?.string || null; - const extensions = JsTodoTxtObject.extensions(); - const hidden = extensions.some(extension => extension.key === 'h' && extension.value === '1'); - const pm = extensions.find(extension => extension.key === 'pm')?.value || null; - const rec = extensions.find(extension => extension.key === 'rec')?.value || null; - const creation = dayjs(JsTodoTxtObject.created()).isValid() ? dayjs(JsTodoTxtObject.created()).format('YYYY-MM-DD') : null; - const completed = dayjs(JsTodoTxtObject.completed()).isValid() ? dayjs(JsTodoTxtObject.completed()).format('YYYY-MM-DD') : null; - - const todoObject: TodoObject = { - id: i, - body, - created: creation, - complete: JsTodoTxtObject.complete(), - completed: completed, - priority: JsTodoTxtObject.priority(), - contexts: JsTodoTxtObject.contexts(), - projects: JsTodoTxtObject.projects(), - due, - dueString, - notify, - t, - tString, - rec, - hidden, - pm, - string: lines[i], - }; - - if(due && !todoObject.complete) { - handleNotification(due, body, badge); + + const todoObjects: TodoObject[] = await Promise.all(lines.map(async (line, i) => { + const todoObject: TodoObject = await createTodoObject(line, i); + if(todoObject.due && todoObject.body && !todoObject.complete) { + handleNotification(todoObject.due, todoObject.body, badge); } - return todoObject; })); @@ -63,4 +66,4 @@ async function createTodoObjects(fileContent: string | null): Promise { const [searchString, setSearchString] = useState(''); const [flattenedTodoObjects, setTodoObjects] = useState(null); const [todoObject, setTodoObject] = useState(null); + const [attributeFields, setAttributeFields] = useState(null); const [headers, setHeaders] = useState(null); const [filters, setFilters] = useState(null); const [attributes, setAttributes] = useState(null); @@ -46,11 +47,20 @@ const App = () => { const [contextMenuPosition, setContextMenuPosition] = useState(null); const [contextMenuItems, setContextMenuItems] = useState(null); const [attributeMapping, setAttributeMapping] = useState(translatedAttributes(i18n.t) || {}); - const [textFieldValue, setTextFieldValue] = useState(null); + const [textFieldValue, setTextFieldValue] = useState(''); const [promptItem, setPromptItem] = useState(null); const [triggerArchiving, setTriggerArchiving] = useState(false); const [showPromptDoneFile, setShowPromptDoneFile] = useState(false); const [matomo, setMatomo] = useState(store.get('matomo') || false); + const [selectedLanguage, setSelectedLanguage] = useState(() => { + const storedLanguage = store.get('language') || navigator.language; + const supportedLanguages: false | readonly string[] | undefined = i18n.options.supportedLngs; + if(supportedLanguages && supportedLanguages.includes(storedLanguage)) { + return storedLanguage; + } + return 'en'; + }); + const searchFieldRef = useRef(null); const handleRequestedData = (requestedData: RequestedData) => { @@ -184,13 +194,6 @@ const App = () => { setSnackBarOpen(true); }, [snackBarContent]); - useEffect(() => { - if(!dialogOpen) { - setTodoObject(null); - setTextFieldValue(''); - } - }, [dialogOpen]); - useEffect(() => { store.set('zoom', zoom); const adjustedFontSize = 16 * (zoom / 100); @@ -210,7 +213,7 @@ const App = () => { s = d.getElementsByTagName('script')[0]; g.async = true; g.src = matomoContainer; - s.parentNode.insertBefore(g, s); + s.parentNode?.insertBefore(g, s); } }, [matomo]); @@ -231,6 +234,7 @@ const App = () => { ipcRenderer.on('saveToClipboard', handleResponse); ipcRenderer.on('triggerArchiving', () => setTriggerArchiving(true)); ipcRenderer.on('ArchivingResult', handleResponse); + ipcRenderer.on('createTodoObject', (todoObject: TodoObject) => setAttributeFields(todoObject)); window.addEventListener('drop', handleDrop); window.addEventListener('dragover', handleDragOver); return () => { @@ -250,6 +254,7 @@ const App = () => { ipcRenderer.off('saveToClipboard', handleResponse); ipcRenderer.off('triggerArchiving', () => setTriggerArchiving(true)); ipcRenderer.off('ArchivingResult', handleResponse); + ipcRenderer.off('createTodoObject', (todoObject: TodoObject) => setAttributeFields(todoObject)); window.removeEventListener('drop', handleDrop); window.removeEventListener('dragover', handleDragOver); }; @@ -271,6 +276,7 @@ const App = () => { setTodoObject={setTodoObject} setTriggerArchiving={setTriggerArchiving} headers={headers} + setAttributeFields={setAttributeFields} /> {files?.length > 0 && ( <> @@ -325,7 +331,6 @@ const App = () => { setContextMenuPosition={setContextMenuPosition} contextMenuItems={contextMenuItems} setContextMenuItems={setContextMenuItems} - setTextFieldValue={setTextFieldValue} setPromptItem={setPromptItem} /> { /> - + {dialogOpen ? ( + + ) : null} setIsSettingsOpen(false)} setAttributeMapping={setAttributeMapping} zoom={zoom} setZoom={setZoom} + selectedLanguage={selectedLanguage} + setSelectedLanguage={setSelectedLanguage} /> {contextMenuItems && ( = ({ type, todoObject, date, - filters + filters, + selectedLanguage, }) => { const [open, setOpen] = useState(false); const chipText = type === 'due' ? "due:" : type === 't' ? "t:" : null; - const handleChange = (updatedDate: dayjs.Dayjs | null) => { - if(!updatedDate || !dayjs(updatedDate).isValid()) return; + const handleChange = (date: dayjs.Dayjs | null) => { + if(!date || !dayjs(date).isValid() || !todoObject.id) return; + const validDate = dayjs(date).format('YYYY-MM-DD'); - const formattedDate = dayjs(updatedDate).format('YYYY-MM-DD'); + const string = todoObject.string.replaceAll(/[\x10\r\n]/g, ` ${String.fromCharCode(16)} `); - if(todoObject?.dueString) { - const stringToReplace = ` ${type}:${todoObject.dueString}`; - todoObject.string = todoObject.string.replace(stringToReplace, ''); - } + const JsTodoTxtObject = new Item(string); + JsTodoTxtObject.setExtension(type, validDate); - const JsTodoTxtObject = new Item(todoObject.string); - JsTodoTxtObject.setExtension(type, formattedDate); + const updatedString = JsTodoTxtObject.toString().replaceAll(` ${String.fromCharCode(16)} `, String.fromCharCode(16)) + + ipcRenderer.send('writeTodoToFile', todoObject.id, updatedString); setOpen(false); - ipcRenderer.send('writeTodoToFile', todoObject.id, JsTodoTxtObject.toString()); }; const DatePickerInline = ({ date, ...props }) => { @@ -71,8 +72,6 @@ const DatePickerInline: React.FC = ({ ); }; - const selectedLanguage = store.get('language'); - return ( = memo(({ let matched = false; for (const expression of expressions) { - const regex = new RegExp(`^(${expression.pattern.source})`); const match = body.match(regex); diff --git a/src/renderer/DataGrid/Grid.tsx b/src/renderer/DataGrid/Grid.tsx index a9604d0b..dc1426b4 100644 --- a/src/renderer/DataGrid/Grid.tsx +++ b/src/renderer/DataGrid/Grid.tsx @@ -8,7 +8,6 @@ interface TodoDataGridProps { attributes: Attributes | null; filters: Filters | null; setDialogOpen: (open: boolean) => void; - setTextFieldValue: (value: string) => void; contextMenuPosition: { top: number; left: number } | null; setContextMenuPosition: (position: { top: number; left: number } | null) => void; contextMenuItems: ContextMenuItem[]; @@ -22,7 +21,6 @@ const TodoDataGrid: React.FC = memo(({ attributes, filters, setDialogOpen, - setTextFieldValue, contextMenuPosition, setContextMenuPosition, contextMenuItems, @@ -95,7 +93,6 @@ const TodoDataGrid: React.FC = memo(({ setTodoObject={setTodoObject} filters={filters} setDialogOpen={setDialogOpen} - setTextFieldValue={setTextFieldValue} contextMenuPosition={contextMenuPosition} setContextMenuPosition={setContextMenuPosition} contextMenuItems={contextMenuItems} diff --git a/src/renderer/DataGrid/Row.tsx b/src/renderer/DataGrid/Row.tsx index 68c421ab..2edef59f 100644 --- a/src/renderer/DataGrid/Row.tsx +++ b/src/renderer/DataGrid/Row.tsx @@ -16,7 +16,6 @@ interface Props extends WithTranslation { row: TodoObject; filters: Filters; setDialogOpen: React.Dispatch>; - setTextFieldValue: React.Dispatch>; setTodoObject: React.Dispatch>; setContextMenuPosition: React.Dispatch>; setContextMenuItems: React.Dispatch>; @@ -28,7 +27,6 @@ const Row: React.FC = memo(({ row, filters, setDialogOpen, - setTextFieldValue, setTodoObject, setContextMenuPosition, setContextMenuItems, @@ -52,20 +50,11 @@ const Row: React.FC = memo(({ const handleContextMenu = (event: React.MouseEvent) => { event.preventDefault(); setContextMenuPosition({ top: event.clientY, left: event.clientX }); - setContextMenuItems([ - itemCopy, - itemDelete, - ]); + setContextMenuItems([itemCopy, itemDelete]); }; const handleCheckboxChange = (event: React.ChangeEvent) => { - ipcRenderer.send( - 'writeTodoToFile', - row.id, - row.string, - event.target.checked, - false - ); + ipcRenderer.send('writeTodoToFile', row.id, row.string, event.target.checked, false); }; const handleRowClick = (event: React.KeyboardEvent | React.MouseEvent) => { @@ -86,7 +75,6 @@ const Row: React.FC = memo(({ setTodoObject(row); setDialogOpen(true); } - setTextFieldValue(row.string); } } else if((event.metaKey || event.ctrlKey) && (event.key === 'Delete' || event.key === 'Backspace')) { setPromptItem(itemDelete); diff --git a/src/renderer/LanguageSelector.tsx b/src/renderer/LanguageSelector.tsx index 9ffb27a2..1ec0f826 100644 --- a/src/renderer/LanguageSelector.tsx +++ b/src/renderer/LanguageSelector.tsx @@ -97,19 +97,16 @@ const friendlyLanguageName: Record = { interface Props { setAttributeMapping: (attributes: Record) => void; + selectedLanguage: string; + setSelectedLanguage: React.Dispatch>; } const LanguageSelector: React.FC = ({ - setAttributeMapping + setAttributeMapping, + selectedLanguage, + setSelectedLanguage, }) => { const supportedLanguages: false | readonly string[] | undefined = i18n.options.supportedLngs; - const [selectedLanguage, setSelectedLanguage] = useState(() => { - const storedLanguage = store.get('language') || navigator.language; - if(supportedLanguages && supportedLanguages.includes(storedLanguage)) { - return storedLanguage; - } - return 'en'; - }); const changeLanguage = (event: React.ChangeEvent<{ value: string }>) => { const language = event.target.value; diff --git a/src/renderer/Navigation.tsx b/src/renderer/Navigation.tsx index 8d7a0208..797e9384 100644 --- a/src/renderer/Navigation.tsx +++ b/src/renderer/Navigation.tsx @@ -20,6 +20,8 @@ interface Props { setIsNavigationOpen: React.Dispatch>; setTriggerArchiving: React.Dispatch>; headers: HeadersObject; + setTodoObject: React.Dispatch>; + setAttributeFields: React.Dispatch>; } const NavigationComponent: React.FC = memo(({ @@ -31,11 +33,20 @@ const NavigationComponent: React.FC = memo(({ setIsNavigationOpen, setTriggerArchiving, headers, + setTodoObject, + setAttributeFields }) => { + + const handleOpen = () => { + setTodoObject(null); + setDialogOpen(true); + setAttributeFields(null); + }; + useEffect(() => { const handleKeyDown = (event: KeyboardEvent) => { if(files.length > 0 && (event.metaKey || event.ctrlKey) && event.key === 'n') { - setDialogOpen(true); + handleOpen(); } }; document.addEventListener('keydown', handleKeyDown); @@ -50,7 +61,7 @@ const NavigationComponent: React.FC = memo(({ sleek {files?.length > 0 && ( <> - - {button1 && } - {button2 && } + {button1 && } + {button2 && } {confirmButton && } diff --git a/src/renderer/Settings.tsx b/src/renderer/Settings.tsx index 35f0312c..659285c9 100644 --- a/src/renderer/Settings.tsx +++ b/src/renderer/Settings.tsx @@ -23,6 +23,8 @@ interface Props extends WithTranslation { setAttributeMapping: React.Dispatch>; zoom: number; setZoom: React.Dispatch>; + selectedLanguage: string; + setSelectedLanguage: React.Dispatch>; t: typeof i18n.t; } @@ -32,6 +34,8 @@ const Settings: React.FC = memo(({ setAttributeMapping, zoom, setZoom, + selectedLanguage, + setSelectedLanguage, t, }) => { const [settings, setSettings] = useState({ @@ -40,7 +44,7 @@ const Settings: React.FC = memo(({ tray: store.get('tray'), showFileTabs: store.get('showFileTabs'), colorTheme: store.get('colorTheme'), - useMultilineForBulkTodoCreation: store.get('useMultilineForBulkTodoCreation'), + bulkTodoCreation: store.get('bulkTodoCreation'), matomo: store.get('matomo'), notificationsAllowed: store.get('notificationsAllowed'), notificationThreshold: store.get('notificationThreshold'), @@ -121,7 +125,11 @@ const Settings: React.FC = memo(({ ))} - + ); diff --git a/src/renderer/TodoDialog/AutoSuggest.tsx b/src/renderer/TodoDialog/AutoSuggest.tsx index 29c6002f..cfc32231 100644 --- a/src/renderer/TodoDialog/AutoSuggest.tsx +++ b/src/renderer/TodoDialog/AutoSuggest.tsx @@ -1,13 +1,11 @@ import React, { useEffect, useState } from 'react'; import Autosuggest from 'react-autosuggest'; -import { Box, Button, IconButton, InputAdornment, TextField } from '@mui/material'; -import OpenInFullIcon from '@mui/icons-material/OpenInFull'; -import CloseFullscreenIcon from '@mui/icons-material/CloseFullscreen'; +import { Box, Button, TextField } from '@mui/material'; import './AutoSuggest.scss'; -const { store } = window.api; +const { ipcRenderer} = window.api; -const regex = /(?<=^| )[+@][^ ]*/g; +const regex: RegExp = /(?<=^| )[+@][^ ]*/g; interface Props { setDialogOpen: (open: boolean) => void; @@ -15,7 +13,6 @@ interface Props { setTextFieldValue: (value: string) => void; attributes: Attributes | null; handleAdd: (id: number, string: string) => void; - todoObject: TodoObject | null; textFieldRef: React.RefObject; } @@ -25,22 +22,18 @@ const AutoSuggest: React.FC = ({ setTextFieldValue, attributes, handleAdd, - todoObject, textFieldRef, }) => { const [suggestions, setSuggestions] = useState([]); const [selectedSuggestionIndex, setSelectedSuggestionIndex] = useState(-1); const [prefix, setPrefix] = useState(null); const [matchPosition, setMatchPosition] = useState<{ start: number; end: number }>({ start: -1, end: -1 }); - const [multilineTextField, setMultilineTextField] = useState(store.get('multilineTextField')); - - const handleSetMultilineTextField = () => { - setMultilineTextField((prevMultilineTextField) => !prevMultilineTextField); - }; const handleSuggestionsFetchRequested = ({ value }: { value: string }) => { - - let content = value.replaceAll('\n', ' ').replaceAll(String.fromCharCode(16), ' '); + let content = + value + .replaceAll(/\n/g, ' ') + .replaceAll(String.fromCharCode(16), ' '); if(!content) return false; const cursorPosition = textFieldRef.current?.selectionStart; @@ -63,28 +56,13 @@ const AutoSuggest: React.FC = ({ } }; - const handleSuggestionSelected = ( - _event: React.SyntheticEvent, - { suggestion }: { suggestion: string } - ) => { - if(!textFieldValue) return; - const createNewValue = (string: string, a: number, b: number) => { - return `${textFieldValue.slice(0, a)}${prefix}${string} ${textFieldValue.slice( - b + 1 - )}`; - }; - const newValue = createNewValue( - suggestion, - matchPosition.start, - matchPosition.end - ); - setTextFieldValue(newValue); + const handleSuggestionSelected = (_event: React.SyntheticEvent, { suggestion }: { suggestion: string }) => { + if(!textFieldValue || !matchPosition) return; + const appendix = (textFieldValue.charAt(matchPosition.end) === '\n') ? '\n': ' '; + const updatedValue = `${textFieldValue.slice(0, matchPosition.start)}${prefix}${suggestion}${appendix}${textFieldValue.slice(matchPosition.end + 1)}`; setSuggestions([]); - }; - - const handleChange = (event: React.ChangeEvent) => { - const newValue = event.target.value; - setTextFieldValue(newValue); + setMatchPosition(null); + setTextFieldValue(updatedValue); }; const handleShouldRenderSuggestions = (reason: string) => { @@ -102,15 +80,10 @@ const AutoSuggest: React.FC = ({ return []; }; - const handleRenderSuggestion = ( - suggestion: string, - { isHighlighted }: { isHighlighted: boolean } - ) => ( + const handleRenderSuggestion = (suggestion: string, { isHighlighted }: { isHighlighted: boolean }) => ( - setSelectedSuggestionIndex(isHighlighted ? suggestions.indexOf(suggestion) : -1) - } + onClick={() => setSelectedSuggestionIndex(isHighlighted ? suggestions.indexOf(suggestion) : -1)} className={isHighlighted ? 'selected' : ''} > @@ -121,15 +94,16 @@ const AutoSuggest: React.FC = ({ setSuggestions([]); }; - const containerStyle = { - width: textFieldRef?.current?.offsetWidth || 'auto', - }; + const handleChange = (event: React.ChangeEvent) => { + try { + ipcRenderer.send('createTodoObject', event.target.value); + setTextFieldValue(event.target.value); + } catch(error) { + console.error(error); + } + }; - const handleKeyDown = ( - event: React.KeyboardEvent, - id: string, - string: string - ) => { + const handleKeyDown = (event: React.KeyboardEvent) => { if(suggestions.length > 0) { if(suggestions.length === 1 || event.key === 'Enter') { if(selectedSuggestionIndex !== -1) { @@ -142,12 +116,9 @@ const AutoSuggest: React.FC = ({ handleSuggestionsClearRequested(); } } else { - if( - (multilineTextField && (event.metaKey || event.ctrlKey) && event.key === 'Enter') || - (!multilineTextField && event.key === 'Enter') - ) { + if((event.metaKey || event.ctrlKey) && event.key === 'Enter') { event.stopPropagation(); - handleAdd(id, string); + handleAdd(); } else if(event.key === 'Escape') { event.stopPropagation(); setDialogOpen(false); @@ -162,49 +133,35 @@ const AutoSuggest: React.FC = ({ } } - const value = () => { - return multilineTextField - ? textFieldValue.replaceAll(String.fromCharCode(16), '\n') - : textFieldValue.replaceAll('\n', String.fromCharCode(16)); - }; - const inputProps: InputProps = { placeholder: `(A) text +project @context due:2020-12-12 t:2021-01-10 rec:d pm:1`, - value: value(), + value: (textFieldValue) ? textFieldValue.replaceAll(String.fromCharCode(16), '\n') : '', onChange: handleChange, inputRef: textFieldRef, - onKeyDown: (event: React.KeyboardEvent) => handleKeyDown(event, todoObject?.id, textFieldValue), + onKeyDown: (event: React.KeyboardEvent) => handleKeyDown(event, textFieldValue), }; - useEffect(() => { - store.set('multilineTextField', multilineTextField); - textFieldRef.current?.focus(); - }, [multilineTextField]); + const containerStyle = { + width: textFieldRef?.current?.offsetWidth || 'auto', + }; useEffect(() => { textFieldRef.current?.focus(); - }, [textFieldValue]); + }, []); return ( <> - multilineTextField ? ( - - ) : ( - - ) - } + renderInputComponent={(inputProps: InputProps) => ( + + )} renderSuggestionsContainer={({ containerProps, children }) => ( {children} )} suggestions={suggestions} - shouldRenderSuggestions={handleShouldRenderSuggestions} - - onSuggestionsFetchRequested={handleSuggestionsFetchRequested} onSuggestionsClearRequested={handleSuggestionsClearRequested} getSuggestionValue={(suggestion: string) => suggestion} @@ -213,11 +170,6 @@ const AutoSuggest: React.FC = ({ onSuggestionHighlighted={handleSuggestionHighlighted} inputProps={inputProps} /> - - - {multilineTextField ? : } - - ); }; diff --git a/src/renderer/TodoDialog/DatePicker.tsx b/src/renderer/TodoDialog/DatePicker.tsx deleted file mode 100644 index 9b899dba..00000000 --- a/src/renderer/TodoDialog/DatePicker.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import React from 'react'; -import { Item } from 'jstodotxt'; -import { withTranslation, WithTranslation } from 'react-i18next'; -import { i18n } from '../LanguageSelector'; -import { DatePicker, LocalizationProvider } from '@mui/x-date-pickers'; -import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; -import dayjs from 'dayjs'; -import './DatePicker.scss'; - -interface Props extends WithTranslation { - todoObject: TodoObject | null; - type: string; - setTextFieldValue: (value: string) => void; - textFieldValue: string; - t: typeof i18n.t; -} - -const { store } = window.api; - -const DatePickerComponent: React.FC = ({ - todoObject, - type, - setTextFieldValue, - textFieldValue, - t, -}) => { - const initialDate: dayjs.Dayjs | null = todoObject && todoObject[type] && !!todoObject[type] && dayjs(todoObject[type]).isValid() ? dayjs(todoObject[type]) : null; - - const handleChange = (updatedDate: dayjs.Dayjs | null) => { - if(!updatedDate || !dayjs(updatedDate).isValid()) return; - - const formattedDate = dayjs(updatedDate).format('YYYY-MM-DD'); - - const content = textFieldValue.replaceAll(/\n/g, ` ${String.fromCharCode(16)}`); - - const updatedTextFieldValue = todoObject?.dueString - ? content.replace(` ${type}:${todoObject.dueString}`, '') - : content; - - const JsTodoTxtObject = new Item(updatedTextFieldValue); - JsTodoTxtObject.setExtension(type, formattedDate); - - setTextFieldValue(JsTodoTxtObject.toString()); - }; - - const selectedLanguage = store.get('language'); - - return ( - - handleChange(updatedDate)} - /> - - ); -}; - -export default withTranslation()(DatePickerComponent); diff --git a/src/renderer/TodoDialog/DueDatePicker.tsx b/src/renderer/TodoDialog/DueDatePicker.tsx new file mode 100644 index 00000000..bedef76c --- /dev/null +++ b/src/renderer/TodoDialog/DueDatePicker.tsx @@ -0,0 +1,56 @@ +import React from 'react'; +import { Item } from 'jstodotxt'; +import { withTranslation, WithTranslation } from 'react-i18next'; +import { i18n } from '../LanguageSelector'; +import { DatePicker, LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import dayjs from 'dayjs'; +import './DatePicker.scss'; + +interface Props extends WithTranslation { + setTextFieldValue: (value: string) => void; + textFieldValue: string; + dueDate: string; + setDueDate: React.Dispatch>; + selectedLanguage: string; + t: typeof i18n.t; +} + +const DueDatePickerComponent: React.FC = ({ + setTextFieldValue, + textFieldValue, + dueDate, + setDueDate, + selectedLanguage, + t, +}) => { + + const handleChange = (date: dayjs.Dayjs | null) => { + try { + if(!date || !dayjs(date).isValid()) return; + const validDate = dayjs(date).format('YYYY-MM-DD'); + const string = textFieldValue.replaceAll(/[\x10\r\n]/g, ` ${String.fromCharCode(16)} `); + const JsTodoTxtObject = new Item(string); + JsTodoTxtObject.setExtension('due', validDate); + const updatedString = JsTodoTxtObject.toString().replaceAll(` ${String.fromCharCode(16)} `, String.fromCharCode(16)) + setTextFieldValue(updatedString); + setDueDate(validDate); + } catch(error) { + console.error(error); + } + }; + + return ( + + handleChange(date)} + /> + + ); +}; + +export default withTranslation()(DueDatePickerComponent); diff --git a/src/renderer/TodoDialog/PomodoroPicker.tsx b/src/renderer/TodoDialog/PomodoroPicker.tsx index df36fff6..873f97fb 100644 --- a/src/renderer/TodoDialog/PomodoroPicker.tsx +++ b/src/renderer/TodoDialog/PomodoroPicker.tsx @@ -1,28 +1,35 @@ -import React, { useState } from 'react'; +import React from 'react'; import { FormControl, TextField } from '@mui/material'; import { Item } from 'jstodotxt'; import { ReactComponent as TomatoIconDuo } from '../../../assets/icons/tomato-duo.svg' import './PomodoroPicker.scss'; interface Props { - todoObject: TodoObject | null; setTextFieldValue: React.Dispatch>; textFieldValue: string; + pomodoro: number; + setPomodoro: React.Dispatch>; } +const { ipcRenderer } = window.api; + const PomodoroPicker: React.FC = ({ - todoObject, setTextFieldValue, - textFieldValue + textFieldValue, + pomodoro, }) => { - const [pomodoro, setPomodoro] = useState(todoObject?.pm || 0); + const handleChange = (event: React.ChangeEvent) => { - const updatedPomodoro = event.target.value; - let string = textFieldValue.replaceAll('\n', ` ${String.fromCharCode(16)}`); - const JsTodoTxtObject = new Item(string); - JsTodoTxtObject.setExtension('pm', updatedPomodoro); - setTextFieldValue(JsTodoTxtObject.toString()); - setPomodoro(updatedPomodoro); + try { + const string = textFieldValue.replaceAll(/[\x10\r\n]/g, ` ${String.fromCharCode(16)} `); + const JsTodoTxtObject = new Item(string); + JsTodoTxtObject.setExtension('pm', event.target.value); + const updatedString = JsTodoTxtObject.toString().replaceAll(` ${String.fromCharCode(16)} `, String.fromCharCode(16)) + setTextFieldValue(updatedString); + ipcRenderer.send('createTodoObject', updatedString); + } catch(error) { + console.error(error); + } }; return ( diff --git a/src/renderer/TodoDialog/PriorityPicker.tsx b/src/renderer/TodoDialog/PriorityPicker.tsx index a334ac1a..c40086da 100644 --- a/src/renderer/TodoDialog/PriorityPicker.tsx +++ b/src/renderer/TodoDialog/PriorityPicker.tsx @@ -1,37 +1,43 @@ -import React, { useState } from 'react'; +import React from 'react'; import { FormControl, InputLabel, Select, MenuItem } from '@mui/material'; import { Item } from 'jstodotxt'; import { withTranslation, WithTranslation } from 'react-i18next'; import { i18n } from '../LanguageSelector'; import './PriorityPicker.scss'; +const { ipcRenderer } = window.api; + const alphabetArray = Array.from({ length: 26 }, (_, index) => String.fromCharCode(65 + index)); const priorities = [{ value: '-', label: '-' }, ...alphabetArray.map((letter) => ({ value: letter, label: letter }))]; interface Props extends WithTranslation { - todoObject: TodoObject | null; setTextFieldValue: React.Dispatch>; textFieldValue: string; + priority: string; t: typeof i18n.t; } const PriorityPicker: React.FC = ({ - todoObject, setTextFieldValue, textFieldValue, + priority, t, }: Props) => { - const [priority, setPriority] = useState(todoObject?.priority || '-'); - - const handleChange = (event: React.ChangeEvent<{ value: unknown }>) => { - const updatedPriority = event.target.value as string; - const JsTodoTxtObject = new Item(textFieldValue); - JsTodoTxtObject.setPriority((updatedPriority === '-') ? null : updatedPriority); - setTextFieldValue(JsTodoTxtObject.toString()); - setPriority(updatedPriority); + + const handleChange = (event: React.ChangeEvent) => { + try { + const string = textFieldValue.replaceAll(/[\x10\r\n]/g, ` ${String.fromCharCode(16)} `); + const JsTodoTxtObject = new Item(string); + JsTodoTxtObject.setPriority(event.target.value); + const updatedString = JsTodoTxtObject.toString().replaceAll(` ${String.fromCharCode(16)} `, String.fromCharCode(16)) + setTextFieldValue(updatedString); + ipcRenderer.send('createTodoObject', updatedString); + } catch(error) { + console.error(error); + } }; - + return ( {t('todoDialog.priorityPicker.label')} diff --git a/src/renderer/TodoDialog/RecurrencePicker.tsx b/src/renderer/TodoDialog/RecurrencePicker.tsx index 7f98a355..594f7a8f 100644 --- a/src/renderer/TodoDialog/RecurrencePicker.tsx +++ b/src/renderer/TodoDialog/RecurrencePicker.tsx @@ -7,42 +7,48 @@ import { withTranslation, WithTranslation } from 'react-i18next'; import { i18n } from '../LanguageSelector'; import './RecurrencePicker.scss'; +const { ipcRenderer } = window.api; + interface Props extends WithTranslation { - todoObject: TodoObject | null; - setTextFieldValue: (value: string) => void; + recurrence: string; + setTextFieldValue: React.Dispatch>; textFieldValue: string; t: typeof i18n.t; } +const getInterval = (recurrence) => { + return recurrence && recurrence.startsWith('+') ? recurrence.slice(2, 3) : recurrence ? recurrence.slice(1, 2) : null; +} + +const getAmount = (recurrence) => { + return recurrence && recurrence.startsWith('+') ? recurrence.slice(1, 2) : recurrence ? recurrence.slice(0, 1) : null; +} + +const getStrictIndicator = (recurrence) => { + return recurrence ? recurrence.startsWith('+') : false; +} + const RecurrencePicker: React.FC = ({ - todoObject, + recurrence, setTextFieldValue, textFieldValue, t }) => { const recurrenceFieldRef = useRef(null); - const [recurrence, setRecurrence] = useState(todoObject?.rec || null); - const [strictRecurrence, setStrictRecurrence] = useState(recurrence ? recurrence.startsWith('+') : false); - const [interval, setInterval] = useState( - recurrence && recurrence.startsWith('+') ? recurrence.slice(2, 3) : recurrence ? recurrence.slice(1, 2) : null - ); - const [amount, setAmount] = useState( - recurrence && recurrence.startsWith('+') ? recurrence.slice(1, 2) : recurrence ? recurrence.slice(0, 1) : null - ); - - const handleChange = (event: React.ChangeEvent | undefined, recurrence: string) => { - // TODO: solves a problem but creates another one: If a task is empty, no recurrence can be added - if(Number(recurrence) === 0 || !textFieldValue) return false; - - const JsTodoTxtObject = new Item(textFieldValue || ''); - JsTodoTxtObject.setExtension('rec', recurrence); - - setTextFieldValue(JsTodoTxtObject.toString()); - - setRecurrence(recurrence); - - if(recurrenceFieldRef.current) { - recurrenceFieldRef.current.value = recurrence; + const [strictRecurrence, setStrictRecurrence] = useState(getStrictIndicator(recurrence)); + const [interval, setInterval] = useState(getInterval(recurrence)); + const [amount, setAmount] = useState(getAmount(recurrence)); + + const handleChange = (event: React.ChangeEvent | undefined, updatedRecurrence: string) => { + try { + const string = textFieldValue.replaceAll(/[\x10\r\n]/g, ` ${String.fromCharCode(16)} `); + const JsTodoTxtObject = new Item(string); + JsTodoTxtObject.setExtension('rec', updatedRecurrence); + const updatedString = JsTodoTxtObject.toString().replaceAll(` ${String.fromCharCode(16)} `, String.fromCharCode(16)) + setTextFieldValue(updatedString); + ipcRenderer.send('createTodoObject', updatedString); + } catch(error) { + console.error(error); } }; @@ -68,6 +74,12 @@ const RecurrencePicker: React.FC = ({ } }, [interval, amount, strictRecurrence]); + useEffect(() => { + setStrictRecurrence(getStrictIndicator(recurrence)); + setInterval(getInterval(recurrence)); + setAmount(getAmount(recurrence)); + }, [recurrence]); + useEffect(() => { const handleEnterKeyPress = (event: KeyboardEvent) => { if(event.key === 'Enter') { @@ -97,7 +109,7 @@ const RecurrencePicker: React.FC = ({ label={t('todoDialog.recurrencePicker.label')} className="recurrencePicker" onChange={handleChange} - defaultValue={recurrence || '-'} + value={recurrence || '-'} inputRef={recurrenceFieldRef} InputLabelProps={{ shrink: true, diff --git a/src/renderer/TodoDialog/ThresholdDatePicker.tsx b/src/renderer/TodoDialog/ThresholdDatePicker.tsx new file mode 100644 index 00000000..c1523d87 --- /dev/null +++ b/src/renderer/TodoDialog/ThresholdDatePicker.tsx @@ -0,0 +1,56 @@ +import React from 'react'; +import { Item } from 'jstodotxt'; +import { withTranslation, WithTranslation } from 'react-i18next'; +import { i18n } from '../LanguageSelector'; +import { DatePicker, LocalizationProvider } from '@mui/x-date-pickers'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import dayjs from 'dayjs'; +import './DatePicker.scss'; + +interface Props extends WithTranslation { + setTextFieldValue: (value: string) => void; + textFieldValue: string; + thresholdDate: string; + setThresholdDate: React.Dispatch>; + selectedLanguage: string; + t: typeof i18n.t; +} + +const ThresholdDatePickerComponent: React.FC = ({ + setTextFieldValue, + textFieldValue, + thresholdDate, + setThresholdDate, + selectedLanguage, + t, +}) => { + + const handleChange = (date: dayjs.Dayjs | null) => { + try { + if(!date || !dayjs(date).isValid()) return; + const validDate = dayjs(date).format('YYYY-MM-DD'); + const string = textFieldValue.replaceAll(/[\x10\r\n]/g, ` ${String.fromCharCode(16)} `); + const JsTodoTxtObject = new Item(string); + JsTodoTxtObject.setExtension('t', validDate); + const updatedString = JsTodoTxtObject.toString().replaceAll(` ${String.fromCharCode(16)} `, String.fromCharCode(16)) + setTextFieldValue(updatedString); + setThresholdDate(validDate); + } catch(error) { + console.error(error); + } + }; + + return ( + + handleChange(date)} + /> + + ); +}; + +export default withTranslation()(ThresholdDatePickerComponent); diff --git a/src/renderer/TodoDialog/TodoDialog.scss b/src/renderer/TodoDialog/TodoDialog.scss index 7d4573c0..02b0730b 100644 --- a/src/renderer/TodoDialog/TodoDialog.scss +++ b/src/renderer/TodoDialog/TodoDialog.scss @@ -11,42 +11,15 @@ flex-wrap: wrap; .input { width: 100%; - input, textarea { - font-size: 1.25em; - padding-right: 3em; - } textarea { - min-height: 3.5em; + font-size: 1.25em; + width: 100%; } } - // input.input { - // width: 100%; - // font-size: 1.25em; - // } - // textarea.input { - // width: 100%; - // height: auto; - // min-height: 3em; - // font-family: 'FreeSans'; - // background: $lighter-grey; - // border: none; - // border-radius: $radius; - // outline: none; - // padding: 0.85em; - // } .react-autosuggest__container { width: 100%; flex-grow: 1; } - .resize { - position: absolute; - right: 2.5em; - top: 3.2em; - svg { - font-size: 1.75em; - color: #1976d2; - } - } } } diff --git a/src/renderer/TodoDialog/TodoDialog.tsx b/src/renderer/TodoDialog/TodoDialog.tsx index 3465c05c..95d32d72 100644 --- a/src/renderer/TodoDialog/TodoDialog.tsx +++ b/src/renderer/TodoDialog/TodoDialog.tsx @@ -1,13 +1,15 @@ -import React, { useRef, memo } from 'react'; +import React, { useRef, useState, useEffect, memo } from 'react'; import { Button, Dialog, DialogContent, DialogActions } from '@mui/material'; import AutoSuggest from './AutoSuggest'; import PriorityPicker from './PriorityPicker'; -import DatePicker from './DatePicker'; +import DueDatePicker from './DueDatePicker'; +import ThresholdDatePicker from './ThresholdDatePicker'; import PomodoroPicker from './PomodoroPicker'; import RecurrencePicker from './RecurrencePicker'; import { withTranslation, WithTranslation } from 'react-i18next'; -import './TodoDialog.scss'; +import dayjs from 'dayjs'; import { i18n } from '../LanguageSelector'; +import './TodoDialog.scss'; const { ipcRenderer, store } = window.api; @@ -15,12 +17,16 @@ interface Props extends WithTranslation { dialogOpen: boolean; setDialogOpen: React.Dispatch>; todoObject: TodoObject; + setTodoObject: React.Dispatch>; attributes: Attributes | null; + attributeFields: TodoObject; + setAttributeFields: React.Dispatch>; setSnackBarSeverity: React.Dispatch>; setSnackBarContent: React.Dispatch>; shouldUseDarkColors: boolean; textFieldValue: string, setTextFieldValue: React.Dispatch>, + selectedLanguage: React.Dispatch>, t: typeof i18n.t; } @@ -28,24 +34,33 @@ const TodoDialog: React.FC = memo(({ dialogOpen, setDialogOpen, todoObject, + setTodoObject, attributes, + attributeFields, + setAttributeFields, setSnackBarSeverity, setSnackBarContent, shouldUseDarkColors, textFieldValue, setTextFieldValue, + selectedLanguage, t }) => { - - const useMultilineForBulkTodoCreation = store.get('useMultilineForBulkTodoCreation'); - const multilineTextField = store.get('multilineTextField'); + const bulkTodoCreation = store.get('bulkTodoCreation'); const textFieldRef = useRef(null); const numRowsWithContent = textFieldValue?.split('\n').filter(line => line.trim() !== '').length; + const [priority, setPriority] = useState('-'); + const [dueDate, setDueDate] = useState(null); + const [thresholdDate, setThresholdDate] = useState(null); + const [recurrence, setRecurrence] = useState(null); + const [pomodoro, setPomodoro] = useState(0); - const handleAdd = (id: number, string: string) => { + const handleAdd = () => { try { - if(string) { - ipcRenderer.send('writeTodoToFile', id, string); + if(textFieldValue) { + const index = (todoObject) ? todoObject.id : -1; + const string = textFieldValue.replaceAll(/\n/g, String.fromCharCode(16)); + ipcRenderer.send('writeTodoToFile', index, string); } else { setSnackBarSeverity('info'); setSnackBarContent(t('todoDialog.snackbar.emptyInput')); @@ -55,6 +70,32 @@ const TodoDialog: React.FC = memo(({ } }; + const handleClose = () => { + setTodoObject(null); + setAttributeFields(null); + setDialogOpen(false); + }; + + useEffect(() => { + setTextFieldValue(todoObject?.string); + setAttributeFields(todoObject); + }, [todoObject]); + + useEffect(() => { + setPriority(attributeFields?.priority || '-'); + setDueDate(attributeFields?.due || null); + setThresholdDate(attributeFields?.t || null); + setRecurrence(attributeFields?.rec || null); + setPomodoro(attributeFields?.pm || 0); + }, [attributeFields]); + + useEffect(() => { + if(!dialogOpen) { + setTodoObject(null); + setAttributeFields(null); + } + }, [dialogOpen]); + return ( = memo(({ handleAdd={handleAdd} todoObject={todoObject} textFieldRef={textFieldRef} + /> - - - {} + recurrence={recurrence} + /> - - + diff --git a/tsconfig.json b/tsconfig.json index 232b51a2..1f228598 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -13,7 +13,7 @@ "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "allowJs": true, - "outDir": ".erb/dll" + "outDir": ".erb/dll", }, "include": ["src"], "exclude": ["test", "release/build", "release/app/dist", ".erb/dll"] diff --git a/yarn.lock b/yarn.lock index d9606a95..567f942c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7,7 +7,7 @@ resolved "https://registry.yarnpkg.com/7zip-bin/-/7zip-bin-5.2.0.tgz#7a03314684dd6572b7dfa89e68ce31d60286854d" integrity sha512-ukTPVhqG4jNzMro2qA9HSCSSVJN3aN7tlb+hfqYCt3ER0yWroeA2VR38MNrOHLQ/cVj+DaIMad0kFCtWWowh/A== -"@adobe/css-tools@^4.0.1": +"@adobe/css-tools@^4.3.1": version "4.3.2" resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.3.2.tgz#a6abc715fb6884851fca9dad37fc34739a04fd11" integrity sha512-DA5a1C0gD/pLOvhv33YMrbf2FK3oUzwNl9oOJqE4XVjuEtt6XIakRcsd7eLiOSPkp1kTRQGICTA8cKra/vFbjw== @@ -1105,13 +1105,14 @@ fs-extra "^9.0.1" promise-retry "^2.0.1" -"@electron/notarize@^1.2.3": - version "1.2.4" - resolved "https://registry.yarnpkg.com/@electron/notarize/-/notarize-1.2.4.tgz#a7d38773f4cad40df111a5edc64037e5d768ea1e" - integrity sha512-W5GQhJEosFNafewnS28d3bpQ37/s91CDWqxVchHfmv2dQSTWpOzNlUVQwYzC1ay5bChRV/A9BTL68yj0Pa+TSg== +"@electron/notarize@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@electron/notarize/-/notarize-2.2.0.tgz#40455f9d8ca8098a74567aa4613b709089d82657" + integrity sha512-Sf7RG47rafeGuUm+kLEbTXMN8XZeYXN70dMBstrcgiykxCq3SLl1uqxFWndxSI1LfMqv4Eq9PTDHLPwiya31Kg== dependencies: debug "^4.1.1" fs-extra "^9.0.1" + promise-retry "^2.0.1" "@electron/osx-sign@1.0.5": version "1.0.5" @@ -1594,78 +1595,78 @@ lodash "^4.17.15" tmp-promise "^3.0.2" -"@mui/base@5.0.0-beta.27", "@mui/base@^5.0.0-beta.22": - version "5.0.0-beta.27" - resolved "https://registry.yarnpkg.com/@mui/base/-/base-5.0.0-beta.27.tgz#21a9c7d954a5f88f6706dfee630154c651ee73af" - integrity sha512-duL37qxihT1N0pW/gyXVezP7SttLkF+cLAs/y6g6ubEFmVadjbnZ45SeF12/vAiKzqwf5M0uFH1cczIPXFZygA== +"@mui/base@5.0.0-beta.28", "@mui/base@^5.0.0-beta.22": + version "5.0.0-beta.28" + resolved "https://registry.yarnpkg.com/@mui/base/-/base-5.0.0-beta.28.tgz#f072e55c0530f456ee5cb5cde2af788fdda3bf05" + integrity sha512-KIoSc5sUFceeCaZTq5MQBapFzhHqMo4kj+4azWaCAjorduhcRQtN+BCgVHmo+gvEjix74bUfxwTqGifnu2fNTg== dependencies: "@babel/runtime" "^7.23.5" "@floating-ui/react-dom" "^2.0.4" "@mui/types" "^7.2.11" - "@mui/utils" "^5.15.0" + "@mui/utils" "^5.15.1" "@popperjs/core" "^2.11.8" clsx "^2.0.0" prop-types "^15.8.1" -"@mui/core-downloads-tracker@^5.15.0": - version "5.15.0" - resolved "https://registry.yarnpkg.com/@mui/core-downloads-tracker/-/core-downloads-tracker-5.15.0.tgz#6b45d5bff38f305402d24d3bf86075b56c578909" - integrity sha512-NpGtlHwuyLfJtdrlERXb8qRqd279O0VnuGaZAor1ehdNhUJOD1bSxHDeXKZkbqNpvi50hasFj7lsbTpluworTQ== +"@mui/core-downloads-tracker@^5.15.1": + version "5.15.1" + resolved "https://registry.yarnpkg.com/@mui/core-downloads-tracker/-/core-downloads-tracker-5.15.1.tgz#8aad47e2b198640244f05f6486a927ce362e814e" + integrity sha512-y/nUEsWHyBzaKYp9zLtqJKrLod/zMNEWpMj488FuQY9QTmqBiyUhI2uh7PVaLqLewXRtdmG6JV0b6T5exyuYRw== "@mui/icons-material@^5.14.9": - version "5.15.0" - resolved "https://registry.yarnpkg.com/@mui/icons-material/-/icons-material-5.15.0.tgz#fdc93611ca77ce3b79128be02fb6c1ae79b972b8" - integrity sha512-zHY6fOkaK7VfhWeyxO8MjO3IAjEYpYMXuqUhX7TkUZJ9+TSH/9dn4ClG4K2j6hdgBU5Yrq2Z/89Bo6BHHp7AdQ== + version "5.15.1" + resolved "https://registry.yarnpkg.com/@mui/icons-material/-/icons-material-5.15.1.tgz#38f51a88d224a107e753313b4d9815247caa5398" + integrity sha512-VPJdBSyap6uOxCb5BLbWbkvd6aeJCp1pQZm8DcZBITCH0NOSv8Mz9c8Zvo8xr4Od7+xyWHUAgvRSL4047pL2WQ== dependencies: "@babel/runtime" "^7.23.5" "@mui/material@^5.0.0", "@mui/material@^5.14.0": - version "5.15.0" - resolved "https://registry.yarnpkg.com/@mui/material/-/material-5.15.0.tgz#f801cf56d505cc52dca225438360ab9c62057285" - integrity sha512-60CDI/hQNwJv9a3vEZtFG7zz0USdQhVwpBd3fZqrzhuXSdiMdYMaZcCXeX/KMuNq0ZxQEAZd74Pv+gOb408QVA== + version "5.15.1" + resolved "https://registry.yarnpkg.com/@mui/material/-/material-5.15.1.tgz#5fc15c6eb9efe4b62b0c30b13bf5fa042bda71a1" + integrity sha512-WA5DVyvacxDakVyAhNqu/rRT28ppuuUFFw1bLpmRzrCJ4uw/zLTATcd4WB3YbB+7MdZNEGG/SJNWTDLEIyn3xQ== dependencies: "@babel/runtime" "^7.23.5" - "@mui/base" "5.0.0-beta.27" - "@mui/core-downloads-tracker" "^5.15.0" - "@mui/system" "^5.15.0" + "@mui/base" "5.0.0-beta.28" + "@mui/core-downloads-tracker" "^5.15.1" + "@mui/system" "^5.15.1" "@mui/types" "^7.2.11" - "@mui/utils" "^5.15.0" - "@types/react-transition-group" "^4.4.9" + "@mui/utils" "^5.15.1" + "@types/react-transition-group" "^4.4.10" clsx "^2.0.0" csstype "^3.1.2" prop-types "^15.8.1" react-is "^18.2.0" react-transition-group "^4.4.5" -"@mui/private-theming@^5.15.0": - version "5.15.0" - resolved "https://registry.yarnpkg.com/@mui/private-theming/-/private-theming-5.15.0.tgz#96de66ce097ba417e1b6b769cd67cbf516bd8876" - integrity sha512-7WxtIhXxNek0JjtsYy+ut2LtFSLpsUW5JSDehQO+jF7itJ8ehy7Bd9bSt2yIllbwGjCFowLfYpPk2Ykgvqm1tA== +"@mui/private-theming@^5.15.1": + version "5.15.1" + resolved "https://registry.yarnpkg.com/@mui/private-theming/-/private-theming-5.15.1.tgz#58fd8da48295e105067fa7361734ee0b166d9cca" + integrity sha512-wTbzuy5KjSvCPE9UVJktWHJ0b/tD5biavY9wvF+OpYDLPpdXK52vc1hTDxSbdkHIFMkJExzrwO9GvpVAHZBnFQ== dependencies: "@babel/runtime" "^7.23.5" - "@mui/utils" "^5.15.0" + "@mui/utils" "^5.15.1" prop-types "^15.8.1" -"@mui/styled-engine@^5.15.0": - version "5.15.0" - resolved "https://registry.yarnpkg.com/@mui/styled-engine/-/styled-engine-5.15.0.tgz#44e068dbb855699053b9e6e4e6d3ed5efe98b7d9" - integrity sha512-6NysIsHkuUS2lF+Lzv1jiK3UjBJk854/vKVcJQVGKlPiqNEVZJNlwaSpsaU5xYXxWEZYfbVFSAomLOS/LV/ovQ== +"@mui/styled-engine@^5.15.1": + version "5.15.1" + resolved "https://registry.yarnpkg.com/@mui/styled-engine/-/styled-engine-5.15.1.tgz#00f179e51afe252022bf356f72354968f9c5bf25" + integrity sha512-7WDZTJLqGexWDjqE9oAgjU8ak6hEtUw2yQU7SIYID5kLVO2Nj/Wi/KicbLsXnTsJNvSqePIlUIWTBSXwWJCPZw== dependencies: "@babel/runtime" "^7.23.5" "@emotion/cache" "^11.11.0" csstype "^3.1.2" prop-types "^15.8.1" -"@mui/system@^5.14.15", "@mui/system@^5.15.0": - version "5.15.0" - resolved "https://registry.yarnpkg.com/@mui/system/-/system-5.15.0.tgz#d4f6fd65ad8e404d4d7c7b56d755d2a63b0edddb" - integrity sha512-8TPjfTlYBNB7/zBJRL4QOD9kImwdZObbiYNh0+hxvhXr2koezGx8USwPXj8y/JynbzGCkIybkUztCdWlMZe6OQ== +"@mui/system@^5.14.15", "@mui/system@^5.15.1": + version "5.15.1" + resolved "https://registry.yarnpkg.com/@mui/system/-/system-5.15.1.tgz#e2a79b5e188ca89a3e58aa4d27e3484edf9e24b0" + integrity sha512-LAnP0ls69rqW9eBgI29phIx/lppv+WDGI7b3EJN7VZIqw0RezA0GD7NRpV12BgEYJABEii6z5Q9B5tg7dsX0Iw== dependencies: "@babel/runtime" "^7.23.5" - "@mui/private-theming" "^5.15.0" - "@mui/styled-engine" "^5.15.0" + "@mui/private-theming" "^5.15.1" + "@mui/styled-engine" "^5.15.1" "@mui/types" "^7.2.11" - "@mui/utils" "^5.15.0" + "@mui/utils" "^5.15.1" clsx "^2.0.0" csstype "^3.1.2" prop-types "^15.8.1" @@ -1675,10 +1676,10 @@ resolved "https://registry.yarnpkg.com/@mui/types/-/types-7.2.11.tgz#36b99a88f8010dc716128e568dc05681a69dc7ae" integrity sha512-KWe/QTEsFFlFSH+qRYf3zoFEj3z67s+qAuSnMMg+gFwbxG7P96Hm6g300inQL1Wy///gSRb8juX7Wafvp93m3w== -"@mui/utils@^5.14.16", "@mui/utils@^5.15.0": - version "5.15.0" - resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-5.15.0.tgz#87b4db92dd2ddf3e2676377427f50662124013b4" - integrity sha512-XSmTKStpKYamewxyJ256+srwEnsT3/6eNo6G7+WC1tj2Iq9GfUJ/6yUoB7YXjOD2jTZ3XobToZm4pVz1LBt6GA== +"@mui/utils@^5.14.16", "@mui/utils@^5.15.1": + version "5.15.1" + resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-5.15.1.tgz#71d69dc8c0f13a1fd6aca20b53ec496636e6b854" + integrity sha512-V1/d0E3Bju5YdB59HJf2G0tnHrFEvWLN+f8hAXp9+JSNy/LC2zKyqUfPPahflR6qsI681P8G9r4mEZte/SrrYA== dependencies: "@babel/runtime" "^7.23.5" "@types/prop-types" "^15.7.11" @@ -1686,9 +1687,9 @@ react-is "^18.2.0" "@mui/x-date-pickers@^6.10.0": - version "6.18.5" - resolved "https://registry.yarnpkg.com/@mui/x-date-pickers/-/x-date-pickers-6.18.5.tgz#a2a70ce2926f0acb8ee414b546ba1f7daf399c21" - integrity sha512-3jImYIWP2Xgi608yzm/Sz1v0MTjQQYdZSQOEIi3dWBfSAU9B06KXDpqlXfRSpTV+rtsnfYIIyiWlz6Ltk7sUWw== + version "6.18.6" + resolved "https://registry.yarnpkg.com/@mui/x-date-pickers/-/x-date-pickers-6.18.6.tgz#416e0b83dd2774547e3c864c89bedf2f4ca3e05a" + integrity sha512-pqOrGPUDVY/1xXrM1hofqwgquno/SB9aG9CVS1m2Rs8hKF1VWRC+jYlEa1Qk08xKmvkia5g7NsdV/BBb+tHUZw== dependencies: "@babel/runtime" "^7.23.2" "@mui/base" "^5.0.0-beta.22" @@ -1734,7 +1735,7 @@ schema-utils "^3.0.0" source-map "^0.7.3" -"@polka/url@^1.0.0-next.20": +"@polka/url@^1.0.0-next.24": version "1.0.0-next.24" resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.24.tgz#58601079e11784d20f82d0585865bb42305c4df3" integrity sha512-2LuNTFBIO0m7kKIQvvPHN6UE63VjpmL9rnEEaOOaiSPbZK+zUOYIzBAWcED+3XYzhYsd/0mD57VdxAEqqV52CQ== @@ -1906,14 +1907,13 @@ lz-string "^1.5.0" pretty-format "^27.0.2" -"@testing-library/jest-dom@^5.16.5": - version "5.17.0" - resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.17.0.tgz#5e97c8f9a15ccf4656da00fecab505728de81e0c" - integrity sha512-ynmNeT7asXyH3aSVv4vvX4Rb+0qjOhdNHnO/3vuZNqPmhDpV/+rCSGwQ7bLcmU2cJ4dvoheIO85LQj0IbJHEtg== +"@testing-library/jest-dom@^6.1.5": + version "6.1.5" + resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-6.1.5.tgz#0a635d0ad4a1a880089d967299d94e9cfc81fbe1" + integrity sha512-3y04JLW+EceVPy2Em3VwNr95dOKqA8DhR0RJHhHKDZNYXcVXnEK7WIrpj4eYU8SVt/qYZ2aRWt/WgQ+grNES8g== dependencies: - "@adobe/css-tools" "^4.0.1" + "@adobe/css-tools" "^4.3.1" "@babel/runtime" "^7.9.2" - "@types/testing-library__jest-dom" "^5.9.1" aria-query "^5.0.0" chalk "^3.0.0" css.escape "^1.5.1" @@ -1977,9 +1977,9 @@ "@types/babel__traverse" "*" "@types/babel__generator@*": - version "7.6.7" - resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.7.tgz#a7aebf15c7bc0eb9abd638bdb5c0b8700399c9d0" - integrity sha512-6Sfsq+EaaLrw4RmdFWE9Onp63TOUue71AWb4Gpa6JxzgTYtimbM086WnYTy2U67AofR++QKCo08ZP6pwx8YFHQ== + version "7.6.8" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.8.tgz#f836c61f48b1346e7d2b0d93c6dacc5b9535d3ab" + integrity sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw== dependencies: "@babel/types" "^7.0.0" @@ -2054,9 +2054,9 @@ "@types/estree" "*" "@types/eslint@*": - version "8.44.9" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.44.9.tgz#5799663009645637bd1c45b2e1a7c8f4caf89534" - integrity sha512-6yBxcvwnnYoYT1Uk2d+jvIfsuP4mb2EdIxFnrPABj5a/838qe5bGkNLFOiipX4ULQ7XVQvTxOh7jO+BTAiqsEw== + version "8.56.0" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.56.0.tgz#e28d045b8e530a33c9cbcfbf02332df0d1380a2c" + integrity sha512-FlsN0p4FhuYRjIxpbdXovvHQhtlG05O1GG/RNWvdAxTboR438IOTwmrY/vLA+Xfgg06BTkP045M3vpFwTMv1dg== dependencies: "@types/estree" "*" "@types/json-schema" "*" @@ -2149,7 +2149,7 @@ dependencies: "@types/istanbul-lib-report" "*" -"@types/jest@*", "@types/jest@^29.5.2": +"@types/jest@^29.5.2": version "29.5.11" resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.11.tgz#0c13aa0da7d0929f078ab080ae5d4ced80fa2f2c" integrity sha512-S2mHmYIVe13vrm6q4kN6fLYYAka15ALQki/vgDC3mIukEOx8WJlv0kQPM+d4w8Gp6u0uSdKND04IlTXBv0rwnQ== @@ -2205,18 +2205,13 @@ dependencies: "@types/node" "*" -"@types/node@*": - version "20.10.4" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.10.4.tgz#b246fd84d55d5b1b71bf51f964bd514409347198" - integrity sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg== +"@types/node@*", "@types/node@20.10.5": + version "20.10.5" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.10.5.tgz#47ad460b514096b7ed63a1dae26fad0914ed3ab2" + integrity sha512-nNPsNE65wjMxEKI93yOP+NPGGBJz/PoN3kZsVLee0XMiJolxSekEVD8wRwBUBqkwc7UWop0edW50yrCQW4CyRw== dependencies: undici-types "~5.26.4" -"@types/node@20.2.5": - version "20.2.5" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.2.5.tgz#26d295f3570323b2837d322180dfbf1ba156fefb" - integrity sha512-JJulVEQXmiY9Px5axXHeYGLSjhkZEnD+MDPDGbCbIAbMslkKwmygtZFy1X6s/075Yo94sf8GuSlFfPzysQrWZQ== - "@types/node@^18.11.18": version "18.19.3" resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.3.tgz#e4723c4cb385641d61b983f6fe0b716abd5f8fc0" @@ -2243,9 +2238,9 @@ integrity sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng== "@types/qs@*": - version "6.9.10" - resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.10.tgz#0af26845b5067e1c9a622658a51f60a3934d51e8" - integrity sha512-3Gnx08Ns1sEoCrWssEgTSJs/rsT2vhGP+Ja9cnnk9k4ALxinORlQneLXFeFKOTJMOeZUFD1s7w+w2AphTpvzZw== + version "6.9.11" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.11.tgz#208d8a30bc507bd82e03ada29e4732ea46a6bbda" + integrity sha512-oGk0gmhnEJK4Yyk+oI7EfXsLayXatCWPHary1MtcmbAifkobT9cM9yutG/hZKIseOU0MqbIwQ/u2nn/Gb+ltuQ== "@types/range-parser@*": version "1.2.7" @@ -2253,9 +2248,9 @@ integrity sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ== "@types/react-dom@^18.0.0", "@types/react-dom@^18.2.4": - version "18.2.17" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.17.tgz#375c55fab4ae671bd98448dcfa153268d01d6f64" - integrity sha512-rvrT/M7Df5eykWFxn6MYt5Pem/Dbyc1N8Y0S9Mrkw2WFCRiqUgw9P7ul2NpwsXCSM1DVdENzdG9J5SreqfAIWg== + version "18.2.18" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.18.tgz#16946e6cd43971256d874bc3d0a72074bb8571dd" + integrity sha512-TJxDm6OfAX2KJWJdMEVTwWke5Sc/E/RlnPGvGfS0W7+6ocy2xhDVQVh/KvC2Uf7kACs+gDytdusDSdWfWkaNzw== dependencies: "@types/react" "*" @@ -2276,7 +2271,7 @@ dependencies: "@types/react" "*" -"@types/react-transition-group@^4.4.8", "@types/react-transition-group@^4.4.9": +"@types/react-transition-group@^4.4.10", "@types/react-transition-group@^4.4.8": version "4.4.10" resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.10.tgz#6ee71127bdab1f18f11ad8fb3322c6da27c327ac" integrity sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q== @@ -2345,13 +2340,6 @@ resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== -"@types/testing-library__jest-dom@^5.9.1": - version "5.14.9" - resolved "https://registry.yarnpkg.com/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.9.tgz#0fb1e6a0278d87b6737db55af5967570b67cb466" - integrity sha512-FSYhIjFlfOpGSRyVoMBMuS3ws5ehFQODymf3vlI7U1K8c7PHwWwFY7VREfmsuzHSOnoKs/9/Y983ayOs7eRzqw== - dependencies: - "@types/jest" "*" - "@types/tough-cookie@*": version "4.0.5" resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.5.tgz#cb6e2a691b70cb177c6e3ae9c1d2e8b2ea8cd304" @@ -2397,63 +2385,63 @@ dependencies: "@types/node" "*" -"@vue/compiler-core@3.3.11": - version "3.3.11" - resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.3.11.tgz#9fa26f8c81b9b34365f94ce1ed4d0e6e6f94a2ac" - integrity sha512-h97/TGWBilnLuRaj58sxNrsUU66fwdRKLOLQ9N/5iNDfp+DZhYH9Obhe0bXxhedl8fjAgpRANpiZfbgWyruQ0w== +"@vue/compiler-core@3.3.13": + version "3.3.13" + resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.3.13.tgz#b3d5f8f84caee5de3f31d95cb568d899fd19c599" + integrity sha512-bwi9HShGu7uaZLOErZgsH2+ojsEdsjerbf2cMXPwmvcgZfVPZ2BVZzCVnwZBxTAYd6Mzbmf6izcUNDkWnBBQ6A== dependencies: "@babel/parser" "^7.23.5" - "@vue/shared" "3.3.11" + "@vue/shared" "3.3.13" estree-walker "^2.0.2" source-map-js "^1.0.2" -"@vue/compiler-dom@3.3.11": - version "3.3.11" - resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.3.11.tgz#36a76ea3a296d41bad133a6912cb0a847d969e4f" - integrity sha512-zoAiUIqSKqAJ81WhfPXYmFGwDRuO+loqLxvXmfUdR5fOitPoUiIeFI9cTTyv9MU5O1+ZZglJVTusWzy+wfk5hw== +"@vue/compiler-dom@3.3.13": + version "3.3.13" + resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.3.13.tgz#d029e222e545e7ab00be35aafd3abed167f962bf" + integrity sha512-EYRDpbLadGtNL0Gph+HoKiYqXLqZ0xSSpR5Dvnu/Ep7ggaCbjRDIus1MMxTS2Qm0koXED4xSlvTZaTnI8cYAsw== dependencies: - "@vue/compiler-core" "3.3.11" - "@vue/shared" "3.3.11" + "@vue/compiler-core" "3.3.13" + "@vue/shared" "3.3.13" "@vue/compiler-sfc@^3.3.4": - version "3.3.11" - resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.3.11.tgz#acfae240c875d067e0e2c9a4e2d910074408c73b" - integrity sha512-U4iqPlHO0KQeK1mrsxCN0vZzw43/lL8POxgpzcJweopmqtoYy9nljJzWDIQS3EfjiYhfdtdk9Gtgz7MRXnz3GA== + version "3.3.13" + resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.3.13.tgz#7b397acefd5c0c3808701d2855be88c4be60155c" + integrity sha512-DQVmHEy/EKIgggvnGRLx21hSqnr1smUS9Aq8tfxiiot8UR0/pXKHN9k78/qQ7etyQTFj5em5nruODON7dBeumw== dependencies: "@babel/parser" "^7.23.5" - "@vue/compiler-core" "3.3.11" - "@vue/compiler-dom" "3.3.11" - "@vue/compiler-ssr" "3.3.11" - "@vue/reactivity-transform" "3.3.11" - "@vue/shared" "3.3.11" + "@vue/compiler-core" "3.3.13" + "@vue/compiler-dom" "3.3.13" + "@vue/compiler-ssr" "3.3.13" + "@vue/reactivity-transform" "3.3.13" + "@vue/shared" "3.3.13" estree-walker "^2.0.2" magic-string "^0.30.5" postcss "^8.4.32" source-map-js "^1.0.2" -"@vue/compiler-ssr@3.3.11": - version "3.3.11" - resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.3.11.tgz#598942a73b64f2bd3f95908b104a7fbb55fc41a2" - integrity sha512-Zd66ZwMvndxRTgVPdo+muV4Rv9n9DwQ4SSgWWKWkPFebHQfVYRrVjeygmmDmPewsHyznCNvJ2P2d6iOOhdv8Qg== +"@vue/compiler-ssr@3.3.13": + version "3.3.13" + resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.3.13.tgz#ad8748abff8d738ac9c6a3c47be42020f0fbaa63" + integrity sha512-d/P3bCeUGmkJNS1QUZSAvoCIW4fkOKK3l2deE7zrp0ypJEy+En2AcypIkqvcFQOcw3F0zt2VfMvNsA9JmExTaw== dependencies: - "@vue/compiler-dom" "3.3.11" - "@vue/shared" "3.3.11" + "@vue/compiler-dom" "3.3.13" + "@vue/shared" "3.3.13" -"@vue/reactivity-transform@3.3.11": - version "3.3.11" - resolved "https://registry.yarnpkg.com/@vue/reactivity-transform/-/reactivity-transform-3.3.11.tgz#2bd486f4eff60c8724309925618891e722fcfadc" - integrity sha512-fPGjH0wqJo68A0wQ1k158utDq/cRyZNlFoxGwNScE28aUFOKFEnCBsvyD8jHn+0kd0UKVpuGuaZEQ6r9FJRqCg== +"@vue/reactivity-transform@3.3.13": + version "3.3.13" + resolved "https://registry.yarnpkg.com/@vue/reactivity-transform/-/reactivity-transform-3.3.13.tgz#dc8e9be961865dc666e367e1aaaea0716afa5c90" + integrity sha512-oWnydGH0bBauhXvh5KXUy61xr9gKaMbtsMHk40IK9M4gMuKPJ342tKFarY0eQ6jef8906m35q37wwA8DMZOm5Q== dependencies: "@babel/parser" "^7.23.5" - "@vue/compiler-core" "3.3.11" - "@vue/shared" "3.3.11" + "@vue/compiler-core" "3.3.13" + "@vue/shared" "3.3.13" estree-walker "^2.0.2" magic-string "^0.30.5" -"@vue/shared@3.3.11": - version "3.3.11" - resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.3.11.tgz#f6a038e15237edefcc90dbfe7edb806dd355c7bd" - integrity sha512-u2G8ZQ9IhMWTMXaWqZycnK4UthG1fA238CD+DP4Dm4WJi5hdUKKLg0RMRaRpDPNMdkTwIDkp7WtD0Rd9BH9fLw== +"@vue/shared@3.3.13": + version "3.3.13" + resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.3.13.tgz#4cb73cda958d77ffd389c8640cf7d93a10ac676f" + integrity sha512-/zYUwiHD8j7gKx2argXEMCUXVST6q/21DFU0sTfNX0URJroCe3b1UF6vLJ3lQDfLNIiiRl2ONp7Nh5UVWS6QnA== "@webassemblyjs/ast@1.11.6", "@webassemblyjs/ast@^1.11.5": version "1.11.6" @@ -3299,9 +3287,9 @@ caniuse-api@^3.0.0: lodash.uniq "^4.5.0" caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001565: - version "1.0.30001570" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001570.tgz#b4e5c1fa786f733ab78fc70f592df6b3f23244ca" - integrity sha512-+3e0ASu4sw1SWaoCtvPeyXp+5PsjigkSt8OXZbF9StH5pQWbxEjLAZE3n8Aup5udop1uRiKA7a4utUk/uoSpUw== + version "1.0.30001571" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001571.tgz#4182e93d696ff42930f4af7eba515ddeb57917ac" + integrity sha512-tYq/6MoXhdezDLFZuCO/TKboTzuQ/xR5cFdgXPfDtM7/kchBO3b4VWghE/OAi/DV7tTdhmLjZiZBZi1fA/GheQ== chalk@^2.4.2: version "2.4.2" @@ -4366,14 +4354,14 @@ electron-store@^8.1.0: type-fest "^2.17.0" electron-to-chromium@^1.4.601: - version "1.4.612" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.612.tgz#350c6fd4201d677307519b931949fa64dae6a5cc" - integrity sha512-dM8BMtXtlH237ecSMnYdYuCkib2QHq0kpWfUnavjdYsyr/6OsAwg5ZGUfnQ9KD1Ga4QgB2sqXlB2NT8zy2GnVg== + version "1.4.616" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.616.tgz#4bddbc2c76e1e9dbf449ecd5da3d8119826ea4fb" + integrity sha512-1n7zWYh8eS0L9Uy+GskE0lkBUNK83cXTVJI0pU3mGprFsbfSdAc15VTFbo+A+Bq4pwstmL30AVcEU3Fo463lNg== electron@^27.1.3: - version "27.1.3" - resolved "https://registry.yarnpkg.com/electron/-/electron-27.1.3.tgz#3fd6decda95c1dd0a7e51a9ac77ee0ba37b7c5c6" - integrity sha512-7eD8VMhhlL5J531OOawn00eMthUkX1e3qN5Nqd7eMK8bg5HxQBrn8bdPlvUEnCano9KhrVwaDnGeuzWoDOGpjQ== + version "27.2.0" + resolved "https://registry.yarnpkg.com/electron/-/electron-27.2.0.tgz#d5bdc006768a6de87dcd077f617d6085a1c69641" + integrity sha512-no/iMICVLI/5G0IqgKFbB89HDN88DWwKeRO+dPfJPkpJISdEX8Cx/sMEOFuuRa4VNInNe5CKCqRWExK5z3AdcQ== dependencies: "@electron/get" "^2.0.0" "@types/node" "^18.11.18" @@ -5212,9 +5200,9 @@ html-parse-stringify@^3.0.1: void-elements "3.1.0" html-webpack-plugin@^5.5.1: - version "5.5.4" - resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-5.5.4.tgz#517a48e6f046ff1ae1a172c983cd993eb79d2f6a" - integrity sha512-3wNSaVVxdxcu0jd4FpQFoICdqgxs4zIQQvj+2yQKFfBOnLETQ6X5CDWdeasuGlSsooFlMkEioWDTqBv1wvw5Iw== + version "5.6.0" + resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-5.6.0.tgz#50a8fa6709245608cb00e811eacecb8e0d7b7ea0" + integrity sha512-iwaY4wzbe48AfKLZ/Cc8k0L+FKG6oSNRaZ8x5A/T/IVDGyXcbHncM9TdDa93wn0FsSm82FhTKW7f3vS61thXAw== dependencies: "@types/html-minifier-terser" "^6.0.0" html-minifier-terser "^6.0.2" @@ -5326,9 +5314,9 @@ humanize-ms@^1.2.1: ms "^2.0.0" i18next@^23.5.1: - version "23.7.10" - resolved "https://registry.yarnpkg.com/i18next/-/i18next-23.7.10.tgz#390436e91b5bea03a9133f072367284132518e33" - integrity sha512-PRFP5uJz7swMKDW+ErbKb/YRawGQdS3J1iaO/d4Mhh7oBnCUqNF04FwVxJAvCLHKNoAOBSwD8wFe8aVNCFPmfA== + version "23.7.11" + resolved "https://registry.yarnpkg.com/i18next/-/i18next-23.7.11.tgz#ee4dfa58f9b27807ebf57d7c33a6c4a0bb4bf7c8" + integrity sha512-A/vOkw8vY99YHU9A1Td3I1dcTiYaPnwBWzrpVzfXUXSYgogK3cmBcmop/0cnXPc6QpUWIyqaugKNxRUEZVk9Nw== dependencies: "@babel/runtime" "^7.23.2" @@ -6775,10 +6763,10 @@ mkdirp@^1.0.3, mkdirp@^1.0.4: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== -mrmime@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-1.0.1.tgz#5f90c825fad4bdd41dc914eff5d1a8cfdaf24f27" - integrity sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw== +mrmime@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-2.0.0.tgz#151082a6e06e59a9a39b46b3e14d5cfe92b3abb4" + integrity sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw== ms@2.0.0: version "2.0.0" @@ -7376,9 +7364,9 @@ postcss-modules-local-by-default@^4.0.3: postcss-value-parser "^4.1.0" postcss-modules-scope@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz#9ef3151456d3bbfa120ca44898dfca6f2fa01f06" - integrity sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg== + version "3.1.0" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.1.0.tgz#fbfddfda93a31f310f1d152c2bb4d3f3c5592ee0" + integrity sha512-SaIbK8XW+MZbd0xHPf7kdfA/3eOt7vxJ72IRecn3EzuZVLr1r0orzf0MX/pN8m+NMDoo6X/SQd8oeKqGZd8PXg== dependencies: postcss-selector-parser "^6.0.4" @@ -7511,16 +7499,11 @@ postcss@^8.4.21, postcss@^8.4.24, postcss@^8.4.32: picocolors "^1.0.0" source-map-js "^1.0.2" -prettier@*: +prettier@*, prettier@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.1.1.tgz#6ba9f23165d690b6cbdaa88cb0807278f7019848" integrity sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw== -prettier@^2.8.8: - version "2.8.8" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" - integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== - pretty-error@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-4.0.0.tgz#90a703f46dd7234adb46d0f84823e9d1cb8f10d6" @@ -7858,9 +7841,9 @@ regenerate@^1.4.2: integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== regenerator-runtime@^0.14.0: - version "0.14.0" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz#5e19d68eb12d486f797e15a3c6a918f7cec5eb45" - integrity sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA== + version "0.14.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" + integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== regenerator-transform@^0.15.2: version "0.15.2" @@ -8316,12 +8299,12 @@ simple-update-notifier@2.0.0: semver "^7.5.3" sirv@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/sirv/-/sirv-2.0.3.tgz#ca5868b87205a74bef62a469ed0296abceccd446" - integrity sha512-O9jm9BsID1P+0HOi81VpXPoDxYP374pkOLzACAoyUQ/3OUVndNpsz6wMnY2z+yOxzbllCKZrM+9QrWsv4THnyA== + version "2.0.4" + resolved "https://registry.yarnpkg.com/sirv/-/sirv-2.0.4.tgz#5dd9a725c578e34e449f332703eb2a74e46a29b0" + integrity sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ== dependencies: - "@polka/url" "^1.0.0-next.20" - mrmime "^1.0.0" + "@polka/url" "^1.0.0-next.24" + mrmime "^2.0.0" totalist "^3.0.0" sisteransi@^1.0.5: