1
0
mirror of https://github.com/laurent22/joplin.git synced 2026-02-01 07:49:31 +02:00

Compare commits

..

7 Commits

Author SHA1 Message Date
Laurent Cozic
8411e1270e fix 2021-08-22 11:25:51 +01:00
Laurent Cozic
e9d4a777fd refactor 2021-08-22 11:23:07 +01:00
Laurent Cozic
85984f1f39 comment 2021-08-21 18:17:17 +01:00
Laurent Cozic
3c0524c6e9 update 2021-08-21 17:50:40 +01:00
Laurent Cozic
769d47a768 flags 2021-08-21 16:59:50 +01:00
Laurent Cozic
87fe0e4dcf update 2021-08-21 15:14:54 +01:00
Laurent Cozic
2513e0aaab update 2021-08-21 15:06:41 +01:00
308 changed files with 3689 additions and 6203 deletions

View File

@@ -64,7 +64,6 @@ packages/tools/PortableAppsLauncher
packages/fork-*
plugin_types/
readme/
**/commands/index.ts
# AUTO-GENERATED - EXCLUDED TYPESCRIPT BUILD
packages/app-cli/app/LinkSelector.d.ts
@@ -85,6 +84,9 @@ packages/app-cli/tests/HtmlToMd.js.map
packages/app-cli/tests/MdToHtml.d.ts
packages/app-cli/tests/MdToHtml.js
packages/app-cli/tests/MdToHtml.js.map
packages/app-cli/tests/MdToMd.d.ts
packages/app-cli/tests/MdToMd.js
packages/app-cli/tests/MdToMd.js.map
packages/app-cli/tests/services/keychain/KeychainService.d.ts
packages/app-cli/tests/services/keychain/KeychainService.js
packages/app-cli/tests/services/keychain/KeychainService.js.map
@@ -118,12 +120,6 @@ packages/app-desktop/InteropServiceHelper.js.map
packages/app-desktop/app.d.ts
packages/app-desktop/app.js
packages/app-desktop/app.js.map
packages/app-desktop/app.reducer.d.ts
packages/app-desktop/app.reducer.js
packages/app-desktop/app.reducer.js.map
packages/app-desktop/app.reducer.test.d.ts
packages/app-desktop/app.reducer.test.js
packages/app-desktop/app.reducer.test.js.map
packages/app-desktop/bridge.d.ts
packages/app-desktop/bridge.js
packages/app-desktop/bridge.js.map
@@ -142,9 +138,6 @@ packages/app-desktop/commands/exportNotes.js.map
packages/app-desktop/commands/focusElement.d.ts
packages/app-desktop/commands/focusElement.js
packages/app-desktop/commands/focusElement.js.map
packages/app-desktop/commands/index.d.ts
packages/app-desktop/commands/index.js
packages/app-desktop/commands/index.js.map
packages/app-desktop/commands/openProfileDirectory.d.ts
packages/app-desktop/commands/openProfileDirectory.js
packages/app-desktop/commands/openProfileDirectory.js.map
@@ -250,9 +243,6 @@ packages/app-desktop/gui/MainScreen/commands/gotoAnything.js.map
packages/app-desktop/gui/MainScreen/commands/hideModalMessage.d.ts
packages/app-desktop/gui/MainScreen/commands/hideModalMessage.js
packages/app-desktop/gui/MainScreen/commands/hideModalMessage.js.map
packages/app-desktop/gui/MainScreen/commands/index.d.ts
packages/app-desktop/gui/MainScreen/commands/index.js
packages/app-desktop/gui/MainScreen/commands/index.js.map
packages/app-desktop/gui/MainScreen/commands/moveToFolder.d.ts
packages/app-desktop/gui/MainScreen/commands/moveToFolder.js
packages/app-desktop/gui/MainScreen/commands/moveToFolder.js.map
@@ -409,24 +399,21 @@ packages/app-desktop/gui/NoteEditor/NoteEditor.js.map
packages/app-desktop/gui/NoteEditor/NoteTitle/NoteTitleBar.d.ts
packages/app-desktop/gui/NoteEditor/NoteTitle/NoteTitleBar.js
packages/app-desktop/gui/NoteEditor/NoteTitle/NoteTitleBar.js.map
packages/app-desktop/gui/NoteEditor/commands/editorCommandDeclarations.d.ts
packages/app-desktop/gui/NoteEditor/commands/editorCommandDeclarations.js
packages/app-desktop/gui/NoteEditor/commands/editorCommandDeclarations.js.map
packages/app-desktop/gui/NoteEditor/commands/focusElementNoteBody.d.ts
packages/app-desktop/gui/NoteEditor/commands/focusElementNoteBody.js
packages/app-desktop/gui/NoteEditor/commands/focusElementNoteBody.js.map
packages/app-desktop/gui/NoteEditor/commands/focusElementNoteTitle.d.ts
packages/app-desktop/gui/NoteEditor/commands/focusElementNoteTitle.js
packages/app-desktop/gui/NoteEditor/commands/focusElementNoteTitle.js.map
packages/app-desktop/gui/NoteEditor/commands/index.d.ts
packages/app-desktop/gui/NoteEditor/commands/index.js
packages/app-desktop/gui/NoteEditor/commands/index.js.map
packages/app-desktop/gui/NoteEditor/commands/showLocalSearch.d.ts
packages/app-desktop/gui/NoteEditor/commands/showLocalSearch.js
packages/app-desktop/gui/NoteEditor/commands/showLocalSearch.js.map
packages/app-desktop/gui/NoteEditor/commands/showRevisions.d.ts
packages/app-desktop/gui/NoteEditor/commands/showRevisions.js
packages/app-desktop/gui/NoteEditor/commands/showRevisions.js.map
packages/app-desktop/gui/NoteEditor/editorCommandDeclarations.d.ts
packages/app-desktop/gui/NoteEditor/editorCommandDeclarations.js
packages/app-desktop/gui/NoteEditor/editorCommandDeclarations.js.map
packages/app-desktop/gui/NoteEditor/styles/index.d.ts
packages/app-desktop/gui/NoteEditor/styles/index.js
packages/app-desktop/gui/NoteEditor/styles/index.js.map
@@ -481,18 +468,12 @@ packages/app-desktop/gui/NoteList/NoteList.js.map
packages/app-desktop/gui/NoteList/commands/focusElementNoteList.d.ts
packages/app-desktop/gui/NoteList/commands/focusElementNoteList.js
packages/app-desktop/gui/NoteList/commands/focusElementNoteList.js.map
packages/app-desktop/gui/NoteList/commands/index.d.ts
packages/app-desktop/gui/NoteList/commands/index.js
packages/app-desktop/gui/NoteList/commands/index.js.map
packages/app-desktop/gui/NoteListControls/NoteListControls.d.ts
packages/app-desktop/gui/NoteListControls/NoteListControls.js
packages/app-desktop/gui/NoteListControls/NoteListControls.js.map
packages/app-desktop/gui/NoteListControls/commands/focusSearch.d.ts
packages/app-desktop/gui/NoteListControls/commands/focusSearch.js
packages/app-desktop/gui/NoteListControls/commands/focusSearch.js.map
packages/app-desktop/gui/NoteListControls/commands/index.d.ts
packages/app-desktop/gui/NoteListControls/commands/index.js
packages/app-desktop/gui/NoteListControls/commands/index.js.map
packages/app-desktop/gui/NoteListItem.d.ts
packages/app-desktop/gui/NoteListItem.js
packages/app-desktop/gui/NoteListItem.js.map
@@ -589,18 +570,12 @@ packages/app-desktop/gui/Sidebar/Sidebar.js.map
packages/app-desktop/gui/Sidebar/commands/focusElementSideBar.d.ts
packages/app-desktop/gui/Sidebar/commands/focusElementSideBar.js
packages/app-desktop/gui/Sidebar/commands/focusElementSideBar.js.map
packages/app-desktop/gui/Sidebar/commands/index.d.ts
packages/app-desktop/gui/Sidebar/commands/index.js
packages/app-desktop/gui/Sidebar/commands/index.js.map
packages/app-desktop/gui/Sidebar/styles/index.d.ts
packages/app-desktop/gui/Sidebar/styles/index.js
packages/app-desktop/gui/Sidebar/styles/index.js.map
packages/app-desktop/gui/StatusScreen/StatusScreen.d.ts
packages/app-desktop/gui/StatusScreen/StatusScreen.js
packages/app-desktop/gui/StatusScreen/StatusScreen.js.map
packages/app-desktop/gui/StyleSheets/StyleSheetContainer.d.ts
packages/app-desktop/gui/StyleSheets/StyleSheetContainer.js
packages/app-desktop/gui/StyleSheets/StyleSheetContainer.js.map
packages/app-desktop/gui/SyncWizard/Dialog.d.ts
packages/app-desktop/gui/SyncWizard/Dialog.js
packages/app-desktop/gui/SyncWizard/Dialog.js.map
@@ -889,9 +864,6 @@ packages/lib/JoplinServerApi.js.map
packages/lib/Logger.d.ts
packages/lib/Logger.js
packages/lib/Logger.js.map
packages/lib/ObjectUtils.d.ts
packages/lib/ObjectUtils.js
packages/lib/ObjectUtils.js.map
packages/lib/PoorManIntervals.d.ts
packages/lib/PoorManIntervals.js
packages/lib/PoorManIntervals.js.map
@@ -925,9 +897,6 @@ packages/lib/commands/historyBackward.js.map
packages/lib/commands/historyForward.d.ts
packages/lib/commands/historyForward.js
packages/lib/commands/historyForward.js.map
packages/lib/commands/index.d.ts
packages/lib/commands/index.js
packages/lib/commands/index.js.map
packages/lib/commands/synchronize.d.ts
packages/lib/commands/synchronize.js
packages/lib/commands/synchronize.js.map
@@ -970,9 +939,6 @@ packages/lib/fs-driver-node.js.map
packages/lib/fsDriver.test.d.ts
packages/lib/fsDriver.test.js
packages/lib/fsDriver.test.js.map
packages/lib/hooks/useAsyncEffect.d.ts
packages/lib/hooks/useAsyncEffect.js
packages/lib/hooks/useAsyncEffect.js.map
packages/lib/hooks/useElementSize.d.ts
packages/lib/hooks/useElementSize.js
packages/lib/hooks/useElementSize.js.map
@@ -1027,9 +993,6 @@ packages/lib/models/Folder.test.js.map
packages/lib/models/ItemChange.d.ts
packages/lib/models/ItemChange.js
packages/lib/models/ItemChange.js.map
packages/lib/models/ItemChange.test.d.ts
packages/lib/models/ItemChange.test.js
packages/lib/models/ItemChange.test.js.map
packages/lib/models/MasterKey.d.ts
packages/lib/models/MasterKey.js
packages/lib/models/MasterKey.js.map
@@ -1132,6 +1095,12 @@ packages/lib/services/CommandService.test.js.map
packages/lib/services/DecryptionWorker.d.ts
packages/lib/services/DecryptionWorker.js
packages/lib/services/DecryptionWorker.js.map
packages/lib/services/EncryptionService.d.ts
packages/lib/services/EncryptionService.js
packages/lib/services/EncryptionService.js.map
packages/lib/services/EncryptionService.test.d.ts
packages/lib/services/EncryptionService.test.js
packages/lib/services/EncryptionService.test.js.map
packages/lib/services/ExternalEditWatcher.d.ts
packages/lib/services/ExternalEditWatcher.js
packages/lib/services/ExternalEditWatcher.js.map
@@ -1225,12 +1194,6 @@ packages/lib/services/database/types.js.map
packages/lib/services/debug/populateDatabase.d.ts
packages/lib/services/debug/populateDatabase.js
packages/lib/services/debug/populateDatabase.js.map
packages/lib/services/e2ee/EncryptionService.d.ts
packages/lib/services/e2ee/EncryptionService.js
packages/lib/services/e2ee/EncryptionService.js.map
packages/lib/services/e2ee/EncryptionService.test.d.ts
packages/lib/services/e2ee/EncryptionService.test.js
packages/lib/services/e2ee/EncryptionService.test.js.map
packages/lib/services/e2ee/types.d.ts
packages/lib/services/e2ee/types.js
packages/lib/services/e2ee/types.js.map
@@ -1285,9 +1248,6 @@ packages/lib/services/interop/InteropService_Importer_Jex.js.map
packages/lib/services/interop/InteropService_Importer_Md.d.ts
packages/lib/services/interop/InteropService_Importer_Md.js
packages/lib/services/interop/InteropService_Importer_Md.js.map
packages/lib/services/interop/InteropService_Importer_Md.test.d.ts
packages/lib/services/interop/InteropService_Importer_Md.test.js
packages/lib/services/interop/InteropService_Importer_Md.test.js.map
packages/lib/services/interop/InteropService_Importer_Raw.d.ts
packages/lib/services/interop/InteropService_Importer_Raw.js
packages/lib/services/interop/InteropService_Importer_Raw.js.map
@@ -1444,12 +1404,6 @@ packages/lib/services/rest/actionApi.desktop.js.map
packages/lib/services/rest/routes/auth.d.ts
packages/lib/services/rest/routes/auth.js
packages/lib/services/rest/routes/auth.js.map
packages/lib/services/rest/routes/events.d.ts
packages/lib/services/rest/routes/events.js
packages/lib/services/rest/routes/events.js.map
packages/lib/services/rest/routes/events.test.d.ts
packages/lib/services/rest/routes/events.test.js
packages/lib/services/rest/routes/events.test.js.map
packages/lib/services/rest/routes/folders.d.ts
packages/lib/services/rest/routes/folders.js
packages/lib/services/rest/routes/folders.js.map
@@ -1531,21 +1485,6 @@ packages/lib/services/spellChecker/SpellCheckerService.js.map
packages/lib/services/spellChecker/SpellCheckerServiceDriverBase.d.ts
packages/lib/services/spellChecker/SpellCheckerServiceDriverBase.js
packages/lib/services/spellChecker/SpellCheckerServiceDriverBase.js.map
packages/lib/services/style/cssToTheme.d.ts
packages/lib/services/style/cssToTheme.js
packages/lib/services/style/cssToTheme.js.map
packages/lib/services/style/cssToTheme.test.d.ts
packages/lib/services/style/cssToTheme.test.js
packages/lib/services/style/cssToTheme.test.js.map
packages/lib/services/style/loadCssToTheme.d.ts
packages/lib/services/style/loadCssToTheme.js
packages/lib/services/style/loadCssToTheme.js.map
packages/lib/services/style/themeToCss.d.ts
packages/lib/services/style/themeToCss.js
packages/lib/services/style/themeToCss.js.map
packages/lib/services/style/themeToCss.test.d.ts
packages/lib/services/style/themeToCss.test.js
packages/lib/services/style/themeToCss.test.js.map
packages/lib/services/synchronizer/ItemUploader.d.ts
packages/lib/services/synchronizer/ItemUploader.js
packages/lib/services/synchronizer/ItemUploader.js.map
@@ -1696,12 +1635,6 @@ packages/plugin-repo-cli/lib/gitCompareUrl.js.map
packages/plugin-repo-cli/lib/gitCompareUrl.test.d.ts
packages/plugin-repo-cli/lib/gitCompareUrl.test.js
packages/plugin-repo-cli/lib/gitCompareUrl.test.js.map
packages/plugin-repo-cli/lib/overrideUtils.d.ts
packages/plugin-repo-cli/lib/overrideUtils.js
packages/plugin-repo-cli/lib/overrideUtils.js.map
packages/plugin-repo-cli/lib/overrideUtils.test.d.ts
packages/plugin-repo-cli/lib/overrideUtils.test.js
packages/plugin-repo-cli/lib/overrideUtils.test.js.map
packages/plugin-repo-cli/lib/types.d.ts
packages/plugin-repo-cli/lib/types.js
packages/plugin-repo-cli/lib/types.js.map
@@ -1711,9 +1644,6 @@ packages/plugin-repo-cli/lib/updateReadme.js.map
packages/plugin-repo-cli/lib/updateReadme.test.d.ts
packages/plugin-repo-cli/lib/updateReadme.test.js
packages/plugin-repo-cli/lib/updateReadme.test.js.map
packages/plugin-repo-cli/lib/utils.d.ts
packages/plugin-repo-cli/lib/utils.js
packages/plugin-repo-cli/lib/utils.js.map
packages/plugins/ToggleSidebars/api/index.d.ts
packages/plugins/ToggleSidebars/api/index.js
packages/plugins/ToggleSidebars/api/index.js.map
@@ -1786,9 +1716,6 @@ packages/renderer/MdToHtml/setupLinkify.js.map
packages/renderer/MdToHtml/validateLinks.d.ts
packages/renderer/MdToHtml/validateLinks.js
packages/renderer/MdToHtml/validateLinks.js.map
packages/renderer/headerAnchor.d.ts
packages/renderer/headerAnchor.js
packages/renderer/headerAnchor.js.map
packages/renderer/htmlUtils.d.ts
packages/renderer/htmlUtils.js
packages/renderer/htmlUtils.js.map
@@ -1807,18 +1734,12 @@ packages/renderer/utils.js.map
packages/tools/buildServerDocker.d.ts
packages/tools/buildServerDocker.js
packages/tools/buildServerDocker.js.map
packages/tools/convertThemesToCss.d.ts
packages/tools/convertThemesToCss.js
packages/tools/convertThemesToCss.js.map
packages/tools/generate-database-types.d.ts
packages/tools/generate-database-types.js
packages/tools/generate-database-types.js.map
packages/tools/generate-images.d.ts
packages/tools/generate-images.js
packages/tools/generate-images.js.map
packages/tools/git-changelog.d.ts
packages/tools/git-changelog.js
packages/tools/git-changelog.js.map
packages/tools/lerna-add.d.ts
packages/tools/lerna-add.js
packages/tools/lerna-add.js.map

