diff --git a/.eslintignore b/.eslintignore
index 3f9c753e354..945f3ce5fb8 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -291,6 +291,7 @@ packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/shouldPasteResources.
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/shouldPasteResources.js
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/types.js
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/useContextMenu.js
+packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/useLinkTooltips.js
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/useScroll.js
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/useWebViewApi.js
packages/app-desktop/gui/NoteEditor/NoteEditor.js
@@ -455,6 +456,8 @@ packages/app-desktop/integration-tests/models/MainScreen.js
packages/app-desktop/integration-tests/models/NoteEditorScreen.js
packages/app-desktop/integration-tests/models/SettingsScreen.js
packages/app-desktop/integration-tests/models/Sidebar.js
+packages/app-desktop/integration-tests/noteList.spec.js
+packages/app-desktop/integration-tests/richTextEditor.spec.js
packages/app-desktop/integration-tests/sidebar.spec.js
packages/app-desktop/integration-tests/simpleBackup.spec.js
packages/app-desktop/integration-tests/util/activateMainMenuItem.js
@@ -463,6 +466,7 @@ packages/app-desktop/integration-tests/util/firstNonDevToolsWindow.js
packages/app-desktop/integration-tests/util/setFilePickerResponse.js
packages/app-desktop/integration-tests/util/setMessageBoxResponse.js
packages/app-desktop/integration-tests/util/test.js
+packages/app-desktop/integration-tests/util/waitForNextOpenPath.js
packages/app-desktop/playwright.config.js
packages/app-desktop/plugins/GotoAnything.js
packages/app-desktop/services/bridge.js
@@ -503,22 +507,28 @@ packages/app-desktop/utils/restartInSafeModeFromMain.test.js
packages/app-desktop/utils/restartInSafeModeFromMain.js
packages/app-mobile/PluginAssetsLoader.js
packages/app-mobile/commands/index.js
+packages/app-mobile/commands/newNote.test.js
+packages/app-mobile/commands/newNote.js
packages/app-mobile/commands/openItem.js
packages/app-mobile/commands/openNote.js
packages/app-mobile/commands/scrollToHash.js
packages/app-mobile/commands/util/goToNote.js
packages/app-mobile/components/ActionButton.js
packages/app-mobile/components/BackButtonDialogBox.js
+packages/app-mobile/components/BetaChip.js
packages/app-mobile/components/CameraView.js
-packages/app-mobile/components/CustomButton.js
packages/app-mobile/components/DismissibleDialog.js
packages/app-mobile/components/Dropdown.test.js
packages/app-mobile/components/Dropdown.js
-packages/app-mobile/components/ExtendedWebView.js
+packages/app-mobile/components/ExtendedWebView/index.jest.js
+packages/app-mobile/components/ExtendedWebView/index.js
+packages/app-mobile/components/ExtendedWebView/types.js
packages/app-mobile/components/FolderPicker.js
packages/app-mobile/components/Icon.js
+packages/app-mobile/components/IconButton.js
packages/app-mobile/components/Modal.js
packages/app-mobile/components/ModalDialog.js
+packages/app-mobile/components/NoteBodyViewer/NoteBodyViewer.test.js
packages/app-mobile/components/NoteBodyViewer/NoteBodyViewer.js
packages/app-mobile/components/NoteBodyViewer/bundledJs/Renderer.test.js
packages/app-mobile/components/NoteBodyViewer/bundledJs/Renderer.js
@@ -584,11 +594,35 @@ packages/app-mobile/components/base-screen.js
packages/app-mobile/components/biometrics/BiometricPopup.js
packages/app-mobile/components/biometrics/biometricAuthenticate.js
packages/app-mobile/components/biometrics/sensorInfo.js
+packages/app-mobile/components/buttons/TextButton.js
+packages/app-mobile/components/buttons/index.js
packages/app-mobile/components/getResponsiveValue.test.js
packages/app-mobile/components/getResponsiveValue.js
packages/app-mobile/components/global-style.js
+packages/app-mobile/components/plugins/PluginRunner.js
+packages/app-mobile/components/plugins/PluginRunnerWebView.js
+packages/app-mobile/components/plugins/backgroundPage/initializeDialogWebView.js
+packages/app-mobile/components/plugins/backgroundPage/initializePluginBackgroundIframe.js
+packages/app-mobile/components/plugins/backgroundPage/pluginRunnerBackgroundPage.js
+packages/app-mobile/components/plugins/backgroundPage/startStopPlugin.js
+packages/app-mobile/components/plugins/backgroundPage/utils/getFormData.test.js
+packages/app-mobile/components/plugins/backgroundPage/utils/getFormData.js
+packages/app-mobile/components/plugins/backgroundPage/utils/makeSandboxedIframe.js
+packages/app-mobile/components/plugins/backgroundPage/utils/reportUnhandledErrors.js
+packages/app-mobile/components/plugins/backgroundPage/utils/wrapConsoleLog.js
+packages/app-mobile/components/plugins/dialogs/PluginDialogManager.js
+packages/app-mobile/components/plugins/dialogs/PluginDialogWebView.js
+packages/app-mobile/components/plugins/dialogs/PluginPanelViewer.js
+packages/app-mobile/components/plugins/dialogs/PluginUserWebView.js
+packages/app-mobile/components/plugins/dialogs/hooks/useDialogMessenger.js
+packages/app-mobile/components/plugins/dialogs/hooks/useDialogSize.js
+packages/app-mobile/components/plugins/dialogs/hooks/useViewInfos.js
+packages/app-mobile/components/plugins/dialogs/hooks/useWebViewSetup.js
+packages/app-mobile/components/plugins/types.js
+packages/app-mobile/components/plugins/utils/createOnLogHandler.js
packages/app-mobile/components/screens/ConfigScreen/ConfigScreen.js
packages/app-mobile/components/screens/ConfigScreen/FileSystemPathSelector.js
+packages/app-mobile/components/screens/ConfigScreen/JoplinCloudConfig.js
packages/app-mobile/components/screens/ConfigScreen/NoteExportSection/ExportDebugReportButton.js
packages/app-mobile/components/screens/ConfigScreen/NoteExportSection/ExportProfileButton.js
packages/app-mobile/components/screens/ConfigScreen/NoteExportSection/NoteExportButton.test.js
@@ -601,26 +635,38 @@ packages/app-mobile/components/screens/ConfigScreen/NoteExportSection/utils/expo
packages/app-mobile/components/screens/ConfigScreen/NoteExportSection/utils/makeImportExportCacheDirectory.js
packages/app-mobile/components/screens/ConfigScreen/SectionDescription.js
packages/app-mobile/components/screens/ConfigScreen/SectionHeader.js
-packages/app-mobile/components/screens/ConfigScreen/SectionSelector.js
+packages/app-mobile/components/screens/ConfigScreen/SectionSelector/SectionTab.js
+packages/app-mobile/components/screens/ConfigScreen/SectionSelector/index.js
packages/app-mobile/components/screens/ConfigScreen/SettingComponent.js
packages/app-mobile/components/screens/ConfigScreen/SettingItem.js
packages/app-mobile/components/screens/ConfigScreen/SettingsButton.js
packages/app-mobile/components/screens/ConfigScreen/SettingsToggle.js
packages/app-mobile/components/screens/ConfigScreen/configScreenStyles.js
packages/app-mobile/components/screens/ConfigScreen/plugins/EnablePluginSupportPage.js
-packages/app-mobile/components/screens/ConfigScreen/plugins/PluginBox/ActionButton.js
-packages/app-mobile/components/screens/ConfigScreen/plugins/PluginBox/PluginInfoButton.js
+packages/app-mobile/components/screens/ConfigScreen/plugins/InstalledPluginBox.js
+packages/app-mobile/components/screens/ConfigScreen/plugins/PluginBox/PluginChip.js
+packages/app-mobile/components/screens/ConfigScreen/plugins/PluginBox/PluginChips.js
+packages/app-mobile/components/screens/ConfigScreen/plugins/PluginBox/PluginTitle.js
+packages/app-mobile/components/screens/ConfigScreen/plugins/PluginBox/RecommendedBadge.js
packages/app-mobile/components/screens/ConfigScreen/plugins/PluginBox/index.js
-packages/app-mobile/components/screens/ConfigScreen/plugins/PluginStates.test.js
+packages/app-mobile/components/screens/ConfigScreen/plugins/PluginInfoModal.js
+packages/app-mobile/components/screens/ConfigScreen/plugins/PluginStates.installed.test.js
+packages/app-mobile/components/screens/ConfigScreen/plugins/PluginStates.search.test.js
packages/app-mobile/components/screens/ConfigScreen/plugins/PluginStates.js
-packages/app-mobile/components/screens/ConfigScreen/plugins/PluginToggle.js
packages/app-mobile/components/screens/ConfigScreen/plugins/PluginUploadButton.js
-packages/app-mobile/components/screens/ConfigScreen/plugins/SearchPlugins.test.js
packages/app-mobile/components/screens/ConfigScreen/plugins/SearchPlugins.js
+packages/app-mobile/components/screens/ConfigScreen/plugins/SectionLabel.js
+packages/app-mobile/components/screens/ConfigScreen/plugins/buttons/ActionButton.js
+packages/app-mobile/components/screens/ConfigScreen/plugins/buttons/InstallButton.js
+packages/app-mobile/components/screens/ConfigScreen/plugins/testUtils/WrappedPluginStates.js
+packages/app-mobile/components/screens/ConfigScreen/plugins/testUtils/mockRepositoryApiConstructor.js
packages/app-mobile/components/screens/ConfigScreen/plugins/testUtils/newRepoApi.js
packages/app-mobile/components/screens/ConfigScreen/plugins/testUtils/pluginServiceSetup.js
packages/app-mobile/components/screens/ConfigScreen/plugins/utils/openWebsiteForPlugin.js
+packages/app-mobile/components/screens/ConfigScreen/plugins/utils/usePluginCallbacks.js
+packages/app-mobile/components/screens/ConfigScreen/plugins/utils/usePluginItem.js
packages/app-mobile/components/screens/ConfigScreen/plugins/utils/useRepoApi.js
+packages/app-mobile/components/screens/ConfigScreen/plugins/utils/useUpdateState.js
packages/app-mobile/components/screens/ConfigScreen/types.js
packages/app-mobile/components/screens/JoplinCloudLoginScreen.js
packages/app-mobile/components/screens/LogScreen.js
@@ -638,34 +684,11 @@ packages/app-mobile/components/screens/status.js
packages/app-mobile/components/side-menu-content.js
packages/app-mobile/components/voiceTyping/VoiceTypingDialog.js
packages/app-mobile/gulpfile.js
-packages/app-mobile/plugins/PlatformImplementation.js
-packages/app-mobile/plugins/PluginRunner/PluginRunner.js
-packages/app-mobile/plugins/PluginRunner/PluginRunnerWebView.js
-packages/app-mobile/plugins/PluginRunner/backgroundPage/initializeDialogWebView.js
-packages/app-mobile/plugins/PluginRunner/backgroundPage/initializePluginBackgroundIframe.js
-packages/app-mobile/plugins/PluginRunner/backgroundPage/pluginRunnerBackgroundPage.js
-packages/app-mobile/plugins/PluginRunner/backgroundPage/startStopPlugin.js
-packages/app-mobile/plugins/PluginRunner/backgroundPage/utils/getFormData.test.js
-packages/app-mobile/plugins/PluginRunner/backgroundPage/utils/getFormData.js
-packages/app-mobile/plugins/PluginRunner/backgroundPage/utils/makeSandboxedIframe.js
-packages/app-mobile/plugins/PluginRunner/backgroundPage/utils/reportUnhandledErrors.js
-packages/app-mobile/plugins/PluginRunner/backgroundPage/utils/wrapConsoleLog.js
-packages/app-mobile/plugins/PluginRunner/dialogs/PluginDialogManager.js
-packages/app-mobile/plugins/PluginRunner/dialogs/PluginDialogWebView.js
-packages/app-mobile/plugins/PluginRunner/dialogs/PluginPanelViewer.js
-packages/app-mobile/plugins/PluginRunner/dialogs/PluginUserWebView.js
-packages/app-mobile/plugins/PluginRunner/dialogs/hooks/useDialogMessenger.js
-packages/app-mobile/plugins/PluginRunner/dialogs/hooks/useDialogSize.js
-packages/app-mobile/plugins/PluginRunner/dialogs/hooks/useViewInfos.js
-packages/app-mobile/plugins/PluginRunner/dialogs/hooks/useWebViewSetup.js
-packages/app-mobile/plugins/PluginRunner/types.js
-packages/app-mobile/plugins/PluginRunner/utils/createOnLogHandler.js
-packages/app-mobile/plugins/hooks/usePlugin.js
-packages/app-mobile/plugins/loadPlugins.js
packages/app-mobile/root.js
packages/app-mobile/services/AlarmServiceDriver.android.js
packages/app-mobile/services/AlarmServiceDriver.ios.js
packages/app-mobile/services/e2ee/RSA.react-native.js
+packages/app-mobile/services/plugins/PlatformImplementation.js
packages/app-mobile/services/profiles/index.js
packages/app-mobile/services/voiceTyping/vosk.android.js
packages/app-mobile/services/voiceTyping/vosk.ios.js
@@ -692,7 +715,11 @@ packages/app-mobile/utils/fs-driver/tarExtract.js
packages/app-mobile/utils/fs-driver/testUtil/createFilesFromPathRecord.js
packages/app-mobile/utils/fs-driver/testUtil/verifyDirectoryMatches.js
packages/app-mobile/utils/getPackageInfo.js
+packages/app-mobile/utils/getVersionInfoText.js
+packages/app-mobile/utils/image/getImageDimensions.js
+packages/app-mobile/utils/image/resizeImage.js
packages/app-mobile/utils/initializeCommandService.js
+packages/app-mobile/utils/injectedJs.js
packages/app-mobile/utils/ipc/RNToWebViewMessenger.js
packages/app-mobile/utils/ipc/WebViewToRNMessenger.js
packages/app-mobile/utils/pickDocument.js
@@ -700,6 +727,7 @@ packages/app-mobile/utils/polyfills/bufferPolyfill.js
packages/app-mobile/utils/polyfills/index.js
packages/app-mobile/utils/setupNotifications.js
packages/app-mobile/utils/shareHandler.js
+packages/app-mobile/utils/shim-init-react.js
packages/app-mobile/utils/showMessageBox.js
packages/app-mobile/utils/testing/createMockReduxStore.js
packages/app-mobile/utils/types.js
@@ -744,8 +772,9 @@ packages/editor/CodeMirror/markdown/markdownCommands.toggleList.test.js
packages/editor/CodeMirror/markdown/markdownCommands.js
packages/editor/CodeMirror/markdown/markdownMathParser.test.js
packages/editor/CodeMirror/markdown/markdownMathParser.js
-packages/editor/CodeMirror/markdown/markdownReformatter.test.js
-packages/editor/CodeMirror/markdown/markdownReformatter.js
+packages/editor/CodeMirror/markdown/utils/renumberSelectedLists.test.js
+packages/editor/CodeMirror/markdown/utils/renumberSelectedLists.js
+packages/editor/CodeMirror/markdown/utils/stripBlockquote.js
packages/editor/CodeMirror/pluginApi/PluginLoader.js
packages/editor/CodeMirror/pluginApi/codeMirrorRequire.js
packages/editor/CodeMirror/pluginApi/customEditorCompletion.test.js
@@ -758,8 +787,23 @@ packages/editor/CodeMirror/testUtil/loadLanguages.js
packages/editor/CodeMirror/testUtil/pressReleaseKey.js
packages/editor/CodeMirror/testUtil/typeText.js
packages/editor/CodeMirror/theme.js
-packages/editor/CodeMirror/util/isInSyntaxNode.js
-packages/editor/CodeMirror/util/setupVim.js
+packages/editor/CodeMirror/utils/formatting/RegionSpec.js
+packages/editor/CodeMirror/utils/formatting/findInlineMatch.test.js
+packages/editor/CodeMirror/utils/formatting/findInlineMatch.js
+packages/editor/CodeMirror/utils/formatting/isIndentationEquivalent.js
+packages/editor/CodeMirror/utils/formatting/tabsToSpaces.test.js
+packages/editor/CodeMirror/utils/formatting/tabsToSpaces.js
+packages/editor/CodeMirror/utils/formatting/toggleInlineFormatGlobally.js
+packages/editor/CodeMirror/utils/formatting/toggleInlineRegionSurrounded.js
+packages/editor/CodeMirror/utils/formatting/toggleInlineSelectionFormat.js
+packages/editor/CodeMirror/utils/formatting/toggleRegionFormatGlobally.test.js
+packages/editor/CodeMirror/utils/formatting/toggleRegionFormatGlobally.js
+packages/editor/CodeMirror/utils/formatting/toggleSelectedLinesStartWith.js
+packages/editor/CodeMirror/utils/formatting/types.js
+packages/editor/CodeMirror/utils/growSelectionToNode.js
+packages/editor/CodeMirror/utils/handlePasteEvent.js
+packages/editor/CodeMirror/utils/isInSyntaxNode.js
+packages/editor/CodeMirror/utils/setupVim.js
packages/editor/SelectionFormatting.js
packages/editor/events.js
packages/editor/types.js
@@ -785,6 +829,7 @@ packages/generator-joplin/generators/app/templates/src/index.js
packages/generator-joplin/tools/updateCategories.js
packages/htmlpack/src/index.js
packages/lib/ArrayUtils.js
+packages/lib/AsyncActionQueue.test.js
packages/lib/AsyncActionQueue.js
packages/lib/BaseApplication.js
packages/lib/BaseModel.js
@@ -857,6 +902,7 @@ packages/lib/geolocation-node.js
packages/lib/hooks/useAsyncEffect.js
packages/lib/hooks/useElementSize.js
packages/lib/hooks/useEventListener.js
+packages/lib/hooks/usePlugin.js
packages/lib/hooks/usePrevious.js
packages/lib/htmlUtils.test.js
packages/lib/htmlUtils.js
@@ -874,6 +920,7 @@ packages/lib/markdownUtils.js
packages/lib/markdownUtils2.test.js
packages/lib/markupLanguageUtils.js
packages/lib/migrations/42.js
+packages/lib/mime-utils.js
packages/lib/models/Alarm.js
packages/lib/models/BaseItem.test.js
packages/lib/models/BaseItem.js
@@ -902,8 +949,10 @@ packages/lib/models/Tag.test.js
packages/lib/models/Tag.js
packages/lib/models/dateTimeFormats.test.js
packages/lib/models/settings/FileHandler.js
+packages/lib/models/settings/builtInMetadata.js
packages/lib/models/settings/settingValidations.test.js
packages/lib/models/settings/settingValidations.js
+packages/lib/models/settings/types.js
packages/lib/models/utils/getCollator.js
packages/lib/models/utils/getConflictFolderId.js
packages/lib/models/utils/isItemId.js
@@ -923,6 +972,7 @@ packages/lib/ntp.js
packages/lib/onedrive-api.test.js
packages/lib/onedrive-api.js
packages/lib/path-utils.js
+packages/lib/reducer.test.js
packages/lib/reducer.js
packages/lib/registry.test.js
packages/lib/registry.js
@@ -1067,7 +1117,11 @@ packages/lib/services/plugins/api/noteListType.js
packages/lib/services/plugins/api/types.js
packages/lib/services/plugins/defaultPlugins/defaultPluginsUtils.js
packages/lib/services/plugins/defaultPlugins/desktopDefaultPluginsInfo.js
+packages/lib/services/plugins/loadPlugins.test.js
+packages/lib/services/plugins/loadPlugins.js
packages/lib/services/plugins/reducer.js
+packages/lib/services/plugins/testing/MockPlatformImplementation.js
+packages/lib/services/plugins/testing/MockPluginRunner.js
packages/lib/services/plugins/utils/createViewHandle.js
packages/lib/services/plugins/utils/executeSandboxCall.js
packages/lib/services/plugins/utils/getPluginIssueReportUrl.test.js
@@ -1205,10 +1259,12 @@ packages/lib/themes/solarizedLight.js
packages/lib/themes/type.js
packages/lib/time.js
packages/lib/types.js
+packages/lib/urlUtils.js
packages/lib/utils/ActionLogger.test.js
packages/lib/utils/ActionLogger.js
packages/lib/utils/credentialFiles.js
packages/lib/utils/focusHandler.js
+packages/lib/utils/frontMatter.js
packages/lib/utils/ipc/RemoteMessenger.test.js
packages/lib/utils/ipc/RemoteMessenger.js
packages/lib/utils/ipc/TestMessenger.js
@@ -1219,7 +1275,8 @@ packages/lib/utils/ipc/utils/mergeCallbacksAndSerializable.js
packages/lib/utils/ipc/utils/separateCallbacksFromSerializable.test.js
packages/lib/utils/ipc/utils/separateCallbacksFromSerializable.js
packages/lib/utils/ipc/utils/separateCallbacksFromSerializableArray.js
-packages/lib/utils/joplinCloud.js
+packages/lib/utils/joplinCloud/index.js
+packages/lib/utils/joplinCloud/types.js
packages/lib/utils/processStartFlags.js
packages/lib/utils/replaceUnsupportedCharacters.test.js
packages/lib/utils/replaceUnsupportedCharacters.js
@@ -1291,6 +1348,7 @@ packages/renderer/MdToHtml/rules/mermaid.js
packages/renderer/MdToHtml/rules/sanitize_html.js
packages/renderer/MdToHtml/rules/source_map.js
packages/renderer/MdToHtml/rules/tableHorizontallyScrollable.js
+packages/renderer/MdToHtml/rules/utils/defaultRule.js
packages/renderer/MdToHtml/setupLinkify.js
packages/renderer/MdToHtml/validateLinks.js
packages/renderer/assetsToHeaders.js
@@ -1339,6 +1397,7 @@ packages/tools/updateMarkdownDoc.js
packages/tools/utils/discourse.js
packages/tools/utils/loadSponsors.js
packages/tools/utils/translation.js
+packages/tools/validateFilenames.js
packages/tools/website/build.js
packages/tools/website/buildTranslations.js
packages/tools/website/processDocs.test.js
diff --git a/.github/workflows/automerge.yml b/.github/workflows/automerge.yml
new file mode 100644
index 00000000000..be81b143bc4
--- /dev/null
+++ b/.github/workflows/automerge.yml
@@ -0,0 +1,17 @@
+name: automerge
+on:
+ schedule:
+ - cron: '*/10 * * * *'
+jobs:
+ automerge:
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write
+ steps:
+ - id: automerge
+ name: automerge
+ uses: "pascalgn/automerge-action@v0.16.3"
+ env:
+ GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
+ MERGE_METHOD: "squash"
+ LOG: "DEBUG"
diff --git a/.github/workflows/build-android.yml b/.github/workflows/build-android.yml
index a33749fcd76..3b261f51e79 100644
--- a/.github/workflows/build-android.yml
+++ b/.github/workflows/build-android.yml
@@ -16,7 +16,7 @@ jobs:
with:
concurrent_skipping: 'same_content_newer'
- BuildAndroidDebug:
+ AssembleRelease:
needs: pre_job
if: github.repository == 'laurent22/joplin' && needs.pre_job.outputs.should_skip != 'true'
runs-on: ubuntu-latest
@@ -45,7 +45,9 @@ jobs:
- name: Install
run: yarn install
- - name: Build Android Release
+ - name: Assemble Android Release
run: |
- cd packages/app-mobile/android && ./gradlew assembleDebug
+ cd packages/app-mobile/android
+ sed -i -- 's/signingConfig signingConfigs.release/signingConfig signingConfigs.debug/' app/build.gradle
+ ./gradlew assembleRelease
\ No newline at end of file
diff --git a/.github/workflows/cla.yml b/.github/workflows/cla.yml
index 4877f57b793..dc742bc0419 100644
--- a/.github/workflows/cla.yml
+++ b/.github/workflows/cla.yml
@@ -13,7 +13,7 @@ jobs:
- name: "CLA Assistant"
if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target'
# Beta Release
- uses: contributor-assistant/github-action@v2.3.1
+ uses: contributor-assistant/github-action@v2.3.2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# the below token should have repo scope and must be manually added by you in the repository's secret
diff --git a/.gitignore b/.gitignore
index a173867befd..f948248b992 100644
--- a/.gitignore
+++ b/.gitignore
@@ -270,6 +270,7 @@ packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/shouldPasteResources.
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/shouldPasteResources.js
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/types.js
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/useContextMenu.js
+packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/useLinkTooltips.js
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/useScroll.js
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/useWebViewApi.js
packages/app-desktop/gui/NoteEditor/NoteEditor.js
@@ -434,6 +435,8 @@ packages/app-desktop/integration-tests/models/MainScreen.js
packages/app-desktop/integration-tests/models/NoteEditorScreen.js
packages/app-desktop/integration-tests/models/SettingsScreen.js
packages/app-desktop/integration-tests/models/Sidebar.js
+packages/app-desktop/integration-tests/noteList.spec.js
+packages/app-desktop/integration-tests/richTextEditor.spec.js
packages/app-desktop/integration-tests/sidebar.spec.js
packages/app-desktop/integration-tests/simpleBackup.spec.js
packages/app-desktop/integration-tests/util/activateMainMenuItem.js
@@ -442,6 +445,7 @@ packages/app-desktop/integration-tests/util/firstNonDevToolsWindow.js
packages/app-desktop/integration-tests/util/setFilePickerResponse.js
packages/app-desktop/integration-tests/util/setMessageBoxResponse.js
packages/app-desktop/integration-tests/util/test.js
+packages/app-desktop/integration-tests/util/waitForNextOpenPath.js
packages/app-desktop/playwright.config.js
packages/app-desktop/plugins/GotoAnything.js
packages/app-desktop/services/bridge.js
@@ -482,22 +486,28 @@ packages/app-desktop/utils/restartInSafeModeFromMain.test.js
packages/app-desktop/utils/restartInSafeModeFromMain.js
packages/app-mobile/PluginAssetsLoader.js
packages/app-mobile/commands/index.js
+packages/app-mobile/commands/newNote.test.js
+packages/app-mobile/commands/newNote.js
packages/app-mobile/commands/openItem.js
packages/app-mobile/commands/openNote.js
packages/app-mobile/commands/scrollToHash.js
packages/app-mobile/commands/util/goToNote.js
packages/app-mobile/components/ActionButton.js
packages/app-mobile/components/BackButtonDialogBox.js
+packages/app-mobile/components/BetaChip.js
packages/app-mobile/components/CameraView.js
-packages/app-mobile/components/CustomButton.js
packages/app-mobile/components/DismissibleDialog.js
packages/app-mobile/components/Dropdown.test.js
packages/app-mobile/components/Dropdown.js
-packages/app-mobile/components/ExtendedWebView.js
+packages/app-mobile/components/ExtendedWebView/index.jest.js
+packages/app-mobile/components/ExtendedWebView/index.js
+packages/app-mobile/components/ExtendedWebView/types.js
packages/app-mobile/components/FolderPicker.js
packages/app-mobile/components/Icon.js
+packages/app-mobile/components/IconButton.js
packages/app-mobile/components/Modal.js
packages/app-mobile/components/ModalDialog.js
+packages/app-mobile/components/NoteBodyViewer/NoteBodyViewer.test.js
packages/app-mobile/components/NoteBodyViewer/NoteBodyViewer.js
packages/app-mobile/components/NoteBodyViewer/bundledJs/Renderer.test.js
packages/app-mobile/components/NoteBodyViewer/bundledJs/Renderer.js
@@ -563,11 +573,35 @@ packages/app-mobile/components/base-screen.js
packages/app-mobile/components/biometrics/BiometricPopup.js
packages/app-mobile/components/biometrics/biometricAuthenticate.js
packages/app-mobile/components/biometrics/sensorInfo.js
+packages/app-mobile/components/buttons/TextButton.js
+packages/app-mobile/components/buttons/index.js
packages/app-mobile/components/getResponsiveValue.test.js
packages/app-mobile/components/getResponsiveValue.js
packages/app-mobile/components/global-style.js
+packages/app-mobile/components/plugins/PluginRunner.js
+packages/app-mobile/components/plugins/PluginRunnerWebView.js
+packages/app-mobile/components/plugins/backgroundPage/initializeDialogWebView.js
+packages/app-mobile/components/plugins/backgroundPage/initializePluginBackgroundIframe.js
+packages/app-mobile/components/plugins/backgroundPage/pluginRunnerBackgroundPage.js
+packages/app-mobile/components/plugins/backgroundPage/startStopPlugin.js
+packages/app-mobile/components/plugins/backgroundPage/utils/getFormData.test.js
+packages/app-mobile/components/plugins/backgroundPage/utils/getFormData.js
+packages/app-mobile/components/plugins/backgroundPage/utils/makeSandboxedIframe.js
+packages/app-mobile/components/plugins/backgroundPage/utils/reportUnhandledErrors.js
+packages/app-mobile/components/plugins/backgroundPage/utils/wrapConsoleLog.js
+packages/app-mobile/components/plugins/dialogs/PluginDialogManager.js
+packages/app-mobile/components/plugins/dialogs/PluginDialogWebView.js
+packages/app-mobile/components/plugins/dialogs/PluginPanelViewer.js
+packages/app-mobile/components/plugins/dialogs/PluginUserWebView.js
+packages/app-mobile/components/plugins/dialogs/hooks/useDialogMessenger.js
+packages/app-mobile/components/plugins/dialogs/hooks/useDialogSize.js
+packages/app-mobile/components/plugins/dialogs/hooks/useViewInfos.js
+packages/app-mobile/components/plugins/dialogs/hooks/useWebViewSetup.js
+packages/app-mobile/components/plugins/types.js
+packages/app-mobile/components/plugins/utils/createOnLogHandler.js
packages/app-mobile/components/screens/ConfigScreen/ConfigScreen.js
packages/app-mobile/components/screens/ConfigScreen/FileSystemPathSelector.js
+packages/app-mobile/components/screens/ConfigScreen/JoplinCloudConfig.js
packages/app-mobile/components/screens/ConfigScreen/NoteExportSection/ExportDebugReportButton.js
packages/app-mobile/components/screens/ConfigScreen/NoteExportSection/ExportProfileButton.js
packages/app-mobile/components/screens/ConfigScreen/NoteExportSection/NoteExportButton.test.js
@@ -580,26 +614,38 @@ packages/app-mobile/components/screens/ConfigScreen/NoteExportSection/utils/expo
packages/app-mobile/components/screens/ConfigScreen/NoteExportSection/utils/makeImportExportCacheDirectory.js
packages/app-mobile/components/screens/ConfigScreen/SectionDescription.js
packages/app-mobile/components/screens/ConfigScreen/SectionHeader.js
-packages/app-mobile/components/screens/ConfigScreen/SectionSelector.js
+packages/app-mobile/components/screens/ConfigScreen/SectionSelector/SectionTab.js
+packages/app-mobile/components/screens/ConfigScreen/SectionSelector/index.js
packages/app-mobile/components/screens/ConfigScreen/SettingComponent.js
packages/app-mobile/components/screens/ConfigScreen/SettingItem.js
packages/app-mobile/components/screens/ConfigScreen/SettingsButton.js
packages/app-mobile/components/screens/ConfigScreen/SettingsToggle.js
packages/app-mobile/components/screens/ConfigScreen/configScreenStyles.js
packages/app-mobile/components/screens/ConfigScreen/plugins/EnablePluginSupportPage.js
-packages/app-mobile/components/screens/ConfigScreen/plugins/PluginBox/ActionButton.js
-packages/app-mobile/components/screens/ConfigScreen/plugins/PluginBox/PluginInfoButton.js
+packages/app-mobile/components/screens/ConfigScreen/plugins/InstalledPluginBox.js
+packages/app-mobile/components/screens/ConfigScreen/plugins/PluginBox/PluginChip.js
+packages/app-mobile/components/screens/ConfigScreen/plugins/PluginBox/PluginChips.js
+packages/app-mobile/components/screens/ConfigScreen/plugins/PluginBox/PluginTitle.js
+packages/app-mobile/components/screens/ConfigScreen/plugins/PluginBox/RecommendedBadge.js
packages/app-mobile/components/screens/ConfigScreen/plugins/PluginBox/index.js
-packages/app-mobile/components/screens/ConfigScreen/plugins/PluginStates.test.js
+packages/app-mobile/components/screens/ConfigScreen/plugins/PluginInfoModal.js
+packages/app-mobile/components/screens/ConfigScreen/plugins/PluginStates.installed.test.js
+packages/app-mobile/components/screens/ConfigScreen/plugins/PluginStates.search.test.js
packages/app-mobile/components/screens/ConfigScreen/plugins/PluginStates.js
-packages/app-mobile/components/screens/ConfigScreen/plugins/PluginToggle.js
packages/app-mobile/components/screens/ConfigScreen/plugins/PluginUploadButton.js
-packages/app-mobile/components/screens/ConfigScreen/plugins/SearchPlugins.test.js
packages/app-mobile/components/screens/ConfigScreen/plugins/SearchPlugins.js
+packages/app-mobile/components/screens/ConfigScreen/plugins/SectionLabel.js
+packages/app-mobile/components/screens/ConfigScreen/plugins/buttons/ActionButton.js
+packages/app-mobile/components/screens/ConfigScreen/plugins/buttons/InstallButton.js
+packages/app-mobile/components/screens/ConfigScreen/plugins/testUtils/WrappedPluginStates.js
+packages/app-mobile/components/screens/ConfigScreen/plugins/testUtils/mockRepositoryApiConstructor.js
packages/app-mobile/components/screens/ConfigScreen/plugins/testUtils/newRepoApi.js
packages/app-mobile/components/screens/ConfigScreen/plugins/testUtils/pluginServiceSetup.js
packages/app-mobile/components/screens/ConfigScreen/plugins/utils/openWebsiteForPlugin.js
+packages/app-mobile/components/screens/ConfigScreen/plugins/utils/usePluginCallbacks.js
+packages/app-mobile/components/screens/ConfigScreen/plugins/utils/usePluginItem.js
packages/app-mobile/components/screens/ConfigScreen/plugins/utils/useRepoApi.js
+packages/app-mobile/components/screens/ConfigScreen/plugins/utils/useUpdateState.js
packages/app-mobile/components/screens/ConfigScreen/types.js
packages/app-mobile/components/screens/JoplinCloudLoginScreen.js
packages/app-mobile/components/screens/LogScreen.js
@@ -617,34 +663,11 @@ packages/app-mobile/components/screens/status.js
packages/app-mobile/components/side-menu-content.js
packages/app-mobile/components/voiceTyping/VoiceTypingDialog.js
packages/app-mobile/gulpfile.js
-packages/app-mobile/plugins/PlatformImplementation.js
-packages/app-mobile/plugins/PluginRunner/PluginRunner.js
-packages/app-mobile/plugins/PluginRunner/PluginRunnerWebView.js
-packages/app-mobile/plugins/PluginRunner/backgroundPage/initializeDialogWebView.js
-packages/app-mobile/plugins/PluginRunner/backgroundPage/initializePluginBackgroundIframe.js
-packages/app-mobile/plugins/PluginRunner/backgroundPage/pluginRunnerBackgroundPage.js
-packages/app-mobile/plugins/PluginRunner/backgroundPage/startStopPlugin.js
-packages/app-mobile/plugins/PluginRunner/backgroundPage/utils/getFormData.test.js
-packages/app-mobile/plugins/PluginRunner/backgroundPage/utils/getFormData.js
-packages/app-mobile/plugins/PluginRunner/backgroundPage/utils/makeSandboxedIframe.js
-packages/app-mobile/plugins/PluginRunner/backgroundPage/utils/reportUnhandledErrors.js
-packages/app-mobile/plugins/PluginRunner/backgroundPage/utils/wrapConsoleLog.js
-packages/app-mobile/plugins/PluginRunner/dialogs/PluginDialogManager.js
-packages/app-mobile/plugins/PluginRunner/dialogs/PluginDialogWebView.js
-packages/app-mobile/plugins/PluginRunner/dialogs/PluginPanelViewer.js
-packages/app-mobile/plugins/PluginRunner/dialogs/PluginUserWebView.js
-packages/app-mobile/plugins/PluginRunner/dialogs/hooks/useDialogMessenger.js
-packages/app-mobile/plugins/PluginRunner/dialogs/hooks/useDialogSize.js
-packages/app-mobile/plugins/PluginRunner/dialogs/hooks/useViewInfos.js
-packages/app-mobile/plugins/PluginRunner/dialogs/hooks/useWebViewSetup.js
-packages/app-mobile/plugins/PluginRunner/types.js
-packages/app-mobile/plugins/PluginRunner/utils/createOnLogHandler.js
-packages/app-mobile/plugins/hooks/usePlugin.js
-packages/app-mobile/plugins/loadPlugins.js
packages/app-mobile/root.js
packages/app-mobile/services/AlarmServiceDriver.android.js
packages/app-mobile/services/AlarmServiceDriver.ios.js
packages/app-mobile/services/e2ee/RSA.react-native.js
+packages/app-mobile/services/plugins/PlatformImplementation.js
packages/app-mobile/services/profiles/index.js
packages/app-mobile/services/voiceTyping/vosk.android.js
packages/app-mobile/services/voiceTyping/vosk.ios.js
@@ -671,7 +694,11 @@ packages/app-mobile/utils/fs-driver/tarExtract.js
packages/app-mobile/utils/fs-driver/testUtil/createFilesFromPathRecord.js
packages/app-mobile/utils/fs-driver/testUtil/verifyDirectoryMatches.js
packages/app-mobile/utils/getPackageInfo.js
+packages/app-mobile/utils/getVersionInfoText.js
+packages/app-mobile/utils/image/getImageDimensions.js
+packages/app-mobile/utils/image/resizeImage.js
packages/app-mobile/utils/initializeCommandService.js
+packages/app-mobile/utils/injectedJs.js
packages/app-mobile/utils/ipc/RNToWebViewMessenger.js
packages/app-mobile/utils/ipc/WebViewToRNMessenger.js
packages/app-mobile/utils/pickDocument.js
@@ -679,6 +706,7 @@ packages/app-mobile/utils/polyfills/bufferPolyfill.js
packages/app-mobile/utils/polyfills/index.js
packages/app-mobile/utils/setupNotifications.js
packages/app-mobile/utils/shareHandler.js
+packages/app-mobile/utils/shim-init-react.js
packages/app-mobile/utils/showMessageBox.js
packages/app-mobile/utils/testing/createMockReduxStore.js
packages/app-mobile/utils/types.js
@@ -723,8 +751,9 @@ packages/editor/CodeMirror/markdown/markdownCommands.toggleList.test.js
packages/editor/CodeMirror/markdown/markdownCommands.js
packages/editor/CodeMirror/markdown/markdownMathParser.test.js
packages/editor/CodeMirror/markdown/markdownMathParser.js
-packages/editor/CodeMirror/markdown/markdownReformatter.test.js
-packages/editor/CodeMirror/markdown/markdownReformatter.js
+packages/editor/CodeMirror/markdown/utils/renumberSelectedLists.test.js
+packages/editor/CodeMirror/markdown/utils/renumberSelectedLists.js
+packages/editor/CodeMirror/markdown/utils/stripBlockquote.js
packages/editor/CodeMirror/pluginApi/PluginLoader.js
packages/editor/CodeMirror/pluginApi/codeMirrorRequire.js
packages/editor/CodeMirror/pluginApi/customEditorCompletion.test.js
@@ -737,8 +766,23 @@ packages/editor/CodeMirror/testUtil/loadLanguages.js
packages/editor/CodeMirror/testUtil/pressReleaseKey.js
packages/editor/CodeMirror/testUtil/typeText.js
packages/editor/CodeMirror/theme.js
-packages/editor/CodeMirror/util/isInSyntaxNode.js
-packages/editor/CodeMirror/util/setupVim.js
+packages/editor/CodeMirror/utils/formatting/RegionSpec.js
+packages/editor/CodeMirror/utils/formatting/findInlineMatch.test.js
+packages/editor/CodeMirror/utils/formatting/findInlineMatch.js
+packages/editor/CodeMirror/utils/formatting/isIndentationEquivalent.js
+packages/editor/CodeMirror/utils/formatting/tabsToSpaces.test.js
+packages/editor/CodeMirror/utils/formatting/tabsToSpaces.js
+packages/editor/CodeMirror/utils/formatting/toggleInlineFormatGlobally.js
+packages/editor/CodeMirror/utils/formatting/toggleInlineRegionSurrounded.js
+packages/editor/CodeMirror/utils/formatting/toggleInlineSelectionFormat.js
+packages/editor/CodeMirror/utils/formatting/toggleRegionFormatGlobally.test.js
+packages/editor/CodeMirror/utils/formatting/toggleRegionFormatGlobally.js
+packages/editor/CodeMirror/utils/formatting/toggleSelectedLinesStartWith.js
+packages/editor/CodeMirror/utils/formatting/types.js
+packages/editor/CodeMirror/utils/growSelectionToNode.js
+packages/editor/CodeMirror/utils/handlePasteEvent.js
+packages/editor/CodeMirror/utils/isInSyntaxNode.js
+packages/editor/CodeMirror/utils/setupVim.js
packages/editor/SelectionFormatting.js
packages/editor/events.js
packages/editor/types.js
@@ -764,6 +808,7 @@ packages/generator-joplin/generators/app/templates/src/index.js
packages/generator-joplin/tools/updateCategories.js
packages/htmlpack/src/index.js
packages/lib/ArrayUtils.js
+packages/lib/AsyncActionQueue.test.js
packages/lib/AsyncActionQueue.js
packages/lib/BaseApplication.js
packages/lib/BaseModel.js
@@ -836,6 +881,7 @@ packages/lib/geolocation-node.js
packages/lib/hooks/useAsyncEffect.js
packages/lib/hooks/useElementSize.js
packages/lib/hooks/useEventListener.js
+packages/lib/hooks/usePlugin.js
packages/lib/hooks/usePrevious.js
packages/lib/htmlUtils.test.js
packages/lib/htmlUtils.js
@@ -853,6 +899,7 @@ packages/lib/markdownUtils.js
packages/lib/markdownUtils2.test.js
packages/lib/markupLanguageUtils.js
packages/lib/migrations/42.js
+packages/lib/mime-utils.js
packages/lib/models/Alarm.js
packages/lib/models/BaseItem.test.js
packages/lib/models/BaseItem.js
@@ -881,8 +928,10 @@ packages/lib/models/Tag.test.js
packages/lib/models/Tag.js
packages/lib/models/dateTimeFormats.test.js
packages/lib/models/settings/FileHandler.js
+packages/lib/models/settings/builtInMetadata.js
packages/lib/models/settings/settingValidations.test.js
packages/lib/models/settings/settingValidations.js
+packages/lib/models/settings/types.js
packages/lib/models/utils/getCollator.js
packages/lib/models/utils/getConflictFolderId.js
packages/lib/models/utils/isItemId.js
@@ -902,6 +951,7 @@ packages/lib/ntp.js
packages/lib/onedrive-api.test.js
packages/lib/onedrive-api.js
packages/lib/path-utils.js
+packages/lib/reducer.test.js
packages/lib/reducer.js
packages/lib/registry.test.js
packages/lib/registry.js
@@ -1046,7 +1096,11 @@ packages/lib/services/plugins/api/noteListType.js
packages/lib/services/plugins/api/types.js
packages/lib/services/plugins/defaultPlugins/defaultPluginsUtils.js
packages/lib/services/plugins/defaultPlugins/desktopDefaultPluginsInfo.js
+packages/lib/services/plugins/loadPlugins.test.js
+packages/lib/services/plugins/loadPlugins.js
packages/lib/services/plugins/reducer.js
+packages/lib/services/plugins/testing/MockPlatformImplementation.js
+packages/lib/services/plugins/testing/MockPluginRunner.js
packages/lib/services/plugins/utils/createViewHandle.js
packages/lib/services/plugins/utils/executeSandboxCall.js
packages/lib/services/plugins/utils/getPluginIssueReportUrl.test.js
@@ -1184,10 +1238,12 @@ packages/lib/themes/solarizedLight.js
packages/lib/themes/type.js
packages/lib/time.js
packages/lib/types.js
+packages/lib/urlUtils.js
packages/lib/utils/ActionLogger.test.js
packages/lib/utils/ActionLogger.js
packages/lib/utils/credentialFiles.js
packages/lib/utils/focusHandler.js
+packages/lib/utils/frontMatter.js
packages/lib/utils/ipc/RemoteMessenger.test.js
packages/lib/utils/ipc/RemoteMessenger.js
packages/lib/utils/ipc/TestMessenger.js
@@ -1198,7 +1254,8 @@ packages/lib/utils/ipc/utils/mergeCallbacksAndSerializable.js
packages/lib/utils/ipc/utils/separateCallbacksFromSerializable.test.js
packages/lib/utils/ipc/utils/separateCallbacksFromSerializable.js
packages/lib/utils/ipc/utils/separateCallbacksFromSerializableArray.js
-packages/lib/utils/joplinCloud.js
+packages/lib/utils/joplinCloud/index.js
+packages/lib/utils/joplinCloud/types.js
packages/lib/utils/processStartFlags.js
packages/lib/utils/replaceUnsupportedCharacters.test.js
packages/lib/utils/replaceUnsupportedCharacters.js
@@ -1270,6 +1327,7 @@ packages/renderer/MdToHtml/rules/mermaid.js
packages/renderer/MdToHtml/rules/sanitize_html.js
packages/renderer/MdToHtml/rules/source_map.js
packages/renderer/MdToHtml/rules/tableHorizontallyScrollable.js
+packages/renderer/MdToHtml/rules/utils/defaultRule.js
packages/renderer/MdToHtml/setupLinkify.js
packages/renderer/MdToHtml/validateLinks.js
packages/renderer/assetsToHeaders.js
@@ -1318,6 +1376,7 @@ packages/tools/updateMarkdownDoc.js
packages/tools/utils/discourse.js
packages/tools/utils/loadSponsors.js
packages/tools/utils/translation.js
+packages/tools/validateFilenames.js
packages/tools/website/build.js
packages/tools/website/buildTranslations.js
packages/tools/website/processDocs.test.js
diff --git a/.yarn/patches/rn-fetch-blob-npm-0.12.0-cf02e3c544.patch b/.yarn/patches/rn-fetch-blob-npm-0.12.0-cf02e3c544.patch
new file mode 100644
index 00000000000..01764ea8b8d
--- /dev/null
+++ b/.yarn/patches/rn-fetch-blob-npm-0.12.0-cf02e3c544.patch
@@ -0,0 +1,118 @@
+# Fixes sync issues caused by locale-sensitive lowercasing
+# of HTTP headers.
+# See https://github.com/laurent22/joplin/issues/10681
+diff --git a/android/src/main/java/com/RNFetchBlob/RNFetchBlobConfig.java b/android/src/main/java/com/RNFetchBlob/RNFetchBlobConfig.java
+index 8ac9e7a855162cefbf99024eb013c8a3b11de1ec..1c639cf9d84821b6ffc132960e2d1c044bedbd48 100644
+--- a/android/src/main/java/com/RNFetchBlob/RNFetchBlobConfig.java
++++ b/android/src/main/java/com/RNFetchBlob/RNFetchBlobConfig.java
+@@ -2,6 +2,7 @@ package com.RNFetchBlob;
+
+ import com.facebook.react.bridge.ReadableArray;
+ import com.facebook.react.bridge.ReadableMap;
++import java.util.Locale;
+
+ class RNFetchBlobConfig {
+
+@@ -33,7 +34,7 @@ class RNFetchBlobConfig {
+ }
+ if(options.hasKey("binaryContentTypes"))
+ this.binaryContentTypes = options.getArray("binaryContentTypes");
+- if(this.path != null && path.toLowerCase().contains("?append=true")) {
++ if(this.path != null && path.toLowerCase(Locale.ROOT).contains("?append=true")) {
+ this.overwrite = false;
+ }
+ if(options.hasKey("overwrite"))
+diff --git a/android/src/main/java/com/RNFetchBlob/RNFetchBlobFS.java b/android/src/main/java/com/RNFetchBlob/RNFetchBlobFS.java
+index a4d70153f41e6c14eec65412b5b59822f1c6750b..d98c439f7b0aeb79afc82ab9f653e9c021086426 100644
+--- a/android/src/main/java/com/RNFetchBlob/RNFetchBlobFS.java
++++ b/android/src/main/java/com/RNFetchBlob/RNFetchBlobFS.java
+@@ -29,6 +29,7 @@ import java.util.ArrayList;
+ import java.util.HashMap;
+ import java.util.Map;
+ import java.util.UUID;
++import java.util.Locale;
+
+ class RNFetchBlobFS {
+
+@@ -210,7 +211,7 @@ class RNFetchBlobFS {
+ return;
+ }
+
+- switch (encoding.toLowerCase()) {
++ switch (encoding.toLowerCase(Locale.ROOT)) {
+ case "base64" :
+ promise.resolve(Base64.encodeToString(bytes, Base64.NO_WRAP));
+ break;
+@@ -1050,7 +1051,7 @@ class RNFetchBlobFS {
+ if(encoding.equalsIgnoreCase("ascii")) {
+ return data.getBytes(Charset.forName("US-ASCII"));
+ }
+- else if(encoding.toLowerCase().contains("base64")) {
++ else if(encoding.toLowerCase(Locale.ROOT).contains("base64")) {
+ return Base64.decode(data, Base64.NO_WRAP);
+
+ }
+diff --git a/android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java b/android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java
+index a8abd71833879201e3438b2fa51d712a311c4551..b70cc13c004229f69157de5f82ae5ec3abf4358e 100644
+--- a/android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java
++++ b/android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java
+@@ -49,6 +49,7 @@ import java.security.KeyStore;
+ import java.util.ArrayList;
+ import java.util.Arrays;
+ import java.util.List;
++import java.util.Locale;
+ import java.util.HashMap;
+
+ import java.util.concurrent.TimeUnit;
+@@ -300,14 +301,14 @@ public class RNFetchBlobReq extends BroadcastReceiver implements Runnable {
+ responseFormat = ResponseFormat.UTF8;
+ }
+ else {
+- builder.header(key.toLowerCase(), value);
+- mheaders.put(key.toLowerCase(), value);
++ builder.header(key.toLowerCase(Locale.ROOT), value);
++ mheaders.put(key.toLowerCase(Locale.ROOT), value);
+ }
+ }
+ }
+
+ if(method.equalsIgnoreCase("post") || method.equalsIgnoreCase("put") || method.equalsIgnoreCase("patch")) {
+- String cType = getHeaderIgnoreCases(mheaders, "Content-Type").toLowerCase();
++ String cType = getHeaderIgnoreCases(mheaders, "Content-Type").toLowerCase(Locale.ROOT);
+
+ if(rawRequestBodyArray != null) {
+ requestType = RequestType.Form;
+@@ -323,7 +324,7 @@ public class RNFetchBlobReq extends BroadcastReceiver implements Runnable {
+ || rawRequestBody.startsWith(RNFetchBlobConst.CONTENT_PREFIX)) {
+ requestType = RequestType.SingleFile;
+ }
+- else if (cType.toLowerCase().contains(";base64") || cType.toLowerCase().startsWith("application/octet")) {
++ else if (cType.toLowerCase(Locale.ROOT).contains(";base64") || cType.toLowerCase(Locale.ROOT).startsWith("application/octet")) {
+ cType = cType.replace(";base64","").replace(";BASE64","");
+ if(mheaders.containsKey("content-type"))
+ mheaders.put("content-type", cType);
+@@ -686,7 +687,7 @@ public class RNFetchBlobReq extends BroadcastReceiver implements Runnable {
+ boolean isCustomBinary = false;
+ if(options.binaryContentTypes != null) {
+ for(int i = 0; i< options.binaryContentTypes.size();i++) {
+- if(ctype.toLowerCase().contains(options.binaryContentTypes.getString(i).toLowerCase())) {
++ if(ctype.toLowerCase(Locale.ROOT).contains(options.binaryContentTypes.getString(i).toLowerCase(Locale.ROOT))) {
+ isCustomBinary = true;
+ break;
+ }
+@@ -698,13 +699,13 @@ public class RNFetchBlobReq extends BroadcastReceiver implements Runnable {
+ private String getHeaderIgnoreCases(Headers headers, String field) {
+ String val = headers.get(field);
+ if(val != null) return val;
+- return headers.get(field.toLowerCase()) == null ? "" : headers.get(field.toLowerCase());
++ return headers.get(field.toLowerCase(Locale.ROOT)) == null ? "" : headers.get(field.toLowerCase(Locale.ROOT));
+ }
+
+ private String getHeaderIgnoreCases(HashMap Joplin now support a trash folder - any deleted notes or notebooks will be moved to that folder. You can also choose to have these notes permanently deleted after a number of days. Support for the trash folder has a somewhat long history in Joplin since it's an obvious and important feature to add, yet it can be particularly tricky once you start realising how many parts of the app it's going to impact. Many attempts have been made over time: my first attempt was based on the note history feature. Indeed since this feature already saves versions of notes, it seems to make sense to use it for the trash feature, and indeed the note history feature was designed for this originally. However that approach turned to be needlessly complicated and after modifying hundreds of files just for this, the idea was dropped. The next one was based on using a special "trash" tag - deleted notes would have this tag attached to them and would appear in a special "trash" folder. This approach also had many issues probably the main one being that notebooks can't be tagged, which means we would have to add support for tagged notebooks and that in itself would also be a massive change. Various, ideas, were also attempted using plugins, by creating a special "trash folder", but in the end no such plugin was ever created, probably due to limitations of the plugin API. In the end, turned out that this old idea of adding a "deleted" property to each note and notebook was the easiest approach. With this it was simpler to get to a working solution relatively quickly, and then it was a matter of ensuring that deleted notes don't appear where they shouldn't, such as search results, etc. Multi-factor authentication (MFA), also known as two-factor authentication (2FA) is a security process that requires you to provide two or more verification factors to gain access to a system or account. It typically includes something you know (password), something you have (security token), and something you are (biometric verification). To better secure your account, Joplin Cloud and all Joplin applications now support MFA. To enable it, go to your Joplin Cloud profile, click on "Enable multi-factor authentication" and follow the instructions. Please note that all your applications will then be disconnected, so you will need to login again (your data of course will remain on the app so you won't have to download it again). In this release we add support for multiple columns in the note list. You can display various properties of the notes, as well as sort the notes by these properties. As usual this feature can be controlled and customised by plugins so for example it should be possible to display custom columns, and display custom information including thumbnails. The plugin API has received several updates to facilitate easy customisation of the app As mentioned above, it is now possible to customise the new note list. Besides this, we've added support for loading PDFs and creating images from them, which can for example be used to create thumbnails. Many other small enhancements have been made to the plugin API to help you tailor the app to your needs! Now when you right-click on an image or PDF you have an option to view the OCR (Optical character recognition) data associated with it. That will allow you for example to easily copy and paste the text. As always, most of the above changes also apply to mobile (iOS and Android), for example the trash folder and MFA support. Additionally the mobile application now adds support for plugins. To enable the feature, go to the settings then to the "Plugins" section. The feature is currently in Beta, in particular it means that some plugins do not work or only partially work. Normally the app should not offer you to install a non-working plugin but that may still happen. In general if you notice any issue with this beta feature please let me us know as we're keen to improve it. Support for cross-platform plugins in Joplin is great news as it means a lot of new features become available on mobile. As of now, we have checked the following plugins and can confirm that they work on mobile: Those are just some examples - many more are working! This is just an overview of the main features. The full changelogs are available there: Optical Character Recognition (OCR) in Joplin enables the transformation of text-containing images into machine-readable text formats. From this version you can enable OCR in the Configuration screen under the "General" section. Once activated, Joplin scans images and PDFs, extracting text data for searchability. While OCR search is available on both desktop and mobile apps, document scanning is limited to the desktop due to resource demands. For more information head to the OCR official documentation!Trash folder🔗
+Joplin Cloud multi-factor authentication🔗
+Note list with multiple columns🔗
+Plugin API enhancement🔗
+View OCR data🔗
+Plugin support on mobile🔗
+
+
+Full changelogs🔗
+Bundled plugins🔗
@@ -394,7 +437,4 @@ sys 0m38.013s
When it's done, please also let us know by posting an update on your forum introduction post.
-If you haven't created a pull request yet, it's still time to create one. Doing so will greatly increase your chances of being selected!
-]]>Markdown images:
+HTML images:
+This | +is | +a | +test | +
---|---|---|---|
This | +table | +has | +line numbers | +
When mapsToLine
is enabled for this file, the table above should have line numbers that link to the original markdown.
{_('Account type')} | +{accountTypeToString(props.joplinCloudAccountType)} | +
{_('Email')} | +{props.userEmail} | +
{_('Any email sent to this address will be converted into a note and added to your collection. The note will be saved into the Inbox notebook')}
{ @@ -38,6 +63,8 @@ const mapStateToProps = (state: AppState) => { return { inboxEmail: state.settings['sync.10.inboxEmail'], joplinCloudAccountType: state.settings['sync.10.accountType'], + userEmail: state.settings['sync.10.userEmail'], + joplinCloudWebsite: state.settings['sync.10.website'], }; }; diff --git a/packages/app-desktop/gui/JoplinCloudLoginScreen.tsx b/packages/app-desktop/gui/JoplinCloudLoginScreen.tsx index 752fc8b39db..6bb79d1318d 100644 --- a/packages/app-desktop/gui/JoplinCloudLoginScreen.tsx +++ b/packages/app-desktop/gui/JoplinCloudLoginScreen.tsx @@ -1,4 +1,4 @@ -import { useEffect, useMemo, useReducer, useState } from 'react'; +import { Fragment, useEffect, useMemo, useReducer, useState } from 'react'; import ButtonBar from './ConfigScreen/ButtonBar'; import { _ } from '@joplin/lib/locale'; import { clipboard } from 'electron'; @@ -9,6 +9,7 @@ import { Dispatch } from 'redux'; import { reducer, defaultState, generateApplicationConfirmUrl, checkIfLoginWasSuccessful } from '@joplin/lib/services/joplinCloudUtils'; import { AppState } from '../app.reducer'; import Logger from '@joplin/utils/Logger'; +import { reg } from '@joplin/lib/registry'; const logger = Logger.create('JoplinCloudLoginScreen'); const { connect } = require('react-redux'); @@ -38,6 +39,7 @@ const JoplinCloudScreenComponent = (props: Props) => { if (response && response.success) { dispatch({ type: 'COMPLETED' }); clearInterval(interval); + void reg.scheduleSync(0); } } catch (error) { logger.error(error); @@ -77,22 +79,26 @@ const JoplinCloudScreenComponent = (props: Props) => { return ({_('To allow Joplin to synchronise with Joplin Cloud, please login using this URL:')}
-{_('To allow Joplin to synchronise with Joplin Cloud, please login using this URL:')}
+{state.message()}
{state.active === 'ERROR' ? (
{state.errorMessage}
diff --git a/packages/app-desktop/gui/MainScreen/MainScreen.tsx b/packages/app-desktop/gui/MainScreen/MainScreen.tsx
index e97e0df6c71..1e4de49e0e0 100644
--- a/packages/app-desktop/gui/MainScreen/MainScreen.tsx
+++ b/packages/app-desktop/gui/MainScreen/MainScreen.tsx
@@ -97,6 +97,7 @@ interface Props {
notesSortOrderField: string;
notesSortOrderReverse: boolean;
notesColumns: NoteListColumns;
+ showInvalidJoplinCloudCredential: boolean;
}
interface ShareFolderDialogOptions {
@@ -592,6 +593,13 @@ class MainScreenComponent extends React.Component