View File

@@ -35,14 +35,6 @@ jobs:
sudo apt-get update || true
sudo apt-get install -y docker-ce docker-ce-cli containerd.io
# the next line enables multi-architecture support for docker, it basically makes it use qemu for non native platforms
# See https://hub.docker.com/r/tonistiigi/binfmt for more info
docker run --privileged --rm tonistiigi/binfmt --install all
# this just prints the info about what platforms are supported in the builder (can help debugging if something isn't working right)
# and also proves the above worked properly
sudo docker buildx ls
- uses: actions/checkout@v2
- uses: olegtarasov/get-tag@v2.1
- uses: actions/setup-node@v2

103
.gitignore vendored
View File

@@ -49,7 +49,6 @@ packages/tools/commit_hook.txt
packages/tools/github_oauth_token.txt
lerna-debug.log
.env
docs/**/*.mustache
# AUTO-GENERATED - EXCLUDED TYPESCRIPT BUILD
packages/app-cli/app/LinkSelector.d.ts
@@ -70,6 +69,9 @@ packages/app-cli/tests/HtmlToMd.js.map
packages/app-cli/tests/MdToHtml.d.ts
packages/app-cli/tests/MdToHtml.js
packages/app-cli/tests/MdToHtml.js.map
packages/app-cli/tests/MdToMd.d.ts
packages/app-cli/tests/MdToMd.js
packages/app-cli/tests/MdToMd.js.map
packages/app-cli/tests/services/keychain/KeychainService.d.ts
packages/app-cli/tests/services/keychain/KeychainService.js
packages/app-cli/tests/services/keychain/KeychainService.js.map
@@ -103,12 +105,6 @@ packages/app-desktop/InteropServiceHelper.js.map
packages/app-desktop/app.d.ts
packages/app-desktop/app.js
packages/app-desktop/app.js.map
packages/app-desktop/app.reducer.d.ts
packages/app-desktop/app.reducer.js
packages/app-desktop/app.reducer.js.map
packages/app-desktop/app.reducer.test.d.ts
packages/app-desktop/app.reducer.test.js
packages/app-desktop/app.reducer.test.js.map
packages/app-desktop/bridge.d.ts
packages/app-desktop/bridge.js
packages/app-desktop/bridge.js.map
@@ -127,9 +123,6 @@ packages/app-desktop/commands/exportNotes.js.map
packages/app-desktop/commands/focusElement.d.ts
packages/app-desktop/commands/focusElement.js
packages/app-desktop/commands/focusElement.js.map
packages/app-desktop/commands/index.d.ts
packages/app-desktop/commands/index.js
packages/app-desktop/commands/index.js.map
packages/app-desktop/commands/openProfileDirectory.d.ts
packages/app-desktop/commands/openProfileDirectory.js
packages/app-desktop/commands/openProfileDirectory.js.map
@@ -235,9 +228,6 @@ packages/app-desktop/gui/MainScreen/commands/gotoAnything.js.map
packages/app-desktop/gui/MainScreen/commands/hideModalMessage.d.ts
packages/app-desktop/gui/MainScreen/commands/hideModalMessage.js
packages/app-desktop/gui/MainScreen/commands/hideModalMessage.js.map
packages/app-desktop/gui/MainScreen/commands/index.d.ts
packages/app-desktop/gui/MainScreen/commands/index.js
packages/app-desktop/gui/MainScreen/commands/index.js.map
packages/app-desktop/gui/MainScreen/commands/moveToFolder.d.ts
packages/app-desktop/gui/MainScreen/commands/moveToFolder.js
packages/app-desktop/gui/MainScreen/commands/moveToFolder.js.map
@@ -394,24 +384,21 @@ packages/app-desktop/gui/NoteEditor/NoteEditor.js.map
packages/app-desktop/gui/NoteEditor/NoteTitle/NoteTitleBar.d.ts
packages/app-desktop/gui/NoteEditor/NoteTitle/NoteTitleBar.js
packages/app-desktop/gui/NoteEditor/NoteTitle/NoteTitleBar.js.map
packages/app-desktop/gui/NoteEditor/commands/editorCommandDeclarations.d.ts
packages/app-desktop/gui/NoteEditor/commands/editorCommandDeclarations.js
packages/app-desktop/gui/NoteEditor/commands/editorCommandDeclarations.js.map
packages/app-desktop/gui/NoteEditor/commands/focusElementNoteBody.d.ts
packages/app-desktop/gui/NoteEditor/commands/focusElementNoteBody.js
packages/app-desktop/gui/NoteEditor/commands/focusElementNoteBody.js.map
packages/app-desktop/gui/NoteEditor/commands/focusElementNoteTitle.d.ts
packages/app-desktop/gui/NoteEditor/commands/focusElementNoteTitle.js
packages/app-desktop/gui/NoteEditor/commands/focusElementNoteTitle.js.map
packages/app-desktop/gui/NoteEditor/commands/index.d.ts
packages/app-desktop/gui/NoteEditor/commands/index.js
packages/app-desktop/gui/NoteEditor/commands/index.js.map
packages/app-desktop/gui/NoteEditor/commands/showLocalSearch.d.ts
packages/app-desktop/gui/NoteEditor/commands/showLocalSearch.js
packages/app-desktop/gui/NoteEditor/commands/showLocalSearch.js.map
packages/app-desktop/gui/NoteEditor/commands/showRevisions.d.ts
packages/app-desktop/gui/NoteEditor/commands/showRevisions.js
packages/app-desktop/gui/NoteEditor/commands/showRevisions.js.map
packages/app-desktop/gui/NoteEditor/editorCommandDeclarations.d.ts
packages/app-desktop/gui/NoteEditor/editorCommandDeclarations.js
packages/app-desktop/gui/NoteEditor/editorCommandDeclarations.js.map
packages/app-desktop/gui/NoteEditor/styles/index.d.ts
packages/app-desktop/gui/NoteEditor/styles/index.js
packages/app-desktop/gui/NoteEditor/styles/index.js.map
@@ -466,18 +453,12 @@ packages/app-desktop/gui/NoteList/NoteList.js.map
packages/app-desktop/gui/NoteList/commands/focusElementNoteList.d.ts
packages/app-desktop/gui/NoteList/commands/focusElementNoteList.js
packages/app-desktop/gui/NoteList/commands/focusElementNoteList.js.map
packages/app-desktop/gui/NoteList/commands/index.d.ts
packages/app-desktop/gui/NoteList/commands/index.js
packages/app-desktop/gui/NoteList/commands/index.js.map
packages/app-desktop/gui/NoteListControls/NoteListControls.d.ts
packages/app-desktop/gui/NoteListControls/NoteListControls.js
packages/app-desktop/gui/NoteListControls/NoteListControls.js.map
packages/app-desktop/gui/NoteListControls/commands/focusSearch.d.ts
packages/app-desktop/gui/NoteListControls/commands/focusSearch.js
packages/app-desktop/gui/NoteListControls/commands/focusSearch.js.map
packages/app-desktop/gui/NoteListControls/commands/index.d.ts
packages/app-desktop/gui/NoteListControls/commands/index.js
packages/app-desktop/gui/NoteListControls/commands/index.js.map
packages/app-desktop/gui/NoteListItem.d.ts
packages/app-desktop/gui/NoteListItem.js
packages/app-desktop/gui/NoteListItem.js.map
@@ -574,18 +555,12 @@ packages/app-desktop/gui/Sidebar/Sidebar.js.map
packages/app-desktop/gui/Sidebar/commands/focusElementSideBar.d.ts
packages/app-desktop/gui/Sidebar/commands/focusElementSideBar.js
packages/app-desktop/gui/Sidebar/commands/focusElementSideBar.js.map
packages/app-desktop/gui/Sidebar/commands/index.d.ts
packages/app-desktop/gui/Sidebar/commands/index.js
packages/app-desktop/gui/Sidebar/commands/index.js.map
packages/app-desktop/gui/Sidebar/styles/index.d.ts
packages/app-desktop/gui/Sidebar/styles/index.js
packages/app-desktop/gui/Sidebar/styles/index.js.map
packages/app-desktop/gui/StatusScreen/StatusScreen.d.ts
packages/app-desktop/gui/StatusScreen/StatusScreen.js
packages/app-desktop/gui/StatusScreen/StatusScreen.js.map
packages/app-desktop/gui/StyleSheets/StyleSheetContainer.d.ts
packages/app-desktop/gui/StyleSheets/StyleSheetContainer.js
packages/app-desktop/gui/StyleSheets/StyleSheetContainer.js.map
packages/app-desktop/gui/SyncWizard/Dialog.d.ts
packages/app-desktop/gui/SyncWizard/Dialog.js
packages/app-desktop/gui/SyncWizard/Dialog.js.map
@@ -874,9 +849,6 @@ packages/lib/JoplinServerApi.js.map
packages/lib/Logger.d.ts
packages/lib/Logger.js
packages/lib/Logger.js.map
packages/lib/ObjectUtils.d.ts
packages/lib/ObjectUtils.js
packages/lib/ObjectUtils.js.map
packages/lib/PoorManIntervals.d.ts
packages/lib/PoorManIntervals.js
packages/lib/PoorManIntervals.js.map
@@ -910,9 +882,6 @@ packages/lib/commands/historyBackward.js.map
packages/lib/commands/historyForward.d.ts
packages/lib/commands/historyForward.js
packages/lib/commands/historyForward.js.map
packages/lib/commands/index.d.ts
packages/lib/commands/index.js
packages/lib/commands/index.js.map
packages/lib/commands/synchronize.d.ts
packages/lib/commands/synchronize.js
packages/lib/commands/synchronize.js.map
@@ -955,9 +924,6 @@ packages/lib/fs-driver-node.js.map
packages/lib/fsDriver.test.d.ts
packages/lib/fsDriver.test.js
packages/lib/fsDriver.test.js.map
packages/lib/hooks/useAsyncEffect.d.ts
packages/lib/hooks/useAsyncEffect.js
packages/lib/hooks/useAsyncEffect.js.map
packages/lib/hooks/useElementSize.d.ts
packages/lib/hooks/useElementSize.js
packages/lib/hooks/useElementSize.js.map
@@ -1012,9 +978,6 @@ packages/lib/models/Folder.test.js.map
packages/lib/models/ItemChange.d.ts
packages/lib/models/ItemChange.js
packages/lib/models/ItemChange.js.map
packages/lib/models/ItemChange.test.d.ts
packages/lib/models/ItemChange.test.js
packages/lib/models/ItemChange.test.js.map
packages/lib/models/MasterKey.d.ts
packages/lib/models/MasterKey.js
packages/lib/models/MasterKey.js.map
@@ -1117,6 +1080,12 @@ packages/lib/services/CommandService.test.js.map
packages/lib/services/DecryptionWorker.d.ts
packages/lib/services/DecryptionWorker.js
packages/lib/services/DecryptionWorker.js.map
packages/lib/services/EncryptionService.d.ts
packages/lib/services/EncryptionService.js
packages/lib/services/EncryptionService.js.map
packages/lib/services/EncryptionService.test.d.ts
packages/lib/services/EncryptionService.test.js
packages/lib/services/EncryptionService.test.js.map
packages/lib/services/ExternalEditWatcher.d.ts
packages/lib/services/ExternalEditWatcher.js
packages/lib/services/ExternalEditWatcher.js.map
@@ -1210,12 +1179,6 @@ packages/lib/services/database/types.js.map
packages/lib/services/debug/populateDatabase.d.ts
packages/lib/services/debug/populateDatabase.js
packages/lib/services/debug/populateDatabase.js.map
packages/lib/services/e2ee/EncryptionService.d.ts
packages/lib/services/e2ee/EncryptionService.js
packages/lib/services/e2ee/EncryptionService.js.map
packages/lib/services/e2ee/EncryptionService.test.d.ts
packages/lib/services/e2ee/EncryptionService.test.js
packages/lib/services/e2ee/EncryptionService.test.js.map
packages/lib/services/e2ee/types.d.ts
packages/lib/services/e2ee/types.js
packages/lib/services/e2ee/types.js.map
@@ -1270,9 +1233,6 @@ packages/lib/services/interop/InteropService_Importer_Jex.js.map
packages/lib/services/interop/InteropService_Importer_Md.d.ts
packages/lib/services/interop/InteropService_Importer_Md.js
packages/lib/services/interop/InteropService_Importer_Md.js.map
packages/lib/services/interop/InteropService_Importer_Md.test.d.ts
packages/lib/services/interop/InteropService_Importer_Md.test.js
packages/lib/services/interop/InteropService_Importer_Md.test.js.map
packages/lib/services/interop/InteropService_Importer_Raw.d.ts
packages/lib/services/interop/InteropService_Importer_Raw.js
packages/lib/services/interop/InteropService_Importer_Raw.js.map
@@ -1429,12 +1389,6 @@ packages/lib/services/rest/actionApi.desktop.js.map
packages/lib/services/rest/routes/auth.d.ts
packages/lib/services/rest/routes/auth.js
packages/lib/services/rest/routes/auth.js.map
packages/lib/services/rest/routes/events.d.ts
packages/lib/services/rest/routes/events.js
packages/lib/services/rest/routes/events.js.map
packages/lib/services/rest/routes/events.test.d.ts
packages/lib/services/rest/routes/events.test.js
packages/lib/services/rest/routes/events.test.js.map
packages/lib/services/rest/routes/folders.d.ts
packages/lib/services/rest/routes/folders.js
packages/lib/services/rest/routes/folders.js.map
@@ -1516,21 +1470,6 @@ packages/lib/services/spellChecker/SpellCheckerService.js.map
packages/lib/services/spellChecker/SpellCheckerServiceDriverBase.d.ts
packages/lib/services/spellChecker/SpellCheckerServiceDriverBase.js
packages/lib/services/spellChecker/SpellCheckerServiceDriverBase.js.map
packages/lib/services/style/cssToTheme.d.ts
packages/lib/services/style/cssToTheme.js
packages/lib/services/style/cssToTheme.js.map
packages/lib/services/style/cssToTheme.test.d.ts
packages/lib/services/style/cssToTheme.test.js
packages/lib/services/style/cssToTheme.test.js.map
packages/lib/services/style/loadCssToTheme.d.ts
packages/lib/services/style/loadCssToTheme.js
packages/lib/services/style/loadCssToTheme.js.map
packages/lib/services/style/themeToCss.d.ts
packages/lib/services/style/themeToCss.js
packages/lib/services/style/themeToCss.js.map
packages/lib/services/style/themeToCss.test.d.ts
packages/lib/services/style/themeToCss.test.js
packages/lib/services/style/themeToCss.test.js.map
packages/lib/services/synchronizer/ItemUploader.d.ts
packages/lib/services/synchronizer/ItemUploader.js
packages/lib/services/synchronizer/ItemUploader.js.map
@@ -1681,12 +1620,6 @@ packages/plugin-repo-cli/lib/gitCompareUrl.js.map
packages/plugin-repo-cli/lib/gitCompareUrl.test.d.ts
packages/plugin-repo-cli/lib/gitCompareUrl.test.js
packages/plugin-repo-cli/lib/gitCompareUrl.test.js.map
packages/plugin-repo-cli/lib/overrideUtils.d.ts
packages/plugin-repo-cli/lib/overrideUtils.js
packages/plugin-repo-cli/lib/overrideUtils.js.map
packages/plugin-repo-cli/lib/overrideUtils.test.d.ts
packages/plugin-repo-cli/lib/overrideUtils.test.js
packages/plugin-repo-cli/lib/overrideUtils.test.js.map
packages/plugin-repo-cli/lib/types.d.ts
packages/plugin-repo-cli/lib/types.js
packages/plugin-repo-cli/lib/types.js.map
@@ -1696,9 +1629,6 @@ packages/plugin-repo-cli/lib/updateReadme.js.map
packages/plugin-repo-cli/lib/updateReadme.test.d.ts
packages/plugin-repo-cli/lib/updateReadme.test.js
packages/plugin-repo-cli/lib/updateReadme.test.js.map
packages/plugin-repo-cli/lib/utils.d.ts
packages/plugin-repo-cli/lib/utils.js
packages/plugin-repo-cli/lib/utils.js.map
packages/plugins/ToggleSidebars/api/index.d.ts
packages/plugins/ToggleSidebars/api/index.js
packages/plugins/ToggleSidebars/api/index.js.map
@@ -1771,9 +1701,6 @@ packages/renderer/MdToHtml/setupLinkify.js.map
packages/renderer/MdToHtml/validateLinks.d.ts
packages/renderer/MdToHtml/validateLinks.js
packages/renderer/MdToHtml/validateLinks.js.map
packages/renderer/headerAnchor.d.ts
packages/renderer/headerAnchor.js
packages/renderer/headerAnchor.js.map
packages/renderer/htmlUtils.d.ts
packages/renderer/htmlUtils.js
packages/renderer/htmlUtils.js.map
@@ -1792,18 +1719,12 @@ packages/renderer/utils.js.map
packages/tools/buildServerDocker.d.ts
packages/tools/buildServerDocker.js
packages/tools/buildServerDocker.js.map
packages/tools/convertThemesToCss.d.ts
packages/tools/convertThemesToCss.js
packages/tools/convertThemesToCss.js.map
packages/tools/generate-database-types.d.ts
packages/tools/generate-database-types.js
packages/tools/generate-database-types.js.map
packages/tools/generate-images.d.ts
packages/tools/generate-images.js
packages/tools/generate-images.js.map
packages/tools/git-changelog.d.ts
packages/tools/git-changelog.js
packages/tools/git-changelog.js.map
packages/tools/lerna-add.d.ts
packages/tools/lerna-add.js
packages/tools/lerna-add.js.map

View File

@@ -29,7 +29,7 @@ ol, ul {
#main-container {
position: relative;
min-height: 100vh;
padding-bottom: 127px; /* Needs to be the height of the footer */
padding-bottom: 225px;
}
.help-page-container img {
@@ -583,7 +583,7 @@ div.navbar-mobile-content a.sponsor-button {
/* footer section */
footer {
padding-top: 30px;
padding-top: 50px;
padding-bottom: 30px;
position: absolute;
bottom: 0;
@@ -594,7 +594,6 @@ footer a,
footer p {
color: #90b1d9;
text-decoration: none;
margin-bottom: 0;
}
footer a:hover {
@@ -618,35 +617,6 @@ footer .right-links a {
margin-left: 15px;
}
footer .footer-right {
margin-left: 30px;
}
footer .social-links {
display: flex;
flex-direction: row;
justify-content: center;
padding-bottom: 20px;
border-bottom: 1px solid #315885;
}
footer .social-links a:hover {
color: #e8f3ff;
}
footer .social-links i {
margin-left: 15px;
font-size: 22px;
}
footer .bottom-links-row {
padding-top: 20px;
}
footer .bottom-links-row p {
font-size: 1.1em;
}
/*****************************************************************
IN THE PRESS
The "In the press" section height needs to be adjusted as the
@@ -709,7 +679,7 @@ footer .bottom-links-row p {
#main-container {
position: relative;
min-height: 100vh;
padding-bottom: 130px;
padding-bottom: 260px;
}
.front-page h1 {
@@ -896,7 +866,7 @@ footer .bottom-links-row p {
.help-page-container {
padding-top: 90px;
padding-bottom: 70px;
padding-bottom: 50px;
}
.donate-links {
@@ -910,7 +880,7 @@ footer .bottom-links-row p {
border-radius: 20px;
padding: 30px 20px;
padding-bottom: 30px;
margin-bottom: 20px;
margin-bottom: 50px;
margin-top: 40px;
}
@@ -953,11 +923,6 @@ footer .bottom-links-row p {
justify-content: center;
}
.plan-group .joplin-cloud-login-info {
margin-bottom: 40px;
text-align: center;
}
.plan-group .plan-price-yearly-per-year {
display: flex;
justify-content: flex-end;

View File

@@ -368,7 +368,40 @@
</div>
</div>
{{> footer}}
<footer class="darkblue-bg">
<div class="container">
<div class="row">
<div class="col-3 d-none d-md-block">
<img src="{{imageBaseUrl}}/logo-text.svg" alt="" width="150" />
</div>
</div>
<div class="row">
<div class="col-12">
<hr />
</div>
</div>
<div class="row">
<div class="col-12 col-md-6">
<a href="{{baseUrl}}">
<img
src="{{imageBaseUrl}}/logo-text.svg"
width="120"
class="img-center d-block d-md-none"
alt=""
/>
</a>
<br class="d-block d-md-none" />
<p class="text-center-sm">Copyright &copy; 2016-{{yyyy}} Laurent Cozic</p>
</div>
<div class="col-12 col-md-6">
<p class="text-right text-center-sm right-links">
<a href="https://github.com/laurent22/joplin/" class="github-link"><i class="fab fa-github"></i> GitHub Repository</a>
<a href="{{baseUrl}}/privacy/">Privacy Policy</a>
</p>
</div>
</div>
</div>
</footer>
</div>
<script

View File

@@ -75,8 +75,38 @@ https://github.com/laurent22/joplin/blob/dev/{{{sourceMarkdownFile}}}
</div>
</div>
{{> footer}}
<footer class="darkblue-bg">
<div class="container">
<div class="row">
<div class="col-3 d-none d-md-block">
<img src="{{imageBaseUrl}}/logo-text.svg" alt="" width="150" />
</div>
</div>
<div class="row">
<div class="col-12">
<hr />
</div>
</div>
<div class="row">
<div class="col-12 col-md-6">
<img
src="{{imageBaseUrl}}/logo-text.svg"
width="120"
class="img-center d-block d-md-none"
alt=""
/>
<br class="d-block d-md-none" />
<p class="text-center-sm">Copyright &copy; 2016-{{yyyy}} Laurent Cozic</p>
</div>
<div class="col-12 col-md-6 right-links">
<p class="text-right text-center-sm">
<a href="https://github.com/laurent22/joplin/" class="github-link"><i class="fab fa-github"></i> GitHub Repository</a>
<a href="{{baseUrl}}/privacy/">Privacy Policy</a>
</p>
</div>
</div>
</div>
</footer>
</div>
<script src="{{jsBaseUrl}}/script.js?t={{buildTime}}"></script>

View File

@@ -1,26 +0,0 @@
<footer class="darkblue-bg">
<div class="container">
<div class="row">
<div class="col-12 col-md-12 social-links">
<a href="https://twitter.com/joplinapp" title="Twitter feed"><i class="fab fa-twitter"></i></a>
<a href="https://github.com/laurent22/joplin/" title="GitHub repository"><i class="fab fa-github"></i></a>
<a href="https://www.patreon.com/joplin" title="Patreon blog"><i class="fab fa-patreon"></i></a>
<a href="https://discordapp.com/invite/d2HMPwE" title="Discord chat"><i class="fab fa-discord"></i></a>
<a href="https://www.reddit.com/r/joplinapp/" title="Subreddit"><i class="fab fa-reddit"></i></a>
</div>
</div>
<div class="row bottom-links-row">
<div class="col-12 col-md-6">
<p class="text-center-sm">Copyright &copy; 2016-{{yyyy}} Laurent Cozic</p>
</div>
<div class="col-12 col-md-6">
<p class="text-right text-center-sm right-links">
<span class="footer-right">
<a href="{{baseUrl}}/privacy/">Privacy Policy</a>
</span>
</p>
</div>
</div>
</div>
</footer>

View File

@@ -6,7 +6,7 @@
Joplin Cloud <span class="frame-bg frame-bg-yellow">plans</span>
</h1>
<p class="text-center sub-title">
<a href="https://joplincloud.com">Joplin Cloud</a> allows you to synchronise your notes across devices. It also lets you publish notes, and collaborate on notebooks with your friends, family or colleagues.
Joplin Cloud allows you to synchronise your notes across devices. It also lets you publish notes, and collaborate on notebooks with your friends, family or colleagues.
</p>
</div>
</div>
@@ -45,8 +45,6 @@
{{#plans.business}}
{{> plan}}
{{/plans.business}}
<p class="joplin-cloud-login-info">Already have a Joplin Cloud account? <a href="https://joplincloud.com">Login now</a></p>
</div>
<div class="row">

View File

@@ -31,14 +31,12 @@ Joplin is available in multiple languages thanks to the help of its users. You c
If you want to start contributing to the project's code, please follow these guidelines before creating a pull request:
- Explain WHY you want to add this change. Explain it inside the pull request and you may link to an issue for additional information, but the PR should gives a clear overview of why you want to add this.
- Bug fixes are always welcome. Start by reviewing the [list of bugs](https://github.com/laurent22/joplin/issues?q=is%3Aissue+is%3Aopen+label%3Abug)
- A good way to easily start contributing is to pick and work on a [good first issue](https://github.com/laurent22/joplin/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22). We try to make these issues as clear as possible and provide basic info on how the code should be changed, and if something is unclear feel free to ask for more information on the issue.
- Before adding a new feature, ask about it in the [Github Issue Tracker](https://github.com/laurent22/joplin/issues?utf8=%E2%9C%93&q=is%3Aissue) or the [Joplin Forum](https://discourse.joplinapp.org/), or check if existing discussions exist to make sure the new functionality is desired.
- **Changes that will consist in more than 50 lines of code should be discussed the [Joplin Forum](https://discourse.joplinapp.org/)**, so that you don't spend too much time implementing something that might not be accepted.
- All the applications share the same backend (database, synchronisation, settings, models, business logic, etc.) so if you change something in the backend in one app, makes sure it still work in the other apps. Usually it does, but keep this in mind.
- Pull requests that make many changes using an automated tool, like for spell fixing, styling, etc. will not be accepted. An exception would be if the changes have been discussed in the forum and someone has agreed to review **and test** the pull request.
- Pull requests that make address multiple issues will most likely stall and eventually be closed. This is because we might be fine with one of the changes but not with others and untangling that kind of pull request is too much hassle both for maintainers and the person who submitted it. So most of the time someone gives up and the PR gets closed. So please keep the pull request focused on one issue.
Building the apps is relatively easy - please [see the build instructions](https://github.com/laurent22/joplin/blob/dev/BUILD.md) for more details.

View File

@@ -1,11 +1,6 @@
# https://versatile.nl/blog/deploying-lerna-web-apps-with-docker
FROM node:16-bullseye
RUN apt-get update \
&& apt-get install -y \
python \
&& rm -rf /var/lib/apt/lists/*
FROM node:16
RUN echo "Node: $(node --version)"
RUN echo "Npm: $(npm --version)"

View File

@@ -184,7 +184,7 @@ if command -v lsb_release &> /dev/null; then
# Check for "The SUID sandbox helper binary was found, but is not configured correctly" problem.
# It is present in Debian 1X. A (temporary) patch will be applied at .desktop file
# Linux Mint 4 Debbie is based on Debian 10 and requires the same param handling.
if [[ $DISTVER =~ Debian1. ]] || [ "$DISTVER" = "Linuxmint4" ] && [ "$DISTCODENAME" = "debbie" ]
if [ $DISTVER =~ Debian1. ] || [ "$DISTVER" = "Linuxmint4" ] && [ "$DISTCODENAME" = "debbie" ]
then
SANDBOXPARAM=" --no-sandbox"
fi

View File

@@ -511,7 +511,7 @@ Current translations:
<img src="https://joplinapp.org/images/flags/es/catalonia.png" width="16px"/> | Catalan | [ca](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/ca.po) | jmontane, 2019 | 95%
<img src="https://joplinapp.org/images/flags/country-4x3/hr.png" width="16px"/> | Croatian (Hrvatska) | [hr_HR](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/hr_HR.po) | [Milo Ivir](mailto:mail@milotype.de) | 96%
<img src="https://joplinapp.org/images/flags/country-4x3/cz.png" width="16px"/> | Czech (Česká republika) | [cs_CZ](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/cs_CZ.po) | [Michal Stanke](mailto:michal@stanke.cz) | 95%
<img src="https://joplinapp.org/images/flags/country-4x3/dk.png" width="16px"/> | Dansk (Danmark) | [da_DK](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/da_DK.po) | Mustafa Al-Dailemi (dailemi@hotmail.com)Language-Team: | 99%
<img src="https://joplinapp.org/images/flags/country-4x3/dk.png" width="16px"/> | Dansk (Danmark) | [da_DK](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/da_DK.po) | Mustafa Al-Dailemi (dailemi@hotmail.com)Language-Team: | 96%
<img src="https://joplinapp.org/images/flags/country-4x3/de.png" width="16px"/> | Deutsch (Deutschland) | [de_DE](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/de_DE.po) | [Atalanttore](mailto:atalanttore@googlemail.com) | 95%
<img src="https://joplinapp.org/images/flags/country-4x3/ee.png" width="16px"/> | Eesti Keel (Eesti) | [et_EE](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/et_EE.po) | | 54%
<img src="https://joplinapp.org/images/flags/country-4x3/gb.png" width="16px"/> | English (United Kingdom) | [en_GB](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/en_GB.po) | | 100%
@@ -527,7 +527,7 @@ Current translations:
<img src="https://joplinapp.org/images/flags/country-4x3/be.png" width="16px"/> | Nederlands (België, Belgique, Belgien) | [nl_BE](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/nl_BE.po) | | 87%
<img src="https://joplinapp.org/images/flags/country-4x3/nl.png" width="16px"/> | Nederlands (Nederland) | [nl_NL](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/nl_NL.po) | [MetBril](mailto:metbril@users.noreply.github.com) | 90%
<img src="https://joplinapp.org/images/flags/country-4x3/no.png" width="16px"/> | Norwegian (Norge, Noreg) | [nb_NO](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/nb_NO.po) | Alexander Dawson | 96%
<img src="https://joplinapp.org/images/flags/country-4x3/ir.png" width="16px"/> | Persian | [fa](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/fa.po) | [Kourosh Firoozbakht](mailto:kourox@protonmail.com) | 67%
<img src="https://joplinapp.org/images/flags/country-4x3/ir.png" width="16px"/> | Persian | [fa](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/fa.po) | [Kourosh Firoozbakht](mailto:kourox@protonmail.com) | 68%
<img src="https://joplinapp.org/images/flags/country-4x3/pl.png" width="16px"/> | Polski (Polska) | [pl_PL](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/pl_PL.po) | [konhi](mailto:hello.konhi@gmail.com) | 90%
<img src="https://joplinapp.org/images/flags/country-4x3/br.png" width="16px"/> | Português (Brasil) | [pt_BR](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/pt_BR.po) | [Nicolas Suzuki](mailto:nicolas.suzuki@pm.me) | 96%
<img src="https://joplinapp.org/images/flags/country-4x3/pt.png" width="16px"/> | Português (Portugal) | [pt_PT](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/pt_PT.po) | [Diogo Caveiro](mailto:dcaveiro@yahoo.com) | 90%
@@ -536,13 +536,13 @@ Current translations:
<img src="https://joplinapp.org/images/flags/country-4x3/se.png" width="16px"/> | Svenska | [sv](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/sv.po) | [Jonatan Nyberg](mailto:jonatan@autistici.org) | 96%
<img src="https://joplinapp.org/images/flags/country-4x3/th.png" width="16px"/> | Thai (ประเทศไทย) | [th_TH](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/th_TH.po) | | 42%
<img src="https://joplinapp.org/images/flags/country-4x3/vi.png" width="16px"/> | Tiếng Việt | [vi](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/vi.po) | | 96%
<img src="https://joplinapp.org/images/flags/country-4x3/tr.png" width="16px"/> | Türkçe (Türkiye) | [tr_TR](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/tr_TR.po) | [Arda Kılıçdağı](mailto:arda@kilicdagi.com) | 99%
<img src="https://joplinapp.org/images/flags/country-4x3/tr.png" width="16px"/> | Türkçe (Türkiye) | [tr_TR](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/tr_TR.po) | [Arda Kılıçdağı](mailto:arda@kilicdagi.com) | 95%
<img src="https://joplinapp.org/images/flags/country-4x3/ua.png" width="16px"/> | Ukrainian (Україна) | [uk_UA](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/uk_UA.po) | [Vyacheslav Andreykiv](mailto:vandreykiv@gmail.com) | 89%
<img src="https://joplinapp.org/images/flags/country-4x3/gr.png" width="16px"/> | Ελληνικά (Ελλάδα) | [el_GR](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/el_GR.po) | [Harris Arvanitis](mailto:xaris@tuta.io) | 92%
<img src="https://joplinapp.org/images/flags/country-4x3/ru.png" width="16px"/> | Русский (Россия) | [ru_RU](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/ru_RU.po) | [Sergey Segeda](mailto:thesermanarm@gmail.com) | 89%
<img src="https://joplinapp.org/images/flags/country-4x3/ru.png" width="16px"/> | Русский (Россия) | [ru_RU](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/ru_RU.po) | [Sergey Segeda](mailto:thesermanarm@gmail.com) | 90%
<img src="https://joplinapp.org/images/flags/country-4x3/rs.png" width="16px"/> | српски језик (Србија) | [sr_RS](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/sr_RS.po) | | 81%
<img src="https://joplinapp.org/images/flags/country-4x3/cn.png" width="16px"/> | 中文 (简体) | [zh_CN](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/zh_CN.po) | [南宫小骏](mailto:jackytsu@vip.qq.com) | 99%
<img src="https://joplinapp.org/images/flags/country-4x3/tw.png" width="16px"/> | 中文 (繁體) | [zh_TW](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/zh_TW.po) | [Po-Chiang Chao](mailto:BobChao%29%20%28bobchao@gmail.com) | 94%
<img src="https://joplinapp.org/images/flags/country-4x3/cn.png" width="16px"/> | 中文 (简体) | [zh_CN](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/zh_CN.po) | [南宫小骏](mailto:jackytsu@vip.qq.com) | 96%
<img src="https://joplinapp.org/images/flags/country-4x3/tw.png" width="16px"/> | 中文 (繁體) | [zh_TW](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/zh_TW.po) | [Po-Chiang Chao](mailto:BobChao%29%20%28bobchao@gmail.com) | 95%
<img src="https://joplinapp.org/images/flags/country-4x3/jp.png" width="16px"/> | 日本語 (日本) | [ja_JP](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/ja_JP.po) | [genneko](mailto:genneko217@gmail.com) | 95%
<img src="https://joplinapp.org/images/flags/country-4x3/kr.png" width="16px"/> | 한국어 | [ko](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/ko.po) | [Ji-Hyeon Gim](mailto:potatogim@potatogim.net) | 95%
<!-- LOCALE-TABLE-AUTO-GENERATED -->

View File

@@ -5,7 +5,6 @@ const tasks = {
// copyLib: require('./packages/tools/gulp/tasks/copyLib'),
// tsc: require('./packages/tools/gulp/tasks/tsc'),
updateIgnoredTypeScriptBuild: require('./packages/tools/gulp/tasks/updateIgnoredTypeScriptBuild'),
buildCommandIndex: require('./packages/tools/gulp/tasks/buildCommandIndex'),
// deleteBuildDirs: require('./packages/tools/gulp/tasks/deleteBuildDirs'),
completePublishAll: {
fn: async () => {

View File

@@ -12,7 +12,6 @@
"bootstrapServerOnly": "lerna bootstrap --force-local --no-ci --include-dependents --include-dependencies --scope @joplin/server",
"build": "lerna run build && npm run tsc",
"buildApiDoc": "npm start --prefix=packages/app-cli -- apidoc ../../readme/api/references/rest_api.md",
"buildCommandIndex": "gulp buildCommandIndex",
"buildDoc": "./packages/tools/build-all.sh",
"buildPluginDoc": "typedoc --name 'Joplin Plugin API Documentation' --mode file -theme './Assets/PluginDocTheme/' --readme './Assets/PluginDocTheme/index.md' --excludeNotExported --excludeExternals --excludePrivate --excludeProtected --out docs/api/references/plugin_api packages/lib/services/plugins/api/",
"buildSettingJsonSchema": "npm start --prefix=packages/app-cli -- settingschema ../../docs/schema/settings.json",

View File

@@ -381,30 +381,6 @@ async function fetchAllNotes() {
}
}
{
const tableFields = reg.db().tableFields('item_changes', { includeDescription: true });
lines.push('# Events');
lines.push('');
lines.push('This end point can be used to retrieve the latest note changes. Currently only note changes are tracked.');
lines.push('');
lines.push('## Properties');
lines.push('');
lines.push(this.createPropertiesTable(tableFields));
lines.push('');
lines.push('## GET /events');
lines.push('');
lines.push('Returns a paginated list of recent events. A `cursor` property should be provided, which tells from what point in time the events should be returned. The API will return a `cursor` property, to tell from where to resume retrieving events, as well as an `has_more` (tells if more changes can be retrieved) and `items` property, which will contain the list of events. Events are kept for up to 90 days.');
lines.push('');
lines.push('If no `cursor` property is provided, the API will respond with the latest change ID. That can be used to retrieve future events later on.');
lines.push('');
lines.push('The results are paginated so will need to may multiple calls to retrieve all the events. Use the `has_more` property to know if more can be retrieved.');
lines.push('');
lines.push('## GET /events/:id');
lines.push('');
lines.push('Returns the event with the given ID.');
}
const outFilePath = args['file'];
await shim.fsDriver().writeFile(outFilePath, lines.join('\n'), 'utf8');

View File

@@ -1,6 +1,6 @@
const { BaseCommand } = require('./base-command.js');
import { _ } from '@joplin/lib/locale';
import EncryptionService from '@joplin/lib/services/e2ee/EncryptionService';
import EncryptionService from '@joplin/lib/services/EncryptionService';
import DecryptionWorker from '@joplin/lib/services/DecryptionWorker';
import BaseItem from '@joplin/lib/models/BaseItem';
import Setting from '@joplin/lib/models/Setting';

View File

@@ -27,7 +27,7 @@ const { shimInit } = require('@joplin/lib/shim-init-node.js');
const shim = require('@joplin/lib/shim').default;
const { _ } = require('@joplin/lib/locale');
const { FileApiDriverLocal } = require('@joplin/lib/file-api-driver-local.js');
const EncryptionService = require('@joplin/lib/services/e2ee/EncryptionService').default;
const EncryptionService = require('@joplin/lib/services/EncryptionService').default;
const envFromArgs = require('@joplin/lib/envFromArgs');
const env = envFromArgs(process.argv);

View File

@@ -32,7 +32,7 @@
],
"owner": "Laurent Cozic"
},
"version": "2.4.0",
"version": "2.3.2",
"bin": {
"joplin": "./main.js"
},
@@ -40,8 +40,8 @@
"node": ">=10.0.0"
},
"dependencies": {
"@joplin/lib": "~2.4",
"@joplin/renderer": "~2.4",
"@joplin/lib": "~2.3",
"@joplin/renderer": "~2.3",
"aws-sdk": "^2.588.0",
"chalk": "^4.1.0",
"compare-version": "^0.1.2",
@@ -65,7 +65,7 @@
"yargs-parser": "^7.0.0"
},
"devDependencies": {
"@joplin/tools": "~2.4",
"@joplin/tools": "~2.3",
"@types/fs-extra": "^9.0.6",
"@types/jest": "^26.0.15",
"@types/node": "^14.14.6",

View File

@@ -0,0 +1,50 @@
const mdImporterService = require('@joplin/lib/services/interop/InteropService_Importer_Md').default;
const Note = require('@joplin/lib/models/Note').default;
import { setupDatabaseAndSynchronizer, switchClient } from '@joplin/lib/testing/test-utils';
const importer = new mdImporterService();
describe('InteropService_Importer_Md: importLocalImages', function() {
beforeEach(async (done) => {
await setupDatabaseAndSynchronizer(1);
await switchClient(1);
done();
});
it('should import linked files and modify tags appropriately', async function() {
const tagNonExistentFile = '![does not exist](does_not_exist.png)';
const note = await importer.importFile(`${__dirname}/md_to_md/sample.md`, 'notebook');
const items = await Note.linkedItems(note.body);
expect(items.length).toBe(2);
const inexistentLinkUnchanged = note.body.includes(tagNonExistentFile);
expect(inexistentLinkUnchanged).toBe(true);
});
it('should only create 1 resource for duplicate links, all tags should be updated', async function() {
const note = await importer.importFile(`${__dirname}/md_to_md/sample-duplicate-links.md`, 'notebook');
const items = await Note.linkedItems(note.body);
expect(items.length).toBe(1);
const reg = new RegExp(items[0].id, 'g');
const matched = note.body.match(reg);
expect(matched.length).toBe(2);
});
it('should import linked files and modify tags appropriately when link is also in alt text', async function() {
const note = await importer.importFile(`${__dirname}/md_to_md/sample-link-in-alt-text.md`, 'notebook');
const items = await Note.linkedItems(note.body);
expect(items.length).toBe(1);
});
it('should passthrough unchanged if no links present', async function() {
const note = await importer.importFile(`${__dirname}/md_to_md/sample-no-links.md`, 'notebook');
const items = await Note.linkedItems(note.body);
expect(items.length).toBe(0);
expect(note.body).toContain('Unidentified vessel travelling at sub warp speed, bearing 235.7. Fluctuations in energy readings from it, Captain. All transporters off.');
});
it('should import linked image with special characters in name', async function() {
const note = await importer.importFile(`${__dirname}/md_to_md/sample-special-chars.md`, 'notebook');
const items = await Note.linkedItems(note.body);
expect(items.length).toBe(1);
});
it('should import resources for files', async function() {
const note = await importer.importFile(`${__dirname}/md_to_md/sample-files.md`, 'notebook');
const items = await Note.linkedItems(note.body);
expect(items.length).toBe(4);
});
});

View File

@@ -0,0 +1,2 @@
![link 1](../support/photo.jpg)
![link 2](../support/photo.jpg)

View File

@@ -0,0 +1,9 @@
# Markdown file test
![../support/photo.jpg](../support/photo.jpg)
[welcome.pdf](../support/welcome.pdf)
[sample.md](sample.md)
[sample2.md](./sample.md)

View File

@@ -0,0 +1,3 @@
# Markdown
![../support/photo.jpg](../support/photo.jpg) should put resource link inside () not []
![../support/photo.jpg]( ../support/photo.jpg ) this case (spaces before/after link but within parens) is not currently covered

View File

@@ -0,0 +1 @@
![link special chars](../support/photo-åäö.jpg)

View File

@@ -0,0 +1,13 @@
# Markdown
lorem ipsum ![alt text here](../support/photo.jpg)
- [ ] check!
- [ ] boxes!
![alt text here](../support/photo-two.jpg)ipsum lorem
**strong text**
![does not exist](does_not_exist.png) lorem ipsum
**some directory**
![a directory](../support) lorem ipsum

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

View File

@@ -1,3 +0,0 @@
# Test Spaces
I hope this get's imported correctly!

View File

@@ -1 +0,0 @@
[Section 1](./sample-no-links.md#markdown)

View File

@@ -1,3 +0,0 @@
# Markdown file test
[sample.md](sample-cycles-b.md)

View File

@@ -1,4 +0,0 @@
# Markdown file test
[sample.md](./sample-cycles-a.md)

View File

@@ -1,2 +0,0 @@
![link 1](../../photo.jpg)
![link 2](../../photo.jpg)

View File

@@ -1 +0,0 @@
![sample](file://../../photo.jpg)

View File

@@ -1,9 +0,0 @@
# Markdown file test
![../../photo.jpg](../../photo.jpg)
[welcome.pdf](../../welcome.pdf)
[sample.md](sample.md)
[sample2.md](./sample.md)

View File

@@ -1,3 +0,0 @@
# Markdown
![../../photo.jpg](../../photo.jpg) should put resource link inside () not []
![../../photo.jpg]( ../../photo.jpg ) this case (spaces before/after link but within parens) is not currently covered

View File

@@ -1,3 +0,0 @@
![Alt text](../../photo.jpg "Scott Joplin")
![Worst Case](<../../photo sample.jpg> "title")
[Worst Case](<./sample spaces.md> "title")

View File

@@ -1 +0,0 @@
I am here, but am I alive?

View File

@@ -1,3 +0,0 @@
# Some Title
[link](./sample-md)

View File

@@ -1,4 +0,0 @@
![link special chars](../../photo-åäö.jpg)
[sample photo](../../photo%20sample.jpg)
[sample.md](./sample%20spaces.md)
[sample special syntax](<../../photo sample.jpg>)

View File

@@ -1,4 +0,0 @@
<img src="../../photo.jpg">
<img src='../../photo-two.jpg'>
<img src='does-not-exist' alt="../../photo.jpg">
<a href="./sample-no-links.md">

View File

@@ -1,13 +0,0 @@
# Markdown
lorem ipsum ![alt text here](../../photo.jpg)
- [ ] check!
- [ ] boxes!
![alt text here](../../photo-two.jpg)ipsum lorem
**strong text**
![does not exist](does_not_exist.png) lorem ipsum
**some directory**
![a directory](../..) lorem ipsum

View File

@@ -1,7 +1,7 @@
{
"manifest_version": 2,
"name": "Joplin Web Clipper [DEV]",
"version": "2.4.0",
"version": "2.3.0",
"description": "Capture and save web pages and screenshots from your browser to Joplin.",
"homepage_url": "https://joplinapp.org",
"content_security_policy": "script-src 'self'; object-src 'self'",

View File

@@ -237,7 +237,7 @@ export default class ElectronAppWrapper {
const iid = setInterval(() => {
if (this.electronApp().isReady()) {
clearInterval(iid);
resolve(null);
resolve();
}
}, 10);
});

View File

@@ -1,47 +0,0 @@
import { AppState } from './app.reducer';
import appReducer, { createAppDefaultState } from './app.reducer';
describe('app.reducer', function() {
it('DIALOG_OPEN', async () => {
const state: AppState = createAppDefaultState({}, {});
let newState = appReducer(state, {
type: 'DIALOG_OPEN',
name: 'syncWizard',
});
expect(newState.dialogs.length).toBe(1);
expect(newState.dialogs[0].name).toBe('syncWizard');
expect(() => appReducer(newState, {
type: 'DIALOG_OPEN',
name: 'syncWizard',
})).toThrow();
newState = appReducer(newState, {
type: 'DIALOG_CLOSE',
name: 'syncWizard',
});
expect(newState.dialogs.length).toBe(0);
expect(() => appReducer(newState, {
type: 'DIALOG_CLOSE',
name: 'syncWizard',
})).toThrow();
newState = appReducer(newState, {
type: 'DIALOG_OPEN',
name: 'syncWizard',
});
newState = appReducer(newState, {
type: 'DIALOG_OPEN',
name: 'setPassword',
});
expect(newState.dialogs).toEqual([{ name: 'syncWizard' }, { name: 'setPassword' }]);
});
});

View File

@@ -1,316 +0,0 @@
import produce from 'immer';
import Setting from '@joplin/lib/models/Setting';
import { defaultState, State } from '@joplin/lib/reducer';
import iterateItems from './gui/ResizableLayout/utils/iterateItems';
import { LayoutItem } from './gui/ResizableLayout/utils/types';
import validateLayout from './gui/ResizableLayout/utils/validateLayout';
export interface AppStateRoute {
type: string;
routeName: string;
props: any;
}
export enum AppStateDialogName {
SyncWizard = 'syncWizard',
MasterPassword = 'masterPassword',
}
export interface AppStateDialog {
name: AppStateDialogName;
}
export interface AppState extends State {
route: AppStateRoute;
navHistory: any[];
noteVisiblePanes: string[];
windowContentSize: any;
watchedNoteFiles: string[];
lastEditorScrollPercents: any;
devToolsVisible: boolean;
visibleDialogs: any; // empty object if no dialog is visible. Otherwise contains the list of visible dialogs.
focusedField: string;
layoutMoveMode: boolean;
startupPluginsLoaded: boolean;
// Extra reducer keys go here
watchedResources: any;
mainLayout: LayoutItem;
dialogs: AppStateDialog[];
}
export function createAppDefaultState(windowContentSize: any, resourceEditWatcherDefaultState: any): AppState {
return {
...defaultState,
route: {
type: 'NAV_GO',
routeName: 'Main',
props: {},
},
navHistory: [],
noteVisiblePanes: ['editor', 'viewer'],
windowContentSize, // bridge().windowContentSize(),
watchedNoteFiles: [],
lastEditorScrollPercents: {},
devToolsVisible: false,
visibleDialogs: {}, // empty object if no dialog is visible. Otherwise contains the list of visible dialogs.
focusedField: null,
layoutMoveMode: false,
mainLayout: null,
startupPluginsLoaded: false,
dialogs: [],
...resourceEditWatcherDefaultState,
};
}
export default function(state: AppState, action: any) {
let newState = state;
try {
switch (action.type) {
case 'NAV_BACK':
case 'NAV_GO':
{
const goingBack = action.type === 'NAV_BACK';
if (goingBack && !state.navHistory.length) break;
const currentRoute = state.route;
newState = Object.assign({}, state);
const newNavHistory = state.navHistory.slice();
if (goingBack) {
let newAction = null;
while (newNavHistory.length) {
newAction = newNavHistory.pop();
if (newAction.routeName !== state.route.routeName) break;
}
if (!newAction) break;
action = newAction;
}
if (!goingBack) newNavHistory.push(currentRoute);
newState.navHistory = newNavHistory;
newState.route = action;
}
break;
case 'STARTUP_PLUGINS_LOADED':
// When all startup plugins have loaded, we also recreate the
// main layout to ensure that it is updated in the UI. There's
// probably a cleaner way to do this, but for now that will do.
if (state.startupPluginsLoaded !== action.value) {
newState = {
...newState,
startupPluginsLoaded: action.value,
mainLayout: JSON.parse(JSON.stringify(newState.mainLayout)),
};
}
break;
case 'WINDOW_CONTENT_SIZE_SET':
newState = Object.assign({}, state);
newState.windowContentSize = action.size;
break;
case 'NOTE_VISIBLE_PANES_TOGGLE':
{
const getNextLayout = (currentLayout: any) => {
currentLayout = panes.length === 2 ? 'both' : currentLayout[0];
let paneOptions;
if (state.settings.layoutButtonSequence === Setting.LAYOUT_EDITOR_VIEWER) {
paneOptions = ['editor', 'viewer'];
} else if (state.settings.layoutButtonSequence === Setting.LAYOUT_EDITOR_SPLIT) {
paneOptions = ['editor', 'both'];
} else if (state.settings.layoutButtonSequence === Setting.LAYOUT_VIEWER_SPLIT) {
paneOptions = ['viewer', 'both'];
} else {
paneOptions = ['editor', 'viewer', 'both'];
}
const currentLayoutIndex = paneOptions.indexOf(currentLayout);
const nextLayoutIndex = currentLayoutIndex === paneOptions.length - 1 ? 0 : currentLayoutIndex + 1;
const nextLayout = paneOptions[nextLayoutIndex];
return nextLayout === 'both' ? ['editor', 'viewer'] : [nextLayout];
};
newState = Object.assign({}, state);
const panes = state.noteVisiblePanes.slice();
newState.noteVisiblePanes = getNextLayout(panes);
}
break;
case 'NOTE_VISIBLE_PANES_SET':
newState = Object.assign({}, state);
newState.noteVisiblePanes = action.panes;
break;
case 'MAIN_LAYOUT_SET':
newState = {
...state,
mainLayout: action.value,
};
break;
case 'MAIN_LAYOUT_SET_ITEM_PROP':
{
let newLayout = produce(state.mainLayout, (draftLayout: LayoutItem) => {
iterateItems(draftLayout, (_itemIndex: number, item: LayoutItem, _parent: LayoutItem) => {
if (item.key === action.itemKey) {
(item as any)[action.propName] = action.propValue;
return false;
}
return true;
});
});
if (newLayout !== state.mainLayout) newLayout = validateLayout(newLayout);
newState = {
...state,
mainLayout: newLayout,
};
}
break;
case 'NOTE_FILE_WATCHER_ADD':
if (newState.watchedNoteFiles.indexOf(action.id) < 0) {
newState = Object.assign({}, state);
const watchedNoteFiles = newState.watchedNoteFiles.slice();
watchedNoteFiles.push(action.id);
newState.watchedNoteFiles = watchedNoteFiles;
}
break;
case 'NOTE_FILE_WATCHER_REMOVE':
{
newState = Object.assign({}, state);
const idx = newState.watchedNoteFiles.indexOf(action.id);
if (idx >= 0) {
const watchedNoteFiles = newState.watchedNoteFiles.slice();
watchedNoteFiles.splice(idx, 1);
newState.watchedNoteFiles = watchedNoteFiles;
}
}
break;
case 'NOTE_FILE_WATCHER_CLEAR':
if (state.watchedNoteFiles.length) {
newState = Object.assign({}, state);
newState.watchedNoteFiles = [];
}
break;
case 'EDITOR_SCROLL_PERCENT_SET':
{
newState = Object.assign({}, state);
const newPercents = Object.assign({}, newState.lastEditorScrollPercents);
newPercents[action.noteId] = action.percent;
newState.lastEditorScrollPercents = newPercents;
}
break;
case 'NOTE_DEVTOOLS_TOGGLE':
newState = Object.assign({}, state);
newState.devToolsVisible = !newState.devToolsVisible;
break;
case 'NOTE_DEVTOOLS_SET':
newState = Object.assign({}, state);
newState.devToolsVisible = action.value;
break;
case 'VISIBLE_DIALOGS_ADD':
newState = Object.assign({}, state);
newState.visibleDialogs = Object.assign({}, newState.visibleDialogs);
newState.visibleDialogs[action.name] = true;
break;
case 'VISIBLE_DIALOGS_REMOVE':
newState = Object.assign({}, state);
newState.visibleDialogs = Object.assign({}, newState.visibleDialogs);
delete newState.visibleDialogs[action.name];
break;
case 'FOCUS_SET':
newState = Object.assign({}, state);
newState.focusedField = action.field;
break;
case 'FOCUS_CLEAR':
// A field can only clear its own state
if (action.field === state.focusedField) {
newState = Object.assign({}, state);
newState.focusedField = null;
}
break;
case 'DIALOG_OPEN':
case 'DIALOG_CLOSE':
{
let isOpen = true;
if (action.type === 'DIALOG_CLOSE') {
isOpen = false;
} else { // DIALOG_OPEN
isOpen = action.isOpen !== false;
}
newState = Object.assign({}, state);
if (isOpen) {
const newDialogs = newState.dialogs.slice();
if (newDialogs.find(d => d.name === action.name)) throw new Error(`Trying to open a dialog is already open: ${action.name}`);
newDialogs.push({
name: action.name,
});
newState.dialogs = newDialogs;
} else {
if (!newState.dialogs.find(d => d.name === action.name)) throw new Error(`Trying to close a dialog that is not open: ${action.name}`);
const newDialogs = newState.dialogs.slice().filter(d => d.name !== action.name);
newState.dialogs = newDialogs;
}
}
break;
case 'LAYOUT_MOVE_MODE_SET':
newState = {
...state,
layoutMoveMode: action.value,
};
break;
}
} catch (error) {
error.message = `In reducer: ${error.message} Action: ${JSON.stringify(action)}`;
throw error;
}
return newState;
}

View File

@@ -3,6 +3,7 @@ import CommandService from '@joplin/lib/services/CommandService';
import KeymapService from '@joplin/lib/services/KeymapService';
import PluginService, { PluginSettings } from '@joplin/lib/services/plugins/PluginService';
import resourceEditWatcherReducer, { defaultState as resourceEditWatcherDefaultState } from '@joplin/lib/services/ResourceEditWatcher/reducer';
import { defaultState, State } from '@joplin/lib/reducer';
import PluginRunner from './services/plugins/PluginRunner';
import PlatformImplementation from './services/plugins/PlatformImplementation';
import shim from '@joplin/lib/shim';
@@ -18,10 +19,13 @@ import SpellCheckerService from '@joplin/lib/services/spellChecker/SpellCheckerS
import SpellCheckerServiceDriverNative from './services/spellChecker/SpellCheckerServiceDriverNative';
import bridge from './services/bridge';
import menuCommandNames from './gui/menuCommandNames';
import { LayoutItem } from './gui/ResizableLayout/utils/types';
import stateToWhenClauseContext from './services/commands/stateToWhenClauseContext';
import ResourceService from '@joplin/lib/services/ResourceService';
import ExternalEditWatcher from '@joplin/lib/services/ExternalEditWatcher';
import appReducer, { createAppDefaultState } from './app.reducer';
import produce from 'immer';
import iterateItems from './gui/ResizableLayout/utils/iterateItems';
import validateLayout from './gui/ResizableLayout/utils/validateLayout';
const { FoldersScreenUtils } = require('@joplin/lib/folders-screen-utils.js');
import Folder from '@joplin/lib/models/Folder';
const fs = require('fs-extra');
@@ -36,38 +40,125 @@ const PluginManager = require('@joplin/lib/services/PluginManager');
import RevisionService from '@joplin/lib/services/RevisionService';
import MigrationService from '@joplin/lib/services/MigrationService';
import { loadCustomCss, injectCustomStyles } from '@joplin/lib/CssUtils';
import mainScreenCommands from './gui/MainScreen/commands/index';
import noteEditorCommands from './gui/NoteEditor/commands/index';
import noteListCommands from './gui/NoteList/commands/index';
import noteListControlsCommands from './gui/NoteListControls/commands/index';
import sidebarCommands from './gui/Sidebar/commands/index';
import appCommands from './commands/index';
import libCommands from '@joplin/lib/commands/index';
// import populateDatabase from '@joplin/lib/services/debug/populateDatabase';
const commands = mainScreenCommands
.concat(noteEditorCommands)
.concat(noteListCommands)
.concat(noteListControlsCommands)
.concat(sidebarCommands);
const commands = [
require('./gui/MainScreen/commands/editAlarm'),
require('./gui/MainScreen/commands/exportPdf'),
require('./gui/MainScreen/commands/gotoAnything'),
require('./gui/MainScreen/commands/commandPalette'),
require('./gui/MainScreen/commands/hideModalMessage'),
require('./gui/MainScreen/commands/moveToFolder'),
require('./gui/MainScreen/commands/newFolder'),
require('./gui/MainScreen/commands/newNote'),
require('./gui/MainScreen/commands/newSubFolder'),
require('./gui/MainScreen/commands/newTodo'),
require('./gui/MainScreen/commands/openFolder'),
require('./gui/MainScreen/commands/openNote'),
require('./gui/MainScreen/commands/openTag'),
require('./gui/MainScreen/commands/print'),
require('./gui/MainScreen/commands/renameFolder'),
require('./gui/MainScreen/commands/renameTag'),
require('./gui/MainScreen/commands/search'),
require('./gui/MainScreen/commands/setTags'),
require('./gui/MainScreen/commands/showModalMessage'),
require('./gui/MainScreen/commands/showNoteContentProperties'),
require('./gui/MainScreen/commands/showNoteProperties'),
require('./gui/MainScreen/commands/showPrompt'),
require('./gui/MainScreen/commands/showShareFolderDialog'),
require('./gui/MainScreen/commands/showShareNoteDialog'),
require('./gui/MainScreen/commands/showSpellCheckerMenu'),
require('./gui/MainScreen/commands/toggleEditors'),
require('./gui/MainScreen/commands/toggleLayoutMoveMode'),
require('./gui/MainScreen/commands/toggleNoteList'),
require('./gui/MainScreen/commands/toggleSideBar'),
require('./gui/MainScreen/commands/toggleVisiblePanes'),
require('./gui/NoteEditor/commands/focusElementNoteBody'),
require('./gui/NoteEditor/commands/focusElementNoteTitle'),
require('./gui/NoteEditor/commands/showLocalSearch'),
require('./gui/NoteEditor/commands/showRevisions'),
require('./gui/NoteList/commands/focusElementNoteList'),
require('./gui/NoteListControls/commands/focusSearch'),
require('./gui/Sidebar/commands/focusElementSideBar'),
];
// Commands that are not tied to any particular component.
// The runtime for these commands can be loaded when the app starts.
const globalCommands = appCommands.concat(libCommands);
const globalCommands = [
require('./commands/copyDevCommand'),
require('./commands/exportFolders'),
require('./commands/exportNotes'),
require('./commands/focusElement'),
require('./commands/openProfileDirectory'),
require('./commands/replaceMisspelling'),
require('./commands/startExternalEditing'),
require('./commands/stopExternalEditing'),
require('./commands/toggleExternalEditing'),
require('./commands/toggleSafeMode'),
require('./commands/restoreNoteRevision'),
require('@joplin/lib/commands/historyBackward'),
require('@joplin/lib/commands/historyForward'),
require('@joplin/lib/commands/synchronize'),
];
import editorCommandDeclarations from './gui/NoteEditor/editorCommandDeclarations';
import editorCommandDeclarations from './gui/NoteEditor/commands/editorCommandDeclarations';
import ShareService from '@joplin/lib/services/share/ShareService';
import checkForUpdates from './checkForUpdates';
import { AppState } from './app.reducer';
const pluginClasses = [
require('./plugins/GotoAnything').default,
];
const appDefaultState = createAppDefaultState(
bridge().windowContentSize(),
resourceEditWatcherDefaultState
);
interface AppStateRoute {
type: string;
routeName: string;
props: any;
}
export interface AppStateDialog {
name: string;
}
export interface AppState extends State {
route: AppStateRoute;
navHistory: any[];
noteVisiblePanes: string[];
windowContentSize: any;
watchedNoteFiles: string[];
lastEditorScrollPercents: any;
devToolsVisible: boolean;
visibleDialogs: any; // empty object if no dialog is visible. Otherwise contains the list of visible dialogs.
focusedField: string;
layoutMoveMode: boolean;
startupPluginsLoaded: boolean;
// Extra reducer keys go here
watchedResources: any;
mainLayout: LayoutItem;
dialogs: AppStateDialog[];
}
const appDefaultState: AppState = {
...defaultState,
route: {
type: 'NAV_GO',
routeName: 'Main',
props: {},
},
navHistory: [],
noteVisiblePanes: ['editor', 'viewer'],
windowContentSize: bridge().windowContentSize(),
watchedNoteFiles: [],
lastEditorScrollPercents: {},
devToolsVisible: false,
visibleDialogs: {}, // empty object if no dialog is visible. Otherwise contains the list of visible dialogs.
focusedField: null,
layoutMoveMode: false,
mainLayout: null,
startupPluginsLoaded: false,
dialogs: [],
...resourceEditWatcherDefaultState,
};
class Application extends BaseApplication {
@@ -84,9 +175,249 @@ class Application extends BaseApplication {
}
reducer(state: AppState = appDefaultState, action: any) {
let newState = appReducer(state, action);
let newState = state;
try {
switch (action.type) {
case 'NAV_BACK':
case 'NAV_GO':
{
const goingBack = action.type === 'NAV_BACK';
if (goingBack && !state.navHistory.length) break;
const currentRoute = state.route;
newState = Object.assign({}, state);
const newNavHistory = state.navHistory.slice();
if (goingBack) {
let newAction = null;
while (newNavHistory.length) {
newAction = newNavHistory.pop();
if (newAction.routeName !== state.route.routeName) break;
}
if (!newAction) break;
action = newAction;
}
if (!goingBack) newNavHistory.push(currentRoute);
newState.navHistory = newNavHistory;
newState.route = action;
}
break;
case 'STARTUP_PLUGINS_LOADED':
// When all startup plugins have loaded, we also recreate the
// main layout to ensure that it is updated in the UI. There's
// probably a cleaner way to do this, but for now that will do.
if (state.startupPluginsLoaded !== action.value) {
newState = {
...newState,
startupPluginsLoaded: action.value,
mainLayout: JSON.parse(JSON.stringify(newState.mainLayout)),
};
}
break;
case 'WINDOW_CONTENT_SIZE_SET':
newState = Object.assign({}, state);
newState.windowContentSize = action.size;
break;
case 'NOTE_VISIBLE_PANES_TOGGLE':
{
const getNextLayout = (currentLayout: any) => {
currentLayout = panes.length === 2 ? 'both' : currentLayout[0];
let paneOptions;
if (state.settings.layoutButtonSequence === Setting.LAYOUT_EDITOR_VIEWER) {
paneOptions = ['editor', 'viewer'];
} else if (state.settings.layoutButtonSequence === Setting.LAYOUT_EDITOR_SPLIT) {
paneOptions = ['editor', 'both'];
} else if (state.settings.layoutButtonSequence === Setting.LAYOUT_VIEWER_SPLIT) {
paneOptions = ['viewer', 'both'];
} else {
paneOptions = ['editor', 'viewer', 'both'];
}
const currentLayoutIndex = paneOptions.indexOf(currentLayout);
const nextLayoutIndex = currentLayoutIndex === paneOptions.length - 1 ? 0 : currentLayoutIndex + 1;
const nextLayout = paneOptions[nextLayoutIndex];
return nextLayout === 'both' ? ['editor', 'viewer'] : [nextLayout];
};
newState = Object.assign({}, state);
const panes = state.noteVisiblePanes.slice();
newState.noteVisiblePanes = getNextLayout(panes);
}
break;
case 'NOTE_VISIBLE_PANES_SET':
newState = Object.assign({}, state);
newState.noteVisiblePanes = action.panes;
break;
case 'MAIN_LAYOUT_SET':
newState = {
...state,
mainLayout: action.value,
};
break;
case 'MAIN_LAYOUT_SET_ITEM_PROP':
{
let newLayout = produce(state.mainLayout, (draftLayout: LayoutItem) => {
iterateItems(draftLayout, (_itemIndex: number, item: LayoutItem, _parent: LayoutItem) => {
if (item.key === action.itemKey) {
(item as any)[action.propName] = action.propValue;
return false;
}
return true;
});
});
if (newLayout !== state.mainLayout) newLayout = validateLayout(newLayout);
newState = {
...state,
mainLayout: newLayout,
};
}
break;
case 'NOTE_FILE_WATCHER_ADD':
if (newState.watchedNoteFiles.indexOf(action.id) < 0) {
newState = Object.assign({}, state);
const watchedNoteFiles = newState.watchedNoteFiles.slice();
watchedNoteFiles.push(action.id);
newState.watchedNoteFiles = watchedNoteFiles;
}
break;
case 'NOTE_FILE_WATCHER_REMOVE':
{
newState = Object.assign({}, state);
const idx = newState.watchedNoteFiles.indexOf(action.id);
if (idx >= 0) {
const watchedNoteFiles = newState.watchedNoteFiles.slice();
watchedNoteFiles.splice(idx, 1);
newState.watchedNoteFiles = watchedNoteFiles;
}
}
break;
case 'NOTE_FILE_WATCHER_CLEAR':
if (state.watchedNoteFiles.length) {
newState = Object.assign({}, state);
newState.watchedNoteFiles = [];
}
break;
case 'EDITOR_SCROLL_PERCENT_SET':
{
newState = Object.assign({}, state);
const newPercents = Object.assign({}, newState.lastEditorScrollPercents);
newPercents[action.noteId] = action.percent;
newState.lastEditorScrollPercents = newPercents;
}
break;
case 'NOTE_DEVTOOLS_TOGGLE':
newState = Object.assign({}, state);
newState.devToolsVisible = !newState.devToolsVisible;
break;
case 'NOTE_DEVTOOLS_SET':
newState = Object.assign({}, state);
newState.devToolsVisible = action.value;
break;
case 'VISIBLE_DIALOGS_ADD':
newState = Object.assign({}, state);
newState.visibleDialogs = Object.assign({}, newState.visibleDialogs);
newState.visibleDialogs[action.name] = true;
break;
case 'VISIBLE_DIALOGS_REMOVE':
newState = Object.assign({}, state);
newState.visibleDialogs = Object.assign({}, newState.visibleDialogs);
delete newState.visibleDialogs[action.name];
break;
case 'FOCUS_SET':
newState = Object.assign({}, state);
newState.focusedField = action.field;
break;
case 'FOCUS_CLEAR':
// A field can only clear its own state
if (action.field === state.focusedField) {
newState = Object.assign({}, state);
newState.focusedField = null;
}
break;
case 'DIALOG_OPEN':
{
newState = Object.assign({}, state);
const newDialogs = newState.dialogs.slice();
if (newDialogs.find(d => d.name === action.name)) throw new Error(`This dialog is already opened: ${action.name}`);
newDialogs.push({
name: action.name,
});
newState.dialogs = newDialogs;
}
break;
case 'DIALOG_CLOSE':
{
newState = Object.assign({}, state);
const newDialogs = newState.dialogs.slice().filter(d => d.name !== action.name);
newState.dialogs = newDialogs;
}
break;
case 'LAYOUT_MOVE_MODE_SET':
newState = {
...state,
layoutMoveMode: action.value,
};
break;
}
} catch (error) {
error.message = `In reducer: ${error.message} Action: ${JSON.stringify(action)}`;
throw error;
}
newState = resourceEditWatcherReducer(newState, action);
newState = super.reducer(newState, action);
return newState;
}
@@ -542,16 +873,6 @@ class Application extends BaseApplication {
// });
// }, 2000);
// setTimeout(() => {
// this.dispatch({
// type: 'NAV_GO',
// routeName: 'Config',
// props: {
// defaultSection: 'plugins',
// },
// });
// }, 2000);
return null;
}

View File

@@ -1,29 +0,0 @@
// AUTO-GENERATED using `gulp buildCommandIndex`
import * as copyDevCommand from './copyDevCommand';
import * as exportFolders from './exportFolders';
import * as exportNotes from './exportNotes';
import * as focusElement from './focusElement';
import * as openProfileDirectory from './openProfileDirectory';
import * as replaceMisspelling from './replaceMisspelling';
import * as restoreNoteRevision from './restoreNoteRevision';
import * as startExternalEditing from './startExternalEditing';
import * as stopExternalEditing from './stopExternalEditing';
import * as toggleExternalEditing from './toggleExternalEditing';
import * as toggleSafeMode from './toggleSafeMode';
const index:any[] = [
copyDevCommand,
exportFolders,
exportNotes,
focusElement,
openProfileDirectory,
replaceMisspelling,
restoreNoteRevision,
startExternalEditing,
stopExternalEditing,
toggleExternalEditing,
toggleSafeMode,
];
export default index;
// AUTO-GENERATED using `gulp buildCommandIndex`

View File

@@ -1,5 +1,5 @@
import CommandService, { CommandRuntime, CommandDeclaration, CommandContext } from '@joplin/lib/services/CommandService';
import { AppState } from '../app.reducer';
import { AppState } from '../app';
import bridge from '../services/bridge';
export const declaration: CommandDeclaration = {

View File

@@ -7,8 +7,8 @@ import { themeStyle } from '@joplin/lib/theme';
import { _ } from '@joplin/lib/locale';
import ClipperServer from '@joplin/lib/ClipperServer';
import Setting from '@joplin/lib/models/Setting';
import EncryptionService from '@joplin/lib/services/e2ee/EncryptionService';
import { AppState } from '../app.reducer';
import EncryptionService from '@joplin/lib/services/EncryptionService';
import { AppState } from '../app';
class ClipperConfigScreenComponent extends React.Component {
constructor() {

View File

@@ -133,20 +133,6 @@ const StyledDescription = styled.div`
line-height: 1.6em;
`;
const RecommendedBadge = styled.a`
font-family: ${props => props.theme.fontFamily};
color: ${props => props.theme.colorWarn};
font-size: ${props => props.theme.fontSize}px;
border: 1px solid ${props => props.theme.colorWarn};
padding: 5px;
border-radius: 50px;
opacity: 0.8;
&:hover {
opacity: 1;
}
`;
export default function(props: Props) {
const item = useMemo(() => {
return props.item ? props.item : manifestToItem(props.manifest);
@@ -158,10 +144,6 @@ export default function(props: Props) {
bridge().openExternal(manifest.homepage_url);
}, [item]);
const onRecommendedClick = useCallback(() => {
bridge().openExternal('https://github.com/joplin/plugins/blob/master/readme/recommended.md#recommended-plugins');
}, []);
// For plugins in dev mode things like enabling/disabling or
// uninstalling them doesn't make sense, as that should be done by
// adding/removing them from wherever they were loaded from.
@@ -240,18 +222,11 @@ export default function(props: Props) {
);
}
function renderRecommendedBadge() {
if (props.onToggle) return null;
if (!item.manifest._recommended) return null;
return <RecommendedBadge href="#" title={_('The Joplin team has vetted this plugin and it meets our standards for security and performance.')} onClick={onRecommendedClick}><i className="fas fa-crown"></i></RecommendedBadge>;
}
return (
<CellRoot isCompatible={props.isCompatible}>
<CellTop>
<StyledNameAndVersion mb={'5px'}><StyledName onClick={onNameClick} href="#" style={{ marginRight: 5 }}>{item.manifest.name} {item.deleted ? _('(%s)', 'Deleted') : ''}</StyledName><StyledVersion>v{item.manifest.version}</StyledVersion></StyledNameAndVersion>
{renderToggleButton()}
{renderRecommendedBadge()}
</CellTop>
<CellContent>
<StyledDescription>{item.manifest.description}</StyledDescription>

View File

@@ -299,7 +299,7 @@ export default function(props: Props) {
function renderRepoApiError() {
if (!repoApiError) return null;
return <RepoApiErrorMessage maxWidth={maxWidth} type="error">{_('Could not connect to plugin repository.')}<br/><br/>- <StyledLink href="#" onClick={() => { setFetchManifestTime(Date.now()); }}>{_('Try again')}</StyledLink><br/><br/>- <StyledLink href="#" onClick={onBrowsePlugins}>{_('Browse all plugins')}</StyledLink></RepoApiErrorMessage>;
return <RepoApiErrorMessage maxWidth={maxWidth} type="error">{_('Could not connect to plugin repository')} - <StyledLink href="#" onClick={() => { setFetchManifestTime(Date.now()); }}>{_('Try again')}</StyledLink></RepoApiErrorMessage>;
}
function renderBottomArea() {

View File

@@ -30,14 +30,6 @@ interface Props {
disabled: boolean;
}
function sortManifestResults(results: PluginManifest[]): PluginManifest[] {
return results.sort((m1, m2) => {
if (m1._recommended && !m2._recommended) return -1;
if (!m1._recommended && m2._recommended) return +1;
return m1.name.toLowerCase() < m2.name.toLowerCase() ? -1 : +1;
});
}
export default function(props: Props) {
const [searchStarted, setSearchStarted] = useState(false);
const [manifests, setManifests] = useState<PluginManifest[]>([]);
@@ -55,7 +47,7 @@ export default function(props: Props) {
setSearchResultCount(null);
} else {
const r = await props.repoApi().search(props.searchQuery);
setManifests(sortManifestResults(r));
setManifests(r);
setSearchResultCount(r.length);
}
});

View File

@@ -1,7 +1,7 @@
const React = require('react');
const { connect } = require('react-redux');
import Setting from '@joplin/lib/models/Setting';
import EncryptionService from '@joplin/lib/services/e2ee/EncryptionService';
import EncryptionService from '@joplin/lib/services/EncryptionService';
import { themeStyle } from '@joplin/lib/theme';
import { _ } from '@joplin/lib/locale';
import time from '@joplin/lib/time';
@@ -12,16 +12,8 @@ import bridge from '../services/bridge';
import shared from '@joplin/lib/components/shared/encryption-config-shared';
import { MasterKeyEntity } from '@joplin/lib/services/e2ee/types';
import { getEncryptionEnabled, masterKeyEnabled, SyncInfo } from '@joplin/lib/services/synchronizer/syncInfoUtils';
import { getDefaultMasterKey, toggleAndSetupEncryption } from '@joplin/lib/services/e2ee/utils';
import { toggleAndSetupEncryption } from '@joplin/lib/services/e2ee/utils';
import MasterKey from '@joplin/lib/models/MasterKey';
import StyledInput from './style/StyledInput';
import Button, { ButtonLevel } from './Button/Button';
import styled from 'styled-components';
const MasterPasswordInput = styled(StyledInput)`
min-width: 300px;
align-items: center;
`;
interface Props {}
@@ -53,10 +45,6 @@ class EncryptionConfigScreenComponent extends React.Component<Props> {
private renderMasterKey(mk: MasterKeyEntity, isDefault: boolean) {
const theme = themeStyle(this.props.themeId);
const onToggleEnabledClick = () => {
return shared.onToggleEnabledClick(this, mk);
};
const passwordStyle = {
color: theme.color,
backgroundColor: theme.backgroundColor,
@@ -72,23 +60,8 @@ class EncryptionConfigScreenComponent extends React.Component<Props> {
return shared.onPasswordChange(this, mk, event.target.value);
};
const renderPasswordInput = (masterKeyId: string) => {
if (this.state.masterPasswordKeys[masterKeyId] || !this.state.passwordChecks['master']) {
return (
<td style={{ ...theme.textStyle, color: theme.colorFaded, fontStyle: 'italic' }}>
({_('Master password')})
</td>
);
} else {
return (
<td style={theme.textStyle}>
<input type="password" style={passwordStyle} value={password} onChange={event => onPasswordChange(event)} />{' '}
<button style={theme.buttonStyle} onClick={() => onSaveClick()}>
{_('Save')}
</button>
</td>
);
}
const onToggleEnabledClick = () => {
return shared.onToggleEnabledClick(this, mk);
};
const password = this.state.passwords[mk.id] ? this.state.passwords[mk.id] : '';
@@ -101,7 +74,12 @@ class EncryptionConfigScreenComponent extends React.Component<Props> {
<td style={theme.textStyle}>{activeIcon}</td>
<td style={theme.textStyle}>{mk.id}<br/>{_('Source: ')}{mk.source_application}</td>
<td style={theme.textStyle}>{_('Created: ')}{time.formatMsToLocal(mk.created_time)}<br/>{_('Updated: ')}{time.formatMsToLocal(mk.updated_time)}</td>
{renderPasswordInput(mk.id)}
<td style={theme.textStyle}>
<input type="password" style={passwordStyle} value={password} onChange={event => onPasswordChange(event)} />{' '}
<button style={theme.buttonStyle} onClick={() => onSaveClick()}>
{_('Save')}
</button>
</td>
<td style={theme.textStyle}>{passwordOk}</td>
<td style={theme.textStyle}>
<button disabled={isActive || isDefault} style={theme.buttonStyle} onClick={() => onToggleEnabledClick()}>{masterKeyEnabled(mk) ? _('Disable') : _('Enable')}</button>
@@ -187,7 +165,7 @@ class EncryptionConfigScreenComponent extends React.Component<Props> {
}
const headerComp = isEnabledMasterKeys ? <h1 style={theme.h1Style}>{_('Master Keys')}</h1> : <a onClick={() => shared.toggleShowDisabledMasterKeys(this) } style={{ ...theme.urlStyle, display: 'inline-block', marginBottom: 10 }} href="#">{showTable ? _('Hide disabled master keys') : _('Show disabled master keys')}</a>;
const infoComp = isEnabledMasterKeys ? <p style={theme.textStyle}>{'Note: Only one master key is going to be used for encryption (the one marked as "active"). Any of the keys might be used for decryption, depending on how the notes or notebooks were originally encrypted.'}</p> : null;
const infoComp = isEnabledMasterKeys ? <p style={theme.textStyle}>{_('Note: Only one master key is going to be used for encryption (the one marked as "active"). Any of the keys might be used for decryption, depending on how the notes or notebooks were originally encrypted.')}</p> : null;
const tableComp = !showTable ? null : (
<table>
<tbody>
@@ -217,39 +195,6 @@ class EncryptionConfigScreenComponent extends React.Component<Props> {
return null;
}
private renderMasterPassword() {
if (!this.props.encryptionEnabled && !this.props.masterKeys.length) return null;
const theme = themeStyle(this.props.themeId);
const onMasterPasswordSave = async () => {
shared.onMasterPasswordSave(this);
if (!(await shared.masterPasswordIsValid(this, this.state.masterPasswordInput))) {
alert('Password is invalid. Please try again.');
}
};
if (this.state.passwordChecks['master']) {
return (
<div style={{ display: 'flex', flexDirection: 'row', alignItems: 'center' }}>
<span style={theme.textStyle}>{_('Master password:')}</span>&nbsp;&nbsp;
<span style={{ ...theme.textStyle, fontWeight: 'bold' }}> {_('Loaded')}</span>
</div>
);
} else {
return (
<div style={{ display: 'flex', flexDirection: 'column' }}>
<span style={theme.textStyle}> {'The master password is not set or is invalid. Please type it below:'}</span>
<div style={{ display: 'flex', flexDirection: 'row', marginTop: 10 }}>
<MasterPasswordInput placeholder={_('Enter your master password')} type="password" value={this.state.masterPasswordInput} onChange={(event: any) => shared.onMasterPasswordChange(this, event.target.value)} />{' '}
<Button ml="10px" level={ButtonLevel.Secondary} onClick={onMasterPasswordSave} title={_('Save')} />
</div>
</div>
);
}
}
render() {
const theme = themeStyle(this.props.themeId);
const masterKeys: MasterKeyEntity[] = this.props.masterKeys;
@@ -270,7 +215,7 @@ class EncryptionConfigScreenComponent extends React.Component<Props> {
const onToggleButtonClick = async () => {
const isEnabled = getEncryptionEnabled();
const masterKey = getDefaultMasterKey();
const masterKey = MasterKey.latest();
let answer = null;
if (isEnabled) {
@@ -359,7 +304,6 @@ class EncryptionConfigScreenComponent extends React.Component<Props> {
<p style={theme.textStyle}>
{_('Encryption is:')} <strong>{this.props.encryptionEnabled ? _('Enabled') : _('Disabled')}</strong>
</p>
{this.renderMasterPassword()}
{decryptedItemsInfo}
{toggleButton}
{needUpgradeSection}
@@ -385,7 +329,6 @@ const mapStateToProps = (state: State) => {
activeMasterKeyId: syncInfo.activeMasterKeyId,
shouldReencrypt: state.settings['encryption.shouldReencrypt'] >= Setting.SHOULD_REENCRYPT_YES,
notLoadedMasterKeys: state.notLoadedMasterKeys,
masterPassword: state.settings['encryption.masterPassword'],
};
};

View File

@@ -17,7 +17,7 @@ import { stateUtils } from '@joplin/lib/reducer';
import InteropServiceHelper from '../../InteropServiceHelper';
import { _ } from '@joplin/lib/locale';
import NoteListWrapper from '../NoteListWrapper/NoteListWrapper';
import { AppState } from '../../app.reducer';
import { AppState } from '../../app';
import { saveLayout, loadLayout } from '../ResizableLayout/utils/persist';
import Setting from '@joplin/lib/models/Setting';
import produce from 'immer';
@@ -29,7 +29,7 @@ import { themeStyle } from '@joplin/lib/theme';
import validateLayout from '../ResizableLayout/utils/validateLayout';
import iterateItems from '../ResizableLayout/utils/iterateItems';
import removeItem from '../ResizableLayout/utils/removeItem';
import EncryptionService from '@joplin/lib/services/e2ee/EncryptionService';
import EncryptionService from '@joplin/lib/services/EncryptionService';
import ShareFolderDialog from '../ShareFolderDialog/ShareFolderDialog';
import { ShareInvitation } from '@joplin/lib/services/share/reducer';
import ShareService from '@joplin/lib/services/share/ShareService';
@@ -37,7 +37,6 @@ import { reg } from '@joplin/lib/registry';
import removeKeylessItems from '../ResizableLayout/utils/removeKeylessItems';
import { localSyncInfoFromState } from '@joplin/lib/services/synchronizer/syncInfoUtils';
import { showMissingMasterKeyMessage } from '@joplin/lib/services/e2ee/utils';
import commands from './commands/index';
const { connect } = require('react-redux');
const { PromptDialog } = require('../PromptDialog.min.js');
@@ -111,6 +110,39 @@ const defaultLayout: LayoutItem = {
],
};
const commands = [
require('./commands/editAlarm'),
require('./commands/exportPdf'),
require('./commands/gotoAnything'),
require('./commands/commandPalette'),
require('./commands/hideModalMessage'),
require('./commands/moveToFolder'),
require('./commands/newFolder'),
require('./commands/newNote'),
require('./commands/newSubFolder'),
require('./commands/newTodo'),
require('./commands/openFolder'),
require('./commands/openNote'),
require('./commands/openTag'),
require('./commands/print'),
require('./commands/renameFolder'),
require('./commands/renameTag'),
require('./commands/search'),
require('./commands/setTags'),
require('./commands/showModalMessage'),
require('./commands/showNoteContentProperties'),
require('./commands/showNoteProperties'),
require('./commands/showPrompt'),
require('./commands/showShareFolderDialog'),
require('./commands/showShareNoteDialog'),
require('./commands/showSpellCheckerMenu'),
require('./commands/toggleEditors'),
require('./commands/toggleLayoutMoveMode'),
require('./commands/toggleNoteList'),
require('./commands/toggleSideBar'),
require('./commands/toggleVisiblePanes'),
];
class MainScreenComponent extends React.Component<Props, State> {
private waitForNotesSavedIID_: any;

View File

@@ -1,67 +0,0 @@
// AUTO-GENERATED using `gulp buildCommandIndex`
import * as commandPalette from './commandPalette';
import * as editAlarm from './editAlarm';
import * as exportPdf from './exportPdf';
import * as gotoAnything from './gotoAnything';
import * as hideModalMessage from './hideModalMessage';
import * as moveToFolder from './moveToFolder';
import * as newFolder from './newFolder';
import * as newNote from './newNote';
import * as newSubFolder from './newSubFolder';
import * as newTodo from './newTodo';
import * as openFolder from './openFolder';
import * as openNote from './openNote';
import * as openTag from './openTag';
import * as print from './print';
import * as renameFolder from './renameFolder';
import * as renameTag from './renameTag';
import * as search from './search';
import * as setTags from './setTags';
import * as showModalMessage from './showModalMessage';
import * as showNoteContentProperties from './showNoteContentProperties';
import * as showNoteProperties from './showNoteProperties';
import * as showPrompt from './showPrompt';
import * as showShareFolderDialog from './showShareFolderDialog';
import * as showShareNoteDialog from './showShareNoteDialog';
import * as showSpellCheckerMenu from './showSpellCheckerMenu';
import * as toggleEditors from './toggleEditors';
import * as toggleLayoutMoveMode from './toggleLayoutMoveMode';
import * as toggleNoteList from './toggleNoteList';
import * as toggleSideBar from './toggleSideBar';
import * as toggleVisiblePanes from './toggleVisiblePanes';
const index:any[] = [
commandPalette,
editAlarm,
exportPdf,
gotoAnything,
hideModalMessage,
moveToFolder,
newFolder,
newNote,
newSubFolder,
newTodo,
openFolder,
openNote,
openTag,
print,
renameFolder,
renameTag,
search,
setTags,
showModalMessage,
showNoteContentProperties,
showNoteProperties,
showPrompt,
showShareFolderDialog,
showShareNoteDialog,
showSpellCheckerMenu,
toggleEditors,
toggleLayoutMoveMode,
toggleNoteList,
toggleSideBar,
toggleVisiblePanes,
];
export default index;
// AUTO-GENERATED using `gulp buildCommandIndex`

View File

@@ -34,7 +34,7 @@ export const runtime = (comp: any): CommandRuntime => {
value: '',
autocomplete: startFolders,
onClose: async (answer: any) => {
if (answer) {
if (answer != null) {
for (let i = 0; i < noteIds.length; i++) {
await Note.moveToFolder(noteIds[i], answer.value);
}

View File

@@ -2,7 +2,7 @@ import { CommandContext, CommandDeclaration, CommandRuntime } from '@joplin/lib/
import { _ } from '@joplin/lib/locale';
import bridge from '../../../services/bridge';
import SpellCheckerService from '@joplin/lib/services/spellChecker/SpellCheckerService';
import { AppState } from '../../../app.reducer';
import { AppState } from '../../../app';
const Menu = bridge().Menu;

View File

@@ -1,6 +1,6 @@
import { CommandDeclaration, CommandRuntime, CommandContext } from '@joplin/lib/services/CommandService';
import { _ } from '@joplin/lib/locale';
import { AppState } from '../../../app.reducer';
import { AppState } from '../../../app';
export const declaration: CommandDeclaration = {
name: 'toggleLayoutMoveMode',

View File

@@ -2,7 +2,7 @@ import { CommandContext, CommandDeclaration, CommandRuntime } from '@joplin/lib/
import { _ } from '@joplin/lib/locale';
import setLayoutItemProps from '../../ResizableLayout/utils/setLayoutItemProps';
import layoutItemProp from '../../ResizableLayout/utils/layoutItemProp';
import { AppState } from '../../../app.reducer';
import { AppState } from '../../../app';
export const declaration: CommandDeclaration = {
name: 'toggleNoteList',

View File

@@ -2,7 +2,7 @@ import { CommandContext, CommandDeclaration, CommandRuntime } from '@joplin/lib/
import { _ } from '@joplin/lib/locale';
import setLayoutItemProps from '../../ResizableLayout/utils/setLayoutItemProps';
import layoutItemProp from '../../ResizableLayout/utils/layoutItemProp';
import { AppState } from '../../../app.reducer';
import { AppState } from '../../../app';
export const declaration: CommandDeclaration = {
name: 'toggleSideBar',

View File

@@ -1,5 +1,5 @@
import { useEffect, useState, useRef, useCallback } from 'react';
import { AppState } from '../app.reducer';
import { AppState } from '../app';
import InteropService from '@joplin/lib/services/interop/InteropService';
import { stateUtils } from '@joplin/lib/reducer';
import CommandService from '@joplin/lib/services/CommandService';

View File

@@ -381,9 +381,6 @@ function CodeMirror(props: NoteBodyEditorProps, ref: any) {
`.CodeMirror-selected {
background: #6b6b6b !important;
}` : '';
// Vim mode draws a fat cursor in the background, we don't want to add background colors
// to the inline code in this case (it would hide the cursor)
const codeBackgroundColor = Setting.value('editor.keyboardMode') !== 'vim' ? theme.codeBackgroundColor : 'inherit';
const monospaceFonts = [];
if (Setting.value('style.editor.monospaceFontFamily')) monospaceFonts.push(`"${Setting.value('style.editor.monospaceFontFamily')}"`);
monospaceFonts.push('monospace');
@@ -479,9 +476,9 @@ function CodeMirror(props: NoteBodyEditorProps, ref: any) {
}
/* Negative margins are needed to componsate for the border */
div.CodeMirror span.cm-comment.cm-jn-inline-code:not(.cm-search-marker):not(.cm-fat-cursor-mark):not(.cm-search-marker-selected):not(.CodeMirror-selectedtext) {
div.CodeMirror span.cm-comment.cm-jn-inline-code {
border: 1px solid ${theme.codeBorderColor};
background-color: ${codeBackgroundColor};
background-color: ${theme.codeBackgroundColor};
margin-left: -1px;
margin-right: -1px;
border-radius: .25em;

View File

@@ -3,7 +3,7 @@ import CommandService from '@joplin/lib/services/CommandService';
import ToolbarBase from '../../../ToolbarBase';
import { utils as pluginUtils } from '@joplin/lib/services/plugins/reducer';
import { connect } from 'react-redux';
import { AppState } from '../../../../app.reducer';
import { AppState } from '../../../../app';
import ToolbarButtonUtils, { ToolbarButtonInfo } from '@joplin/lib/services/commands/ToolbarButtonUtils';
import stateToWhenClauseContext from '../../../../services/commands/stateToWhenClauseContext';
const { buildStyle } = require('@joplin/lib/theme');

View File

@@ -20,7 +20,7 @@ import CommandService from '@joplin/lib/services/CommandService';
import ToolbarButton from '../ToolbarButton/ToolbarButton';
import Button, { ButtonLevel } from '../Button/Button';
import eventManager from '@joplin/lib/eventManager';
import { AppState } from '../../app.reducer';
import { AppState } from '../../app';
import ToolbarButtonUtils from '@joplin/lib/services/commands/ToolbarButtonUtils';
import { _ } from '@joplin/lib/locale';
import TagList from '../TagList';

View File

@@ -1,15 +0,0 @@
// AUTO-GENERATED using `gulp buildCommandIndex`
import * as focusElementNoteBody from './focusElementNoteBody';
import * as focusElementNoteTitle from './focusElementNoteTitle';
import * as showLocalSearch from './showLocalSearch';
import * as showRevisions from './showRevisions';
const index:any[] = [
focusElementNoteBody,
focusElementNoteTitle,
showLocalSearch,
showRevisions,
];
export default index;
// AUTO-GENERATED using `gulp buildCommandIndex`

View File

@@ -1,11 +1,6 @@
import { useState, useCallback } from 'react';
import Logger from '@joplin/lib/Logger';
import { SearchMarkers } from './useSearchMarkers';
const logger = Logger.create('useNoteSearchBar');
const queryMaxLength = 1000;
interface LocalSearch {
query: string;
selectedIndex: number;
@@ -29,14 +24,6 @@ export default function useNoteSearchBar() {
const [localSearch, setLocalSearch] = useState<LocalSearch>(defaultLocalSearch());
const onChange = useCallback((query: string) => {
// A query that's too long would make CodeMirror throw an exception
// which would crash the app.
// https://github.com/laurent22/joplin/issues/5380
if (query.length > queryMaxLength) {
logger.warn(`Query is longer than ${queryMaxLength} characters - it is going to be trimmed`);
query = query.substr(0, queryMaxLength);
}
setLocalSearch((prev: LocalSearch) => {
return {
query: query,

View File

@@ -1,6 +1,6 @@
import { useEffect } from 'react';
import { FormNote, ScrollOptionTypes } from './types';
import editorCommandDeclarations from '../editorCommandDeclarations';
import editorCommandDeclarations from '../commands/editorCommandDeclarations';
import CommandService, { CommandDeclaration, CommandRuntime, CommandContext } from '@joplin/lib/services/CommandService';
import time from '@joplin/lib/time';
import { reg } from '@joplin/lib/registry';

View File

@@ -1,4 +1,4 @@
import { AppState } from '../../app.reducer';
import { AppState } from '../../app';
import eventManager from '@joplin/lib/eventManager';
import NoteListUtils from '../utils/NoteListUtils';
import { _ } from '@joplin/lib/locale';

View File

@@ -1,9 +0,0 @@
// AUTO-GENERATED using `gulp buildCommandIndex`
import * as focusElementNoteList from './focusElementNoteList';
const index:any[] = [
focusElementNoteList,
];
export default index;
// AUTO-GENERATED using `gulp buildCommandIndex`

View File

@@ -1,9 +0,0 @@
// AUTO-GENERATED using `gulp buildCommandIndex`
import * as focusSearch from './focusSearch';
const index:any[] = [
focusSearch,
];
export default index;
// AUTO-GENERATED using `gulp buildCommandIndex`

View File

@@ -1,5 +1,4 @@
import app from '../app';
import { AppState, AppStateDialog } from '../app.reducer';
import app, { AppState, AppStateDialog } from '../app';
import MainScreen from './MainScreen/MainScreen';
import ConfigScreen from './ConfigScreen/ConfigScreen';
import StatusScreen from './StatusScreen/StatusScreen';
@@ -20,7 +19,6 @@ import DialogTitle from './DialogTitle';
import DialogButtonRow, { ButtonSpec, ClickEvent, ClickEventHandler } from './DialogButtonRow';
import Dialog from './Dialog';
import SyncWizardDialog from './SyncWizard/Dialog';
import StyleSheetContainer from './StyleSheets/StyleSheetContainer';
const { ImportScreen } = require('./ImportScreen.min.js');
const { ResourceScreen } = require('./ResourceScreen.js');
const { Navigator } = require('./Navigator.min.js');
@@ -209,7 +207,6 @@ class RootComponent extends React.Component<Props, any> {
return (
<StyleSheetManager disableVendorPrefixes>
<ThemeProvider theme={theme}>
<StyleSheetContainer themeId={this.props.themeId}></StyleSheetContainer>
<MenuBar/>
<GlobalStyle/>
<Navigator style={navigatorStyle} screens={screens} />

View File

@@ -16,7 +16,6 @@ import { ShareUserStatus, StateShare, StateShareUser } from '@joplin/lib/service
import { State } from '@joplin/lib/reducer';
import { connect } from 'react-redux';
import { reg } from '@joplin/lib/registry';
import useAsyncEffect, { AsyncEffectEvent } from '@joplin/lib/hooks/useAsyncEffect';
const logger = Logger.create('ShareFolderDialog');
@@ -101,6 +100,20 @@ interface RecipientDeleteEvent {
shareUserId: string;
}
interface AsyncEffectEvent {
cancelled: boolean;
}
function useAsyncEffect(effect: Function, dependencies: any[]) {
useEffect(() => {
const event = { cancelled: false };
effect(event);
return () => {
event.cancelled = true;
};
}, dependencies);
}
enum ShareState {
Idle = 0,
Synchronizing = 1,

View File

@@ -13,7 +13,7 @@ import { StateShare } from '@joplin/lib/services/share/reducer';
import { NoteEntity } from '@joplin/lib/services/database/types';
import Button from './Button/Button';
import { connect } from 'react-redux';
import { AppState } from '../app.reducer';
import { AppState } from '../app';
import { getEncryptionEnabled } from '@joplin/lib/services/synchronizer/syncInfoUtils';
const { clipboard } = require('electron');

View File

@@ -10,7 +10,7 @@ import InteropServiceHelper from '../../InteropServiceHelper';
import { _ } from '@joplin/lib/locale';
import { PluginStates, utils as pluginUtils } from '@joplin/lib/services/plugins/reducer';
import { MenuItemLocation } from '@joplin/lib/services/plugins/api/types';
import { AppState } from '../../app.reducer';
import { AppState } from '../../app';
import { ModelType } from '@joplin/lib/BaseModel';
import BaseModel from '@joplin/lib/BaseModel';
import Folder from '@joplin/lib/models/Folder';

View File

@@ -1,7 +1,7 @@
import { CommandRuntime, CommandDeclaration, CommandContext } from '@joplin/lib/services/CommandService';
import { _ } from '@joplin/lib/locale';
import layoutItemProp from '../../ResizableLayout/utils/layoutItemProp';
import { AppState } from '../../../app.reducer';
import { AppState } from '../../../app';
export const declaration: CommandDeclaration = {
name: 'focusElementSideBar',

View File

@@ -1,9 +0,0 @@
// AUTO-GENERATED using `gulp buildCommandIndex`
import * as focusElementSideBar from './focusElementSideBar';
const index:any[] = [
focusElementSideBar,
];
export default index;
// AUTO-GENERATED using `gulp buildCommandIndex`

View File

@@ -1,41 +0,0 @@
// This component is perhaps a bit of a hack but the approach should be
// reliable. It converts the current (JS) theme to CSS, and add it to the HEAD
// tag. The component itself doesn't render anything where it's located (just an
// empty invisible DIV), so it means it could be put anywhere and would have the
// same effect.
//
// It's still reliable because the lifecyle of adding the CSS and removing on
// unmout is handled properly. There should only be one such component on the
// page.
import { useEffect, useState } from 'react';
import useAsyncEffect, { AsyncEffectEvent } from '@joplin/lib/hooks/useAsyncEffect';
import themeToCss from '@joplin/lib/services/style/themeToCss';
import { themeById } from '@joplin/lib/theme';
interface Props {
themeId: any;
}
export default function(props: Props): any {
const [styleSheetContent, setStyleSheetContent] = useState('');
useAsyncEffect(async (event: AsyncEffectEvent) => {
const theme = themeById(props.themeId);
const themeCss = themeToCss(theme);
if (event.cancelled) return;
setStyleSheetContent(themeCss);
}, [props.themeId]);
useEffect(() => {
const element = document.createElement('style');
element.setAttribute('id', 'main-theme-stylesheet-container');
document.head.appendChild(element);
element.appendChild(document.createTextNode(styleSheetContent));
return () => {
document.head.removeChild(element);
};
}, [styleSheetContent]);
return <div style={{ display: 'none' }}></div>;
}

View File

@@ -1,6 +1,6 @@
import * as React from 'react';
import { useMemo } from 'react';
import { AppState } from '../app.reducer';
import { AppState } from '../app';
const { connect } = require('react-redux');
const { themeStyle } = require('@joplin/lib/theme');

View File

@@ -19,7 +19,6 @@ const tasks = {
},
tsc: require('@joplin/tools/gulp/tasks/tsc'),
updateIgnoredTypeScriptBuild: require('@joplin/tools/gulp/tasks/updateIgnoredTypeScriptBuild'),
buildCommandIndex: require('@joplin/tools/gulp/tasks/buildCommandIndex'),
};
utils.registerGulpTasks(gulp, tasks);
@@ -29,8 +28,7 @@ const buildParallel = [
'compilePackageInfo',
'copyPluginAssets',
'copyTinyMceLangs',
'updateIgnoredTypeScriptBuild',
'buildCommandIndex',
// 'updateIgnoredTypeScriptBuild',
];
gulp.task('build', gulp.parallel(...buildParallel));

View File

@@ -24,7 +24,7 @@ const Logger = require('@joplin/lib/Logger').default;
const FsDriverNode = require('@joplin/lib/fs-driver-node').default;
const shim = require('@joplin/lib/shim').default;
const { shimInit } = require('@joplin/lib/shim-init-node.js');
const EncryptionService = require('@joplin/lib/services/e2ee/EncryptionService').default;
const EncryptionService = require('@joplin/lib/services/EncryptionService').default;
const bridge = require('electron').remote.require('./bridge').default;
const { FileApiDriverLocal } = require('@joplin/lib/file-api-driver-local.js');
const React = require('react');

View File

@@ -1,12 +1,12 @@
{
"name": "@joplin/app-desktop",
"version": "2.4.4",
"version": "2.3.5",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@joplin/app-desktop",
"version": "2.4.4",
"version": "2.3.5",
"license": "MIT",
"dependencies": {
"@fortawesome/fontawesome-free": "^5.13.0",

View File

@@ -1,6 +1,6 @@
{
"name": "@joplin/app-desktop",
"version": "2.4.4",
"version": "2.3.5",
"description": "Joplin for Desktop",
"main": "main.js",
"private": true,
@@ -93,7 +93,7 @@
},
"homepage": "https://github.com/laurent22/joplin#readme",
"devDependencies": {
"@joplin/tools": "~2.4",
"@joplin/tools": "~2.3",
"@testing-library/react-hooks": "^3.4.2",
"@types/jest": "^26.0.15",
"@types/node": "^14.14.6",
@@ -122,8 +122,8 @@
},
"dependencies": {
"@fortawesome/fontawesome-free": "^5.13.0",
"@joplin/lib": "~2.4",
"@joplin/renderer": "~2.4",
"@joplin/lib": "~2.3",
"@joplin/renderer": "~2.3",
"async-mutex": "^0.1.3",
"codemirror": "^5.56.0",
"color": "^3.1.2",

View File

@@ -1,5 +1,5 @@
import * as React from 'react';
import { AppState } from '../app.reducer';
import { AppState } from '../app';
import CommandService, { SearchResult as CommandSearchResult } from '@joplin/lib/services/CommandService';
import KeymapService from '@joplin/lib/services/KeymapService';
import shim from '@joplin/lib/shim';
@@ -337,10 +337,6 @@ class Dialog extends React.PureComponent<Props, State> {
// @ts-ignore
const notesById = notes.reduce((obj, { id, body, markup_language }) => ((obj[[id]] = { id, body, markup_language }), obj), {});
// Filter out search results that are associated with non-existing notes.
// https://github.com/laurent22/joplin/issues/5417
results = results.filter(r => !!notesById[r.id]);
for (let i = 0; i < results.length; i++) {
const row = results[i];
const path = Folder.folderPathString(this.props.folders, row.parent_id);

View File

@@ -3,7 +3,7 @@
// general, any desktop component should import this file, and not the lib
// one.
import { AppState } from '../../app.reducer';
import { AppState } from '../../app';
import libStateToWhenClauseContext, { WhenClauseContextOptions } from '@joplin/lib/services/commands/stateToWhenClauseContext';
import layoutItemProp from '../../gui/ResizableLayout/utils/layoutItemProp';

View File

@@ -1,4 +1,4 @@
import { AppState } from '../../app.reducer';
import { AppState } from '../../app';
export interface DesktopCommandContext {
state: AppState;

View File

@@ -64,6 +64,28 @@ a {
opacity: 1;
}
/*
.note-list .list-item-container:hover {
background-color: rgba(0,160,255,0.1) !important;
}
*/
/*
.editor-toolbar .button:not(.disabled):hover,
.header .button:not(.disabled):hover {
background-color: rgba(0,160,255,0.1);
border: 1px solid rgba(0,160,255,0.5);
box-sizing: 'border-box';
}
.editor-toolbar .button:not(.disabled):active,
.header .button:not(.disabled):active {
background-color: rgba(0,160,255,0.2);
border: 1px solid rgba(0,160,255,0.7);
box-sizing: 'border-box';
}
*/
.editor-toolbar .button,
.header .button {
border: 1px solid rgba(0,160,255,0);
@@ -141,6 +163,11 @@ a {
to {transform: rotate(360deg);}
}
/* .joplin-tinymce .tox-editor-header {
padding-left: 88px;
padding-right: 150px;
} */
*:focus {
outline: none;
}

View File

@@ -141,8 +141,8 @@ android {
applicationId "net.cozic.joplin"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 2097649
versionName "2.4.1"
versionCode 2097648
versionName "2.3.4"
ndk {
abiFilters "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
}

View File

@@ -6,7 +6,7 @@ const { BaseScreenComponent } = require('../base-screen.js');
const { themeStyle } = require('../global-style.js');
const DialogBox = require('react-native-dialogbox').default;
const { dialogs } = require('../../utils/dialogs.js');
import EncryptionService from '@joplin/lib/services/e2ee/EncryptionService';
import EncryptionService from '@joplin/lib/services/EncryptionService';
import { _ } from '@joplin/lib/locale';
import time from '@joplin/lib/time';
import shared from '@joplin/lib/components/shared/encryption-config-shared';
@@ -116,29 +116,15 @@ class EncryptionConfigScreenComponent extends BaseScreenComponent<Props> {
inputStyle.borderBottomWidth = 1;
inputStyle.borderBottomColor = theme.dividerColor;
const renderPasswordInput = (masterKeyId: string) => {
if (this.state.masterPasswordKeys[masterKeyId] || !this.state.passwordChecks['master']) {
return (
<Text style={{ ...this.styles().normalText, color: theme.colorFaded, fontStyle: 'italic' }}>({_('Master password')})</Text>
);
} else {
return (
<View style={{ flex: 1, flexDirection: 'row', alignItems: 'center' }}>
<TextInput selectionColor={theme.textSelectionColor} keyboardAppearance={theme.keyboardAppearance} secureTextEntry={true} value={password} onChangeText={(text: string) => onPasswordChange(text)} style={inputStyle}></TextInput>
<Text style={{ fontSize: theme.fontSize, marginRight: 10, color: theme.color }}>{passwordOk}</Text>
<Button title={_('Save')} onPress={() => onSaveClick()}></Button>
</View>
);
}
};
return (
<View key={mk.id}>
<Text style={this.styles().titleText}>{_('Master Key %s', mk.id.substr(0, 6))}</Text>
<Text style={this.styles().normalText}>{_('Created: %s', time.formatMsToLocal(mk.created_time))}</Text>
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
<Text style={{ flex: 0, fontSize: theme.fontSize, marginRight: 10, color: theme.color }}>{_('Password:')}</Text>
{renderPasswordInput(mk.id)}
<TextInput selectionColor={theme.textSelectionColor} keyboardAppearance={theme.keyboardAppearance} secureTextEntry={true} value={password} onChangeText={(text: string) => onPasswordChange(text)} style={inputStyle}></TextInput>
<Text style={{ fontSize: theme.fontSize, marginRight: 10, color: theme.color }}>{passwordOk}</Text>
<Button title={_('Save')} onPress={() => onSaveClick()}></Button>
</View>
</View>
);
@@ -217,43 +203,6 @@ class EncryptionConfigScreenComponent extends BaseScreenComponent<Props> {
);
}
private renderMasterPassword() {
if (!this.props.encryptionEnabled && !this.props.masterKeys.length) return null;
const theme = themeStyle(this.props.themeId);
const onMasterPasswordSave = async () => {
shared.onMasterPasswordSave(this);
if (!(await shared.masterPasswordIsValid(this, this.state.masterPasswordInput))) {
alert('Password is invalid. Please try again.');
}
};
const inputStyle: any = { flex: 1, marginRight: 10, color: theme.color };
inputStyle.borderBottomWidth = 1;
inputStyle.borderBottomColor = theme.dividerColor;
if (this.state.passwordChecks['master']) {
return (
<View style={{ display: 'flex', flexDirection: 'row', alignItems: 'center' }}>
<Text style={{ ...this.styles().normalText, flex: 0, marginRight: 5 }}>{_('Master password:')}</Text>
<Text style={{ ...this.styles().normalText, fontWeight: 'bold' }}>{_('Loaded')}</Text>
</View>
);
} else {
return (
<View style={{ display: 'flex', flexDirection: 'column', marginTop: 10 }}>
<Text style={this.styles().normalText}>{'The master password is not set or is invalid. Please type it below:'}</Text>
<View style={{ display: 'flex', flexDirection: 'row', marginTop: 10 }}>
<TextInput selectionColor={theme.textSelectionColor} keyboardAppearance={theme.keyboardAppearance} secureTextEntry={true} value={this.state.masterPasswordInput} onChangeText={(text: string) => shared.onMasterPasswordChange(this, text)} style={inputStyle}></TextInput>
<Button onPress={onMasterPasswordSave} title={_('Save')} />
</View>
</View>
);
}
}
render() {
const theme = themeStyle(this.props.themeId);
const masterKeys = this.props.masterKeys;
@@ -340,7 +289,6 @@ class EncryptionConfigScreenComponent extends BaseScreenComponent<Props> {
<Text style={this.styles().titleText}>{_('Status')}</Text>
<Text style={this.styles().normalText}>{_('Encryption is: %s', this.props.encryptionEnabled ? _('Enabled') : _('Disabled'))}</Text>
{decryptedItemsInfo}
{this.renderMasterPassword()}
{toggleButton}
{passwordPromptComp}
{mkComps}
@@ -367,7 +315,6 @@ const EncryptionConfigScreen = connect((state: State) => {
encryptionEnabled: syncInfo.e2ee,
activeMasterKeyId: syncInfo.activeMasterKeyId,
notLoadedMasterKeys: state.notLoadedMasterKeys,
masterPassword: state.settings['encryption.masterPassword'],
};
})(EncryptionConfigScreenComponent);

View File

@@ -492,7 +492,7 @@
INFOPLIST_FILE = Joplin/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 12.4.0;
MARKETING_VERSION = 12.3.1;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
@@ -519,7 +519,7 @@
INFOPLIST_FILE = Joplin/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 12.4.0;
MARKETING_VERSION = 12.3.1;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
@@ -666,7 +666,7 @@
INFOPLIST_FILE = ShareExtension/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
MARKETING_VERSION = 12.4.0;
MARKETING_VERSION = 12.3.1;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = net.cozic.joplin.ShareExtension;
@@ -697,7 +697,7 @@
INFOPLIST_FILE = ShareExtension/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
MARKETING_VERSION = 12.4.0;
MARKETING_VERSION = 12.3.1;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = net.cozic.joplin.ShareExtension;
PRODUCT_NAME = "$(TARGET_NAME)";

View File

@@ -46,11 +46,6 @@
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
<key>api.joplincloud.local</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
<key>NSCameraUsageDescription</key>

View File

@@ -488,7 +488,7 @@ SPEC CHECKSUMS:
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
DoubleConversion: cf9b38bf0b2d048436d9a82ad2abe1404f11e7de
FBLazyVector: e686045572151edef46010a6f819ade377dfeb4b
FBReactNativeSpec: 6da2c8ff1ebe6b6cf4510fcca58c24c4d02b16fc
FBReactNativeSpec: d2f54de51f69366bd1f5c1fb9270698dce678f8d
glog: 73c2498ac6884b13ede40eda8228cb1eee9d9d62
JoplinCommonShareExtension: 270b4f8eb4e22828eeda433a04ed689fc1fd09b5
JoplinRNShareExtension: 7137e9787374e1b0797ecbef9103d1588d90e403

View File

@@ -14,7 +14,7 @@ import ResourceService from '@joplin/lib/services/ResourceService';
import KvStore from '@joplin/lib/services/KvStore';
import NoteScreen from './components/screens/Note';
import UpgradeSyncTargetScreen from './components/screens/UpgradeSyncTargetScreen';
import Setting, { Env } from '@joplin/lib/models/Setting';
import Setting from '@joplin/lib/models/Setting';
import RNFetchBlob from 'rn-fetch-blob';
import PoorManIntervals from '@joplin/lib/PoorManIntervals';
import reducer from '@joplin/lib/reducer';
@@ -97,13 +97,13 @@ SyncTargetRegistry.addClass(SyncTargetJoplinCloud);
import FsDriverRN from './utils/fs-driver-rn';
import DecryptionWorker from '@joplin/lib/services/DecryptionWorker';
import EncryptionService from '@joplin/lib/services/e2ee/EncryptionService';
import EncryptionService from '@joplin/lib/services/EncryptionService';
import MigrationService from '@joplin/lib/services/MigrationService';
import { clearSharedFilesCache } from './utils/ShareUtils';
import setIgnoreTlsErrors from './utils/TlsUtils';
import ShareService from '@joplin/lib/services/share/ShareService';
import setupNotifications from './utils/setupNotifications';
import { loadMasterKeysFromSettings, migrateMasterPassword } from '@joplin/lib/services/e2ee/utils';
import { loadMasterKeysFromSettings } from '@joplin/lib/services/e2ee/utils';
import SyncTargetNone from '../lib/SyncTargetNone';
let storeDispatch = function(_action: any) {};
@@ -474,24 +474,15 @@ async function initialize(dispatch: Function) {
if (Setting.value('env') == 'prod') {
await db.open({ name: 'joplin.sqlite' });
} else {
await db.open({ name: 'joplin-104.sqlite' });
await db.open({ name: 'joplin-101.sqlite' });
// await db.clearForTesting();
}
reg.logger().info('Database is ready.');
reg.logger().info('Loading settings...');
await loadKeychainServiceAndSettings(KeychainServiceDriverMobile);
await migrateMasterPassword();
if (Setting.value('env') === Env.Dev) {
// Setting.setValue('sync.10.path', 'https://api.joplincloud.com');
// Setting.setValue('sync.10.userContentPath', 'https://joplinusercontent.com');
Setting.setValue('sync.10.path', 'http://api.joplincloud.local:22300');
Setting.setValue('sync.10.userContentPath', 'http://joplinusercontent.local:22300');
}
if (!Setting.value('clientId')) Setting.setValue('clientId', uuid.create());
@@ -539,6 +530,7 @@ async function initialize(dispatch: Function) {
// ----------------------------------------------------------------
EncryptionService.fsDriver_ = fsDriver;
EncryptionService.instance().setLogger(mainLogger);
// eslint-disable-next-line require-atomic-updates
BaseItem.encryptionService_ = EncryptionService.instance();
BaseItem.shareService_ = ShareService.instance();
@@ -642,7 +634,7 @@ async function initialize(dispatch: Function) {
class AppComponent extends React.Component {
public constructor() {
constructor() {
super();
this.state = {
@@ -685,7 +677,7 @@ class AppComponent extends React.Component {
// https://github.com/laurent22/joplin/issues/3807
// https://discourse.joplinapp.org/t/webdav-config-encryption-config-randomly-lost-on-android/11364
// https://discourse.joplinapp.org/t/android-keeps-on-resetting-my-sync-and-theme/11443
public async componentDidMount() {
async componentDidMount() {
if (this.props.appState == 'starting') {
this.props.dispatch({
type: 'APP_STATE_SET',
@@ -733,18 +725,15 @@ class AppComponent extends React.Component {
setupQuickActions(this.props.dispatch, this.props.selectedFolderId);
await setupNotifications(this.props.dispatch);
// Setting.setValue('encryption.masterPassword', 'WRONG');
// setTimeout(() => NavService.go('EncryptionConfig'), 2000);
}
public componentWillUnmount() {
componentWillUnmount() {
AppState.removeEventListener('change', this.onAppStateChange_);
Linking.removeEventListener('url', this.handleOpenURL_);
if (this.unsubscribeNetInfoHandler_) this.unsubscribeNetInfoHandler_();
}
public componentDidUpdate(prevProps: any) {
componentDidUpdate(prevProps: any) {
if (this.props.showSideMenu !== prevProps.showSideMenu) {
Animated.timing(this.state.sideMenuContentOpacity, {
toValue: this.props.showSideMenu ? 0.5 : 0,
@@ -753,7 +742,7 @@ class AppComponent extends React.Component {
}
}
private async backButtonHandler() {
async backButtonHandler() {
if (this.props.noteSelectionEnabled) {
this.props.dispatch({ type: 'NOTE_SELECTION_END' });
return true;
@@ -774,7 +763,7 @@ class AppComponent extends React.Component {
return false;
}
private async handleShareData() {
async handleShareData() {
const sharedData = await ShareExtension.data();
if (sharedData) {
reg.logger().info('Received shared data');
@@ -786,14 +775,14 @@ class AppComponent extends React.Component {
}
}
public UNSAFE_componentWillReceiveProps(newProps: any) {
UNSAFE_componentWillReceiveProps(newProps: any) {
if (newProps.syncStarted != this.lastSyncStarted_) {
if (!newProps.syncStarted) FoldersScreenUtils.refreshFolders();
this.lastSyncStarted_ = newProps.syncStarted;
}
}
private sideMenu_change(isOpen: boolean) {
sideMenu_change(isOpen: boolean) {
// Make sure showSideMenu property of state is updated
// when the menu is open/closed.
this.props.dispatch({
@@ -801,7 +790,7 @@ class AppComponent extends React.Component {
});
}
public render() {
render() {
if (this.props.appState != 'ready') return null;
const theme = themeStyle(this.props.themeId);

View File

@@ -1,6 +1,6 @@
{
"name": "@joplin/fork-htmlparser2",
"version": "4.1.34",
"version": "4.1.33",
"lockfileVersion": 2,
"requires": true,
"packages": {

View File

@@ -1,7 +1,7 @@
{
"name": "@joplin/fork-htmlparser2",
"description": "Fast & forgiving HTML/XML/RSS parser",
"version": "4.1.34",
"version": "4.1.33",
"author": "Felix Boehm <me@feedic.com>",
"publishConfig": {
"access": "public"

View File

@@ -1,6 +1,6 @@
{
"name": "@joplin/fork-sax",
"version": "1.2.38",
"version": "1.2.37",
"lockfileVersion": 2,
"requires": true,
"packages": {

View File

@@ -2,7 +2,7 @@
"name": "@joplin/fork-sax",
"description": "An evented streaming XML parser in JavaScript",
"author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/)",
"version": "1.2.38",
"version": "1.2.37",
"main": "lib/sax.js",
"publishConfig": {
"access": "public"

View File

@@ -1,7 +1,7 @@
{
"manifest_version": 1,
"id": "<%= pluginId %>",
"app_min_version": "2.4",
"app_min_version": "2.3",
"version": "1.0.0",
"name": "<%= pluginName %>",
"description": "<%= pluginDescription %>",

View File

@@ -1,6 +1,6 @@
{
"name": "generator-joplin",
"version": "2.4.0",
"version": "2.3.0",
"description": "Scaffolds out a new Joplin plugin",
"homepage": "https://github.com/laurent22/joplin/tree/dev/packages/generator-joplin",
"author": {

View File

@@ -36,14 +36,14 @@ const SyncTargetNextcloud = require('./SyncTargetNextcloud.js');
const SyncTargetWebDAV = require('./SyncTargetWebDAV.js');
const SyncTargetDropbox = require('./SyncTargetDropbox.js');
const SyncTargetAmazonS3 = require('./SyncTargetAmazonS3.js');
import EncryptionService from './services/e2ee/EncryptionService';
import EncryptionService from './services/EncryptionService';
import ResourceFetcher from './services/ResourceFetcher';
import SearchEngineUtils from './services/searchengine/SearchEngineUtils';
import SearchEngine from './services/searchengine/SearchEngine';
import RevisionService from './services/RevisionService';
import ResourceService from './services/ResourceService';
import DecryptionWorker from './services/DecryptionWorker';
import { loadKeychainServiceAndSettings } from './services/SettingUtils';
const { loadKeychainServiceAndSettings } = require('./services/SettingUtils');
import MigrationService from './services/MigrationService';
import ShareService from './services/share/ShareService';
import handleSyncStartupOperation from './services/synchronizer/utils/handleSyncStartupOperation';
@@ -51,7 +51,7 @@ import SyncTargetJoplinCloud from './SyncTargetJoplinCloud';
const { toSystemSlashes } = require('./path-utils');
const { setAutoFreeze } = require('immer');
import { getEncryptionEnabled } from './services/synchronizer/syncInfoUtils';
import { loadMasterKeysFromSettings, migrateMasterPassword } from './services/e2ee/utils';
import { loadMasterKeysFromSettings } from './services/e2ee/utils';
import SyncTargetNone from './SyncTargetNone';
const appLogger: LoggerWrapper = Logger.create('App');
@@ -465,7 +465,6 @@ export default class BaseApplication {
sideEffects['timeFormat'] = sideEffects['dateFormat'];
sideEffects['locale'] = sideEffects['dateFormat'];
sideEffects['encryption.passwordCache'] = sideEffects['syncInfoCache'];
sideEffects['encryption.masterPassword'] = sideEffects['syncInfoCache'];
if (action) {
const effect = sideEffects[action.key];
@@ -769,7 +768,6 @@ export default class BaseApplication {
BaseModel.setDb(this.database_);
await loadKeychainServiceAndSettings(options.keychainEnabled ? KeychainServiceDriver : KeychainServiceDriverDummy);
await migrateMasterPassword();
await handleSyncStartupOperation();
appLogger.info(`Client ID: ${Setting.value('clientId')}`);
@@ -827,6 +825,7 @@ export default class BaseApplication {
KvStore.instance().setDb(reg.db());
EncryptionService.instance().setLogger(globalLogger);
BaseItem.encryptionService_ = EncryptionService.instance();
BaseItem.shareService_ = ShareService.instance();
DecryptionWorker.instance().setLogger(globalLogger);

View File

@@ -1,6 +1,6 @@
import Logger from './Logger';
import Synchronizer from './Synchronizer';
import EncryptionService from './services/e2ee/EncryptionService';
import EncryptionService from './services/EncryptionService';
import shim from './shim';
import ResourceService from './services/ResourceService';
import ShareService from './services/share/ShareService';

Some files were not shown because too many files have changed in this diff Show More