You've already forked joplin
mirror of
https://github.com/laurent22/joplin.git
synced 2025-12-26 23:38:08 +02:00
Compare commits
113 Commits
v2.12.7
...
mobile_plu
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6001e07cbc | ||
|
|
6210d85192 | ||
|
|
2633bcef69 | ||
|
|
772c8abdcf | ||
|
|
ac098759ea | ||
|
|
349dda30b8 | ||
|
|
cbbd9b9a61 | ||
|
|
14ef0d725b | ||
|
|
0c981ae4a7 | ||
|
|
401eee568a | ||
|
|
0b85e16125 | ||
|
|
40b89f61bd | ||
|
|
23c4020eea | ||
|
|
5ba374c03b | ||
|
|
f76ae86204 | ||
|
|
46ccd94514 | ||
|
|
7140675181 | ||
|
|
0368c26ead | ||
|
|
31f8e725dd | ||
|
|
5edbdb2466 | ||
|
|
83cf5eb617 | ||
|
|
5b0c332477 | ||
|
|
21a5feb322 | ||
|
|
16c87c36da | ||
|
|
a0ec928fca | ||
|
|
b9659bb9c1 | ||
|
|
35f375d756 | ||
|
|
04c80fe00e | ||
|
|
06732d8b8a | ||
|
|
8fc1e71fb3 | ||
|
|
aebfa6e96d | ||
|
|
3453abb670 | ||
|
|
637a0eac7f | ||
|
|
abe479d03f | ||
|
|
d1558d84b1 | ||
|
|
36e9e0a33c | ||
|
|
d78ab16021 | ||
|
|
c718706f9c | ||
|
|
f6586239c4 | ||
|
|
287d8fee73 | ||
|
|
5357b2b0dc | ||
|
|
0c4513838a | ||
|
|
d8a54da496 | ||
|
|
672ef1fd7c | ||
|
|
c50181f0a6 | ||
|
|
778f317f9f | ||
|
|
0394694a91 | ||
|
|
fec853735b | ||
|
|
087b206982 | ||
|
|
3bd04aeaf4 | ||
|
|
74e81eb6f3 | ||
|
|
3cb8fd035f | ||
|
|
0a96c3d56b | ||
|
|
2d16151fa8 | ||
|
|
93c5f6c9d3 | ||
|
|
e47985c101 | ||
|
|
1c1d20f82c | ||
|
|
880304c2fb | ||
|
|
bd3d5f213e | ||
|
|
0d6f4c9361 | ||
|
|
c49b53cb4b | ||
|
|
da177d3025 | ||
|
|
6d184fb47c | ||
|
|
3691662da2 | ||
|
|
776b6d8f12 | ||
|
|
82c33c4f0c | ||
|
|
ab77f0e0f4 | ||
|
|
df3c60e43f | ||
|
|
9aafdd2d10 | ||
|
|
1fe01dc0ce | ||
|
|
f0b5ec3e3a | ||
|
|
955f724d36 | ||
|
|
6cf0ed6166 | ||
|
|
1bcaf9d167 | ||
|
|
06b2ba9d75 | ||
|
|
85079ad213 | ||
|
|
b9225d1daa | ||
|
|
c88b6b608a | ||
|
|
56cd782175 | ||
|
|
6ce8865719 | ||
|
|
ac66332a4e | ||
|
|
c70afe3478 | ||
|
|
3c2f193714 | ||
|
|
bb9e970f8f | ||
|
|
9c8fbe831f | ||
|
|
4e1ee87269 | ||
|
|
9a32472522 | ||
|
|
1ecd6883d5 | ||
|
|
f89c6523e4 | ||
|
|
5c7b48fce1 | ||
|
|
1e2e8ed099 | ||
|
|
4d7399973e | ||
|
|
2f8275be8c | ||
|
|
58e5b83648 | ||
|
|
49e3f01a0a | ||
|
|
f64305e858 | ||
|
|
0470a3168c | ||
|
|
77482a0c95 | ||
|
|
b5193e1174 | ||
|
|
1d709a3b5c | ||
|
|
cc4e69bf92 | ||
|
|
4cf6d12704 | ||
|
|
7c52c3e9a8 | ||
|
|
68ffdc5c0f | ||
|
|
8d32cc794e | ||
|
|
8d3f60ed1f | ||
|
|
05395781cc | ||
|
|
33ba934937 | ||
|
|
f4019dbcd3 | ||
|
|
ffc40b2797 | ||
|
|
7a780e3087 | ||
|
|
712efe357e | ||
|
|
49638774f0 |
197
.eslintignore
197
.eslintignore
@@ -76,14 +76,15 @@ plugin_types/
|
||||
readme/
|
||||
packages/react-native-vosk/lib/
|
||||
packages/lib/countable/Countable.js
|
||||
packages/app-mobile/plugins
|
||||
|
||||
# AUTO-GENERATED - EXCLUDED TYPESCRIPT BUILD
|
||||
packages/app-cli/app/LinkSelector.js
|
||||
packages/app-cli/app/base-command.js
|
||||
packages/app-cli/app/command-done.test.js
|
||||
packages/app-cli/app/command-e2ee.js
|
||||
packages/app-cli/app/command-mkbook.js
|
||||
packages/app-cli/app/command-mkbook.test.js
|
||||
packages/app-cli/app/command-mkbook.js
|
||||
packages/app-cli/app/command-settingschema.js
|
||||
packages/app-cli/app/command-sync.js
|
||||
packages/app-cli/app/command-testing.js
|
||||
@@ -92,6 +93,7 @@ packages/app-cli/app/services/plugins/PluginRunner.js
|
||||
packages/app-cli/app/setupCommand.js
|
||||
packages/app-cli/app/utils/testUtils.js
|
||||
packages/app-cli/tests/HtmlToMd.js
|
||||
packages/app-cli/tests/MarkupToHtml.js
|
||||
packages/app-cli/tests/MdToHtml.js
|
||||
packages/app-cli/tests/services/keychain/KeychainService.js
|
||||
packages/app-cli/tests/services/plugins/PluginService.js
|
||||
@@ -105,9 +107,9 @@ packages/app-cli/tests/testUtils.js
|
||||
packages/app-cli/tools/populateDatabase.js
|
||||
packages/app-desktop/ElectronAppWrapper.js
|
||||
packages/app-desktop/InteropServiceHelper.js
|
||||
packages/app-desktop/app.js
|
||||
packages/app-desktop/app.reducer.js
|
||||
packages/app-desktop/app.reducer.test.js
|
||||
packages/app-desktop/app.reducer.js
|
||||
packages/app-desktop/app.js
|
||||
packages/app-desktop/bridge.js
|
||||
packages/app-desktop/checkForUpdates.js
|
||||
packages/app-desktop/commands/copyDevCommand.js
|
||||
@@ -135,13 +137,14 @@ packages/app-desktop/gui/ConfigScreen/Sidebar.js
|
||||
packages/app-desktop/gui/ConfigScreen/controls/plugins/PluginBox.js
|
||||
packages/app-desktop/gui/ConfigScreen/controls/plugins/PluginsStates.js
|
||||
packages/app-desktop/gui/ConfigScreen/controls/plugins/SearchPlugins.js
|
||||
packages/app-desktop/gui/ConfigScreen/controls/plugins/useOnInstallHandler.js
|
||||
packages/app-desktop/gui/ConfigScreen/controls/plugins/useOnInstallHandler.test.js
|
||||
packages/app-desktop/gui/ConfigScreen/controls/plugins/useOnInstallHandler.js
|
||||
packages/app-desktop/gui/Dialog.js
|
||||
packages/app-desktop/gui/DialogButtonRow.js
|
||||
packages/app-desktop/gui/DialogButtonRow/useKeyboardHandler.js
|
||||
packages/app-desktop/gui/DialogTitle.js
|
||||
packages/app-desktop/gui/DropboxLoginScreen.js
|
||||
packages/app-desktop/gui/Dropdown/Dropdown.js
|
||||
packages/app-desktop/gui/EditFolderDialog/Dialog.js
|
||||
packages/app-desktop/gui/EditFolderDialog/IconSelector.js
|
||||
packages/app-desktop/gui/EmojiBox.js
|
||||
@@ -153,6 +156,7 @@ packages/app-desktop/gui/HelpButton.js
|
||||
packages/app-desktop/gui/IconButton.js
|
||||
packages/app-desktop/gui/ImportScreen.js
|
||||
packages/app-desktop/gui/ItemList.js
|
||||
packages/app-desktop/gui/JoplinCloudConfigScreen.js
|
||||
packages/app-desktop/gui/KeymapConfig/KeymapConfigScreen.js
|
||||
packages/app-desktop/gui/KeymapConfig/ShortcutRecorder.js
|
||||
packages/app-desktop/gui/KeymapConfig/styles/index.js
|
||||
@@ -162,6 +166,9 @@ packages/app-desktop/gui/KeymapConfig/utils/useKeymap.js
|
||||
packages/app-desktop/gui/MainScreen/MainScreen.js
|
||||
packages/app-desktop/gui/MainScreen/commands/addProfile.js
|
||||
packages/app-desktop/gui/MainScreen/commands/commandPalette.js
|
||||
packages/app-desktop/gui/MainScreen/commands/deleteFolder.js
|
||||
packages/app-desktop/gui/MainScreen/commands/deleteNote.js
|
||||
packages/app-desktop/gui/MainScreen/commands/duplicateNote.js
|
||||
packages/app-desktop/gui/MainScreen/commands/editAlarm.js
|
||||
packages/app-desktop/gui/MainScreen/commands/exportPdf.js
|
||||
packages/app-desktop/gui/MainScreen/commands/gotoAnything.js
|
||||
@@ -196,6 +203,7 @@ packages/app-desktop/gui/MainScreen/commands/showSpellCheckerMenu.js
|
||||
packages/app-desktop/gui/MainScreen/commands/toggleEditors.js
|
||||
packages/app-desktop/gui/MainScreen/commands/toggleLayoutMoveMode.js
|
||||
packages/app-desktop/gui/MainScreen/commands/toggleNoteList.js
|
||||
packages/app-desktop/gui/MainScreen/commands/toggleNoteType.js
|
||||
packages/app-desktop/gui/MainScreen/commands/toggleNotesSortOrderField.js
|
||||
packages/app-desktop/gui/MainScreen/commands/toggleNotesSortOrderReverse.js
|
||||
packages/app-desktop/gui/MainScreen/commands/togglePerFolderSortOrder.js
|
||||
@@ -212,8 +220,8 @@ packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/Toolbar.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/styles/index.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/index.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/types.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useCursorUtils.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useCursorUtils.test.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useCursorUtils.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useEditorSearch.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useExternalPlugins.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useJoplinCommands.js
|
||||
@@ -241,11 +249,12 @@ packages/app-desktop/gui/NoteEditor/commands/showLocalSearch.js
|
||||
packages/app-desktop/gui/NoteEditor/commands/showRevisions.js
|
||||
packages/app-desktop/gui/NoteEditor/editorCommandDeclarations.js
|
||||
packages/app-desktop/gui/NoteEditor/styles/index.js
|
||||
packages/app-desktop/gui/NoteEditor/utils/clipboardUtils.js
|
||||
packages/app-desktop/gui/NoteEditor/utils/clipboardUtils.test.js
|
||||
packages/app-desktop/gui/NoteEditor/utils/clipboardUtils.js
|
||||
packages/app-desktop/gui/NoteEditor/utils/contextMenu.js
|
||||
packages/app-desktop/gui/NoteEditor/utils/contextMenuUtils.js
|
||||
packages/app-desktop/gui/NoteEditor/utils/index.js
|
||||
packages/app-desktop/gui/NoteEditor/utils/resourceHandling.test.js
|
||||
packages/app-desktop/gui/NoteEditor/utils/resourceHandling.js
|
||||
packages/app-desktop/gui/NoteEditor/utils/types.js
|
||||
packages/app-desktop/gui/NoteEditor/utils/useDropHandler.js
|
||||
@@ -283,17 +292,17 @@ packages/app-desktop/gui/ResizableLayout/utils/findItemByKey.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/isTempContainer.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/iterateItems.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/layoutItemProp.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/movements.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/movements.test.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/persist.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/movements.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/persist.test.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/persist.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/removeItem.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/removeKeylessItems.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/setLayoutItemProps.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/style.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/types.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/useLayoutItemSizes.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/useLayoutItemSizes.test.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/useLayoutItemSizes.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/useWindowResizeEvent.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/validateLayout.js
|
||||
packages/app-desktop/gui/ResourceScreen.js
|
||||
@@ -352,14 +361,14 @@ packages/app-desktop/services/plugins/hooks/useViewIsReady.js
|
||||
packages/app-desktop/services/plugins/hooks/useWebviewToPluginMessages.js
|
||||
packages/app-desktop/services/restart.js
|
||||
packages/app-desktop/services/share/invitationRespond.js
|
||||
packages/app-desktop/services/sortOrder/PerFolderSortOrderService.js
|
||||
packages/app-desktop/services/sortOrder/PerFolderSortOrderService.test.js
|
||||
packages/app-desktop/services/sortOrder/notesSortOrderUtils.js
|
||||
packages/app-desktop/services/sortOrder/PerFolderSortOrderService.js
|
||||
packages/app-desktop/services/sortOrder/notesSortOrderUtils.test.js
|
||||
packages/app-desktop/services/sortOrder/notesSortOrderUtils.js
|
||||
packages/app-desktop/services/spellChecker/SpellCheckerServiceDriverNative.js
|
||||
packages/app-desktop/tools/notarizeMacApp.js
|
||||
packages/app-desktop/utils/checkForUpdatesUtils.js
|
||||
packages/app-desktop/utils/checkForUpdatesUtils.test.js
|
||||
packages/app-desktop/utils/checkForUpdatesUtils.js
|
||||
packages/app-desktop/utils/markupLanguageUtils.js
|
||||
packages/app-mobile/PluginAssetsLoader.js
|
||||
packages/app-mobile/components/ActionButton.js
|
||||
@@ -374,17 +383,17 @@ packages/app-mobile/components/NoteBodyViewer/NoteBodyViewer.js
|
||||
packages/app-mobile/components/NoteBodyViewer/hooks/useOnMessage.js
|
||||
packages/app-mobile/components/NoteBodyViewer/hooks/useOnResourceLongPress.js
|
||||
packages/app-mobile/components/NoteBodyViewer/hooks/useSource.js
|
||||
packages/app-mobile/components/NoteEditor/CodeMirror/CodeMirror.js
|
||||
packages/app-mobile/components/NoteEditor/CodeMirror/CodeMirror.test.js
|
||||
packages/app-mobile/components/NoteEditor/CodeMirror/CodeMirror.js
|
||||
packages/app-mobile/components/NoteEditor/CodeMirror/decoratorExtension.js
|
||||
packages/app-mobile/components/NoteEditor/CodeMirror/markdownCommands.bulletedVsChecklist.test.js
|
||||
packages/app-mobile/components/NoteEditor/CodeMirror/markdownCommands.js
|
||||
packages/app-mobile/components/NoteEditor/CodeMirror/markdownCommands.test.js
|
||||
packages/app-mobile/components/NoteEditor/CodeMirror/markdownCommands.toggleList.test.js
|
||||
packages/app-mobile/components/NoteEditor/CodeMirror/markdownMathParser.js
|
||||
packages/app-mobile/components/NoteEditor/CodeMirror/markdownCommands.js
|
||||
packages/app-mobile/components/NoteEditor/CodeMirror/markdownMathParser.test.js
|
||||
packages/app-mobile/components/NoteEditor/CodeMirror/markdownReformatter.js
|
||||
packages/app-mobile/components/NoteEditor/CodeMirror/markdownMathParser.js
|
||||
packages/app-mobile/components/NoteEditor/CodeMirror/markdownReformatter.test.js
|
||||
packages/app-mobile/components/NoteEditor/CodeMirror/markdownReformatter.js
|
||||
packages/app-mobile/components/NoteEditor/CodeMirror/syntaxHighlightingLanguages.js
|
||||
packages/app-mobile/components/NoteEditor/CodeMirror/testUtil/createEditor.js
|
||||
packages/app-mobile/components/NoteEditor/CodeMirror/testUtil/forceFullParse.js
|
||||
@@ -415,9 +424,14 @@ packages/app-mobile/components/app-nav.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/getResponsiveValue.js
|
||||
packages/app-mobile/components/getResponsiveValue.test.js
|
||||
packages/app-mobile/components/screens/ConfigScreen.js
|
||||
packages/app-mobile/components/getResponsiveValue.js
|
||||
packages/app-mobile/components/screens/ConfigScreen/ConfigScreen.js
|
||||
packages/app-mobile/components/screens/ConfigScreen/ConfigScreenButton.js
|
||||
packages/app-mobile/components/screens/ConfigScreen/NoteExportSection/NoteExportButton.test.js
|
||||
packages/app-mobile/components/screens/ConfigScreen/NoteExportSection/NoteExportButton.js
|
||||
packages/app-mobile/components/screens/ConfigScreen/NoteExportSection/exportAllFolders.js
|
||||
packages/app-mobile/components/screens/ConfigScreen/configScreenStyles.js
|
||||
packages/app-mobile/components/screens/Note.js
|
||||
packages/app-mobile/components/screens/Notes.js
|
||||
packages/app-mobile/components/screens/UpgradeSyncTargetScreen.js
|
||||
@@ -430,6 +444,7 @@ 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/PluginRunner.js
|
||||
packages/app-mobile/services/profiles/index.js
|
||||
packages/app-mobile/services/voiceTyping/vosk.android.js
|
||||
packages/app-mobile/services/voiceTyping/vosk.ios.js
|
||||
@@ -438,27 +453,29 @@ packages/app-mobile/tools/buildInjectedJs.js
|
||||
packages/app-mobile/utils/ShareExtension.js
|
||||
packages/app-mobile/utils/ShareUtils.js
|
||||
packages/app-mobile/utils/TlsUtils.js
|
||||
packages/app-mobile/utils/autodetectTheme.js
|
||||
packages/app-mobile/utils/checkPermissions.js
|
||||
packages/app-mobile/utils/createRootStyle.js
|
||||
packages/app-mobile/utils/debounce.js
|
||||
packages/app-mobile/utils/fs-driver-rn.js
|
||||
packages/app-mobile/utils/markupLanguageUtils.js
|
||||
packages/app-mobile/utils/setupNotifications.js
|
||||
packages/app-mobile/utils/shareHandler.js
|
||||
packages/app-mobile/utils/types.js
|
||||
packages/fork-htmlparser2/src/CollectingHandler.js
|
||||
packages/fork-htmlparser2/src/FeedHandler.js
|
||||
packages/fork-htmlparser2/src/FeedHandler.spec.js
|
||||
packages/fork-htmlparser2/src/FeedHandler.js
|
||||
packages/fork-htmlparser2/src/MultiplexHandler.js
|
||||
packages/fork-htmlparser2/src/Parser.js
|
||||
packages/fork-htmlparser2/src/Parser.spec.js
|
||||
packages/fork-htmlparser2/src/Parser.js
|
||||
packages/fork-htmlparser2/src/Tokenizer.js
|
||||
packages/fork-htmlparser2/src/WritableStream.js
|
||||
packages/fork-htmlparser2/src/WritableStream.spec.js
|
||||
packages/fork-htmlparser2/src/WritableStream.js
|
||||
packages/fork-htmlparser2/src/__fixtures__/test-helper.js
|
||||
packages/fork-htmlparser2/src/__tests__/events.js
|
||||
packages/fork-htmlparser2/src/__tests__/stream.js
|
||||
packages/fork-htmlparser2/src/index.js
|
||||
packages/fork-htmlparser2/src/index.spec.js
|
||||
packages/fork-htmlparser2/src/index.js
|
||||
packages/generator-joplin/generators/app/templates/api/index.js
|
||||
packages/generator-joplin/generators/app/templates/api/types.js
|
||||
packages/generator-joplin/generators/app/templates/api_index.js
|
||||
@@ -471,17 +488,18 @@ packages/lib/BaseModel.js
|
||||
packages/lib/BaseSyncTarget.js
|
||||
packages/lib/ClipperServer.js
|
||||
packages/lib/CssUtils.js
|
||||
packages/lib/EventDispatcher.js
|
||||
packages/lib/EventDispatcher.test.js
|
||||
packages/lib/EventDispatcher.js
|
||||
packages/lib/HtmlToMd.js
|
||||
packages/lib/InMemoryCache.js
|
||||
packages/lib/InMemoryCache.test.js
|
||||
packages/lib/InMemoryCache.js
|
||||
packages/lib/JoplinDatabase.js
|
||||
packages/lib/JoplinError.js
|
||||
packages/lib/JoplinServerApi.js
|
||||
packages/lib/Logger.js
|
||||
packages/lib/ObjectUtils.js
|
||||
packages/lib/PoorManIntervals.js
|
||||
packages/lib/RotatingLogs.test.js
|
||||
packages/lib/RotatingLogs.js
|
||||
packages/lib/SyncTargetJoplinCloud.js
|
||||
packages/lib/SyncTargetJoplinServer.js
|
||||
packages/lib/SyncTargetNone.js
|
||||
@@ -491,8 +509,8 @@ packages/lib/Synchronizer.js
|
||||
packages/lib/TaskQueue.js
|
||||
packages/lib/WelcomeUtils.js
|
||||
packages/lib/array.js
|
||||
packages/lib/callbackUrlUtils.js
|
||||
packages/lib/callbackUrlUtils.test.js
|
||||
packages/lib/callbackUrlUtils.js
|
||||
packages/lib/commands/historyBackward.js
|
||||
packages/lib/commands/historyForward.js
|
||||
packages/lib/commands/index.js
|
||||
@@ -500,12 +518,14 @@ packages/lib/commands/openMasterPasswordDialog.js
|
||||
packages/lib/commands/synchronize.js
|
||||
packages/lib/components/EncryptionConfigScreen/utils.js
|
||||
packages/lib/components/shared/note-screen-shared.js
|
||||
packages/lib/components/shared/reduxSharedMiddleware.js
|
||||
packages/lib/database-driver-better-sqlite.js
|
||||
packages/lib/database.js
|
||||
packages/lib/debug/DebugService.js
|
||||
packages/lib/dom.js
|
||||
packages/lib/dummy.test.js
|
||||
packages/lib/errorUtils.js
|
||||
packages/lib/errors.js
|
||||
packages/lib/eventManager.js
|
||||
packages/lib/file-api-driver-joplinServer.js
|
||||
packages/lib/file-api-driver-memory.js
|
||||
@@ -518,41 +538,41 @@ packages/lib/geolocation-node.js
|
||||
packages/lib/hooks/useAsyncEffect.js
|
||||
packages/lib/hooks/useElementSize.js
|
||||
packages/lib/hooks/useEventListener.js
|
||||
packages/lib/htmlUtils.js
|
||||
packages/lib/htmlUtils.test.js
|
||||
packages/lib/htmlUtils.js
|
||||
packages/lib/htmlUtils2.test.js
|
||||
packages/lib/import-enex-md-gen.js
|
||||
packages/lib/import-enex-md-gen.test.js
|
||||
packages/lib/import-enex-md-gen.js
|
||||
packages/lib/import-enex.js
|
||||
packages/lib/locale.js
|
||||
packages/lib/locale.test.js
|
||||
packages/lib/markdownUtils.js
|
||||
packages/lib/locale.js
|
||||
packages/lib/markdownUtils.test.js
|
||||
packages/lib/markdownUtils.js
|
||||
packages/lib/markdownUtils2.test.js
|
||||
packages/lib/markupLanguageUtils.js
|
||||
packages/lib/migrations/42.js
|
||||
packages/lib/models/Alarm.js
|
||||
packages/lib/models/BaseItem.js
|
||||
packages/lib/models/Folder.js
|
||||
packages/lib/models/Folder.sharing.test.js
|
||||
packages/lib/models/Folder.test.js
|
||||
packages/lib/models/ItemChange.js
|
||||
packages/lib/models/Folder.js
|
||||
packages/lib/models/ItemChange.test.js
|
||||
packages/lib/models/MasterKey.js
|
||||
packages/lib/models/ItemChange.js
|
||||
packages/lib/models/MasterKey.test.js
|
||||
packages/lib/models/MasterKey.js
|
||||
packages/lib/models/Migration.js
|
||||
packages/lib/models/Note.js
|
||||
packages/lib/models/Note.test.js
|
||||
packages/lib/models/Note.js
|
||||
packages/lib/models/NoteResource.js
|
||||
packages/lib/models/NoteTag.js
|
||||
packages/lib/models/Resource.js
|
||||
packages/lib/models/Resource.test.js
|
||||
packages/lib/models/Resource.js
|
||||
packages/lib/models/ResourceLocalState.js
|
||||
packages/lib/models/Revision.js
|
||||
packages/lib/models/Revision.test.js
|
||||
packages/lib/models/Revision.js
|
||||
packages/lib/models/Search.js
|
||||
packages/lib/models/Setting.js
|
||||
packages/lib/models/Setting.test.js
|
||||
packages/lib/models/Setting.js
|
||||
packages/lib/models/SmartFilter.js
|
||||
packages/lib/models/Tag.js
|
||||
packages/lib/models/dateTimeFormats.test.js
|
||||
@@ -560,21 +580,22 @@ packages/lib/models/settings/FileHandler.js
|
||||
packages/lib/models/utils/itemCanBeEncrypted.js
|
||||
packages/lib/models/utils/paginatedFeed.js
|
||||
packages/lib/models/utils/paginationToSql.js
|
||||
packages/lib/models/utils/readOnly.js
|
||||
packages/lib/models/utils/types.js
|
||||
packages/lib/models/utils/userData.js
|
||||
packages/lib/models/utils/userData.test.js
|
||||
packages/lib/models/utils/userData.js
|
||||
packages/lib/net-utils.js
|
||||
packages/lib/ntp.js
|
||||
packages/lib/onedrive-api.js
|
||||
packages/lib/path-utils.js
|
||||
packages/lib/reducer.js
|
||||
packages/lib/registry.js
|
||||
packages/lib/registry.test.js
|
||||
packages/lib/registry.js
|
||||
packages/lib/services/AlarmService.js
|
||||
packages/lib/services/AlarmServiceDriverNode.js
|
||||
packages/lib/services/BaseService.js
|
||||
packages/lib/services/CommandService.js
|
||||
packages/lib/services/CommandService.test.js
|
||||
packages/lib/services/CommandService.js
|
||||
packages/lib/services/DecryptionWorker.js
|
||||
packages/lib/services/ExternalEditWatcher.js
|
||||
packages/lib/services/ExternalEditWatcher/utils.js
|
||||
@@ -590,14 +611,14 @@ packages/lib/services/ReportService.js
|
||||
packages/lib/services/ResourceEditWatcher/index.js
|
||||
packages/lib/services/ResourceEditWatcher/reducer.js
|
||||
packages/lib/services/ResourceFetcher.js
|
||||
packages/lib/services/ResourceService.js
|
||||
packages/lib/services/ResourceService.test.js
|
||||
packages/lib/services/RevisionService.js
|
||||
packages/lib/services/ResourceService.js
|
||||
packages/lib/services/RevisionService.test.js
|
||||
packages/lib/services/RevisionService.js
|
||||
packages/lib/services/SettingUtils.js
|
||||
packages/lib/services/UndoRedoService.js
|
||||
packages/lib/services/WhenClause.js
|
||||
packages/lib/services/WhenClause.test.js
|
||||
packages/lib/services/WhenClause.js
|
||||
packages/lib/services/commands/MenuUtils.js
|
||||
packages/lib/services/commands/ToolbarButtonUtils.js
|
||||
packages/lib/services/commands/commandsToMarkdownTable.js
|
||||
@@ -608,40 +629,40 @@ packages/lib/services/commands/stateToWhenClauseContext.js
|
||||
packages/lib/services/contextkey/contextkey.js
|
||||
packages/lib/services/database/types.js
|
||||
packages/lib/services/debug/populateDatabase.js
|
||||
packages/lib/services/e2ee/EncryptionService.js
|
||||
packages/lib/services/e2ee/EncryptionService.test.js
|
||||
packages/lib/services/e2ee/EncryptionService.js
|
||||
packages/lib/services/e2ee/RSA.node.js
|
||||
packages/lib/services/e2ee/ppk.js
|
||||
packages/lib/services/e2ee/ppk.test.js
|
||||
packages/lib/services/e2ee/ppk.js
|
||||
packages/lib/services/e2ee/ppkTestUtils.js
|
||||
packages/lib/services/e2ee/types.js
|
||||
packages/lib/services/e2ee/utils.js
|
||||
packages/lib/services/e2ee/utils.test.js
|
||||
packages/lib/services/interop/InteropService.js
|
||||
packages/lib/services/e2ee/utils.js
|
||||
packages/lib/services/interop/InteropService.test.js
|
||||
packages/lib/services/interop/InteropService.js
|
||||
packages/lib/services/interop/InteropService_Exporter_Base.js
|
||||
packages/lib/services/interop/InteropService_Exporter_Custom.js
|
||||
packages/lib/services/interop/InteropService_Exporter_Html.js
|
||||
packages/lib/services/interop/InteropService_Exporter_Html.test.js
|
||||
packages/lib/services/interop/InteropService_Exporter_Html.js
|
||||
packages/lib/services/interop/InteropService_Exporter_Jex.js
|
||||
packages/lib/services/interop/InteropService_Exporter_Md.js
|
||||
packages/lib/services/interop/InteropService_Exporter_Md.test.js
|
||||
packages/lib/services/interop/InteropService_Exporter_Md_frontmatter.js
|
||||
packages/lib/services/interop/InteropService_Exporter_Md.js
|
||||
packages/lib/services/interop/InteropService_Exporter_Md_frontmatter.test.js
|
||||
packages/lib/services/interop/InteropService_Exporter_Md_frontmatter.js
|
||||
packages/lib/services/interop/InteropService_Exporter_Raw.js
|
||||
packages/lib/services/interop/InteropService_Importer_Base.js
|
||||
packages/lib/services/interop/InteropService_Importer_Custom.js
|
||||
packages/lib/services/interop/InteropService_Importer_EnexToHtml.js
|
||||
packages/lib/services/interop/InteropService_Importer_EnexToMd.js
|
||||
packages/lib/services/interop/InteropService_Importer_Jex.js
|
||||
packages/lib/services/interop/InteropService_Importer_Md.js
|
||||
packages/lib/services/interop/InteropService_Importer_Md.test.js
|
||||
packages/lib/services/interop/InteropService_Importer_Md_frontmatter.js
|
||||
packages/lib/services/interop/InteropService_Importer_Md.js
|
||||
packages/lib/services/interop/InteropService_Importer_Md_frontmatter.test.js
|
||||
packages/lib/services/interop/InteropService_Importer_Raw.js
|
||||
packages/lib/services/interop/InteropService_Importer_Md_frontmatter.js
|
||||
packages/lib/services/interop/InteropService_Importer_Raw.test.js
|
||||
packages/lib/services/interop/Module.js
|
||||
packages/lib/services/interop/InteropService_Importer_Raw.js
|
||||
packages/lib/services/interop/Module.test.js
|
||||
packages/lib/services/interop/Module.js
|
||||
packages/lib/services/interop/types.js
|
||||
packages/lib/services/joplinServer/personalizedUserContentBaseUrl.js
|
||||
packages/lib/services/keychain/KeychainService.js
|
||||
@@ -688,23 +709,23 @@ packages/lib/services/plugins/utils/makeListener.js
|
||||
packages/lib/services/plugins/utils/manifestFromObject.js
|
||||
packages/lib/services/plugins/utils/mapEventHandlersToIds.js
|
||||
packages/lib/services/plugins/utils/types.js
|
||||
packages/lib/services/plugins/utils/validatePluginId.js
|
||||
packages/lib/services/plugins/utils/validatePluginId.test.js
|
||||
packages/lib/services/plugins/utils/validatePluginVersion.js
|
||||
packages/lib/services/plugins/utils/validatePluginId.js
|
||||
packages/lib/services/plugins/utils/validatePluginVersion.test.js
|
||||
packages/lib/services/profileConfig/index.js
|
||||
packages/lib/services/plugins/utils/validatePluginVersion.js
|
||||
packages/lib/services/profileConfig/index.test.js
|
||||
packages/lib/services/profileConfig/index.js
|
||||
packages/lib/services/profileConfig/initProfile.js
|
||||
packages/lib/services/profileConfig/mergeGlobalAndLocalSettings.js
|
||||
packages/lib/services/profileConfig/splitGlobalAndLocalSettings.js
|
||||
packages/lib/services/profileConfig/types.js
|
||||
packages/lib/services/rest/Api.js
|
||||
packages/lib/services/rest/Api.test.js
|
||||
packages/lib/services/rest/Api.js
|
||||
packages/lib/services/rest/ApiResponse.js
|
||||
packages/lib/services/rest/actionApi.desktop.js
|
||||
packages/lib/services/rest/routes/auth.js
|
||||
packages/lib/services/rest/routes/events.js
|
||||
packages/lib/services/rest/routes/events.test.js
|
||||
packages/lib/services/rest/routes/events.js
|
||||
packages/lib/services/rest/routes/folders.js
|
||||
packages/lib/services/rest/routes/master_keys.js
|
||||
packages/lib/services/rest/routes/notes.js
|
||||
@@ -722,26 +743,26 @@ packages/lib/services/rest/utils/readonlyProperties.js
|
||||
packages/lib/services/rest/utils/requestFields.js
|
||||
packages/lib/services/rest/utils/requestPaginationOptions.js
|
||||
packages/lib/services/searchengine/SearchEngine.js
|
||||
packages/lib/services/searchengine/SearchEngineUtils.js
|
||||
packages/lib/services/searchengine/SearchEngineUtils.test.js
|
||||
packages/lib/services/searchengine/SearchEngineUtils.js
|
||||
packages/lib/services/searchengine/SearchFilter.test.js
|
||||
packages/lib/services/searchengine/filterParser.js
|
||||
packages/lib/services/searchengine/filterParser.test.js
|
||||
packages/lib/services/searchengine/gotoAnythingStyleQuery.js
|
||||
packages/lib/services/searchengine/filterParser.js
|
||||
packages/lib/services/searchengine/gotoAnythingStyleQuery.test.js
|
||||
packages/lib/services/searchengine/gotoAnythingStyleQuery.js
|
||||
packages/lib/services/searchengine/queryBuilder.js
|
||||
packages/lib/services/share/ShareService.js
|
||||
packages/lib/services/share/ShareService.test.js
|
||||
packages/lib/services/share/ShareService.js
|
||||
packages/lib/services/share/reducer.js
|
||||
packages/lib/services/spellChecker/SpellCheckerService.js
|
||||
packages/lib/services/spellChecker/SpellCheckerServiceDriverBase.js
|
||||
packages/lib/services/style/cssToTheme.js
|
||||
packages/lib/services/style/cssToTheme.test.js
|
||||
packages/lib/services/style/cssToTheme.js
|
||||
packages/lib/services/style/loadCssToTheme.js
|
||||
packages/lib/services/style/themeToCss.js
|
||||
packages/lib/services/style/themeToCss.test.js
|
||||
packages/lib/services/synchronizer/ItemUploader.js
|
||||
packages/lib/services/style/themeToCss.js
|
||||
packages/lib/services/synchronizer/ItemUploader.test.js
|
||||
packages/lib/services/synchronizer/ItemUploader.js
|
||||
packages/lib/services/synchronizer/LockHandler.js
|
||||
packages/lib/services/synchronizer/MigrationHandler.js
|
||||
packages/lib/services/synchronizer/Synchronizer.basics.test.js
|
||||
@@ -758,12 +779,15 @@ packages/lib/services/synchronizer/migrations/1.js
|
||||
packages/lib/services/synchronizer/migrations/2.js
|
||||
packages/lib/services/synchronizer/migrations/3.js
|
||||
packages/lib/services/synchronizer/syncDebugLog.js
|
||||
packages/lib/services/synchronizer/syncInfoUtils.js
|
||||
packages/lib/services/synchronizer/syncInfoUtils.test.js
|
||||
packages/lib/services/synchronizer/syncInfoUtils.js
|
||||
packages/lib/services/synchronizer/synchronizer_LockHandler.test.js
|
||||
packages/lib/services/synchronizer/synchronizer_MigrationHandler.test.js
|
||||
packages/lib/services/synchronizer/tools.js
|
||||
packages/lib/services/synchronizer/utils/handleConflictAction.js
|
||||
packages/lib/services/synchronizer/utils/handleSyncStartupOperation.js
|
||||
packages/lib/services/synchronizer/utils/resourceRemotePath.js
|
||||
packages/lib/services/synchronizer/utils/syncDeleteStep.js
|
||||
packages/lib/services/synchronizer/utils/types.js
|
||||
packages/lib/shim.js
|
||||
packages/lib/testing/syncTargetUtils.js
|
||||
@@ -782,11 +806,12 @@ packages/lib/themes/type.js
|
||||
packages/lib/time.js
|
||||
packages/lib/utils/credentialFiles.js
|
||||
packages/lib/utils/joplinCloud.js
|
||||
packages/lib/utils/webDAVUtils.js
|
||||
packages/lib/utils/userFetcher.js
|
||||
packages/lib/utils/webDAVUtils.test.js
|
||||
packages/lib/utils/webDAVUtils.js
|
||||
packages/lib/uuid.js
|
||||
packages/lib/versionInfo.js
|
||||
packages/lib/versionInfo.test.js
|
||||
packages/lib/versionInfo.js
|
||||
packages/pdf-viewer/FullViewer.js
|
||||
packages/pdf-viewer/Page.js
|
||||
packages/pdf-viewer/PdfDocument.js
|
||||
@@ -807,30 +832,31 @@ packages/pdf-viewer/ui/IconButtons.js
|
||||
packages/pdf-viewer/ui/ZoomControls.js
|
||||
packages/plugin-repo-cli/commands/updateRelease.js
|
||||
packages/plugin-repo-cli/index.js
|
||||
packages/plugin-repo-cli/lib/checkIfPluginCanBeAdded.js
|
||||
packages/plugin-repo-cli/lib/checkIfPluginCanBeAdded.test.js
|
||||
packages/plugin-repo-cli/lib/errorsHaveChanged.js
|
||||
packages/plugin-repo-cli/lib/checkIfPluginCanBeAdded.js
|
||||
packages/plugin-repo-cli/lib/errorsHaveChanged.test.js
|
||||
packages/plugin-repo-cli/lib/gitCompareUrl.js
|
||||
packages/plugin-repo-cli/lib/errorsHaveChanged.js
|
||||
packages/plugin-repo-cli/lib/gitCompareUrl.test.js
|
||||
packages/plugin-repo-cli/lib/overrideUtils.js
|
||||
packages/plugin-repo-cli/lib/gitCompareUrl.js
|
||||
packages/plugin-repo-cli/lib/overrideUtils.test.js
|
||||
packages/plugin-repo-cli/lib/overrideUtils.js
|
||||
packages/plugin-repo-cli/lib/types.js
|
||||
packages/plugin-repo-cli/lib/updateReadme.js
|
||||
packages/plugin-repo-cli/lib/updateReadme.test.js
|
||||
packages/plugin-repo-cli/lib/updateReadme.js
|
||||
packages/plugin-repo-cli/lib/utils.js
|
||||
packages/plugins/ToggleSidebars/api/index.js
|
||||
packages/plugins/ToggleSidebars/api/types.js
|
||||
packages/plugins/ToggleSidebars/src/index.js
|
||||
packages/react-native-saf-x/src/index.js
|
||||
packages/renderer/HtmlToHtml.test.js
|
||||
packages/renderer/HtmlToHtml.js
|
||||
packages/renderer/InMemoryCache.js
|
||||
packages/renderer/MarkupToHtml.js
|
||||
packages/renderer/MdToHtml.js
|
||||
packages/renderer/MdToHtml/createEventHandlingAttrs.js
|
||||
packages/renderer/MdToHtml/createEventHandlingAttrs.test.js
|
||||
packages/renderer/MdToHtml/linkReplacement.js
|
||||
packages/renderer/MdToHtml/createEventHandlingAttrs.js
|
||||
packages/renderer/MdToHtml/linkReplacement.test.js
|
||||
packages/renderer/MdToHtml/linkReplacement.js
|
||||
packages/renderer/MdToHtml/renderMedia.js
|
||||
packages/renderer/MdToHtml/rules/checkbox.js
|
||||
packages/renderer/MdToHtml/rules/code_inline.js
|
||||
@@ -849,25 +875,26 @@ packages/renderer/MdToHtml/setupLinkify.js
|
||||
packages/renderer/MdToHtml/validateLinks.js
|
||||
packages/renderer/headerAnchor.js
|
||||
packages/renderer/highlight.js
|
||||
packages/renderer/htmlUtils.js
|
||||
packages/renderer/htmlUtils.test.js
|
||||
packages/renderer/htmlUtils.js
|
||||
packages/renderer/index.js
|
||||
packages/renderer/noteStyle.js
|
||||
packages/renderer/pathUtils.js
|
||||
packages/renderer/utils.js
|
||||
packages/tools/build-release-stats.js
|
||||
packages/tools/build-welcome.js
|
||||
packages/tools/buildServerDocker.js
|
||||
packages/tools/buildServerDocker.test.js
|
||||
packages/tools/bundleDefaultPlugins.js
|
||||
packages/tools/buildServerDocker.js
|
||||
packages/tools/bundleDefaultPlugins.test.js
|
||||
packages/tools/checkLibPaths.js
|
||||
packages/tools/bundleDefaultPlugins.js
|
||||
packages/tools/checkIgnoredFiles.js
|
||||
packages/tools/checkLibPaths.test.js
|
||||
packages/tools/checkLibPaths.js
|
||||
packages/tools/convertThemesToCss.js
|
||||
packages/tools/generate-database-types.js
|
||||
packages/tools/generate-images.js
|
||||
packages/tools/git-changelog.js
|
||||
packages/tools/git-changelog.test.js
|
||||
packages/tools/git-changelog.js
|
||||
packages/tools/licenseChecker.js
|
||||
packages/tools/release-android.js
|
||||
packages/tools/release-cli.js
|
||||
@@ -879,8 +906,8 @@ packages/tools/setupNewRelease.js
|
||||
packages/tools/spellcheck.js
|
||||
packages/tools/tagServerLatest.js
|
||||
packages/tools/tool-utils.js
|
||||
packages/tools/update-readme-download.js
|
||||
packages/tools/update-readme-download.test.js
|
||||
packages/tools/update-readme-download.js
|
||||
packages/tools/update-readme-sponsors.js
|
||||
packages/tools/updateMarkdownDoc.js
|
||||
packages/tools/utils/discourse.js
|
||||
@@ -890,14 +917,14 @@ packages/tools/website/build.js
|
||||
packages/tools/website/buildTranslations.js
|
||||
packages/tools/website/updateDownloadPage.js
|
||||
packages/tools/website/updateNews.js
|
||||
packages/tools/website/utils/applyTranslations.js
|
||||
packages/tools/website/utils/applyTranslations.test.js
|
||||
packages/tools/website/utils/convertLinksToLocale.js
|
||||
packages/tools/website/utils/applyTranslations.js
|
||||
packages/tools/website/utils/convertLinksToLocale.test.js
|
||||
packages/tools/website/utils/convertLinksToLocale.js
|
||||
packages/tools/website/utils/frontMatter.js
|
||||
packages/tools/website/utils/news.js
|
||||
packages/tools/website/utils/openGraph.js
|
||||
packages/tools/website/utils/openGraph.test.js
|
||||
packages/tools/website/utils/openGraph.js
|
||||
packages/tools/website/utils/parser.js
|
||||
packages/tools/website/utils/pressCarousel.js
|
||||
packages/tools/website/utils/processTranslations.js
|
||||
|
||||
25
.github/scripts/run_ci.sh
vendored
25
.github/scripts/run_ci.sh
vendored
@@ -153,6 +153,24 @@ if [ "$IS_PULL_REQUEST" == "1" ] || [ "$IS_DEV_BRANCH" = "1" ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
# =============================================================================
|
||||
# Check .gitignore and .eslintignore files - they should be updated when
|
||||
# new TypeScript files are added by running `yarn run updateIgnored`.
|
||||
# See coding_style.md
|
||||
# =============================================================================
|
||||
|
||||
if [ "$IS_PULL_REQUEST" == "1" ]; then
|
||||
if [ "$IS_LINUX" == "1" ]; then
|
||||
echo "Step: Checking for files that should have been ignored..."
|
||||
|
||||
node packages/tools/checkIgnoredFiles.js
|
||||
testResult=$?
|
||||
if [ $testResult -ne 0 ]; then
|
||||
exit $testResult
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# =============================================================================
|
||||
# Find out if we should run the build or not. Electron-builder gets stuck when
|
||||
# building PRs so we disable it in this case. The Linux build should provide
|
||||
@@ -213,6 +231,13 @@ else
|
||||
if [ "$IS_MACOS" == "1" ]; then
|
||||
# See above why we need to specify Python
|
||||
alias python=$(which python3)
|
||||
|
||||
# We also want to disable signing the app in this case, because
|
||||
# it randomly fails and we don't even need it
|
||||
# https://www.electron.build/code-signing#how-to-disable-code-signing-during-the-build-process-on-macos
|
||||
export CSC_IDENTITY_AUTO_DISCOVERY=false
|
||||
npm pkg set 'build.mac.identity'=null --json
|
||||
|
||||
USE_HARD_LINKS=false yarn run dist --publish=never
|
||||
else
|
||||
USE_HARD_LINKS=false yarn run dist --publish=never
|
||||
|
||||
2
.github/workflows/build-macos-m1.yml
vendored
2
.github/workflows/build-macos-m1.yml
vendored
@@ -49,7 +49,7 @@ jobs:
|
||||
yarn install
|
||||
cd packages/app-desktop
|
||||
npm pkg set 'build.mac.artifactName'='${productName}-${version}-${arch}.${ext}'
|
||||
npm pkg set 'build.mac.target.target'='default'
|
||||
npm pkg set 'build.mac.target.target'='dmg'
|
||||
npm pkg set 'build.mac.target.arch[0]'='arm64'
|
||||
|
||||
if [[ $GIT_TAG_NAME = v* ]]; then
|
||||
|
||||
2
.github/workflows/github-actions-main.yml
vendored
2
.github/workflows/github-actions-main.yml
vendored
@@ -183,7 +183,7 @@ jobs:
|
||||
docker run -p 22300:22300 joplin/server:0.0.0-beta node dist/app.js --env dev &
|
||||
|
||||
# Wait for server to start
|
||||
sleep 10
|
||||
sleep 30
|
||||
|
||||
# Check if status code is correct
|
||||
# if the actual_status DOES NOT include the expected_status
|
||||
|
||||
196
.gitignore
vendored
196
.gitignore
vendored
@@ -67,8 +67,8 @@ packages/app-cli/app/LinkSelector.js
|
||||
packages/app-cli/app/base-command.js
|
||||
packages/app-cli/app/command-done.test.js
|
||||
packages/app-cli/app/command-e2ee.js
|
||||
packages/app-cli/app/command-mkbook.js
|
||||
packages/app-cli/app/command-mkbook.test.js
|
||||
packages/app-cli/app/command-mkbook.js
|
||||
packages/app-cli/app/command-settingschema.js
|
||||
packages/app-cli/app/command-sync.js
|
||||
packages/app-cli/app/command-testing.js
|
||||
@@ -77,6 +77,7 @@ packages/app-cli/app/services/plugins/PluginRunner.js
|
||||
packages/app-cli/app/setupCommand.js
|
||||
packages/app-cli/app/utils/testUtils.js
|
||||
packages/app-cli/tests/HtmlToMd.js
|
||||
packages/app-cli/tests/MarkupToHtml.js
|
||||
packages/app-cli/tests/MdToHtml.js
|
||||
packages/app-cli/tests/services/keychain/KeychainService.js
|
||||
packages/app-cli/tests/services/plugins/PluginService.js
|
||||
@@ -90,9 +91,9 @@ packages/app-cli/tests/testUtils.js
|
||||
packages/app-cli/tools/populateDatabase.js
|
||||
packages/app-desktop/ElectronAppWrapper.js
|
||||
packages/app-desktop/InteropServiceHelper.js
|
||||
packages/app-desktop/app.js
|
||||
packages/app-desktop/app.reducer.js
|
||||
packages/app-desktop/app.reducer.test.js
|
||||
packages/app-desktop/app.reducer.js
|
||||
packages/app-desktop/app.js
|
||||
packages/app-desktop/bridge.js
|
||||
packages/app-desktop/checkForUpdates.js
|
||||
packages/app-desktop/commands/copyDevCommand.js
|
||||
@@ -120,13 +121,14 @@ packages/app-desktop/gui/ConfigScreen/Sidebar.js
|
||||
packages/app-desktop/gui/ConfigScreen/controls/plugins/PluginBox.js
|
||||
packages/app-desktop/gui/ConfigScreen/controls/plugins/PluginsStates.js
|
||||
packages/app-desktop/gui/ConfigScreen/controls/plugins/SearchPlugins.js
|
||||
packages/app-desktop/gui/ConfigScreen/controls/plugins/useOnInstallHandler.js
|
||||
packages/app-desktop/gui/ConfigScreen/controls/plugins/useOnInstallHandler.test.js
|
||||
packages/app-desktop/gui/ConfigScreen/controls/plugins/useOnInstallHandler.js
|
||||
packages/app-desktop/gui/Dialog.js
|
||||
packages/app-desktop/gui/DialogButtonRow.js
|
||||
packages/app-desktop/gui/DialogButtonRow/useKeyboardHandler.js
|
||||
packages/app-desktop/gui/DialogTitle.js
|
||||
packages/app-desktop/gui/DropboxLoginScreen.js
|
||||
packages/app-desktop/gui/Dropdown/Dropdown.js
|
||||
packages/app-desktop/gui/EditFolderDialog/Dialog.js
|
||||
packages/app-desktop/gui/EditFolderDialog/IconSelector.js
|
||||
packages/app-desktop/gui/EmojiBox.js
|
||||
@@ -138,6 +140,7 @@ packages/app-desktop/gui/HelpButton.js
|
||||
packages/app-desktop/gui/IconButton.js
|
||||
packages/app-desktop/gui/ImportScreen.js
|
||||
packages/app-desktop/gui/ItemList.js
|
||||
packages/app-desktop/gui/JoplinCloudConfigScreen.js
|
||||
packages/app-desktop/gui/KeymapConfig/KeymapConfigScreen.js
|
||||
packages/app-desktop/gui/KeymapConfig/ShortcutRecorder.js
|
||||
packages/app-desktop/gui/KeymapConfig/styles/index.js
|
||||
@@ -147,6 +150,9 @@ packages/app-desktop/gui/KeymapConfig/utils/useKeymap.js
|
||||
packages/app-desktop/gui/MainScreen/MainScreen.js
|
||||
packages/app-desktop/gui/MainScreen/commands/addProfile.js
|
||||
packages/app-desktop/gui/MainScreen/commands/commandPalette.js
|
||||
packages/app-desktop/gui/MainScreen/commands/deleteFolder.js
|
||||
packages/app-desktop/gui/MainScreen/commands/deleteNote.js
|
||||
packages/app-desktop/gui/MainScreen/commands/duplicateNote.js
|
||||
packages/app-desktop/gui/MainScreen/commands/editAlarm.js
|
||||
packages/app-desktop/gui/MainScreen/commands/exportPdf.js
|
||||
packages/app-desktop/gui/MainScreen/commands/gotoAnything.js
|
||||
@@ -181,6 +187,7 @@ packages/app-desktop/gui/MainScreen/commands/showSpellCheckerMenu.js
|
||||
packages/app-desktop/gui/MainScreen/commands/toggleEditors.js
|
||||
packages/app-desktop/gui/MainScreen/commands/toggleLayoutMoveMode.js
|
||||
packages/app-desktop/gui/MainScreen/commands/toggleNoteList.js
|
||||
packages/app-desktop/gui/MainScreen/commands/toggleNoteType.js
|
||||
packages/app-desktop/gui/MainScreen/commands/toggleNotesSortOrderField.js
|
||||
packages/app-desktop/gui/MainScreen/commands/toggleNotesSortOrderReverse.js
|
||||
packages/app-desktop/gui/MainScreen/commands/togglePerFolderSortOrder.js
|
||||
@@ -197,8 +204,8 @@ packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/Toolbar.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/styles/index.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/index.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/types.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useCursorUtils.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useCursorUtils.test.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useCursorUtils.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useEditorSearch.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useExternalPlugins.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useJoplinCommands.js
|
||||
@@ -226,11 +233,12 @@ packages/app-desktop/gui/NoteEditor/commands/showLocalSearch.js
|
||||
packages/app-desktop/gui/NoteEditor/commands/showRevisions.js
|
||||
packages/app-desktop/gui/NoteEditor/editorCommandDeclarations.js
|
||||
packages/app-desktop/gui/NoteEditor/styles/index.js
|
||||
packages/app-desktop/gui/NoteEditor/utils/clipboardUtils.js
|
||||
packages/app-desktop/gui/NoteEditor/utils/clipboardUtils.test.js
|
||||
packages/app-desktop/gui/NoteEditor/utils/clipboardUtils.js
|
||||
packages/app-desktop/gui/NoteEditor/utils/contextMenu.js
|
||||
packages/app-desktop/gui/NoteEditor/utils/contextMenuUtils.js
|
||||
packages/app-desktop/gui/NoteEditor/utils/index.js
|
||||
packages/app-desktop/gui/NoteEditor/utils/resourceHandling.test.js
|
||||
packages/app-desktop/gui/NoteEditor/utils/resourceHandling.js
|
||||
packages/app-desktop/gui/NoteEditor/utils/types.js
|
||||
packages/app-desktop/gui/NoteEditor/utils/useDropHandler.js
|
||||
@@ -268,17 +276,17 @@ packages/app-desktop/gui/ResizableLayout/utils/findItemByKey.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/isTempContainer.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/iterateItems.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/layoutItemProp.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/movements.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/movements.test.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/persist.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/movements.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/persist.test.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/persist.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/removeItem.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/removeKeylessItems.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/setLayoutItemProps.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/style.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/types.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/useLayoutItemSizes.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/useLayoutItemSizes.test.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/useLayoutItemSizes.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/useWindowResizeEvent.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/validateLayout.js
|
||||
packages/app-desktop/gui/ResourceScreen.js
|
||||
@@ -337,14 +345,14 @@ packages/app-desktop/services/plugins/hooks/useViewIsReady.js
|
||||
packages/app-desktop/services/plugins/hooks/useWebviewToPluginMessages.js
|
||||
packages/app-desktop/services/restart.js
|
||||
packages/app-desktop/services/share/invitationRespond.js
|
||||
packages/app-desktop/services/sortOrder/PerFolderSortOrderService.js
|
||||
packages/app-desktop/services/sortOrder/PerFolderSortOrderService.test.js
|
||||
packages/app-desktop/services/sortOrder/notesSortOrderUtils.js
|
||||
packages/app-desktop/services/sortOrder/PerFolderSortOrderService.js
|
||||
packages/app-desktop/services/sortOrder/notesSortOrderUtils.test.js
|
||||
packages/app-desktop/services/sortOrder/notesSortOrderUtils.js
|
||||
packages/app-desktop/services/spellChecker/SpellCheckerServiceDriverNative.js
|
||||
packages/app-desktop/tools/notarizeMacApp.js
|
||||
packages/app-desktop/utils/checkForUpdatesUtils.js
|
||||
packages/app-desktop/utils/checkForUpdatesUtils.test.js
|
||||
packages/app-desktop/utils/checkForUpdatesUtils.js
|
||||
packages/app-desktop/utils/markupLanguageUtils.js
|
||||
packages/app-mobile/PluginAssetsLoader.js
|
||||
packages/app-mobile/components/ActionButton.js
|
||||
@@ -359,17 +367,17 @@ packages/app-mobile/components/NoteBodyViewer/NoteBodyViewer.js
|
||||
packages/app-mobile/components/NoteBodyViewer/hooks/useOnMessage.js
|
||||
packages/app-mobile/components/NoteBodyViewer/hooks/useOnResourceLongPress.js
|
||||
packages/app-mobile/components/NoteBodyViewer/hooks/useSource.js
|
||||
packages/app-mobile/components/NoteEditor/CodeMirror/CodeMirror.js
|
||||
packages/app-mobile/components/NoteEditor/CodeMirror/CodeMirror.test.js
|
||||
packages/app-mobile/components/NoteEditor/CodeMirror/CodeMirror.js
|
||||
packages/app-mobile/components/NoteEditor/CodeMirror/decoratorExtension.js
|
||||
packages/app-mobile/components/NoteEditor/CodeMirror/markdownCommands.bulletedVsChecklist.test.js
|
||||
packages/app-mobile/components/NoteEditor/CodeMirror/markdownCommands.js
|
||||
packages/app-mobile/components/NoteEditor/CodeMirror/markdownCommands.test.js
|
||||
packages/app-mobile/components/NoteEditor/CodeMirror/markdownCommands.toggleList.test.js
|
||||
packages/app-mobile/components/NoteEditor/CodeMirror/markdownMathParser.js
|
||||
packages/app-mobile/components/NoteEditor/CodeMirror/markdownCommands.js
|
||||
packages/app-mobile/components/NoteEditor/CodeMirror/markdownMathParser.test.js
|
||||
packages/app-mobile/components/NoteEditor/CodeMirror/markdownReformatter.js
|
||||
packages/app-mobile/components/NoteEditor/CodeMirror/markdownMathParser.js
|
||||
packages/app-mobile/components/NoteEditor/CodeMirror/markdownReformatter.test.js
|
||||
packages/app-mobile/components/NoteEditor/CodeMirror/markdownReformatter.js
|
||||
packages/app-mobile/components/NoteEditor/CodeMirror/syntaxHighlightingLanguages.js
|
||||
packages/app-mobile/components/NoteEditor/CodeMirror/testUtil/createEditor.js
|
||||
packages/app-mobile/components/NoteEditor/CodeMirror/testUtil/forceFullParse.js
|
||||
@@ -400,9 +408,14 @@ packages/app-mobile/components/app-nav.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/getResponsiveValue.js
|
||||
packages/app-mobile/components/getResponsiveValue.test.js
|
||||
packages/app-mobile/components/screens/ConfigScreen.js
|
||||
packages/app-mobile/components/getResponsiveValue.js
|
||||
packages/app-mobile/components/screens/ConfigScreen/ConfigScreen.js
|
||||
packages/app-mobile/components/screens/ConfigScreen/ConfigScreenButton.js
|
||||
packages/app-mobile/components/screens/ConfigScreen/NoteExportSection/NoteExportButton.test.js
|
||||
packages/app-mobile/components/screens/ConfigScreen/NoteExportSection/NoteExportButton.js
|
||||
packages/app-mobile/components/screens/ConfigScreen/NoteExportSection/exportAllFolders.js
|
||||
packages/app-mobile/components/screens/ConfigScreen/configScreenStyles.js
|
||||
packages/app-mobile/components/screens/Note.js
|
||||
packages/app-mobile/components/screens/Notes.js
|
||||
packages/app-mobile/components/screens/UpgradeSyncTargetScreen.js
|
||||
@@ -415,6 +428,7 @@ 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/PluginRunner.js
|
||||
packages/app-mobile/services/profiles/index.js
|
||||
packages/app-mobile/services/voiceTyping/vosk.android.js
|
||||
packages/app-mobile/services/voiceTyping/vosk.ios.js
|
||||
@@ -423,27 +437,29 @@ packages/app-mobile/tools/buildInjectedJs.js
|
||||
packages/app-mobile/utils/ShareExtension.js
|
||||
packages/app-mobile/utils/ShareUtils.js
|
||||
packages/app-mobile/utils/TlsUtils.js
|
||||
packages/app-mobile/utils/autodetectTheme.js
|
||||
packages/app-mobile/utils/checkPermissions.js
|
||||
packages/app-mobile/utils/createRootStyle.js
|
||||
packages/app-mobile/utils/debounce.js
|
||||
packages/app-mobile/utils/fs-driver-rn.js
|
||||
packages/app-mobile/utils/markupLanguageUtils.js
|
||||
packages/app-mobile/utils/setupNotifications.js
|
||||
packages/app-mobile/utils/shareHandler.js
|
||||
packages/app-mobile/utils/types.js
|
||||
packages/fork-htmlparser2/src/CollectingHandler.js
|
||||
packages/fork-htmlparser2/src/FeedHandler.js
|
||||
packages/fork-htmlparser2/src/FeedHandler.spec.js
|
||||
packages/fork-htmlparser2/src/FeedHandler.js
|
||||
packages/fork-htmlparser2/src/MultiplexHandler.js
|
||||
packages/fork-htmlparser2/src/Parser.js
|
||||
packages/fork-htmlparser2/src/Parser.spec.js
|
||||
packages/fork-htmlparser2/src/Parser.js
|
||||
packages/fork-htmlparser2/src/Tokenizer.js
|
||||
packages/fork-htmlparser2/src/WritableStream.js
|
||||
packages/fork-htmlparser2/src/WritableStream.spec.js
|
||||
packages/fork-htmlparser2/src/WritableStream.js
|
||||
packages/fork-htmlparser2/src/__fixtures__/test-helper.js
|
||||
packages/fork-htmlparser2/src/__tests__/events.js
|
||||
packages/fork-htmlparser2/src/__tests__/stream.js
|
||||
packages/fork-htmlparser2/src/index.js
|
||||
packages/fork-htmlparser2/src/index.spec.js
|
||||
packages/fork-htmlparser2/src/index.js
|
||||
packages/generator-joplin/generators/app/templates/api/index.js
|
||||
packages/generator-joplin/generators/app/templates/api/types.js
|
||||
packages/generator-joplin/generators/app/templates/api_index.js
|
||||
@@ -456,17 +472,18 @@ packages/lib/BaseModel.js
|
||||
packages/lib/BaseSyncTarget.js
|
||||
packages/lib/ClipperServer.js
|
||||
packages/lib/CssUtils.js
|
||||
packages/lib/EventDispatcher.js
|
||||
packages/lib/EventDispatcher.test.js
|
||||
packages/lib/EventDispatcher.js
|
||||
packages/lib/HtmlToMd.js
|
||||
packages/lib/InMemoryCache.js
|
||||
packages/lib/InMemoryCache.test.js
|
||||
packages/lib/InMemoryCache.js
|
||||
packages/lib/JoplinDatabase.js
|
||||
packages/lib/JoplinError.js
|
||||
packages/lib/JoplinServerApi.js
|
||||
packages/lib/Logger.js
|
||||
packages/lib/ObjectUtils.js
|
||||
packages/lib/PoorManIntervals.js
|
||||
packages/lib/RotatingLogs.test.js
|
||||
packages/lib/RotatingLogs.js
|
||||
packages/lib/SyncTargetJoplinCloud.js
|
||||
packages/lib/SyncTargetJoplinServer.js
|
||||
packages/lib/SyncTargetNone.js
|
||||
@@ -476,8 +493,8 @@ packages/lib/Synchronizer.js
|
||||
packages/lib/TaskQueue.js
|
||||
packages/lib/WelcomeUtils.js
|
||||
packages/lib/array.js
|
||||
packages/lib/callbackUrlUtils.js
|
||||
packages/lib/callbackUrlUtils.test.js
|
||||
packages/lib/callbackUrlUtils.js
|
||||
packages/lib/commands/historyBackward.js
|
||||
packages/lib/commands/historyForward.js
|
||||
packages/lib/commands/index.js
|
||||
@@ -485,12 +502,14 @@ packages/lib/commands/openMasterPasswordDialog.js
|
||||
packages/lib/commands/synchronize.js
|
||||
packages/lib/components/EncryptionConfigScreen/utils.js
|
||||
packages/lib/components/shared/note-screen-shared.js
|
||||
packages/lib/components/shared/reduxSharedMiddleware.js
|
||||
packages/lib/database-driver-better-sqlite.js
|
||||
packages/lib/database.js
|
||||
packages/lib/debug/DebugService.js
|
||||
packages/lib/dom.js
|
||||
packages/lib/dummy.test.js
|
||||
packages/lib/errorUtils.js
|
||||
packages/lib/errors.js
|
||||
packages/lib/eventManager.js
|
||||
packages/lib/file-api-driver-joplinServer.js
|
||||
packages/lib/file-api-driver-memory.js
|
||||
@@ -503,41 +522,41 @@ packages/lib/geolocation-node.js
|
||||
packages/lib/hooks/useAsyncEffect.js
|
||||
packages/lib/hooks/useElementSize.js
|
||||
packages/lib/hooks/useEventListener.js
|
||||
packages/lib/htmlUtils.js
|
||||
packages/lib/htmlUtils.test.js
|
||||
packages/lib/htmlUtils.js
|
||||
packages/lib/htmlUtils2.test.js
|
||||
packages/lib/import-enex-md-gen.js
|
||||
packages/lib/import-enex-md-gen.test.js
|
||||
packages/lib/import-enex-md-gen.js
|
||||
packages/lib/import-enex.js
|
||||
packages/lib/locale.js
|
||||
packages/lib/locale.test.js
|
||||
packages/lib/markdownUtils.js
|
||||
packages/lib/locale.js
|
||||
packages/lib/markdownUtils.test.js
|
||||
packages/lib/markdownUtils.js
|
||||
packages/lib/markdownUtils2.test.js
|
||||
packages/lib/markupLanguageUtils.js
|
||||
packages/lib/migrations/42.js
|
||||
packages/lib/models/Alarm.js
|
||||
packages/lib/models/BaseItem.js
|
||||
packages/lib/models/Folder.js
|
||||
packages/lib/models/Folder.sharing.test.js
|
||||
packages/lib/models/Folder.test.js
|
||||
packages/lib/models/ItemChange.js
|
||||
packages/lib/models/Folder.js
|
||||
packages/lib/models/ItemChange.test.js
|
||||
packages/lib/models/MasterKey.js
|
||||
packages/lib/models/ItemChange.js
|
||||
packages/lib/models/MasterKey.test.js
|
||||
packages/lib/models/MasterKey.js
|
||||
packages/lib/models/Migration.js
|
||||
packages/lib/models/Note.js
|
||||
packages/lib/models/Note.test.js
|
||||
packages/lib/models/Note.js
|
||||
packages/lib/models/NoteResource.js
|
||||
packages/lib/models/NoteTag.js
|
||||
packages/lib/models/Resource.js
|
||||
packages/lib/models/Resource.test.js
|
||||
packages/lib/models/Resource.js
|
||||
packages/lib/models/ResourceLocalState.js
|
||||
packages/lib/models/Revision.js
|
||||
packages/lib/models/Revision.test.js
|
||||
packages/lib/models/Revision.js
|
||||
packages/lib/models/Search.js
|
||||
packages/lib/models/Setting.js
|
||||
packages/lib/models/Setting.test.js
|
||||
packages/lib/models/Setting.js
|
||||
packages/lib/models/SmartFilter.js
|
||||
packages/lib/models/Tag.js
|
||||
packages/lib/models/dateTimeFormats.test.js
|
||||
@@ -545,21 +564,22 @@ packages/lib/models/settings/FileHandler.js
|
||||
packages/lib/models/utils/itemCanBeEncrypted.js
|
||||
packages/lib/models/utils/paginatedFeed.js
|
||||
packages/lib/models/utils/paginationToSql.js
|
||||
packages/lib/models/utils/readOnly.js
|
||||
packages/lib/models/utils/types.js
|
||||
packages/lib/models/utils/userData.js
|
||||
packages/lib/models/utils/userData.test.js
|
||||
packages/lib/models/utils/userData.js
|
||||
packages/lib/net-utils.js
|
||||
packages/lib/ntp.js
|
||||
packages/lib/onedrive-api.js
|
||||
packages/lib/path-utils.js
|
||||
packages/lib/reducer.js
|
||||
packages/lib/registry.js
|
||||
packages/lib/registry.test.js
|
||||
packages/lib/registry.js
|
||||
packages/lib/services/AlarmService.js
|
||||
packages/lib/services/AlarmServiceDriverNode.js
|
||||
packages/lib/services/BaseService.js
|
||||
packages/lib/services/CommandService.js
|
||||
packages/lib/services/CommandService.test.js
|
||||
packages/lib/services/CommandService.js
|
||||
packages/lib/services/DecryptionWorker.js
|
||||
packages/lib/services/ExternalEditWatcher.js
|
||||
packages/lib/services/ExternalEditWatcher/utils.js
|
||||
@@ -575,14 +595,14 @@ packages/lib/services/ReportService.js
|
||||
packages/lib/services/ResourceEditWatcher/index.js
|
||||
packages/lib/services/ResourceEditWatcher/reducer.js
|
||||
packages/lib/services/ResourceFetcher.js
|
||||
packages/lib/services/ResourceService.js
|
||||
packages/lib/services/ResourceService.test.js
|
||||
packages/lib/services/RevisionService.js
|
||||
packages/lib/services/ResourceService.js
|
||||
packages/lib/services/RevisionService.test.js
|
||||
packages/lib/services/RevisionService.js
|
||||
packages/lib/services/SettingUtils.js
|
||||
packages/lib/services/UndoRedoService.js
|
||||
packages/lib/services/WhenClause.js
|
||||
packages/lib/services/WhenClause.test.js
|
||||
packages/lib/services/WhenClause.js
|
||||
packages/lib/services/commands/MenuUtils.js
|
||||
packages/lib/services/commands/ToolbarButtonUtils.js
|
||||
packages/lib/services/commands/commandsToMarkdownTable.js
|
||||
@@ -593,40 +613,40 @@ packages/lib/services/commands/stateToWhenClauseContext.js
|
||||
packages/lib/services/contextkey/contextkey.js
|
||||
packages/lib/services/database/types.js
|
||||
packages/lib/services/debug/populateDatabase.js
|
||||
packages/lib/services/e2ee/EncryptionService.js
|
||||
packages/lib/services/e2ee/EncryptionService.test.js
|
||||
packages/lib/services/e2ee/EncryptionService.js
|
||||
packages/lib/services/e2ee/RSA.node.js
|
||||
packages/lib/services/e2ee/ppk.js
|
||||
packages/lib/services/e2ee/ppk.test.js
|
||||
packages/lib/services/e2ee/ppk.js
|
||||
packages/lib/services/e2ee/ppkTestUtils.js
|
||||
packages/lib/services/e2ee/types.js
|
||||
packages/lib/services/e2ee/utils.js
|
||||
packages/lib/services/e2ee/utils.test.js
|
||||
packages/lib/services/interop/InteropService.js
|
||||
packages/lib/services/e2ee/utils.js
|
||||
packages/lib/services/interop/InteropService.test.js
|
||||
packages/lib/services/interop/InteropService.js
|
||||
packages/lib/services/interop/InteropService_Exporter_Base.js
|
||||
packages/lib/services/interop/InteropService_Exporter_Custom.js
|
||||
packages/lib/services/interop/InteropService_Exporter_Html.js
|
||||
packages/lib/services/interop/InteropService_Exporter_Html.test.js
|
||||
packages/lib/services/interop/InteropService_Exporter_Html.js
|
||||
packages/lib/services/interop/InteropService_Exporter_Jex.js
|
||||
packages/lib/services/interop/InteropService_Exporter_Md.js
|
||||
packages/lib/services/interop/InteropService_Exporter_Md.test.js
|
||||
packages/lib/services/interop/InteropService_Exporter_Md_frontmatter.js
|
||||
packages/lib/services/interop/InteropService_Exporter_Md.js
|
||||
packages/lib/services/interop/InteropService_Exporter_Md_frontmatter.test.js
|
||||
packages/lib/services/interop/InteropService_Exporter_Md_frontmatter.js
|
||||
packages/lib/services/interop/InteropService_Exporter_Raw.js
|
||||
packages/lib/services/interop/InteropService_Importer_Base.js
|
||||
packages/lib/services/interop/InteropService_Importer_Custom.js
|
||||
packages/lib/services/interop/InteropService_Importer_EnexToHtml.js
|
||||
packages/lib/services/interop/InteropService_Importer_EnexToMd.js
|
||||
packages/lib/services/interop/InteropService_Importer_Jex.js
|
||||
packages/lib/services/interop/InteropService_Importer_Md.js
|
||||
packages/lib/services/interop/InteropService_Importer_Md.test.js
|
||||
packages/lib/services/interop/InteropService_Importer_Md_frontmatter.js
|
||||
packages/lib/services/interop/InteropService_Importer_Md.js
|
||||
packages/lib/services/interop/InteropService_Importer_Md_frontmatter.test.js
|
||||
packages/lib/services/interop/InteropService_Importer_Raw.js
|
||||
packages/lib/services/interop/InteropService_Importer_Md_frontmatter.js
|
||||
packages/lib/services/interop/InteropService_Importer_Raw.test.js
|
||||
packages/lib/services/interop/Module.js
|
||||
packages/lib/services/interop/InteropService_Importer_Raw.js
|
||||
packages/lib/services/interop/Module.test.js
|
||||
packages/lib/services/interop/Module.js
|
||||
packages/lib/services/interop/types.js
|
||||
packages/lib/services/joplinServer/personalizedUserContentBaseUrl.js
|
||||
packages/lib/services/keychain/KeychainService.js
|
||||
@@ -673,23 +693,23 @@ packages/lib/services/plugins/utils/makeListener.js
|
||||
packages/lib/services/plugins/utils/manifestFromObject.js
|
||||
packages/lib/services/plugins/utils/mapEventHandlersToIds.js
|
||||
packages/lib/services/plugins/utils/types.js
|
||||
packages/lib/services/plugins/utils/validatePluginId.js
|
||||
packages/lib/services/plugins/utils/validatePluginId.test.js
|
||||
packages/lib/services/plugins/utils/validatePluginVersion.js
|
||||
packages/lib/services/plugins/utils/validatePluginId.js
|
||||
packages/lib/services/plugins/utils/validatePluginVersion.test.js
|
||||
packages/lib/services/profileConfig/index.js
|
||||
packages/lib/services/plugins/utils/validatePluginVersion.js
|
||||
packages/lib/services/profileConfig/index.test.js
|
||||
packages/lib/services/profileConfig/index.js
|
||||
packages/lib/services/profileConfig/initProfile.js
|
||||
packages/lib/services/profileConfig/mergeGlobalAndLocalSettings.js
|
||||
packages/lib/services/profileConfig/splitGlobalAndLocalSettings.js
|
||||
packages/lib/services/profileConfig/types.js
|
||||
packages/lib/services/rest/Api.js
|
||||
packages/lib/services/rest/Api.test.js
|
||||
packages/lib/services/rest/Api.js
|
||||
packages/lib/services/rest/ApiResponse.js
|
||||
packages/lib/services/rest/actionApi.desktop.js
|
||||
packages/lib/services/rest/routes/auth.js
|
||||
packages/lib/services/rest/routes/events.js
|
||||
packages/lib/services/rest/routes/events.test.js
|
||||
packages/lib/services/rest/routes/events.js
|
||||
packages/lib/services/rest/routes/folders.js
|
||||
packages/lib/services/rest/routes/master_keys.js
|
||||
packages/lib/services/rest/routes/notes.js
|
||||
@@ -707,26 +727,26 @@ packages/lib/services/rest/utils/readonlyProperties.js
|
||||
packages/lib/services/rest/utils/requestFields.js
|
||||
packages/lib/services/rest/utils/requestPaginationOptions.js
|
||||
packages/lib/services/searchengine/SearchEngine.js
|
||||
packages/lib/services/searchengine/SearchEngineUtils.js
|
||||
packages/lib/services/searchengine/SearchEngineUtils.test.js
|
||||
packages/lib/services/searchengine/SearchEngineUtils.js
|
||||
packages/lib/services/searchengine/SearchFilter.test.js
|
||||
packages/lib/services/searchengine/filterParser.js
|
||||
packages/lib/services/searchengine/filterParser.test.js
|
||||
packages/lib/services/searchengine/gotoAnythingStyleQuery.js
|
||||
packages/lib/services/searchengine/filterParser.js
|
||||
packages/lib/services/searchengine/gotoAnythingStyleQuery.test.js
|
||||
packages/lib/services/searchengine/gotoAnythingStyleQuery.js
|
||||
packages/lib/services/searchengine/queryBuilder.js
|
||||
packages/lib/services/share/ShareService.js
|
||||
packages/lib/services/share/ShareService.test.js
|
||||
packages/lib/services/share/ShareService.js
|
||||
packages/lib/services/share/reducer.js
|
||||
packages/lib/services/spellChecker/SpellCheckerService.js
|
||||
packages/lib/services/spellChecker/SpellCheckerServiceDriverBase.js
|
||||
packages/lib/services/style/cssToTheme.js
|
||||
packages/lib/services/style/cssToTheme.test.js
|
||||
packages/lib/services/style/cssToTheme.js
|
||||
packages/lib/services/style/loadCssToTheme.js
|
||||
packages/lib/services/style/themeToCss.js
|
||||
packages/lib/services/style/themeToCss.test.js
|
||||
packages/lib/services/synchronizer/ItemUploader.js
|
||||
packages/lib/services/style/themeToCss.js
|
||||
packages/lib/services/synchronizer/ItemUploader.test.js
|
||||
packages/lib/services/synchronizer/ItemUploader.js
|
||||
packages/lib/services/synchronizer/LockHandler.js
|
||||
packages/lib/services/synchronizer/MigrationHandler.js
|
||||
packages/lib/services/synchronizer/Synchronizer.basics.test.js
|
||||
@@ -743,12 +763,15 @@ packages/lib/services/synchronizer/migrations/1.js
|
||||
packages/lib/services/synchronizer/migrations/2.js
|
||||
packages/lib/services/synchronizer/migrations/3.js
|
||||
packages/lib/services/synchronizer/syncDebugLog.js
|
||||
packages/lib/services/synchronizer/syncInfoUtils.js
|
||||
packages/lib/services/synchronizer/syncInfoUtils.test.js
|
||||
packages/lib/services/synchronizer/syncInfoUtils.js
|
||||
packages/lib/services/synchronizer/synchronizer_LockHandler.test.js
|
||||
packages/lib/services/synchronizer/synchronizer_MigrationHandler.test.js
|
||||
packages/lib/services/synchronizer/tools.js
|
||||
packages/lib/services/synchronizer/utils/handleConflictAction.js
|
||||
packages/lib/services/synchronizer/utils/handleSyncStartupOperation.js
|
||||
packages/lib/services/synchronizer/utils/resourceRemotePath.js
|
||||
packages/lib/services/synchronizer/utils/syncDeleteStep.js
|
||||
packages/lib/services/synchronizer/utils/types.js
|
||||
packages/lib/shim.js
|
||||
packages/lib/testing/syncTargetUtils.js
|
||||
@@ -767,11 +790,12 @@ packages/lib/themes/type.js
|
||||
packages/lib/time.js
|
||||
packages/lib/utils/credentialFiles.js
|
||||
packages/lib/utils/joplinCloud.js
|
||||
packages/lib/utils/webDAVUtils.js
|
||||
packages/lib/utils/userFetcher.js
|
||||
packages/lib/utils/webDAVUtils.test.js
|
||||
packages/lib/utils/webDAVUtils.js
|
||||
packages/lib/uuid.js
|
||||
packages/lib/versionInfo.js
|
||||
packages/lib/versionInfo.test.js
|
||||
packages/lib/versionInfo.js
|
||||
packages/pdf-viewer/FullViewer.js
|
||||
packages/pdf-viewer/Page.js
|
||||
packages/pdf-viewer/PdfDocument.js
|
||||
@@ -792,30 +816,31 @@ packages/pdf-viewer/ui/IconButtons.js
|
||||
packages/pdf-viewer/ui/ZoomControls.js
|
||||
packages/plugin-repo-cli/commands/updateRelease.js
|
||||
packages/plugin-repo-cli/index.js
|
||||
packages/plugin-repo-cli/lib/checkIfPluginCanBeAdded.js
|
||||
packages/plugin-repo-cli/lib/checkIfPluginCanBeAdded.test.js
|
||||
packages/plugin-repo-cli/lib/errorsHaveChanged.js
|
||||
packages/plugin-repo-cli/lib/checkIfPluginCanBeAdded.js
|
||||
packages/plugin-repo-cli/lib/errorsHaveChanged.test.js
|
||||
packages/plugin-repo-cli/lib/gitCompareUrl.js
|
||||
packages/plugin-repo-cli/lib/errorsHaveChanged.js
|
||||
packages/plugin-repo-cli/lib/gitCompareUrl.test.js
|
||||
packages/plugin-repo-cli/lib/overrideUtils.js
|
||||
packages/plugin-repo-cli/lib/gitCompareUrl.js
|
||||
packages/plugin-repo-cli/lib/overrideUtils.test.js
|
||||
packages/plugin-repo-cli/lib/overrideUtils.js
|
||||
packages/plugin-repo-cli/lib/types.js
|
||||
packages/plugin-repo-cli/lib/updateReadme.js
|
||||
packages/plugin-repo-cli/lib/updateReadme.test.js
|
||||
packages/plugin-repo-cli/lib/updateReadme.js
|
||||
packages/plugin-repo-cli/lib/utils.js
|
||||
packages/plugins/ToggleSidebars/api/index.js
|
||||
packages/plugins/ToggleSidebars/api/types.js
|
||||
packages/plugins/ToggleSidebars/src/index.js
|
||||
packages/react-native-saf-x/src/index.js
|
||||
packages/renderer/HtmlToHtml.test.js
|
||||
packages/renderer/HtmlToHtml.js
|
||||
packages/renderer/InMemoryCache.js
|
||||
packages/renderer/MarkupToHtml.js
|
||||
packages/renderer/MdToHtml.js
|
||||
packages/renderer/MdToHtml/createEventHandlingAttrs.js
|
||||
packages/renderer/MdToHtml/createEventHandlingAttrs.test.js
|
||||
packages/renderer/MdToHtml/linkReplacement.js
|
||||
packages/renderer/MdToHtml/createEventHandlingAttrs.js
|
||||
packages/renderer/MdToHtml/linkReplacement.test.js
|
||||
packages/renderer/MdToHtml/linkReplacement.js
|
||||
packages/renderer/MdToHtml/renderMedia.js
|
||||
packages/renderer/MdToHtml/rules/checkbox.js
|
||||
packages/renderer/MdToHtml/rules/code_inline.js
|
||||
@@ -834,25 +859,26 @@ packages/renderer/MdToHtml/setupLinkify.js
|
||||
packages/renderer/MdToHtml/validateLinks.js
|
||||
packages/renderer/headerAnchor.js
|
||||
packages/renderer/highlight.js
|
||||
packages/renderer/htmlUtils.js
|
||||
packages/renderer/htmlUtils.test.js
|
||||
packages/renderer/htmlUtils.js
|
||||
packages/renderer/index.js
|
||||
packages/renderer/noteStyle.js
|
||||
packages/renderer/pathUtils.js
|
||||
packages/renderer/utils.js
|
||||
packages/tools/build-release-stats.js
|
||||
packages/tools/build-welcome.js
|
||||
packages/tools/buildServerDocker.js
|
||||
packages/tools/buildServerDocker.test.js
|
||||
packages/tools/bundleDefaultPlugins.js
|
||||
packages/tools/buildServerDocker.js
|
||||
packages/tools/bundleDefaultPlugins.test.js
|
||||
packages/tools/checkLibPaths.js
|
||||
packages/tools/bundleDefaultPlugins.js
|
||||
packages/tools/checkIgnoredFiles.js
|
||||
packages/tools/checkLibPaths.test.js
|
||||
packages/tools/checkLibPaths.js
|
||||
packages/tools/convertThemesToCss.js
|
||||
packages/tools/generate-database-types.js
|
||||
packages/tools/generate-images.js
|
||||
packages/tools/git-changelog.js
|
||||
packages/tools/git-changelog.test.js
|
||||
packages/tools/git-changelog.js
|
||||
packages/tools/licenseChecker.js
|
||||
packages/tools/release-android.js
|
||||
packages/tools/release-cli.js
|
||||
@@ -864,8 +890,8 @@ packages/tools/setupNewRelease.js
|
||||
packages/tools/spellcheck.js
|
||||
packages/tools/tagServerLatest.js
|
||||
packages/tools/tool-utils.js
|
||||
packages/tools/update-readme-download.js
|
||||
packages/tools/update-readme-download.test.js
|
||||
packages/tools/update-readme-download.js
|
||||
packages/tools/update-readme-sponsors.js
|
||||
packages/tools/updateMarkdownDoc.js
|
||||
packages/tools/utils/discourse.js
|
||||
@@ -875,14 +901,14 @@ packages/tools/website/build.js
|
||||
packages/tools/website/buildTranslations.js
|
||||
packages/tools/website/updateDownloadPage.js
|
||||
packages/tools/website/updateNews.js
|
||||
packages/tools/website/utils/applyTranslations.js
|
||||
packages/tools/website/utils/applyTranslations.test.js
|
||||
packages/tools/website/utils/convertLinksToLocale.js
|
||||
packages/tools/website/utils/applyTranslations.js
|
||||
packages/tools/website/utils/convertLinksToLocale.test.js
|
||||
packages/tools/website/utils/convertLinksToLocale.js
|
||||
packages/tools/website/utils/frontMatter.js
|
||||
packages/tools/website/utils/news.js
|
||||
packages/tools/website/utils/openGraph.js
|
||||
packages/tools/website/utils/openGraph.test.js
|
||||
packages/tools/website/utils/openGraph.js
|
||||
packages/tools/website/utils/parser.js
|
||||
packages/tools/website/utils/pressCarousel.js
|
||||
packages/tools/website/utils/processTranslations.js
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
diff --git a/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedModule.java b/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedModule.java
|
||||
index 0f52b73c61625db2a3081c0950b6bdd2b06e3d40..b0fc3de4be0b3a26b638683613c63c783c2739bb 100644
|
||||
--- a/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedModule.java
|
||||
+++ b/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedModule.java
|
||||
@@ -38,7 +38,7 @@ import com.facebook.react.uimanager.common.ViewUtil;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
-import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
+import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
@@ -151,7 +151,10 @@ public class NativeAnimatedModule extends NativeAnimatedModuleSpec
|
||||
}
|
||||
|
||||
private class ConcurrentOperationQueue {
|
||||
- private final Queue<UIThreadOperation> mQueue = new ConcurrentLinkedQueue<>();
|
||||
+ // Patch: Use LinkedBlockingQueue instead of ConcurrentLinkedQueue.
|
||||
+ // In some versions of Android, ConcurrentLinkedQueue is known to drop
|
||||
+ // items, causing crashing. See https://github.com/laurent22/joplin/issues/8425
|
||||
+ private final Queue<UIThreadOperation> mQueue = new LinkedBlockingQueue<>();
|
||||
@Nullable private UIThreadOperation mPeekedOperation = null;
|
||||
|
||||
@AnyThread
|
||||
@@ -0,0 +1,27 @@
|
||||
diff --git a/android/src/main/java/com/swmansion/reanimated/NodesManager.java b/android/src/main/java/com/swmansion/reanimated/NodesManager.java
|
||||
index e974f8eb827a35be4d7e5fa9b096af9387c595dd..bc9e5ff566c9484274e8eacefc88327a5ff30def 100644
|
||||
--- a/android/src/main/java/com/swmansion/reanimated/NodesManager.java
|
||||
+++ b/android/src/main/java/com/swmansion/reanimated/NodesManager.java
|
||||
@@ -34,7 +34,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
-import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
+import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.Semaphore;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
@@ -80,7 +80,12 @@ public class NodesManager implements EventDispatcherListener {
|
||||
private ReactApplicationContext mReactApplicationContext;
|
||||
private RCTEventEmitter mCustomEventHandler;
|
||||
private List<OnAnimationFrame> mFrameCallbacks = new ArrayList<>();
|
||||
- private ConcurrentLinkedQueue<CopiedEvent> mEventQueue = new ConcurrentLinkedQueue<>();
|
||||
+
|
||||
+ // Patch: On some versions of Android, ConcurrentLinkedQueue is known to
|
||||
+ // drop items. LinkedBlockingQueue is a potentially-slower alternative that
|
||||
+ // should not drop items.
|
||||
+ // See https://github.com/laurent22/joplin/issues/8425
|
||||
+ private LinkedBlockingQueue<CopiedEvent> mEventQueue = new LinkedBlockingQueue<>();
|
||||
public double currentFrameTimeMs;
|
||||
public Set<String> uiProps = Collections.emptySet();
|
||||
public Set<String> nativeProps = Collections.emptySet();
|
||||
@@ -24,3 +24,9 @@ logFilters:
|
||||
# eg "string.prototype.matchall@npm:4.0.8 can't be found in the cache and will be fetched from the remote registry"
|
||||
- code: YN0013
|
||||
level: discard
|
||||
|
||||
# To avoid the error "The remote archive doesn't match the expected checksum".
|
||||
# Yarn offers no way to understand what the issue is when it happens, or what
|
||||
# needs to be done so it's just security theater that we have no choice but to
|
||||
# disable.
|
||||
checksumBehavior: update
|
||||
|
||||
@@ -789,7 +789,7 @@ footer .bottom-links-row p {
|
||||
}
|
||||
|
||||
#menu-mobile .social-links .social-link-mastodon,
|
||||
#menu-mobile .social-links .social-link-reddit,
|
||||
#menu-mobile .social-links .social-link-lemmy,
|
||||
#menu-mobile .social-links .social-link-linkedin,
|
||||
#menu-mobile .social-links .social-link-patreon {
|
||||
display: none;
|
||||
|
||||
BIN
Assets/WebsiteAssets/images/email_to_note/desktop.png
Normal file
BIN
Assets/WebsiteAssets/images/email_to_note/desktop.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 46 KiB |
BIN
Assets/WebsiteAssets/images/email_to_note/mobile.png
Normal file
BIN
Assets/WebsiteAssets/images/email_to_note/mobile.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
BIN
Assets/WebsiteAssets/images/email_to_note/website.png
Normal file
BIN
Assets/WebsiteAssets/images/email_to_note/website.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 23 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 83 KiB |
BIN
Assets/WebsiteAssets/images/sponsors/CitricSheep.png
Normal file
BIN
Assets/WebsiteAssets/images/sponsors/CitricSheep.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 48 KiB |
@@ -5,7 +5,7 @@
|
||||
<a class="social-link-patreon" href="https://www.patreon.com/joplin" title="Joplin Patreon"><i class="fab fa-patreon"></i></a>
|
||||
<a class="social-link-discord" href="https://discord.gg/VSj7AFHvpq" title="Joplin Discord chat"><i class="fab fa-discord"></i></a>
|
||||
<a class="social-link-linkedin" href="https://www.linkedin.com/company/joplin" title="Joplin LinkedIn Feed"><i class="fab fa-linkedin"></i></a>
|
||||
<a class="social-link-reddit" href="https://www.reddit.com/r/joplinapp/" title="Joplin Subreddit"><i class="fab fa-reddit"></i></a>
|
||||
<a class="social-link-lemmy" href="https://sopuli.xyz/c/joplinapp" title="Joplin Lemmy Community"><i class="fas fa-otter"></i></a>
|
||||
<a class="social-link-github" href="https://github.com/laurent22/joplin/" title="Joplin GitHub repository"><i class="fab fa-github"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -96,6 +96,8 @@
|
||||
|
||||
console.info('Creating Stripe session for price:', priceId, 'Promotion code:', promotionCode);
|
||||
|
||||
const source = localStorage.getItem('source');
|
||||
|
||||
return fetch("{{{stripeConfig.webhookBaseUrl}}}/stripe/createCheckoutSession", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
@@ -105,6 +107,7 @@
|
||||
priceId,
|
||||
promotionCode,
|
||||
email: checkoutSessionUser ? checkoutSessionUser.email : '',
|
||||
source,
|
||||
})
|
||||
}).then(async function(result) {
|
||||
if (!result.ok) {
|
||||
|
||||
16
README.md
16
README.md
@@ -66,7 +66,7 @@ A community maintained list of these distributions can be found here: [Unofficia
|
||||
# Sponsors
|
||||
|
||||
<!-- SPONSORS-ORG -->
|
||||
<a href="https://seirei.ne.jp"><img title="Serei Network" width="256" src="https://joplinapp.org/images/sponsors/SeireiNetwork.png"/></a> <a href="https://www.hosting.de/nextcloud/?mtm_campaign=managed-nextcloud&mtm_kwd=joplinapp&mtm_source=joplinapp-webseite&mtm_medium=banner"><img title="Hosting.de" width="256" src="https://joplinapp.org/images/sponsors/HostingDe.png"/></a> <a href="https://residence-greece.com/"><img title="Greece Golden Visa" width="256" src="https://joplinapp.org/images/sponsors/ResidenceGreece.jpg"/></a> <a href="https://grundstueckspreise.info/"><img title="SP Software GmbH" width="256" src="https://joplinapp.org/images/sponsors/Grundstueckspreise.png"/></a> <a href="https://tranio.com/spain/"><img title="Property for sale in Spain" width="256" src="https://joplinapp.org/images/sponsors/TranioOverseasProperty.jpg"/></a>
|
||||
<a href="https://seirei.ne.jp"><img title="Serei Network" width="256" src="https://joplinapp.org/images/sponsors/SeireiNetwork.png"/></a> <a href="https://www.hosting.de/nextcloud/?mtm_campaign=managed-nextcloud&mtm_kwd=joplinapp&mtm_source=joplinapp-webseite&mtm_medium=banner"><img title="Hosting.de" width="256" src="https://joplinapp.org/images/sponsors/HostingDe.png"/></a> <a href="https://residence-greece.com/"><img title="Greece Golden Visa" width="256" src="https://joplinapp.org/images/sponsors/ResidenceGreece.jpg"/></a> <a href="https://grundstueckspreise.info/"><img title="SP Software GmbH" width="256" src="https://joplinapp.org/images/sponsors/Grundstueckspreise.png"/></a> <a href="https://tranio.com/spain/"><img title="Property for sale in Spain" width="256" src="https://joplinapp.org/images/sponsors/TranioOverseasProperty.jpg"/></a> <a href="https://citricsheep.com"><img title="Citric Sheep" width="256" src="https://joplinapp.org/images/sponsors/CitricSheep.png"/></a>
|
||||
<!-- SPONSORS-ORG -->
|
||||
|
||||
* * *
|
||||
@@ -75,11 +75,11 @@ A community maintained list of these distributions can be found here: [Unofficia
|
||||
| | | | |
|
||||
| :---: | :---: | :---: | :---: |
|
||||
| <img width="50" src="https://avatars2.githubusercontent.com/u/215668?s=96&v=4"/></br>[avanderberg](https://github.com/avanderberg) | <img width="50" src="https://avatars2.githubusercontent.com/u/67130?s=96&v=4"/></br>[chr15m](https://github.com/chr15m) | <img width="50" src="https://avatars2.githubusercontent.com/u/2793530?s=96&v=4"/></br>[CyberXZT](https://github.com/CyberXZT) | <img width="50" src="https://avatars2.githubusercontent.com/u/1307332?s=96&v=4"/></br>[dbrandonjohnson](https://github.com/dbrandonjohnson) |
|
||||
| <img width="50" src="https://avatars2.githubusercontent.com/u/56287?s=96&v=4"/></br>[fats](https://github.com/fats) | <img width="50" src="https://avatars2.githubusercontent.com/u/49439044?s=96&v=4"/></br>[fourstepper](https://github.com/fourstepper) | <img width="50" src="https://avatars2.githubusercontent.com/u/64712218?s=96&v=4"/></br>[Hegghammer](https://github.com/Hegghammer) | <img width="50" src="https://avatars2.githubusercontent.com/u/3266447?s=96&v=4"/></br>[iamwillbar](https://github.com/iamwillbar) |
|
||||
| <img width="50" src="https://avatars2.githubusercontent.com/u/1310474?s=96&v=4"/></br>[jknowles](https://github.com/jknowles) | <img width="50" src="https://avatars2.githubusercontent.com/u/11947658?s=96&v=4"/></br>[KentBrockman](https://github.com/KentBrockman) | <img width="50" src="https://avatars2.githubusercontent.com/u/5588131?s=96&v=4"/></br>[kianenigma](https://github.com/kianenigma) | <img width="50" src="https://avatars2.githubusercontent.com/u/24908652?s=96&v=4"/></br>[konishi-t](https://github.com/konishi-t) |
|
||||
| <img width="50" src="https://avatars2.githubusercontent.com/u/42319182?s=96&v=4"/></br>[marcdw1289](https://github.com/marcdw1289) | <img width="50" src="https://avatars2.githubusercontent.com/u/126279083?s=96&v=4"/></br>[matmoly](https://github.com/matmoly) | <img width="50" src="https://avatars2.githubusercontent.com/u/1788010?s=96&v=4"/></br>[maxtruxa](https://github.com/maxtruxa) | <img width="50" src="https://avatars2.githubusercontent.com/u/29300939?s=96&v=4"/></br>[mcejp](https://github.com/mcejp) |
|
||||
| <img width="50" src="https://avatars2.githubusercontent.com/u/31054972?s=96&v=4"/></br>[saarantras](https://github.com/saarantras) | <img width="50" src="https://avatars2.githubusercontent.com/u/327998?s=96&v=4"/></br>[sif](https://github.com/sif) | <img width="50" src="https://avatars2.githubusercontent.com/u/765564?s=96&v=4"/></br>[taskcruncher](https://github.com/taskcruncher) | <img width="50" src="https://avatars2.githubusercontent.com/u/333944?s=96&v=4"/></br>[tateisu](https://github.com/tateisu) |
|
||||
| | | | |
|
||||
| <img width="50" src="https://avatars2.githubusercontent.com/u/14873877?s=96&v=4"/></br>[dchecks](https://github.com/dchecks) | <img width="50" src="https://avatars2.githubusercontent.com/u/56287?s=96&v=4"/></br>[fats](https://github.com/fats) | <img width="50" src="https://avatars2.githubusercontent.com/u/49439044?s=96&v=4"/></br>[fourstepper](https://github.com/fourstepper) | <img width="50" src="https://avatars2.githubusercontent.com/u/64712218?s=96&v=4"/></br>[Hegghammer](https://github.com/Hegghammer) |
|
||||
| <img width="50" src="https://avatars2.githubusercontent.com/u/3266447?s=96&v=4"/></br>[iamwillbar](https://github.com/iamwillbar) | <img width="50" src="https://avatars2.githubusercontent.com/u/1310474?s=96&v=4"/></br>[jknowles](https://github.com/jknowles) | <img width="50" src="https://avatars2.githubusercontent.com/u/11947658?s=96&v=4"/></br>[KentBrockman](https://github.com/KentBrockman) | <img width="50" src="https://avatars2.githubusercontent.com/u/5588131?s=96&v=4"/></br>[kianenigma](https://github.com/kianenigma) |
|
||||
| <img width="50" src="https://avatars2.githubusercontent.com/u/24908652?s=96&v=4"/></br>[konishi-t](https://github.com/konishi-t) | <img width="50" src="https://avatars2.githubusercontent.com/u/42319182?s=96&v=4"/></br>[marcdw1289](https://github.com/marcdw1289) | <img width="50" src="https://avatars2.githubusercontent.com/u/126279083?s=96&v=4"/></br>[matmoly](https://github.com/matmoly) | <img width="50" src="https://avatars2.githubusercontent.com/u/1788010?s=96&v=4"/></br>[maxtruxa](https://github.com/maxtruxa) |
|
||||
| <img width="50" src="https://avatars2.githubusercontent.com/u/29300939?s=96&v=4"/></br>[mcejp](https://github.com/mcejp) | <img width="50" src="https://avatars2.githubusercontent.com/u/31054972?s=96&v=4"/></br>[saarantras](https://github.com/saarantras) | <img width="50" src="https://avatars2.githubusercontent.com/u/327998?s=96&v=4"/></br>[sif](https://github.com/sif) | <img width="50" src="https://avatars2.githubusercontent.com/u/765564?s=96&v=4"/></br>[taskcruncher](https://github.com/taskcruncher) |
|
||||
| <img width="50" src="https://avatars2.githubusercontent.com/u/333944?s=96&v=4"/></br>[tateisu](https://github.com/tateisu) | | | |
|
||||
<!-- SPONSORS-GITHUB -->
|
||||
|
||||
<!-- TOC -->
|
||||
@@ -107,6 +107,7 @@ A community maintained list of these distributions can be found here: [Unofficia
|
||||
|
||||
- [Sharing a notebook](https://github.com/laurent22/joplin/blob/dev/readme/share_notebook.md)
|
||||
- [Publishing a note](https://github.com/laurent22/joplin/blob/dev/readme/publish_note.md)
|
||||
- [Email to Note](https://github.com/laurent22/joplin/blob/dev/readme/email_to_note.md)
|
||||
|
||||
- Joplin API - Get Started
|
||||
|
||||
@@ -140,6 +141,7 @@ A community maintained list of these distributions can be found here: [Unofficia
|
||||
- [Server: File URL Format](https://github.com/laurent22/joplin/blob/dev/readme/spec/server_file_url_format.md)
|
||||
- [Server: Delta Sync](https://github.com/laurent22/joplin/blob/dev/readme/spec/server_delta_sync.md)
|
||||
- [Server: Sharing](https://github.com/laurent22/joplin/blob/dev/readme/spec/server_sharing.md)
|
||||
- [Read-only items](https://github.com/laurent22/joplin/blob/dev/readme/spec/read_only.md)
|
||||
|
||||
- Google Summer of Code 2022
|
||||
|
||||
@@ -510,7 +512,7 @@ Name | Description
|
||||
[Patreon page](https://www.patreon.com/joplin) |The latest news are often posted there
|
||||
[Discord server](https://discord.gg/VSj7AFHvpq) | Our chat server
|
||||
[LinkedIn](https://www.linkedin.com/company/joplin) | Our LinkedIn page
|
||||
[Sub-reddit](https://www.reddit.com/r/joplinapp/) | Also a good place to get help
|
||||
[Lemmy Community](https://sopuli.xyz/c/joplinapp) | Also a good place to get help
|
||||
|
||||
# Contributing
|
||||
|
||||
|
||||
@@ -13,5 +13,6 @@ module.exports = {
|
||||
'*.{js,jsx,ts,tsx}': [
|
||||
'yarn run linter-precommit',
|
||||
'yarn run checkLibPaths',
|
||||
'node packages/tools/checkIgnoredFiles.js',
|
||||
],
|
||||
};
|
||||
|
||||
10
package.json
10
package.json
@@ -81,8 +81,8 @@
|
||||
"gulp": "4.0.2",
|
||||
"husky": "3.1.0",
|
||||
"lerna": "3.22.1",
|
||||
"lint-staged": "13.2.2",
|
||||
"madge": "6.0.0",
|
||||
"lint-staged": "13.2.3",
|
||||
"madge": "6.1.0",
|
||||
"npm-package-json-lint": "6.4.0",
|
||||
"typescript": "5.0.2"
|
||||
},
|
||||
@@ -90,7 +90,7 @@
|
||||
"@types/fs-extra": "11.0.1",
|
||||
"eslint-plugin-github": "4.8.0",
|
||||
"http-server": "14.1.1",
|
||||
"node-gyp": "9.3.1",
|
||||
"node-gyp": "9.4.0",
|
||||
"nodemon": "2.0.22"
|
||||
},
|
||||
"packageManager": "yarn@3.5.0",
|
||||
@@ -99,6 +99,8 @@
|
||||
"react-native-vosk@0.1.12": "patch:react-native-vosk@npm%3A0.1.12#./.yarn/patches/react-native-vosk-npm-0.1.12-76b1caaae8.patch",
|
||||
"eslint@8.39.0": "patch:eslint@npm%3A8.39.0#./.yarn/patches/eslint-npm-8.39.0-d92bace04d.patch",
|
||||
"eslint@^8.13.0": "patch:eslint@npm%3A8.39.0#./.yarn/patches/eslint-npm-8.39.0-d92bace04d.patch",
|
||||
"app-builder-lib@24.4.0": "patch:app-builder-lib@npm%3A24.4.0#./.yarn/patches/app-builder-lib-npm-24.4.0-05322ff057.patch"
|
||||
"app-builder-lib@24.4.0": "patch:app-builder-lib@npm%3A24.4.0#./.yarn/patches/app-builder-lib-npm-24.4.0-05322ff057.patch",
|
||||
"react-native@0.71.10": "patch:react-native@npm%3A0.71.10#./.yarn/patches/react-native-animation-fix/react-native-npm-0.71.10-f9c32562d8.patch",
|
||||
"react-native-reanimated@3.3.0": "patch:react-native-reanimated@npm%3A3.3.0#./.yarn/patches/react-native-animation-fix/react-native-reanimated-npm-3.3.0-fb4272741c.patch"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const Logger = require('@joplin/lib/Logger').default;
|
||||
const Logger = require('@joplin/utils/Logger').default;
|
||||
const { findAvailablePort } = require('@joplin/lib/net-utils');
|
||||
|
||||
const http = require('http');
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const Logger = require('@joplin/lib/Logger').default;
|
||||
const Logger = require('@joplin/utils/Logger').default;
|
||||
const Folder = require('@joplin/lib/models/Folder').default;
|
||||
const BaseItem = require('@joplin/lib/models/BaseItem').default;
|
||||
const Tag = require('@joplin/lib/models/Tag').default;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/* eslint-disable no-console */
|
||||
|
||||
const fs = require('fs-extra');
|
||||
const Logger = require('@joplin/lib/Logger').default;
|
||||
const Logger = require('@joplin/utils/Logger').default;
|
||||
const { dirname } = require('@joplin/lib/path-utils');
|
||||
const { DatabaseDriverNode } = require('@joplin/lib/database-driver-node.js');
|
||||
const JoplinDatabase = require('@joplin/lib/JoplinDatabase').default;
|
||||
|
||||
@@ -2,7 +2,7 @@ const yargParser = require('yargs-parser');
|
||||
const { _ } = require('@joplin/lib/locale');
|
||||
const time = require('@joplin/lib/time').default;
|
||||
const stringPadding = require('string-padding');
|
||||
const Logger = require('@joplin/lib/Logger').default;
|
||||
const Logger = require('@joplin/utils/Logger').default;
|
||||
|
||||
const cliUtils = {};
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const BaseCommand = require('./base-command').default;
|
||||
const { _ } = require('@joplin/lib/locale');
|
||||
const Setting = require('@joplin/lib/models/Setting').default;
|
||||
const Logger = require('@joplin/lib/Logger').default;
|
||||
const Logger = require('@joplin/utils/Logger').default;
|
||||
const shim = require('@joplin/lib/shim').default;
|
||||
|
||||
class Command extends BaseCommand {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const time = require('@joplin/lib/time').default;
|
||||
const Logger = require('@joplin/lib/Logger').default;
|
||||
const Logger = require('@joplin/utils/Logger').default;
|
||||
const Resource = require('@joplin/lib/models/Resource').default;
|
||||
const { dirname } = require('@joplin/lib/path-utils');
|
||||
const FsDriverNode = require('@joplin/lib/fs-driver-node').default;
|
||||
|
||||
@@ -20,7 +20,7 @@ const NoteTag = require('@joplin/lib/models/NoteTag').default;
|
||||
const MasterKey = require('@joplin/lib/models/MasterKey').default;
|
||||
const Setting = require('@joplin/lib/models/Setting').default;
|
||||
const Revision = require('@joplin/lib/models/Revision').default;
|
||||
const Logger = require('@joplin/lib/Logger').default;
|
||||
const Logger = require('@joplin/utils/Logger').default;
|
||||
const FsDriverNode = require('@joplin/lib/fs-driver-node').default;
|
||||
const sharp = require('sharp');
|
||||
const { shimInit } = require('@joplin/lib/shim-init-node.js');
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
const MarkupToHtml = require('@joplin/renderer/MarkupToHtml').default;
|
||||
import MarkupToHtml, { MarkupLanguage, RenderResult } from '@joplin/renderer/MarkupToHtml';
|
||||
|
||||
describe('MarkupToHtml', () => {
|
||||
|
||||
@@ -31,7 +31,7 @@ describe('MarkupToHtml', () => {
|
||||
const input = t[0];
|
||||
const expected = t[1];
|
||||
const actual = service.stripMarkup(Number(markup), input);
|
||||
expect(actual).toBe(expected, `Markup: ${markup}`);
|
||||
expect(actual).toBe(expected);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,4 +40,18 @@ describe('MarkupToHtml', () => {
|
||||
expect(service.stripMarkup(1, 'one line\n two line', { collapseWhiteSpaces: true })).toBe('one line two line');
|
||||
}));
|
||||
|
||||
|
||||
test('should escape HTML in safe mode', async () => {
|
||||
const service = new MarkupToHtml({ isSafeMode: true });
|
||||
|
||||
const testString = '</pre>.<b>Test</b>';
|
||||
const expectedOutput: RenderResult = {
|
||||
html: '<pre></pre>.<b>Test</b></pre>',
|
||||
cssStrings: [],
|
||||
pluginAssets: [],
|
||||
};
|
||||
|
||||
expect(await service.render(MarkupLanguage.Html, testString, {}, {})).toMatchObject(expectedOutput);
|
||||
expect(await service.render(MarkupLanguage.Markdown, testString, {}, {})).toMatchObject(expectedOutput);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1 @@
|
||||
<p><b> A test... </b>Test</p>
|
||||
@@ -0,0 +1 @@
|
||||
**A test...** Test
|
||||
10
packages/app-cli/tests/html_to_md/linebreaks.html
Normal file
10
packages/app-cli/tests/html_to_md/linebreaks.html
Normal file
@@ -0,0 +1,10 @@
|
||||
<h1>Linebreaks</h1>
|
||||
<div><br>-style linebreaks should be replaced with two spaces followed by a
|
||||
newline.<br/>This allows the generated mark<br/>down to render to equivalent HTML
|
||||
even if the <code>markdown.plugin.softbreaks</code> setting is enabled.</div>
|
||||
<pre class="some-code" style="font-family:monospace;"><br>s shouldn't<br/>lead<br/>to trailing spaces in
|
||||
code
|
||||
however.
|
||||
</pre>
|
||||
<p>Because it isn't</p>
|
||||
<div>necessary.<br/><br/><br/><br/>...</div>
|
||||
21
packages/app-cli/tests/html_to_md/linebreaks.md
Normal file
21
packages/app-cli/tests/html_to_md/linebreaks.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Linebreaks
|
||||
|
||||
<br>-style linebreaks should be replaced with two spaces followed by a newline.
|
||||
This allows the generated mark
|
||||
down to render to equivalent HTML even if the `markdown.plugin.softbreaks` setting is enabled.
|
||||
|
||||
```
|
||||
<br>s shouldn't
|
||||
lead
|
||||
to trailing spaces in
|
||||
code
|
||||
however.
|
||||
```
|
||||
|
||||
Because it isn't
|
||||
|
||||
necessary.
|
||||
|
||||
|
||||
|
||||
...
|
||||
@@ -0,0 +1,3 @@
|
||||
<p>Paragraphs with a single nonbreaking space should be preserved:</p>
|
||||
<p> </p>
|
||||
<p> </p>
|
||||
@@ -0,0 +1,5 @@
|
||||
Paragraphs with a single nonbreaking space should be preserved:
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
Some pictures:  
|
||||
Some pictures: 
|
||||
@@ -5,5 +5,6 @@
|
||||
| [Source](https://github.com/nim-lang/nim) | The github project |
|
||||
| [nimble](https://github.com/nim-lang/nimble) | The nim package manager |
|
||||
| [choosenim](https://github.com/dom96/choosenim) | Toolchain installer |
|
||||
| | |
|
||||
| **Community** | |
|
||||
| [Forums](https://forum.nim-lang.org) | An async discussion board |
|
||||
@@ -1 +1 @@
|
||||
<map name="test" class="jop-noMdConv"><area coords="0,0,1000,1000" href="#" class="jop-noMdConv"/></map><img usemap="#test" src="https://github.com/Ry0taK.png" class="jop-noMdConv"/>
|
||||
<img usemap="#test" src="https://github.com/Ry0taK.png" class="jop-noMdConv"/>
|
||||
@@ -1,4 +1,4 @@
|
||||
import Logger from '@joplin/lib/Logger';
|
||||
import Logger from '@joplin/utils/Logger';
|
||||
import { PluginMessage } from './services/plugins/PluginRunner';
|
||||
import shim from '@joplin/lib/shim';
|
||||
import { isCallbackUrl } from '@joplin/lib/callbackUrlUtils';
|
||||
|
||||
@@ -4,7 +4,7 @@ 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';
|
||||
import Logger from '@joplin/lib/Logger';
|
||||
import Logger from '@joplin/utils/Logger';
|
||||
|
||||
const logger = Logger.create('app.reducer');
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import PlatformImplementation from './services/plugins/PlatformImplementation';
|
||||
import shim from '@joplin/lib/shim';
|
||||
import AlarmService from '@joplin/lib/services/AlarmService';
|
||||
import AlarmServiceDriverNode from '@joplin/lib/services/AlarmServiceDriverNode';
|
||||
import Logger, { TargetType } from '@joplin/lib/Logger';
|
||||
import Logger, { TargetType } from '@joplin/utils/Logger';
|
||||
import Setting from '@joplin/lib/models/Setting';
|
||||
import actionApi from '@joplin/lib/services/rest/actionApi.desktop';
|
||||
import BaseApplication from '@joplin/lib/BaseApplication';
|
||||
@@ -66,7 +66,7 @@ import syncDebugLog from '@joplin/lib/services/synchronizer/syncDebugLog';
|
||||
import eventManager from '@joplin/lib/eventManager';
|
||||
import path = require('path');
|
||||
import { checkPreInstalledDefaultPlugins, installDefaultPlugins, setSettingsForDefaultPlugins } from '@joplin/lib/services/plugins/defaultPlugins/defaultPluginsUtils';
|
||||
// import { runIntegrationTests } from '@joplin/lib/services/e2ee/ppkTestUtils';
|
||||
import userFetcher, { initializeUserFetcher } from '@joplin/lib/utils/userFetcher';
|
||||
|
||||
const pluginClasses = [
|
||||
require('./plugins/GotoAnything').default,
|
||||
@@ -262,6 +262,8 @@ class Application extends BaseApplication {
|
||||
if (this.initPluginServiceDone_) return;
|
||||
this.initPluginServiceDone_ = true;
|
||||
|
||||
PlatformImplementation.instance().initialize((action: any) => this.dispatch(action));
|
||||
|
||||
const service = PluginService.instance();
|
||||
|
||||
const pluginRunner = new PluginRunner();
|
||||
@@ -487,6 +489,9 @@ class Application extends BaseApplication {
|
||||
shim.setInterval(() => { runAutoUpdateCheck(); }, 12 * 60 * 60 * 1000);
|
||||
}
|
||||
|
||||
initializeUserFetcher();
|
||||
shim.setInterval(() => { void userFetcher(); }, 1000 * 60 * 60);
|
||||
|
||||
this.updateTray();
|
||||
|
||||
shim.setTimeout(() => {
|
||||
|
||||
@@ -96,11 +96,7 @@ export class Bridge {
|
||||
electronApp: this.electronApp(),
|
||||
|
||||
shouldShowMenu: (_event: any, params: any) => {
|
||||
// params.inputFieldType === 'none' when right-clicking the text
|
||||
// editor. This is a bit of a hack to detect it because in this
|
||||
// case we don't want to use the built-in context menu but a
|
||||
// custom one.
|
||||
return params.isEditable && params.inputFieldType !== 'none';
|
||||
return params.isEditable;
|
||||
},
|
||||
|
||||
// menu: (actions: any, props: any) => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import shim from '@joplin/lib/shim';
|
||||
import Logger from '@joplin/lib/Logger';
|
||||
import Logger from '@joplin/utils/Logger';
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
import bridge from './services/bridge';
|
||||
import KvStore from '@joplin/lib/services/KvStore';
|
||||
|
||||
@@ -23,6 +23,6 @@ export const runtime = (): CommandRuntime => {
|
||||
bridge().showErrorMessageBox(_('Error opening note in editor: %s', error.message));
|
||||
}
|
||||
},
|
||||
enabledCondition: 'oneNoteSelected',
|
||||
enabledCondition: 'oneNoteSelected && !noteIsReadOnly',
|
||||
};
|
||||
};
|
||||
|
||||
@@ -15,6 +15,6 @@ export const runtime = (): CommandRuntime => {
|
||||
noteId = noteId || stateUtils.selectedNoteId(context.state);
|
||||
void ExternalEditWatcher.instance().stopWatching(noteId);
|
||||
},
|
||||
enabledCondition: 'oneNoteSelected',
|
||||
enabledCondition: 'oneNoteSelected && !noteIsReadOnly',
|
||||
};
|
||||
};
|
||||
|
||||
@@ -2,6 +2,7 @@ import CommandService, { CommandRuntime, CommandDeclaration } from '@joplin/lib/
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
import { stateUtils } from '@joplin/lib/reducer';
|
||||
import { DesktopCommandContext } from '../services/commands/types';
|
||||
import { enabledCondition } from '../gui/NoteEditor/editorCommandDeclarations';
|
||||
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'toggleExternalEditing',
|
||||
@@ -22,7 +23,7 @@ export const runtime = (): CommandRuntime => {
|
||||
void CommandService.instance().execute('startExternalEditing', noteId);
|
||||
}
|
||||
},
|
||||
enabledCondition: 'oneNoteSelected',
|
||||
enabledCondition: enabledCondition(declaration.name),
|
||||
mapStateToTitle: (state: any) => {
|
||||
const noteId = stateUtils.selectedNoteId(state);
|
||||
return state.watchedNoteFiles.includes(noteId) ? _('Stop') : '';
|
||||
|
||||
@@ -18,6 +18,7 @@ import restart from '../../services/restart';
|
||||
import PluginService from '@joplin/lib/services/plugins/PluginService';
|
||||
import { getDefaultPluginsInstallState, updateDefaultPluginsInstallState } from '@joplin/lib/services/plugins/defaultPlugins/defaultPluginsUtils';
|
||||
import getDefaultPluginsInfo from '@joplin/lib/services/plugins/defaultPlugins/desktopDefaultPluginsInfo';
|
||||
import JoplinCloudConfigScreen from '../JoplinCloudConfigScreen';
|
||||
const { KeymapConfigScreen } = require('../KeymapConfig/KeymapConfigScreen');
|
||||
|
||||
const settingKeyToControl: any = {
|
||||
@@ -106,6 +107,7 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
if (screenName === 'encryption') return <EncryptionConfigScreen/>;
|
||||
if (screenName === 'server') return <ClipperConfigScreen themeId={this.props.themeId}/>;
|
||||
if (screenName === 'keymap') return <KeymapConfigScreen themeId={this.props.themeId}/>;
|
||||
if (screenName === 'joplinCloud') return <JoplinCloudConfigScreen />;
|
||||
|
||||
throw new Error(`Invalid screen name: ${screenName}`);
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import { PluginItem } from './PluginBox';
|
||||
import RepositoryApi from '@joplin/lib/services/plugins/RepositoryApi';
|
||||
import Setting from '@joplin/lib/models/Setting';
|
||||
import useOnInstallHandler, { OnPluginSettingChangeEvent } from './useOnInstallHandler';
|
||||
import Logger from '@joplin/lib/Logger';
|
||||
import Logger from '@joplin/utils/Logger';
|
||||
import StyledMessage from '../../../style/StyledMessage';
|
||||
import StyledLink from '../../../style/StyledLink';
|
||||
const { space } = require('styled-system');
|
||||
|
||||
@@ -2,7 +2,7 @@ import { useCallback } from 'react';
|
||||
import PluginService, { defaultPluginSetting, PluginSettings } from '@joplin/lib/services/plugins/PluginService';
|
||||
import produce from 'immer';
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
import Logger from '@joplin/lib/Logger';
|
||||
import Logger from '@joplin/utils/Logger';
|
||||
import { ItemEvent } from './PluginBox';
|
||||
|
||||
const logger = Logger.create('useOnInstallHandler');
|
||||
|
||||
53
packages/app-desktop/gui/Dropdown/Dropdown.tsx
Normal file
53
packages/app-desktop/gui/Dropdown/Dropdown.tsx
Normal file
@@ -0,0 +1,53 @@
|
||||
import * as React from 'react';
|
||||
import { useMemo, useCallback } from 'react';
|
||||
|
||||
export type DropdownOptions = Record<string, string>;
|
||||
export enum DropdownVariant {
|
||||
Default = 1,
|
||||
NoBorder,
|
||||
}
|
||||
|
||||
export interface ChangeEvent {
|
||||
value: string;
|
||||
}
|
||||
|
||||
export type ChangeEventHandler = (event: ChangeEvent)=> void;
|
||||
|
||||
interface Props {
|
||||
options: DropdownOptions;
|
||||
variant?: DropdownVariant;
|
||||
className?: string;
|
||||
onChange?: ChangeEventHandler;
|
||||
value?: string;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
export const Dropdown = (props: Props) => {
|
||||
const renderOptions = () => {
|
||||
const optionComps = [];
|
||||
for (const [value, label] of Object.entries(props.options)) {
|
||||
optionComps.push(<option key={value} value={value}>{label}</option>);
|
||||
}
|
||||
return optionComps;
|
||||
};
|
||||
|
||||
const onChange = useCallback((event: any) => {
|
||||
props.onChange({ value: event.target.value });
|
||||
}, [props.onChange]);
|
||||
|
||||
const classNames = useMemo(() => {
|
||||
const variant = props.variant || DropdownVariant.Default;
|
||||
const output = [
|
||||
'dropdown-control',
|
||||
`-variant${variant}`,
|
||||
];
|
||||
if (props.className) output.push(props.className);
|
||||
return output.join(' ');
|
||||
}, [props.variant, props.className]);
|
||||
|
||||
return (
|
||||
<select disabled={props.disabled} className={classNames} onChange={onChange} value={props.value}>
|
||||
{renderOptions()}
|
||||
</select>
|
||||
);
|
||||
};
|
||||
14
packages/app-desktop/gui/Dropdown/style.scss
Normal file
14
packages/app-desktop/gui/Dropdown/style.scss
Normal file
@@ -0,0 +1,14 @@
|
||||
.dropdown-control {
|
||||
border: 1px solid var(--joplin-border-color4);
|
||||
border-radius: 3px;
|
||||
font-size: var(--joplin-font-size)px;
|
||||
color: var(--joplin-color);
|
||||
padding: 0 8px;
|
||||
box-sizing: border-box;
|
||||
background-color: var(--joplin-background-color4);
|
||||
min-height: 26px;
|
||||
|
||||
&.-variant2 {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
@@ -63,6 +63,8 @@ export default function(props: Props) {
|
||||
const folder: FolderEntity = {
|
||||
title: folderTitle,
|
||||
icon: Folder.serializeIcon(folderIcon),
|
||||
is_shared: 0,
|
||||
share_id: '',
|
||||
};
|
||||
|
||||
if (!isNew) folder.id = props.folderId;
|
||||
|
||||
3
packages/app-desktop/gui/JoplinCloudConfigScreen.scss
Normal file
3
packages/app-desktop/gui/JoplinCloudConfigScreen.scss
Normal file
@@ -0,0 +1,3 @@
|
||||
.inbox-email-value {
|
||||
font-weight: bold;
|
||||
}
|
||||
32
packages/app-desktop/gui/JoplinCloudConfigScreen.tsx
Normal file
32
packages/app-desktop/gui/JoplinCloudConfigScreen.tsx
Normal file
@@ -0,0 +1,32 @@
|
||||
const { connect } = require('react-redux');
|
||||
import { AppState } from '../app.reducer';
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
import { clipboard } from 'electron';
|
||||
import Button from './Button/Button';
|
||||
|
||||
type JoplinCloudConfigScreenProps = {
|
||||
inboxEmail: string;
|
||||
};
|
||||
|
||||
const JoplinCloudConfigScreen = (props: JoplinCloudConfigScreenProps) => {
|
||||
const copyToClipboard = () => {
|
||||
clipboard.writeText(props.inboxEmail);
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h2>{_('Email to note')}</h2>
|
||||
<p>{_('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')}</p>
|
||||
<p className='inbox-email-value'>{props.inboxEmail}</p>
|
||||
<Button onClick={copyToClipboard} title={_('Copy to clipboard')} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const mapStateToProps = (state: AppState) => {
|
||||
return {
|
||||
inboxEmail: state.settings['sync.10.inboxEmail'],
|
||||
};
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps)(JoplinCloudConfigScreen);
|
||||
32
packages/app-desktop/gui/MainScreen/commands/deleteFolder.ts
Normal file
32
packages/app-desktop/gui/MainScreen/commands/deleteFolder.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { CommandRuntime, CommandDeclaration, CommandContext } from '@joplin/lib/services/CommandService';
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
import bridge from '../../../services/bridge';
|
||||
import Folder from '@joplin/lib/models/Folder';
|
||||
const { substrWithEllipsis } = require('@joplin/lib/string-utils');
|
||||
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'deleteFolder',
|
||||
label: () => _('Delete notebook'),
|
||||
};
|
||||
|
||||
export const runtime = (): CommandRuntime => {
|
||||
return {
|
||||
execute: async (context: CommandContext, folderId: string = null) => {
|
||||
if (folderId === null) folderId = context.state.selectedFolderId;
|
||||
|
||||
const folder = await Folder.load(folderId);
|
||||
if (!folder) throw new Error(`No such folder: ${folderId}`);
|
||||
|
||||
let deleteMessage = _('Delete notebook "%s"?\n\nAll notes and sub-notebooks within this notebook will also be deleted.', substrWithEllipsis(folder.title, 0, 32));
|
||||
if (folderId === context.state.settings['sync.10.inboxId']) {
|
||||
deleteMessage = _('Delete the Inbox notebook?\n\nIf you delete the inbox notebook, any email that\'s recently been sent to it may be lost.');
|
||||
}
|
||||
|
||||
const ok = bridge().showConfirmMessageBox(deleteMessage);
|
||||
if (!ok) return;
|
||||
|
||||
await Folder.delete(folderId);
|
||||
},
|
||||
enabledCondition: '!folderIsReadOnly',
|
||||
};
|
||||
};
|
||||
32
packages/app-desktop/gui/MainScreen/commands/deleteNote.ts
Normal file
32
packages/app-desktop/gui/MainScreen/commands/deleteNote.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { CommandRuntime, CommandDeclaration, CommandContext } from '@joplin/lib/services/CommandService';
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
import Note from '@joplin/lib/models/Note';
|
||||
import bridge from '../../../services/bridge';
|
||||
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'deleteNote',
|
||||
label: () => _('Delete note'),
|
||||
iconName: 'fa-times',
|
||||
};
|
||||
|
||||
export const runtime = (): CommandRuntime => {
|
||||
return {
|
||||
execute: async (context: CommandContext, noteIds: string[] = null) => {
|
||||
if (noteIds === null) noteIds = context.state.selectedNoteIds;
|
||||
|
||||
if (!noteIds.length) return;
|
||||
|
||||
const msg = await Note.deleteMessage(noteIds);
|
||||
if (!msg) return;
|
||||
|
||||
const ok = bridge().showConfirmMessageBox(msg, {
|
||||
buttons: [_('Delete'), _('Cancel')],
|
||||
defaultId: 1,
|
||||
});
|
||||
|
||||
if (!ok) return;
|
||||
await Note.batchDelete(noteIds);
|
||||
},
|
||||
enabledCondition: '!noteIsReadOnly',
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,24 @@
|
||||
import { CommandRuntime, CommandDeclaration, CommandContext } from '@joplin/lib/services/CommandService';
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
import Note from '@joplin/lib/models/Note';
|
||||
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'duplicateNote',
|
||||
label: () => _('Duplicate'),
|
||||
};
|
||||
|
||||
export const runtime = (): CommandRuntime => {
|
||||
return {
|
||||
execute: async (context: CommandContext, noteIds: string[] = null) => {
|
||||
if (noteIds === null) noteIds = context.state.selectedNoteIds;
|
||||
|
||||
for (let i = 0; i < noteIds.length; i++) {
|
||||
const note = await Note.load(noteIds[i]);
|
||||
await Note.duplicate(noteIds[i], {
|
||||
uniqueTitle: _('%s - Copy', note.title),
|
||||
});
|
||||
}
|
||||
},
|
||||
enabledCondition: '!noteIsReadOnly',
|
||||
};
|
||||
};
|
||||
@@ -1,6 +1,9 @@
|
||||
// AUTO-GENERATED using `gulp buildCommandIndex`
|
||||
import * as addProfile from './addProfile';
|
||||
import * as commandPalette from './commandPalette';
|
||||
import * as deleteFolder from './deleteFolder';
|
||||
import * as deleteNote from './deleteNote';
|
||||
import * as duplicateNote from './duplicateNote';
|
||||
import * as editAlarm from './editAlarm';
|
||||
import * as exportPdf from './exportPdf';
|
||||
import * as gotoAnything from './gotoAnything';
|
||||
@@ -34,6 +37,7 @@ import * as showSpellCheckerMenu from './showSpellCheckerMenu';
|
||||
import * as toggleEditors from './toggleEditors';
|
||||
import * as toggleLayoutMoveMode from './toggleLayoutMoveMode';
|
||||
import * as toggleNoteList from './toggleNoteList';
|
||||
import * as toggleNoteType from './toggleNoteType';
|
||||
import * as toggleNotesSortOrderField from './toggleNotesSortOrderField';
|
||||
import * as toggleNotesSortOrderReverse from './toggleNotesSortOrderReverse';
|
||||
import * as togglePerFolderSortOrder from './togglePerFolderSortOrder';
|
||||
@@ -43,6 +47,9 @@ import * as toggleVisiblePanes from './toggleVisiblePanes';
|
||||
const index:any[] = [
|
||||
addProfile,
|
||||
commandPalette,
|
||||
deleteFolder,
|
||||
deleteNote,
|
||||
duplicateNote,
|
||||
editAlarm,
|
||||
exportPdf,
|
||||
gotoAnything,
|
||||
@@ -76,6 +83,7 @@ const index:any[] = [
|
||||
toggleEditors,
|
||||
toggleLayoutMoveMode,
|
||||
toggleNoteList,
|
||||
toggleNoteType,
|
||||
toggleNotesSortOrderField,
|
||||
toggleNotesSortOrderReverse,
|
||||
togglePerFolderSortOrder,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { CommandRuntime, CommandDeclaration, CommandContext } from '@joplin/lib/services/CommandService';
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
import ShareService from '@joplin/lib/services/share/ShareService';
|
||||
import Logger from '@joplin/lib/Logger';
|
||||
import Logger from '@joplin/utils/Logger';
|
||||
|
||||
const logger = Logger.create('leaveSharedFolder');
|
||||
|
||||
|
||||
@@ -44,6 +44,6 @@ export const runtime = (comp: any): CommandRuntime => {
|
||||
},
|
||||
});
|
||||
},
|
||||
enabledCondition: 'someNotesSelected',
|
||||
enabledCondition: 'someNotesSelected && !noteIsReadOnly',
|
||||
};
|
||||
};
|
||||
|
||||
@@ -18,5 +18,6 @@ export const runtime = (): CommandRuntime => {
|
||||
|
||||
void CommandService.instance().execute('openFolderDialog', options);
|
||||
},
|
||||
enabledCondition: '!folderIsReadOnly',
|
||||
};
|
||||
};
|
||||
|
||||
@@ -30,6 +30,6 @@ export const runtime = (): CommandRuntime => {
|
||||
id: newNote.id,
|
||||
});
|
||||
},
|
||||
enabledCondition: 'oneFolderSelected && !inConflictFolder',
|
||||
enabledCondition: 'oneFolderSelected && !inConflictFolder && !folderIsReadOnly',
|
||||
};
|
||||
};
|
||||
|
||||
@@ -13,5 +13,6 @@ export const runtime = (): CommandRuntime => {
|
||||
parentId = parentId || context.state.selectedFolderId;
|
||||
return CommandService.instance().execute('newFolder', parentId);
|
||||
},
|
||||
enabledCondition: '!folderIsReadOnly',
|
||||
};
|
||||
};
|
||||
|
||||
@@ -12,6 +12,6 @@ export const runtime = (): CommandRuntime => {
|
||||
execute: async (_context: CommandContext, body = '') => {
|
||||
return CommandService.instance().execute('newNote', body, true);
|
||||
},
|
||||
enabledCondition: 'oneFolderSelected && !inConflictFolder',
|
||||
enabledCondition: 'oneFolderSelected && !inConflictFolder && !folderIsReadOnly',
|
||||
};
|
||||
};
|
||||
|
||||
@@ -33,5 +33,6 @@ export const runtime = (): CommandRuntime => {
|
||||
},
|
||||
});
|
||||
},
|
||||
enabledCondition: '!folderIsReadOnly',
|
||||
};
|
||||
};
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
import { CommandRuntime, CommandDeclaration, CommandContext } from '@joplin/lib/services/CommandService';
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
import Note from '@joplin/lib/models/Note';
|
||||
import eventManager from '@joplin/lib/eventManager';
|
||||
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'toggleNoteType',
|
||||
label: () => _('Switch between note and to-do type'),
|
||||
};
|
||||
|
||||
export const runtime = (): CommandRuntime => {
|
||||
return {
|
||||
execute: async (context: CommandContext, noteIds: string[] = null) => {
|
||||
if (noteIds === null) noteIds = context.state.selectedNoteIds;
|
||||
|
||||
for (let i = 0; i < noteIds.length; i++) {
|
||||
const note = await Note.load(noteIds[i]);
|
||||
const newNote = await Note.save(Note.toggleIsTodo(note), { userSideValidation: true });
|
||||
const eventNote = {
|
||||
id: newNote.id,
|
||||
is_todo: newNote.is_todo,
|
||||
todo_due: newNote.todo_due,
|
||||
todo_completed: newNote.todo_completed,
|
||||
};
|
||||
eventManager.emit('noteTypeToggle', { noteId: note.id, note: eventNote });
|
||||
}
|
||||
},
|
||||
enabledCondition: '!noteIsReadOnly',
|
||||
};
|
||||
};
|
||||
@@ -40,6 +40,7 @@ import ErrorBoundary from '../../../ErrorBoundary';
|
||||
import { MarkupToHtmlOptions } from '../../utils/useMarkupToHtml';
|
||||
import eventManager from '@joplin/lib/eventManager';
|
||||
import { EditContextMenuFilterObject } from '@joplin/lib/services/plugins/api/JoplinWorkspace';
|
||||
import type { ContextMenuEvent, ContextMenuParams } from 'electron';
|
||||
|
||||
const menuUtils = new MenuUtils(CommandService.instance());
|
||||
|
||||
@@ -782,20 +783,50 @@ function CodeMirror(props: NoteBodyEditorProps, ref: any) {
|
||||
// It might be buggy, refer to the below issue
|
||||
// https://github.com/laurent22/joplin/pull/3974#issuecomment-718936703
|
||||
useEffect(() => {
|
||||
function pointerInsideEditor(params: any) {
|
||||
const x = params.x, y = params.y, isEditable = params.isEditable, inputFieldType = params.inputFieldType;
|
||||
const isAncestorOfCodeMirrorEditor = (elem: HTMLElement) => {
|
||||
for (; elem.parentElement; elem = elem.parentElement) {
|
||||
if (elem.classList.contains('codeMirrorEditor')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
let lastInCodeMirrorContextMenuTimestamp = 0;
|
||||
|
||||
// The browser's contextmenu event provides additional information about the
|
||||
// target of the event, not provided by the Electron context-menu event.
|
||||
const onBrowserContextMenu = (event: Event) => {
|
||||
if (isAncestorOfCodeMirrorEditor(event.target as HTMLElement)) {
|
||||
lastInCodeMirrorContextMenuTimestamp = Date.now();
|
||||
}
|
||||
};
|
||||
|
||||
function pointerInsideEditor(params: ContextMenuParams) {
|
||||
const x = params.x, y = params.y, isEditable = params.isEditable;
|
||||
const elements = document.getElementsByClassName('codeMirrorEditor');
|
||||
|
||||
// inputFieldType: The input field type of CodeMirror is "textarea" so the inputFieldType = "none",
|
||||
// and any single-line input above codeMirror has inputFieldType value according to the type of input e.g.(text = plainText, password = password, ...).
|
||||
if (!elements.length || !isEditable || inputFieldType !== 'none') return null;
|
||||
// Note: We can't check inputFieldType here. When spellcheck is enabled,
|
||||
// params.inputFieldType is "none". When spellcheck is disabled,
|
||||
// params.inputFieldType is "plainText". Thus, such a check would be inconsistent.
|
||||
if (!elements.length || !isEditable) return false;
|
||||
|
||||
const maximumMsSinceBrowserEvent = 100;
|
||||
if (Date.now() - lastInCodeMirrorContextMenuTimestamp > maximumMsSinceBrowserEvent) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const rect = convertToScreenCoordinates(Setting.value('windowContentZoomFactor'), elements[0].getBoundingClientRect());
|
||||
return rect.x < x && rect.y < y && rect.right > x && rect.bottom > y;
|
||||
}
|
||||
|
||||
async function onContextMenu(_event: any, params: any) {
|
||||
async function onContextMenu(event: ContextMenuEvent, params: ContextMenuParams) {
|
||||
if (!pointerInsideEditor(params)) return;
|
||||
|
||||
// Don't show the default menu.
|
||||
event.preventDefault();
|
||||
|
||||
const menu = new Menu();
|
||||
|
||||
const hasSelectedText = editorRef.current && !!editorRef.current.getSelection() ;
|
||||
@@ -872,10 +903,15 @@ function CodeMirror(props: NoteBodyEditorProps, ref: any) {
|
||||
menu.popup();
|
||||
}
|
||||
|
||||
bridge().window().webContents.on('context-menu', onContextMenu);
|
||||
// Prepend the event listener so that it gets called before
|
||||
// the listener that shows the default menu.
|
||||
bridge().window().webContents.prependListener('context-menu', onContextMenu);
|
||||
|
||||
window.addEventListener('contextmenu', onBrowserContextMenu);
|
||||
|
||||
return () => {
|
||||
bridge().window().webContents.off('context-menu', onContextMenu);
|
||||
window.removeEventListener('contextmenu', onBrowserContextMenu);
|
||||
};
|
||||
// eslint-disable-next-line @seiyab/react-hooks/exhaustive-deps -- Old code before rule was applied
|
||||
}, [props.plugins]);
|
||||
@@ -893,7 +929,7 @@ function CodeMirror(props: NoteBodyEditorProps, ref: any) {
|
||||
mode={props.contentMarkupLanguage === MarkupToHtml.MARKUP_LANGUAGE_HTML ? 'xml' : 'joplin-markdown'}
|
||||
codeMirrorTheme={styles.editor.codeMirrorTheme}
|
||||
style={styles.editor}
|
||||
readOnly={props.visiblePanes.indexOf('editor') < 0}
|
||||
readOnly={props.disabled || props.visiblePanes.indexOf('editor') < 0}
|
||||
autoMatchBraces={matchBracesOptions}
|
||||
keyMap={props.keyboardMode}
|
||||
plugins={props.plugins}
|
||||
@@ -927,7 +963,7 @@ function CodeMirror(props: NoteBodyEditorProps, ref: any) {
|
||||
<ErrorBoundary message="The text editor encountered a fatal error and could not continue. The error might be due to a plugin, so please try to disable some of them and try again.">
|
||||
<div style={styles.root} ref={rootRef}>
|
||||
<div style={styles.rowToolbar}>
|
||||
<Toolbar themeId={props.themeId} />
|
||||
<Toolbar themeId={props.themeId}/>
|
||||
{props.noteToolbar}
|
||||
</div>
|
||||
<div style={styles.rowEditorViewer}>
|
||||
|
||||
@@ -167,6 +167,7 @@ function Editor(props: EditorProps, ref: any) {
|
||||
|
||||
const safeOptions: Record<string, any> = {
|
||||
value: props.value,
|
||||
readOnly: props.readOnly,
|
||||
};
|
||||
|
||||
const unsafeOptions: Record<string, any> = {
|
||||
|
||||
@@ -11,6 +11,7 @@ const { buildStyle } = require('@joplin/lib/theme');
|
||||
interface ToolbarProps {
|
||||
themeId: number;
|
||||
toolbarButtonInfos: ToolbarButtonInfo[];
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
function styles_(props: ToolbarProps) {
|
||||
@@ -28,7 +29,7 @@ const toolbarButtonUtils = new ToolbarButtonUtils(CommandService.instance());
|
||||
|
||||
function Toolbar(props: ToolbarProps) {
|
||||
const styles = styles_(props);
|
||||
return <ToolbarBase style={styles.root} items={props.toolbarButtonInfos} />;
|
||||
return <ToolbarBase style={styles.root} items={props.toolbarButtonInfos} disabled={!!props.disabled} />;
|
||||
}
|
||||
|
||||
const mapStateToProps = (state: AppState) => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import shim from '@joplin/lib/shim';
|
||||
import Logger from '@joplin/lib/Logger';
|
||||
import Logger from '@joplin/utils/Logger';
|
||||
|
||||
const logger = Logger.create('useEditorSearch');
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ let dispatchDidUpdateIID_: any = null;
|
||||
let changeId_ = 1;
|
||||
|
||||
const TinyMCE = (props: NoteBodyEditorProps, ref: any) => {
|
||||
const [editor, setEditor] = useState(null);
|
||||
const [editor, setEditor] = useState<Editor|null>(null);
|
||||
const [scriptLoaded, setScriptLoaded] = useState(false);
|
||||
const [editorReady, setEditorReady] = useState(false);
|
||||
const [draggingStarted, setDraggingStarted] = useState(false);
|
||||
@@ -480,6 +480,23 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: any) => {
|
||||
border-top: none !important;
|
||||
}
|
||||
|
||||
/* Override the TinyMCE font styles with more specific CSS selectors.
|
||||
Without this, the built-in FontAwesome styles are not applied because
|
||||
they are overridden by TinyMCE. */
|
||||
.plugin-icon.fa, .plugin-icon.far, .plugin-icon.fas {
|
||||
font-family: "Font Awesome 5 Free";
|
||||
font-size: ${theme.toolbarHeight - theme.toolbarPadding}px;
|
||||
}
|
||||
|
||||
.plugin-icon.fa, .plugin-icon.fas {
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.plugin-icon.fab, .plugin-icon.far {
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
|
||||
.joplin-tinymce .tox-toolbar__group {
|
||||
background-color: ${theme.backgroundColor3};
|
||||
padding-top: ${theme.toolbarPadding}px;
|
||||
@@ -548,15 +565,7 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: any) => {
|
||||
'bold', 'italic', 'joplinHighlight', 'joplinStrikethrough', 'formattingExtras', '|',
|
||||
'link', 'joplinInlineCode', 'joplinCodeBlock', 'joplinAttach', '|',
|
||||
'bullist', 'numlist', 'joplinChecklist', '|',
|
||||
'h1', 'h2', 'h3', 'hr', 'blockquote', 'inserttable', `joplinInsertDateTime${toolbarPluginButtons}`,
|
||||
];
|
||||
|
||||
// Available table toolbar buttons:
|
||||
// https://www.tiny.cloud/docs/advanced/available-toolbar-buttons/#tableplugin
|
||||
const tableToolbar = [
|
||||
'tabledelete',
|
||||
'tableinsertrowafter tablecopyrow tablepasterowafter tabledeleterow',
|
||||
'tableinsertcolafter tablecopycol tablepastecolafter tabledeletecol',
|
||||
'h1', 'h2', 'h3', 'hr', 'blockquote', 'table', `joplinInsertDateTime${toolbarPluginButtons}`,
|
||||
];
|
||||
|
||||
const editors = await (window as any).tinymce.init({
|
||||
@@ -569,7 +578,12 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: any) => {
|
||||
icons_url: 'gui/NoteEditor/NoteBody/TinyMCE/icons.js',
|
||||
plugins: 'noneditable link joplinLists hr searchreplace codesample table',
|
||||
noneditable_noneditable_class: 'joplin-editable', // Can be a regex too
|
||||
valid_elements: '*[*]', // We already filter in sanitize_html
|
||||
|
||||
// #p: Pad empty paragraphs with to prevent them from being removed.
|
||||
// *[*]: Allow all elements and attributes -- we already filter in sanitize_html
|
||||
// See https://www.tiny.cloud/docs/configure/content-filtering/#controlcharacters
|
||||
valid_elements: '#p,*[*]',
|
||||
|
||||
menubar: false,
|
||||
relative_urls: false,
|
||||
branding: false,
|
||||
@@ -578,7 +592,6 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: any) => {
|
||||
// Handle the first table row as table header.
|
||||
// https://www.tiny.cloud/docs/plugins/table/#table_header_type
|
||||
table_header_type: 'sectionCells',
|
||||
table_toolbar: tableToolbar.join(' | '),
|
||||
table_resize_bars: false,
|
||||
language_url: ['en_US', 'en_GB'].includes(language) ? undefined : `${bridge().vendorDir()}/lib/tinymce/langs/${language}`,
|
||||
toolbar: toolbar.join(' '),
|
||||
@@ -591,6 +604,7 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: any) => {
|
||||
joplinInsert: { inline: 'ins', remove: 'all' },
|
||||
joplinSub: { inline: 'sub', remove: 'all' },
|
||||
joplinSup: { inline: 'sup', remove: 'all' },
|
||||
code: { inline: 'code', remove: 'all', attributes: { spellcheck: false } },
|
||||
},
|
||||
setup: (editor: Editor) => {
|
||||
editor.addCommand('joplinAttach', () => {
|
||||
@@ -631,22 +645,6 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: any) => {
|
||||
},
|
||||
});
|
||||
|
||||
editor.ui.registry.addMenuButton('inserttable', {
|
||||
icon: 'table',
|
||||
tooltip: 'Table',
|
||||
fetch: (callback) => {
|
||||
callback([
|
||||
{
|
||||
type: 'fancymenuitem',
|
||||
fancytype: 'inserttable',
|
||||
onAction: (data) => {
|
||||
editor.execCommand('mceInsertTable', false, { rows: data.numRows, columns: data.numColumns, options: { headerRows: 1 } });
|
||||
},
|
||||
},
|
||||
]);
|
||||
},
|
||||
});
|
||||
|
||||
editor.ui.registry.addButton('joplinInsertDateTime', {
|
||||
tooltip: _('Insert time'),
|
||||
icon: 'insert-time',
|
||||
@@ -656,9 +654,16 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: any) => {
|
||||
});
|
||||
|
||||
for (const pluginCommandName of pluginCommandNames) {
|
||||
const iconClassName = CommandService.instance().iconName(pluginCommandName);
|
||||
|
||||
// Only allow characters that appear in Font Awesome class names: letters, spaces, and dashes.
|
||||
const safeIconClassName = iconClassName.replace(/[^a-z0-9 -]/g, '');
|
||||
|
||||
editor.ui.registry.addIcon(pluginCommandName, `<i class="plugin-icon ${safeIconClassName}"></i>`);
|
||||
|
||||
editor.ui.registry.addButton(pluginCommandName, {
|
||||
tooltip: CommandService.instance().label(pluginCommandName),
|
||||
icon: CommandService.instance().iconName(pluginCommandName, 'tinymce'),
|
||||
icon: pluginCommandName,
|
||||
onAction: function() {
|
||||
void CommandService.instance().execute(pluginCommandName);
|
||||
},
|
||||
@@ -698,7 +703,17 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: any) => {
|
||||
setEditorReady(true);
|
||||
});
|
||||
|
||||
const preprocessContent = () => {
|
||||
// Disable spellcheck for all inline code blocks.
|
||||
const codeElements = editor.dom.doc.querySelectorAll('code.inline-code');
|
||||
for (const code of codeElements) {
|
||||
code.setAttribute('spellcheck', 'false');
|
||||
}
|
||||
};
|
||||
|
||||
editor.on('SetContent', () => {
|
||||
preprocessContent();
|
||||
|
||||
props_onMessage.current({ channel: 'noteRenderComplete' });
|
||||
});
|
||||
},
|
||||
@@ -715,18 +730,10 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: any) => {
|
||||
// Set the initial content and load the plugin CSS and JS files
|
||||
// -----------------------------------------------------------------------------------------
|
||||
|
||||
const loadDocumentAssets = (editor: any, pluginAssets: any[]) => {
|
||||
// Note: The way files are cached is not correct because it assumes there's only one version
|
||||
// of each file. However, when the theme change, a new CSS file, specific to the theme, is
|
||||
// created. That file should not be loaded on top of the previous one, but as a replacement.
|
||||
// Otherwise it would do this:
|
||||
// - Try to load CSS for theme 1 => OK
|
||||
// - Try to load CSS for theme 2 => OK
|
||||
// - Try to load CSS for theme 1 => Skip because the file is in cache. As a result, theme 2
|
||||
// incorrectly stay.
|
||||
// The fix would be to make allAssets() return a name and a version for each asset. Then the loading
|
||||
// code would check this and either append the CSS or replace.
|
||||
const documentCssElements: Record<string, HTMLLinkElement> = {};
|
||||
const documentScriptElements: Record<string, HTMLScriptElement> = {};
|
||||
|
||||
const loadDocumentAssets = (editor: any, pluginAssets: any[]) => {
|
||||
const theme = themeStyle(props.themeId);
|
||||
|
||||
let docHead_: any = null;
|
||||
@@ -737,49 +744,72 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: any) => {
|
||||
return docHead_;
|
||||
}
|
||||
|
||||
const cssFiles = [
|
||||
const allCssFiles = [
|
||||
`${bridge().vendorDir()}/lib/@fortawesome/fontawesome-free/css/all.min.css`,
|
||||
`gui/note-viewer/pluginAssets/highlight.js/${theme.codeThemeCss}`,
|
||||
].concat(
|
||||
pluginAssets
|
||||
.filter((a: any) => a.mime === 'text/css')
|
||||
.map((a: any) => a.path)
|
||||
).filter((path: string) => !loadedCssFiles_.includes(path));
|
||||
);
|
||||
|
||||
const jsFiles = [].concat(
|
||||
const allJsFiles = [].concat(
|
||||
pluginAssets
|
||||
.filter((a: any) => a.mime === 'application/javascript')
|
||||
.map((a: any) => a.path)
|
||||
).filter((path: string) => !loadedJsFiles_.includes(path));
|
||||
);
|
||||
|
||||
for (const cssFile of cssFiles) loadedCssFiles_.push(cssFile);
|
||||
for (const jsFile of jsFiles) loadedJsFiles_.push(jsFile);
|
||||
|
||||
// Remove all previously loaded files that aren't in the assets this time.
|
||||
// Note: This is important to ensure that we properly change themes.
|
||||
// See https://github.com/laurent22/joplin/issues/8520
|
||||
for (const cssFile of loadedCssFiles_) {
|
||||
if (!allCssFiles.includes(cssFile)) {
|
||||
documentCssElements[cssFile]?.remove();
|
||||
delete documentCssElements[cssFile];
|
||||
}
|
||||
}
|
||||
|
||||
for (const jsFile of loadedJsFiles_) {
|
||||
if (!allJsFiles.includes(jsFile)) {
|
||||
documentScriptElements[jsFile]?.remove();
|
||||
delete documentScriptElements[jsFile];
|
||||
}
|
||||
}
|
||||
|
||||
const newCssFiles = allCssFiles.filter((path: string) => !loadedCssFiles_.includes(path));
|
||||
const newJsFiles = allJsFiles.filter((path: string) => !loadedJsFiles_.includes(path));
|
||||
|
||||
loadedCssFiles_ = allCssFiles;
|
||||
loadedJsFiles_ = allJsFiles;
|
||||
|
||||
// console.info('loadDocumentAssets: files to load', cssFiles, jsFiles);
|
||||
|
||||
if (cssFiles.length) {
|
||||
for (const cssFile of cssFiles) {
|
||||
const script = editor.dom.create('link', {
|
||||
if (newCssFiles.length) {
|
||||
for (const cssFile of newCssFiles) {
|
||||
const style = editor.dom.create('link', {
|
||||
rel: 'stylesheet',
|
||||
type: 'text/css',
|
||||
href: cssFile,
|
||||
class: 'jop-tinymce-css',
|
||||
});
|
||||
|
||||
docHead().appendChild(script);
|
||||
documentCssElements[cssFile] = style;
|
||||
docHead().appendChild(style);
|
||||
}
|
||||
}
|
||||
|
||||
if (jsFiles.length) {
|
||||
if (newJsFiles.length) {
|
||||
const editorElementId = editor.dom.uniqueId();
|
||||
|
||||
for (const jsFile of jsFiles) {
|
||||
for (const jsFile of newJsFiles) {
|
||||
const script = editor.dom.create('script', {
|
||||
id: editorElementId,
|
||||
type: 'text/javascript',
|
||||
src: jsFile,
|
||||
});
|
||||
|
||||
documentScriptElements[jsFile] = script;
|
||||
docHead().appendChild(script);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ import usePrevious from '../hooks/usePrevious';
|
||||
import Setting from '@joplin/lib/models/Setting';
|
||||
import stateToWhenClauseContext from '../../services/commands/stateToWhenClauseContext';
|
||||
import ExternalEditWatcher from '@joplin/lib/services/ExternalEditWatcher';
|
||||
|
||||
import { itemIsReadOnly } from '@joplin/lib/models/utils/readOnly';
|
||||
const { themeStyle } = require('@joplin/lib/theme');
|
||||
const { substrWithEllipsis } = require('@joplin/lib/string-utils');
|
||||
import NoteSearchBar from '../NoteSearchBar';
|
||||
@@ -40,6 +40,12 @@ import Note from '@joplin/lib/models/Note';
|
||||
import Folder from '@joplin/lib/models/Folder';
|
||||
const bridge = require('@electron/remote').require('./bridge').default;
|
||||
import NoteRevisionViewer from '../NoteRevisionViewer';
|
||||
import { readFromSettings } from '@joplin/lib/services/share/reducer';
|
||||
import useAsyncEffect from '@joplin/lib/hooks/useAsyncEffect';
|
||||
import { ModelType } from '@joplin/lib/BaseModel';
|
||||
import BaseItem from '@joplin/lib/models/BaseItem';
|
||||
import { ErrorCode } from '@joplin/lib/errors';
|
||||
import ItemChange from '@joplin/lib/models/ItemChange';
|
||||
|
||||
const commands = [
|
||||
require('./commands/showRevisions'),
|
||||
@@ -51,6 +57,7 @@ function NoteEditor(props: NoteEditorProps) {
|
||||
const [showRevisions, setShowRevisions] = useState(false);
|
||||
const [titleHasBeenManuallyChanged, setTitleHasBeenManuallyChanged] = useState(false);
|
||||
const [scrollWhenReady, setScrollWhenReady] = useState<ScrollOptions>(null);
|
||||
const [isReadOnly, setIsReadOnly] = useState<boolean>(false);
|
||||
|
||||
const editorRef = useRef<any>();
|
||||
const titleInputRef = useRef<any>();
|
||||
@@ -279,6 +286,23 @@ function NoteEditor(props: NoteEditorProps) {
|
||||
// }
|
||||
// }, [props.dispatch]);
|
||||
|
||||
useAsyncEffect(async event => {
|
||||
if (!formNote.id) return;
|
||||
|
||||
try {
|
||||
const result = await itemIsReadOnly(BaseItem, ModelType.Note, ItemChange.SOURCE_UNSPECIFIED, formNote.id, props.syncUserId, props.shareCache);
|
||||
if (event.cancelled) return;
|
||||
setIsReadOnly(result);
|
||||
} catch (error) {
|
||||
if (error.code === ErrorCode.NotFound) {
|
||||
// Can happen if the note has been deleted but a render is
|
||||
// triggered anyway. It can be ignored.
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}, [formNote.id, props.syncUserId, props.shareCache]);
|
||||
|
||||
const onBodyWillChange = useCallback((event: any) => {
|
||||
handleProvisionalFlag();
|
||||
|
||||
@@ -406,7 +430,7 @@ function NoteEditor(props: NoteEditorProps) {
|
||||
htmlToMarkdown: htmlToMarkdown,
|
||||
markupToHtml: markupToHtml,
|
||||
allAssets: allAssets,
|
||||
disabled: false,
|
||||
disabled: isReadOnly,
|
||||
themeId: props.themeId,
|
||||
dispatch: props.dispatch,
|
||||
noteToolbar: null,
|
||||
@@ -570,6 +594,7 @@ function NoteEditor(props: NoteEditorProps) {
|
||||
noteTitle={formNote.title}
|
||||
noteUserUpdatedTime={formNote.user_updated_time}
|
||||
onTitleChange={onTitleChange}
|
||||
disabled={isReadOnly}
|
||||
/>
|
||||
{renderSearchInfo()}
|
||||
<div style={{ display: 'flex', flex: 1, paddingLeft: theme.editorPaddingLeft, maxHeight: '100%' }}>
|
||||
@@ -629,7 +654,9 @@ const mapStateToProps = (state: AppState) => {
|
||||
], whenClauseContext)[0],
|
||||
contentMaxWidth: state.settings['style.editor.contentMaxWidth'],
|
||||
isSafeMode: state.settings.isSafeMode,
|
||||
useCustomPdfViewer: false, // state.settings.useCustomPdfViewer,
|
||||
useCustomPdfViewer: false,
|
||||
syncUserId: state.settings['sync.userId'],
|
||||
shareCache: readFromSettings(state),
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ interface Props {
|
||||
isProvisional: boolean;
|
||||
titleInputRef: any;
|
||||
onTitleChange(event: ChangeEvent<HTMLInputElement>): void;
|
||||
disabled: boolean;
|
||||
}
|
||||
|
||||
function styles_(props: Props) {
|
||||
@@ -98,6 +99,7 @@ export default function NoteTitleBar(props: Props) {
|
||||
return <NoteToolbar
|
||||
themeId={props.themeId}
|
||||
style={styles.toolbarStyle}
|
||||
disabled={props.disabled}
|
||||
/>;
|
||||
}
|
||||
|
||||
@@ -109,6 +111,7 @@ export default function NoteTitleBar(props: Props) {
|
||||
ref={props.titleInputRef}
|
||||
placeholder={props.isProvisional ? _('Creating new %s...', props.noteIsTodo ? _('to-do') : _('note')) : ''}
|
||||
style={styles.titleInput}
|
||||
readOnly={props.disabled}
|
||||
onChange={props.onTitleChange}
|
||||
onKeyDown={onTitleKeydown}
|
||||
value={props.noteTitle}
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
import { CommandDeclaration } from '@joplin/lib/services/CommandService';
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
import { joplinCommandToTinyMceCommands } from './NoteBody/TinyMCE/utils/joplinCommandToTinyMceCommands';
|
||||
|
||||
export const enabledCondition = (commandName: string) => {
|
||||
const markdownEditorOnly = !Object.keys(joplinCommandToTinyMceCommands).includes(commandName);
|
||||
return `(!modalDialogVisible || gotoAnythingVisible) ${markdownEditorOnly ? '&& markdownEditorPaneVisible' : ''} && oneNoteSelected && noteIsMarkdown && !noteIsReadOnly`;
|
||||
};
|
||||
|
||||
const declarations: CommandDeclaration[] = [
|
||||
{
|
||||
|
||||
@@ -7,10 +7,13 @@ const Menu = bridge().Menu;
|
||||
const MenuItem = bridge().MenuItem;
|
||||
import Resource from '@joplin/lib/models/Resource';
|
||||
import BaseItem from '@joplin/lib/models/BaseItem';
|
||||
import BaseModel from '@joplin/lib/BaseModel';
|
||||
import BaseModel, { ModelType } from '@joplin/lib/BaseModel';
|
||||
import { processPastedHtml } from './resourceHandling';
|
||||
import { NoteEntity, ResourceEntity } from '@joplin/lib/services/database/types';
|
||||
import { TinyMceEditorEvents } from '../NoteBody/TinyMCE/utils/types';
|
||||
import { itemIsReadOnlySync, ItemSlice } from '@joplin/lib/models/utils/readOnly';
|
||||
import Setting from '@joplin/lib/models/Setting';
|
||||
import ItemChange from '@joplin/lib/models/ItemChange';
|
||||
const fs = require('fs-extra');
|
||||
const { writeFile } = require('fs-extra');
|
||||
const { clipboard } = require('electron');
|
||||
@@ -50,7 +53,11 @@ export async function openItemById(itemId: string, dispatch: Function, hash = ''
|
||||
}
|
||||
|
||||
try {
|
||||
await ResourceEditWatcher.instance().openAndWatch(resource.id);
|
||||
if (itemIsReadOnlySync(ModelType.Resource, ItemChange.SOURCE_UNSPECIFIED, resource as ItemSlice, Setting.value('sync.userId'), BaseItem.syncShareCache)) {
|
||||
await ResourceEditWatcher.instance().openAsReadOnly(resource.id);
|
||||
} else {
|
||||
await ResourceEditWatcher.instance().openAndWatch(resource.id);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
bridge().showErrorMessageBox(error.message);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import Resource from '@joplin/lib/models/Resource';
|
||||
import Logger from '@joplin/lib/Logger';
|
||||
import Logger from '@joplin/utils/Logger';
|
||||
const logger = Logger.create('contextMenuUtils');
|
||||
export enum ContextMenuItemType {
|
||||
None = '',
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import { processPastedHtml } from './resourceHandling';
|
||||
|
||||
describe('resourceHandling', () => {
|
||||
it('should sanitize pasted HTML', async () => {
|
||||
const testCases = [
|
||||
['Test: <style onload="evil()"></style>', 'Test: <style></style>'],
|
||||
['<a href="javascript: alert()">test</a>', '<a href="#">test</a>'],
|
||||
['<script >evil()</script>', ''],
|
||||
['<script>evil()</script>', ''],
|
||||
[
|
||||
'<img onload="document.body.innerHTML = evil;" src="data:image/svg+xml;base64,=="/>',
|
||||
'<img src="data:image/svg+xml;base64,=="/>',
|
||||
],
|
||||
];
|
||||
|
||||
for (const [html, expected] of testCases) {
|
||||
expect(await processPastedHtml(html)).toBe(expected);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -6,7 +6,8 @@ import Resource from '@joplin/lib/models/Resource';
|
||||
const bridge = require('@electron/remote').require('./bridge').default;
|
||||
import ResourceFetcher from '@joplin/lib/services/ResourceFetcher';
|
||||
import htmlUtils from '@joplin/lib/htmlUtils';
|
||||
import Logger from '@joplin/lib/Logger';
|
||||
import rendererHtmlUtils from '@joplin/renderer/htmlUtils';
|
||||
import Logger from '@joplin/utils/Logger';
|
||||
const { fileUriToPath } = require('@joplin/lib/urlUtils');
|
||||
const joplinRendererUtils = require('@joplin/renderer').utils;
|
||||
const { clipboard } = require('electron');
|
||||
@@ -159,6 +160,8 @@ export async function processPastedHtml(html: string) {
|
||||
const createdResource = await shim.createResourceFromPath(imageFilePath);
|
||||
mappedResources[imageSrc] = `file://${encodeURI(Resource.fullPath(createdResource))}`;
|
||||
}
|
||||
} else if (imageSrc.startsWith('data:')) { // Data URIs
|
||||
mappedResources[imageSrc] = imageSrc;
|
||||
} else {
|
||||
const filePath = `${Setting.value('tempDir')}/${md5(Date.now() + Math.random())}`;
|
||||
await shim.fetchBlob(imageSrc, { path: filePath });
|
||||
@@ -173,7 +176,9 @@ export async function processPastedHtml(html: string) {
|
||||
}
|
||||
}
|
||||
|
||||
return htmlUtils.replaceImageUrls(html, (src: string) => {
|
||||
return mappedResources[src];
|
||||
});
|
||||
return rendererHtmlUtils.sanitizeHtml(
|
||||
htmlUtils.replaceImageUrls(html, (src: string) => {
|
||||
return mappedResources[src];
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import AsyncActionQueue from '@joplin/lib/AsyncActionQueue';
|
||||
import { ToolbarButtonInfo } from '@joplin/lib/services/commands/ToolbarButtonUtils';
|
||||
import { PluginStates } from '@joplin/lib/services/plugins/reducer';
|
||||
import { State as ShareState } from '@joplin/lib/services/share/reducer';
|
||||
import { MarkupLanguage } from '@joplin/renderer';
|
||||
import { RenderResult, RenderResultPluginAsset } from '@joplin/renderer/MarkupToHtml';
|
||||
import { MarkupToHtmlOptions } from './useMarkupToHtml';
|
||||
@@ -45,6 +46,8 @@ export interface NoteEditorProps {
|
||||
contentMaxWidth: number;
|
||||
isSafeMode: boolean;
|
||||
useCustomPdfViewer: boolean;
|
||||
shareCache: ShareState;
|
||||
syncUserId: string;
|
||||
}
|
||||
|
||||
export interface NoteBodyEditorProps {
|
||||
|
||||
@@ -3,7 +3,7 @@ import { FormNote, defaultFormNote, ResourceInfos } from './types';
|
||||
import { clearResourceCache, attachedResources } from './resourceHandling';
|
||||
import AsyncActionQueue from '@joplin/lib/AsyncActionQueue';
|
||||
import { handleResourceDownloadMode } from './resourceHandling';
|
||||
import HtmlToHtml from '@joplin/renderer/HtmlToHtml';
|
||||
import { splitHtml } from '@joplin/renderer/HtmlToHtml';
|
||||
import Setting from '@joplin/lib/models/Setting';
|
||||
import usePrevious from '../../hooks/usePrevious';
|
||||
import ResourceEditWatcher from '@joplin/lib/services/ResourceEditWatcher/index';
|
||||
@@ -73,8 +73,7 @@ export default function useFormNote(dependencies: HookDependencies) {
|
||||
let originalCss = '';
|
||||
|
||||
if (n.markup_language === MarkupToHtml.MARKUP_LANGUAGE_HTML) {
|
||||
const htmlToHtml = new HtmlToHtml();
|
||||
const splitted = htmlToHtml.splitHtml(n.body);
|
||||
const splitted = splitHtml(n.body);
|
||||
originalCss = splitted.css;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useState, useCallback, MutableRefObject, useEffect } from 'react';
|
||||
import Logger from '@joplin/lib/Logger';
|
||||
import Logger from '@joplin/utils/Logger';
|
||||
import { SearchMarkers } from './useSearchMarkers';
|
||||
const CommandService = require('@joplin/lib/services/CommandService').default;
|
||||
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { useEffect } from 'react';
|
||||
import { FormNote, ScrollOptionTypes } from './types';
|
||||
import editorCommandDeclarations from '../editorCommandDeclarations';
|
||||
import editorCommandDeclarations, { enabledCondition } from '../editorCommandDeclarations';
|
||||
import CommandService, { CommandDeclaration, CommandRuntime, CommandContext } from '@joplin/lib/services/CommandService';
|
||||
import time from '@joplin/lib/time';
|
||||
import { reg } from '@joplin/lib/registry';
|
||||
import { joplinCommandToTinyMceCommands } from '../NoteBody/TinyMCE/utils/joplinCommandToTinyMceCommands';
|
||||
|
||||
const commandsWithDependencies = [
|
||||
require('../commands/showLocalSearch'),
|
||||
@@ -30,8 +29,6 @@ interface HookDependencies {
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types -- Old code before rule was applied
|
||||
function editorCommandRuntime(declaration: CommandDeclaration, editorRef: any, setFormNote: Function): CommandRuntime {
|
||||
const markdownEditorOnly = !Object.keys(joplinCommandToTinyMceCommands).includes(declaration.name);
|
||||
|
||||
return {
|
||||
execute: async (_context: CommandContext, ...args: any[]) => {
|
||||
if (!editorRef.current) {
|
||||
@@ -73,7 +70,7 @@ function editorCommandRuntime(declaration: CommandDeclaration, editorRef: any, s
|
||||
// currently selected text.
|
||||
//
|
||||
// https://github.com/laurent22/joplin/issues/5707
|
||||
enabledCondition: `(!modalDialogVisible || gotoAnythingVisible) ${markdownEditorOnly ? '&& markdownEditorPaneVisible' : ''} && oneNoteSelected && noteIsMarkdown`,
|
||||
enabledCondition: enabledCondition(declaration.name),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import eventManager from '@joplin/lib/eventManager';
|
||||
import NoteListUtils from '../utils/NoteListUtils';
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
import time from '@joplin/lib/time';
|
||||
import BaseModel from '@joplin/lib/BaseModel';
|
||||
import BaseModel, { ModelType } from '@joplin/lib/BaseModel';
|
||||
import bridge from '../../services/bridge';
|
||||
import Setting from '@joplin/lib/models/Setting';
|
||||
import NoteListItem from '../NoteListItem';
|
||||
@@ -19,6 +19,9 @@ import Note from '@joplin/lib/models/Note';
|
||||
import Folder from '@joplin/lib/models/Folder';
|
||||
import { Props } from './types';
|
||||
import usePrevious from '../hooks/usePrevious';
|
||||
import { itemIsReadOnlySync, ItemSlice } from '@joplin/lib/models/utils/readOnly';
|
||||
import { FolderEntity } from '@joplin/lib/services/database/types';
|
||||
import ItemChange from '@joplin/lib/models/ItemChange';
|
||||
|
||||
const commands = [
|
||||
require('./commands/focusElementNoteList'),
|
||||
@@ -186,7 +189,7 @@ const NoteListComponent = (props: Props) => {
|
||||
setDragOverTargetNoteIndex(null);
|
||||
|
||||
const targetNoteIndex = dragTargetNoteIndex_(event);
|
||||
const noteIds = JSON.parse(dt.getData('text/x-jop-note-ids'));
|
||||
const noteIds: string[] = JSON.parse(dt.getData('text/x-jop-note-ids'));
|
||||
|
||||
void Note.insertNotesAt(props.selectedFolderId, noteIds, targetNoteIndex, props.uncompletedTodosOnTop, props.showCompletedTodos);
|
||||
};
|
||||
@@ -223,7 +226,9 @@ const NoteListComponent = (props: Props) => {
|
||||
}
|
||||
};
|
||||
|
||||
const noteItem_dragStart = (event: any) => {
|
||||
const noteItem_dragStart = useCallback((event: any) => {
|
||||
if (props.parentFolderIsReadOnly) return false;
|
||||
|
||||
let noteIds = [];
|
||||
|
||||
// Here there is two cases:
|
||||
@@ -236,13 +241,17 @@ const NoteListComponent = (props: Props) => {
|
||||
if (clickedNoteId) noteIds.push(clickedNoteId);
|
||||
}
|
||||
|
||||
if (!noteIds.length) return;
|
||||
if (!noteIds.length) return false;
|
||||
|
||||
event.dataTransfer.setDragImage(new Image(), 1, 1);
|
||||
event.dataTransfer.clearData();
|
||||
event.dataTransfer.setData('text/x-jop-note-ids', JSON.stringify(noteIds));
|
||||
event.dataTransfer.effectAllowed = 'move';
|
||||
};
|
||||
// While setting
|
||||
// event.dataTransfer.effectAllowed = 'move';
|
||||
// causes the drag cursor to have a "move", rather than an "add", icon,
|
||||
// this breaks note drag and drop into the markdown editor.
|
||||
return true;
|
||||
}, [props.parentFolderIsReadOnly, props.selectedNoteIds]);
|
||||
|
||||
const renderItem = useCallback((item: any, index: number) => {
|
||||
const highlightedWords = () => {
|
||||
@@ -278,6 +287,7 @@ const NoteListComponent = (props: Props) => {
|
||||
onNoteDragOver={noteItem_noteDragOver}
|
||||
onTitleClick={noteItem_titleClick}
|
||||
onContextMenu={itemContextMenu}
|
||||
draggable={!props.parentFolderIsReadOnly}
|
||||
/>;
|
||||
// eslint-disable-next-line @seiyab/react-hooks/exhaustive-deps -- Old code before rule was applied
|
||||
}, [style, props.themeId, width, itemHeight, dragOverTargetNoteIndex, props.provisionalNoteIds, props.selectedNoteIds, props.watchedNoteFiles,
|
||||
@@ -286,6 +296,7 @@ const NoteListComponent = (props: Props) => {
|
||||
props.searches,
|
||||
props.selectedSearchId,
|
||||
props.highlightedWords,
|
||||
props.parentFolderIsReadOnly,
|
||||
]);
|
||||
|
||||
const previousSelectedNoteIds = usePrevious(props.selectedNoteIds, []);
|
||||
@@ -393,7 +404,8 @@ const NoteListComponent = (props: Props) => {
|
||||
if (noteIds.length && (keyCode === 46 || (keyCode === 8 && event.metaKey))) {
|
||||
// DELETE / CMD+Backspace
|
||||
event.preventDefault();
|
||||
await NoteListUtils.confirmDeleteNotes(noteIds);
|
||||
void CommandService.instance().execute('deleteNote', noteIds);
|
||||
// await NoteListUtils.confirmDeleteNotes(noteIds);
|
||||
}
|
||||
|
||||
if (noteIds.length && keyCode === 32) {
|
||||
@@ -541,6 +553,9 @@ const NoteListComponent = (props: Props) => {
|
||||
};
|
||||
|
||||
const mapStateToProps = (state: AppState) => {
|
||||
const selectedFolder: FolderEntity = state.notesParentType === 'Folder' ? BaseModel.byId(state.folders, state.selectedFolderId) : null;
|
||||
const userId = state.settings['sync.userId'];
|
||||
|
||||
return {
|
||||
notes: state.notes,
|
||||
folders: state.folders,
|
||||
@@ -560,6 +575,7 @@ const mapStateToProps = (state: AppState) => {
|
||||
plugins: state.pluginService.plugins,
|
||||
customCss: state.customCss,
|
||||
focusedField: state.focusedField,
|
||||
parentFolderIsReadOnly: state.notesParentType === 'Folder' && selectedFolder ? itemIsReadOnlySync(ModelType.Folder, ItemChange.SOURCE_UNSPECIFIED, selectedFolder as ItemSlice, userId, state.shareService) : false,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -25,4 +25,5 @@ export interface Props {
|
||||
provisionalNoteIds: string[];
|
||||
visible: boolean;
|
||||
focusedField: string;
|
||||
parentFolderIsReadOnly: boolean;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,8 @@ import Note from '@joplin/lib/models/Note';
|
||||
import { notesSortOrderNextField } from '../../services/sortOrder/notesSortOrderUtils';
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
const { connect } = require('react-redux');
|
||||
const styled = require('styled-components').default;
|
||||
import styled from 'styled-components';
|
||||
import stateToWhenClauseContext from '../../services/commands/stateToWhenClauseContext';
|
||||
|
||||
enum BaseBreakpoint {
|
||||
Sm = 75,
|
||||
@@ -27,6 +28,8 @@ interface Props {
|
||||
height: number;
|
||||
width: number;
|
||||
onContentHeightChange: (sameRow: boolean)=> void;
|
||||
newNoteButtonEnabled: boolean;
|
||||
newTodoButtonEnabled: boolean;
|
||||
}
|
||||
|
||||
interface Breakpoints {
|
||||
@@ -255,6 +258,7 @@ function NoteListControls(props: Props) {
|
||||
level={ButtonLevel.Primary}
|
||||
size={ButtonSize.Small}
|
||||
onClick={onNewNoteButtonClick}
|
||||
disabled={!props.newNoteButtonEnabled}
|
||||
/>
|
||||
<StyledButton ref={newTodoRef}
|
||||
className="new-todo-button"
|
||||
@@ -264,6 +268,7 @@ function NoteListControls(props: Props) {
|
||||
level={ButtonLevel.Secondary}
|
||||
size={ButtonSize.Small}
|
||||
onClick={onNewTodoButtonClick}
|
||||
disabled={!props.newTodoButtonEnabled}
|
||||
/>
|
||||
</TopRow>
|
||||
);
|
||||
@@ -300,9 +305,13 @@ function NoteListControls(props: Props) {
|
||||
}
|
||||
|
||||
const mapStateToProps = (state: AppState) => {
|
||||
const whenClauseContext = stateToWhenClauseContext(state);
|
||||
|
||||
return {
|
||||
// TODO: showNewNoteButtons and the logic associated is not needed anymore.
|
||||
showNewNoteButtons: true,
|
||||
newNoteButtonEnabled: CommandService.instance().isEnabled('newNote', whenClauseContext),
|
||||
newTodoButtonEnabled: CommandService.instance().isEnabled('newTodo', whenClauseContext),
|
||||
sortOrderButtonsVisible: state.settings['notes.sortOrder.buttonsVisible'],
|
||||
sortOrderField: state.settings['notes.sortOrder.field'],
|
||||
sortOrderReverse: state.settings['notes.sortOrder.reverse'],
|
||||
|
||||
@@ -58,6 +58,7 @@ interface NoteListItemProps {
|
||||
onNoteDragOver: any;
|
||||
onTitleClick: any;
|
||||
onContextMenu(event: React.MouseEvent<HTMLAnchorElement, MouseEvent>): void;
|
||||
draggable: boolean;
|
||||
}
|
||||
|
||||
function NoteListItem(props: NoteListItemProps, ref: any) {
|
||||
@@ -185,7 +186,7 @@ function NoteListItem(props: NoteListItemProps, ref: any) {
|
||||
ref={anchorRef}
|
||||
onContextMenu={props.onContextMenu}
|
||||
href="#"
|
||||
draggable={true}
|
||||
draggable={props.draggable}
|
||||
style={listItemTitleStyle}
|
||||
onClick={onTitleClick}
|
||||
onDragStart={props.onDragStart}
|
||||
|
||||
@@ -11,6 +11,7 @@ interface NoteToolbarProps {
|
||||
themeId: number;
|
||||
style: any;
|
||||
toolbarButtonInfos: ToolbarButtonInfo[];
|
||||
disabled: boolean;
|
||||
}
|
||||
|
||||
function styles_(props: NoteToolbarProps) {
|
||||
@@ -27,7 +28,7 @@ function styles_(props: NoteToolbarProps) {
|
||||
|
||||
function NoteToolbar(props: NoteToolbarProps) {
|
||||
const styles = styles_(props);
|
||||
return <ToolbarBase style={styles.root} items={props.toolbarButtonInfos} />;
|
||||
return <ToolbarBase style={styles.root} items={props.toolbarButtonInfos} disabled={props.disabled}/>;
|
||||
}
|
||||
|
||||
const toolbarButtonUtils = new ToolbarButtonUtils(CommandService.instance());
|
||||
|
||||
@@ -2,7 +2,7 @@ import Dialog from '../Dialog';
|
||||
import DialogButtonRow, { ClickEvent, ButtonSpec } from '../DialogButtonRow';
|
||||
import DialogTitle from '../DialogTitle';
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { FolderEntity } from '@joplin/lib/services/database/types';
|
||||
import Folder from '@joplin/lib/models/Folder';
|
||||
import ShareService, { ApiShare } from '@joplin/lib/services/share/ShareService';
|
||||
@@ -10,13 +10,14 @@ import styled from 'styled-components';
|
||||
import StyledFormLabel from '../style/StyledFormLabel';
|
||||
import StyledInput from '../style/StyledInput';
|
||||
import Button, { ButtonSize } from '../Button/Button';
|
||||
import Logger from '@joplin/lib/Logger';
|
||||
import Logger from '@joplin/utils/Logger';
|
||||
import StyledMessage from '../style/StyledMessage';
|
||||
import { ShareUserStatus, StateShare, StateShareUser } from '@joplin/lib/services/share/reducer';
|
||||
import { SharePermissions, ShareUserStatus, StateShare, StateShareUser } from '@joplin/lib/services/share/reducer';
|
||||
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';
|
||||
import { ChangeEvent, Dropdown, DropdownOptions, DropdownVariant } from '../Dropdown/Dropdown';
|
||||
|
||||
const logger = Logger.create('ShareFolderDialog');
|
||||
|
||||
@@ -95,6 +96,7 @@ interface Props {
|
||||
onClose(): void;
|
||||
shares: StateShare[];
|
||||
shareUsers: Record<string, StateShareUser[]>;
|
||||
canUseSharePermissions: boolean;
|
||||
}
|
||||
|
||||
interface RecipientDeleteEvent {
|
||||
@@ -108,13 +110,20 @@ enum ShareState {
|
||||
}
|
||||
|
||||
function ShareFolderDialog(props: Props) {
|
||||
const permissionOptions: DropdownOptions = {
|
||||
'can_read': _('Can view'),
|
||||
'can_read_and_write': _('Can view and edit'),
|
||||
};
|
||||
|
||||
const [folder, setFolder] = useState<FolderEntity>(null);
|
||||
const [recipientEmail, setRecipientEmail] = useState<string>('');
|
||||
const [recipientPermissions, setRecipientPermissions] = useState<string>('can_read_and_write');
|
||||
const [latestError, setLatestError] = useState<Error>(null);
|
||||
const [share, setShare] = useState<StateShare>(null);
|
||||
const [shareUsers, setShareUsers] = useState<StateShareUser[]>([]);
|
||||
const [shareState, setShareState] = useState<ShareState>(ShareState.Idle);
|
||||
const [customButtons, setCustomButtons] = useState<ButtonSpec[]>([]);
|
||||
const [recipientsBeingUpdated, setRecipientsBeingUpdated] = useState<Record<string, boolean>>({});
|
||||
|
||||
async function synchronize(event: AsyncEffectEvent = null) {
|
||||
setShareState(ShareState.Synchronizing);
|
||||
@@ -140,8 +149,7 @@ function ShareFolderDialog(props: Props) {
|
||||
useEffect(() => {
|
||||
const s = props.shares.find(s => s.folder_id === props.folderId);
|
||||
setShare(s);
|
||||
// eslint-disable-next-line @seiyab/react-hooks/exhaustive-deps -- Old code before rule was applied
|
||||
}, [props.shares]);
|
||||
}, [props.shares, props.folderId]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!share) return;
|
||||
@@ -166,7 +174,14 @@ function ShareFolderDialog(props: Props) {
|
||||
void ShareService.instance().refreshShares();
|
||||
}, [props.folderId]);
|
||||
|
||||
async function shareRecipient_click() {
|
||||
const permissionsFromString = (p: string): SharePermissions => {
|
||||
return {
|
||||
can_read: 1,
|
||||
can_write: p === 'can_read_and_write' ? 1 : 0,
|
||||
};
|
||||
};
|
||||
|
||||
const shareRecipient_click = useCallback(async () => {
|
||||
setShareState(ShareState.Creating);
|
||||
setLatestError(null);
|
||||
|
||||
@@ -192,7 +207,7 @@ function ShareFolderDialog(props: Props) {
|
||||
}
|
||||
|
||||
try {
|
||||
await ShareService.instance().addShareRecipient(share.id, share.master_key_id, recipientEmail);
|
||||
await ShareService.instance().addShareRecipient(share.id, share.master_key_id, recipientEmail, permissionsFromString(recipientPermissions));
|
||||
} catch (error) {
|
||||
// Handle the error but continue the process because we need to at
|
||||
// least refresh the shares since one has been created above.
|
||||
@@ -212,7 +227,7 @@ function ShareFolderDialog(props: Props) {
|
||||
} finally {
|
||||
defer(null);
|
||||
}
|
||||
}
|
||||
}, [recipientPermissions, props.folderId, recipientEmail]);
|
||||
|
||||
function recipientEmail_change(event: any) {
|
||||
setRecipientEmail(event.target.value);
|
||||
@@ -239,19 +254,43 @@ function ShareFolderDialog(props: Props) {
|
||||
);
|
||||
}
|
||||
|
||||
const recipientPermissions_change = useCallback((event: ChangeEvent) => {
|
||||
setRecipientPermissions(event.value);
|
||||
}, []);
|
||||
|
||||
function renderAddRecipient() {
|
||||
const disabled = shareState !== ShareState.Idle;
|
||||
|
||||
const dropdown = !props.canUseSharePermissions ? null : <Dropdown className="permission-dropdown" options={permissionOptions} value={recipientPermissions} onChange={recipientPermissions_change}/>;
|
||||
|
||||
return (
|
||||
<StyledAddRecipient>
|
||||
<StyledFormLabel>{_('Add recipient:')}</StyledFormLabel>
|
||||
<StyledRecipientControls>
|
||||
<StyledRecipientInput disabled={disabled} type="email" placeholder="example@domain.com" value={recipientEmail} onChange={recipientEmail_change} />
|
||||
{dropdown}
|
||||
<Button size={ButtonSize.Small} disabled={disabled} title={_('Share')} onClick={shareRecipient_click}></Button>
|
||||
</StyledRecipientControls>
|
||||
</StyledAddRecipient>
|
||||
);
|
||||
}
|
||||
|
||||
const recipient_permissionChange = useCallback(async (shareUserId: string, value: string) => {
|
||||
try {
|
||||
setRecipientsBeingUpdated(prev => {
|
||||
return { ...prev, [shareUserId]: true };
|
||||
});
|
||||
await ShareService.instance().setPermissions(share.id, shareUserId, permissionsFromString(value));
|
||||
} catch (error) {
|
||||
alert(`Could not set permissions: ${error.message}`);
|
||||
logger.error(error);
|
||||
} finally {
|
||||
setRecipientsBeingUpdated(prev => {
|
||||
return { ...prev, [shareUserId]: false };
|
||||
});
|
||||
}
|
||||
}, [share]);
|
||||
|
||||
function renderRecipient(index: number, shareUser: StateShareUser) {
|
||||
const statusToIcon = {
|
||||
[ShareUserStatus.Waiting]: 'fas fa-question',
|
||||
@@ -265,11 +304,16 @@ function ShareFolderDialog(props: Props) {
|
||||
[ShareUserStatus.Accepted]: _('Recipient has accepted the invitation'),
|
||||
};
|
||||
|
||||
const permission = shareUser.can_write ? 'can_read_and_write' : 'can_read';
|
||||
const enabled = !recipientsBeingUpdated[shareUser.id];
|
||||
const dropdown = !props.canUseSharePermissions ? null : <Dropdown disabled={!enabled} className="permission-dropdown" value={permission} options={permissionOptions} variant={DropdownVariant.NoBorder} onChange={event => recipient_permissionChange(shareUser.id, event.value)}/>;
|
||||
|
||||
return (
|
||||
<StyledRecipient key={shareUser.user.email} index={index}>
|
||||
<StyledRecipientName>{shareUser.user.email}</StyledRecipientName>
|
||||
{dropdown}
|
||||
<StyledRecipientStatusIcon title={statusToMessage[shareUser.status]} className={statusToIcon[shareUser.status]}></StyledRecipientStatusIcon>
|
||||
<Button size={ButtonSize.Small} iconName="far fa-times-circle" onClick={() => recipient_delete({ shareUserId: shareUser.id })}/>
|
||||
<Button disabled={!enabled} size={ButtonSize.Small} iconName="far fa-times-circle" onClick={() => recipient_delete({ shareUserId: shareUser.id })}/>
|
||||
</StyledRecipient>
|
||||
);
|
||||
}
|
||||
@@ -335,7 +379,7 @@ function ShareFolderDialog(props: Props) {
|
||||
|
||||
function renderContent() {
|
||||
return (
|
||||
<StyledRoot>
|
||||
<StyledRoot className="share-folder-dialog">
|
||||
<DialogTitle title={_('Share Notebook')}/>
|
||||
{renderFolder()}
|
||||
{renderAddRecipient()}
|
||||
@@ -363,6 +407,7 @@ const mapStateToProps = (state: State) => {
|
||||
return {
|
||||
shares: state.shareService.shares,
|
||||
shareUsers: state.shareService.shareUsers,
|
||||
canUseSharePermissions: state.settings['sync.target'] === 10 && state.settings['sync.10.canUseSharePermissions'],
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
5
packages/app-desktop/gui/ShareFolderDialog/style.scss
Normal file
5
packages/app-desktop/gui/ShareFolderDialog/style.scss
Normal file
@@ -0,0 +1,5 @@
|
||||
.share-folder-dialog {
|
||||
.permission-dropdown {
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@ import BaseModel from '@joplin/lib/BaseModel';
|
||||
import Folder from '@joplin/lib/models/Folder';
|
||||
import Note from '@joplin/lib/models/Note';
|
||||
import Tag from '@joplin/lib/models/Tag';
|
||||
import Logger from '@joplin/lib/Logger';
|
||||
import Logger from '@joplin/utils/Logger';
|
||||
import { FolderEntity, FolderIcon, FolderIconType } from '@joplin/lib/services/database/types';
|
||||
import stateToWhenClauseContext from '../../services/commands/stateToWhenClauseContext';
|
||||
import { store } from '@joplin/lib/reducer';
|
||||
@@ -296,12 +296,9 @@ const SidebarComponent = (props: Props) => {
|
||||
const state: AppState = store().getState();
|
||||
|
||||
let deleteMessage = '';
|
||||
let deleteButtonLabel = _('Remove');
|
||||
if (itemType === BaseModel.TYPE_FOLDER) {
|
||||
const folder = await Folder.load(itemId);
|
||||
deleteMessage = _('Delete notebook "%s"?\n\nAll notes and sub-notebooks within this notebook will also be deleted.', substrWithEllipsis(folder.title, 0, 32));
|
||||
deleteButtonLabel = _('Delete');
|
||||
} else if (itemType === BaseModel.TYPE_TAG) {
|
||||
const deleteButtonLabel = _('Remove');
|
||||
|
||||
if (itemType === BaseModel.TYPE_TAG) {
|
||||
const tag = await Tag.load(itemId);
|
||||
deleteMessage = _('Remove tag "%s" from all notes?', substrWithEllipsis(tag.title, 0, 32));
|
||||
} else if (itemType === BaseModel.TYPE_SEARCH) {
|
||||
@@ -321,29 +318,33 @@ const SidebarComponent = (props: Props) => {
|
||||
);
|
||||
}
|
||||
|
||||
menu.append(
|
||||
new MenuItem({
|
||||
label: deleteButtonLabel,
|
||||
click: async () => {
|
||||
const ok = bridge().showConfirmMessageBox(deleteMessage, {
|
||||
buttons: [deleteButtonLabel, _('Cancel')],
|
||||
defaultId: 1,
|
||||
});
|
||||
if (!ok) return;
|
||||
|
||||
if (itemType === BaseModel.TYPE_FOLDER) {
|
||||
await Folder.delete(itemId);
|
||||
} else if (itemType === BaseModel.TYPE_TAG) {
|
||||
await Tag.untagAll(itemId);
|
||||
} else if (itemType === BaseModel.TYPE_SEARCH) {
|
||||
props.dispatch({
|
||||
type: 'SEARCH_DELETE',
|
||||
id: itemId,
|
||||
if (itemType === BaseModel.TYPE_FOLDER) {
|
||||
menu.append(
|
||||
new MenuItem(menuUtils.commandToStatefulMenuItem('deleteFolder', itemId))
|
||||
);
|
||||
} else {
|
||||
menu.append(
|
||||
new MenuItem({
|
||||
label: deleteButtonLabel,
|
||||
click: async () => {
|
||||
const ok = bridge().showConfirmMessageBox(deleteMessage, {
|
||||
buttons: [deleteButtonLabel, _('Cancel')],
|
||||
defaultId: 1,
|
||||
});
|
||||
}
|
||||
},
|
||||
})
|
||||
);
|
||||
if (!ok) return;
|
||||
|
||||
if (itemType === BaseModel.TYPE_TAG) {
|
||||
await Tag.untagAll(itemId);
|
||||
} else if (itemType === BaseModel.TYPE_SEARCH) {
|
||||
props.dispatch({
|
||||
type: 'SEARCH_DELETE',
|
||||
id: itemId,
|
||||
});
|
||||
}
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
if (itemType === BaseModel.TYPE_FOLDER && !item.encryption_applied) {
|
||||
menu.append(new MenuItem(menuUtils.commandToStatefulMenuItem('openFolderDialog', { folderId: itemId })));
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
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';
|
||||
import { addExtraStyles, themeById } from '@joplin/lib/theme';
|
||||
|
||||
interface Props {
|
||||
themeId: any;
|
||||
@@ -21,7 +21,7 @@ export default function(props: Props): any {
|
||||
const [styleSheetContent, setStyleSheetContent] = useState('');
|
||||
|
||||
useAsyncEffect(async (event: AsyncEffectEvent) => {
|
||||
const theme = themeById(props.themeId);
|
||||
const theme = addExtraStyles(themeById(props.themeId));
|
||||
const themeCss = themeToCss(theme);
|
||||
if (event.cancelled) return;
|
||||
setStyleSheetContent(themeCss);
|
||||
|
||||
@@ -9,6 +9,7 @@ interface Props {
|
||||
themeId: number;
|
||||
style: any;
|
||||
items: any[];
|
||||
disabled: boolean;
|
||||
}
|
||||
|
||||
class ToolbarBaseComponent extends React.Component<Props, any> {
|
||||
@@ -46,6 +47,7 @@ class ToolbarBaseComponent extends React.Component<Props, any> {
|
||||
const props = {
|
||||
key: key,
|
||||
themeId: this.props.themeId,
|
||||
disabled: this.props.disabled,
|
||||
...o,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import Logger from '@joplin/lib/Logger';
|
||||
import Logger from '@joplin/utils/Logger';
|
||||
|
||||
// Can't upgrade beyond 2.x because it doesn't work with Electron. If trying to
|
||||
// upgrade again, check that adding a link from the CodeMirror editor works/
|
||||
|
||||
@@ -53,17 +53,7 @@ export default class NoteListUtils {
|
||||
);
|
||||
|
||||
menu.append(
|
||||
new MenuItem({
|
||||
label: _('Duplicate'),
|
||||
click: async () => {
|
||||
for (let i = 0; i < noteIds.length; i++) {
|
||||
const note = await Note.load(noteIds[i]);
|
||||
await Note.duplicate(noteIds[i], {
|
||||
uniqueTitle: _('%s - Copy', note.title),
|
||||
});
|
||||
}
|
||||
},
|
||||
})
|
||||
new MenuItem(menuUtils.commandToStatefulMenuItem('duplicateNote', noteIds))
|
||||
);
|
||||
|
||||
if (singleNoteId) {
|
||||
@@ -73,22 +63,9 @@ export default class NoteListUtils {
|
||||
|
||||
if (noteIds.length <= 1) {
|
||||
menu.append(
|
||||
new MenuItem({
|
||||
label: _('Switch between note and to-do type'),
|
||||
click: async () => {
|
||||
for (let i = 0; i < noteIds.length; i++) {
|
||||
const note = await Note.load(noteIds[i]);
|
||||
const newNote = await Note.save(Note.toggleIsTodo(note), { userSideValidation: true });
|
||||
const eventNote = {
|
||||
id: newNote.id,
|
||||
is_todo: newNote.is_todo,
|
||||
todo_due: newNote.todo_due,
|
||||
todo_completed: newNote.todo_completed,
|
||||
};
|
||||
eventManager.emit('noteTypeToggle', { noteId: note.id, note: eventNote });
|
||||
}
|
||||
},
|
||||
})
|
||||
new MenuItem(
|
||||
menuUtils.commandToStatefulMenuItem('toggleNoteType', noteIds)
|
||||
)
|
||||
);
|
||||
} else {
|
||||
const switchNoteType = async (noteIds: string[], type: string) => {
|
||||
@@ -189,12 +166,9 @@ export default class NoteListUtils {
|
||||
}
|
||||
|
||||
menu.append(
|
||||
new MenuItem({
|
||||
label: _('Delete'),
|
||||
click: async () => {
|
||||
await this.confirmDeleteNotes(noteIds);
|
||||
},
|
||||
})
|
||||
new MenuItem(
|
||||
menuUtils.commandToStatefulMenuItem('deleteNote', noteIds)
|
||||
)
|
||||
);
|
||||
|
||||
const pluginViewInfos = pluginUtils.viewInfosByType(props.plugins, 'menuItem');
|
||||
@@ -213,19 +187,4 @@ export default class NoteListUtils {
|
||||
return menu;
|
||||
}
|
||||
|
||||
public static async confirmDeleteNotes(noteIds: string[]) {
|
||||
if (!noteIds.length) return;
|
||||
|
||||
const msg = await Note.deleteMessage(noteIds);
|
||||
if (!msg) return;
|
||||
|
||||
const ok = bridge().showConfirmMessageBox(msg, {
|
||||
buttons: [_('Delete'), _('Cancel')],
|
||||
defaultId: 1,
|
||||
});
|
||||
|
||||
if (!ok) return;
|
||||
await Note.batchDelete(noteIds);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import Logger from '@joplin/lib/Logger';
|
||||
import Logger from '@joplin/utils/Logger';
|
||||
|
||||
const logger = Logger.create('loadScript');
|
||||
|
||||
|
||||
@@ -116,7 +116,7 @@ module.exports = {
|
||||
// setupFiles: [],
|
||||
|
||||
// A list of paths to modules that run some code to configure or set up the testing framework before each test
|
||||
// setupFilesAfterEnv: [],
|
||||
setupFilesAfterEnv: [`${__dirname}/jest.setup.js`],
|
||||
|
||||
// The number of seconds after which a test is considered as slow and reported as such in the results.
|
||||
// slowTestThreshold: 5,
|
||||
|
||||
19
packages/app-desktop/jest.setup.js
Normal file
19
packages/app-desktop/jest.setup.js
Normal file
@@ -0,0 +1,19 @@
|
||||
|
||||
const { default: Logger, TargetType } = require('@joplin/utils/Logger');
|
||||
|
||||
// TODO: Some libraries required by test-utils.js seem to fail to import with the
|
||||
// jsdom environment.
|
||||
//
|
||||
// Thus, require('@joplin/lib/testing/test-utils.js') fails and some setup must be
|
||||
// copied.
|
||||
|
||||
const logger = new Logger();
|
||||
logger.addTarget(TargetType.Console);
|
||||
logger.setLevel(Logger.LEVEL_WARN);
|
||||
Logger.initializeGlobalLogger(logger);
|
||||
|
||||
|
||||
// @electron/remote requires electron to be running. Mock it.
|
||||
jest.mock('@electron/remote', () => {
|
||||
return { require };
|
||||
});
|
||||
@@ -20,7 +20,7 @@ const NoteTag = require('@joplin/lib/models/NoteTag').default;
|
||||
const MasterKey = require('@joplin/lib/models/MasterKey').default;
|
||||
const Setting = require('@joplin/lib/models/Setting').default;
|
||||
const Revision = require('@joplin/lib/models/Revision').default;
|
||||
const Logger = require('@joplin/lib/Logger').default;
|
||||
const Logger = require('@joplin/utils/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');
|
||||
@@ -30,6 +30,13 @@ const { FileApiDriverLocal } = require('@joplin/lib/file-api-driver-local');
|
||||
const React = require('react');
|
||||
const nodeSqlite = require('sqlite3');
|
||||
|
||||
// Security: If we attempt to navigate away from the root HTML page, it's likely because
|
||||
// of an improperly sanitized link. Prevent this by closing the window before we can
|
||||
// navigate away.
|
||||
window.onbeforeunload = () => {
|
||||
window.close();
|
||||
};
|
||||
|
||||
if (bridge().env() === 'dev') {
|
||||
const newConsole = function(oldConsole) {
|
||||
const output = {};
|
||||
|
||||
@@ -4,7 +4,7 @@ const electronApp = require('electron').app;
|
||||
require('@electron/remote/main').initialize();
|
||||
const ElectronAppWrapper = require('./ElectronAppWrapper').default;
|
||||
const { initBridge } = require('./bridge');
|
||||
const Logger = require('@joplin/lib/Logger').default;
|
||||
const Logger = require('@joplin/utils/Logger').default;
|
||||
const FsDriverNode = require('@joplin/lib/fs-driver-node').default;
|
||||
const envFromArgs = require('@joplin/lib/envFromArgs');
|
||||
const packageInfo = require('./packageInfo.js');
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/app-desktop",
|
||||
"version": "2.12.7",
|
||||
"version": "2.12.10",
|
||||
"description": "Joplin for Desktop",
|
||||
"main": "main.js",
|
||||
"private": true,
|
||||
@@ -115,7 +115,7 @@
|
||||
"@types/react": "16.14.41",
|
||||
"@types/react-redux": "7.1.25",
|
||||
"@types/styled-components": "5.1.26",
|
||||
"electron": "25.2.0",
|
||||
"electron": "25.3.1",
|
||||
"electron-builder": "24.4.0",
|
||||
"glob": "10.2.7",
|
||||
"gulp": "4.0.2",
|
||||
@@ -138,6 +138,7 @@
|
||||
"@joeattardi/emoji-button": "4.6.4",
|
||||
"@joplin/lib": "~2.12",
|
||||
"@joplin/renderer": "~2.12",
|
||||
"@joplin/utils": "~2.12",
|
||||
"async-mutex": "0.4.0",
|
||||
"codemirror": "5.65.9",
|
||||
"color": "3.2.1",
|
||||
@@ -161,7 +162,7 @@
|
||||
"react": "18.2.0",
|
||||
"react-datetime": "3.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"react-redux": "8.0.7",
|
||||
"react-redux": "8.1.1",
|
||||
"react-select": "5.7.3",
|
||||
"react-toggle-button": "2.2.0",
|
||||
"react-tooltip": "4.5.1",
|
||||
|
||||
@@ -18,7 +18,7 @@ const { surroundKeywords, nextWhitespaceIndex, removeDiacritics } = require('@jo
|
||||
import { mergeOverlappingIntervals } from '@joplin/lib/ArrayUtils';
|
||||
import markupLanguageUtils from '../utils/markupLanguageUtils';
|
||||
import focusEditorIfEditorCommand from '@joplin/lib/services/commands/focusEditorIfEditorCommand';
|
||||
import Logger from '@joplin/lib/Logger';
|
||||
import Logger from '@joplin/utils/Logger';
|
||||
import { MarkupToHtml } from '@joplin/renderer';
|
||||
|
||||
const logger = Logger.create('GotoAnything');
|
||||
|
||||
@@ -31,6 +31,12 @@
|
||||
# ./runForTesting.sh 1 createUsers,createData,reset,sync && ./runForTesting.sh 1a reset,sync && ./runForTesting.sh 1
|
||||
# ./runForTesting.sh 1a
|
||||
|
||||
# ----------------------------------------------------------------------------------
|
||||
# Team accounts:
|
||||
# ----------------------------------------------------------------------------------
|
||||
|
||||
# ./runForTesting.sh 1 createTeams,createData,resetTeam,sync && ./runForTesting.sh 2 resetTeam,sync && ./runForTesting.sh 1
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
|
||||
@@ -54,13 +60,26 @@ if [ "$USER_NUM" = "1b" ]; then
|
||||
USER_PROFILE_NUM=1b
|
||||
fi
|
||||
|
||||
if [ "$USER_NUM" = "2a" ]; then
|
||||
USER_NUM=2
|
||||
USER_PROFILE_NUM=2a
|
||||
fi
|
||||
|
||||
if [ "$USER_NUM" = "2b" ]; then
|
||||
USER_NUM=2
|
||||
USER_PROFILE_NUM=2b
|
||||
fi
|
||||
|
||||
COMMANDS=($(echo $2 | tr "," "\n"))
|
||||
PROFILE_DIR=~/.config/joplindev-desktop-$USER_PROFILE_NUM
|
||||
SYNC_TARGET=10
|
||||
|
||||
CMD_FILE="$SCRIPT_DIR/runForTestingCommands-$USER_PROFILE_NUM.txt"
|
||||
rm -f "$CMD_FILE"
|
||||
touch "$CMD_FILE"
|
||||
|
||||
echo "Using sync target: $SYNC_TARGET"
|
||||
|
||||
for CMD in "${COMMANDS[@]}"
|
||||
do
|
||||
if [[ $CMD == "createUsers" ]]; then
|
||||
@@ -71,6 +90,10 @@ do
|
||||
|
||||
curl --data '{"action": "createUserDeletions"}' -H 'Content-Type: application/json' http://api.joplincloud.local:22300/api/debug
|
||||
|
||||
elif [[ $CMD == "createTeams" ]]; then
|
||||
|
||||
curl --data '{"action": "createTeams"}' -H 'Content-Type: application/json' http://api.joplincloud.local:22300/api/debug
|
||||
|
||||
elif [[ $CMD == "createData" ]]; then
|
||||
|
||||
echo 'mkbook "shared"' >> "$CMD_FILE"
|
||||
@@ -84,18 +107,26 @@ do
|
||||
USER_EMAIL="user$USER_NUM@example.com"
|
||||
rm -rf "$PROFILE_DIR"
|
||||
|
||||
# rm -rf "$HOME/Temp/SyncTestE2EE copy"
|
||||
# rsync -a "$HOME/Temp/SyncTestE2EE/" "$HOME/Temp/SyncTestE2EE copy/"
|
||||
echo "config keychain.supported 0" >> "$CMD_FILE"
|
||||
echo "config sync.target $SYNC_TARGET" >> "$CMD_FILE"
|
||||
echo "config sync.$SYNC_TARGET.username $USER_EMAIL" >> "$CMD_FILE"
|
||||
echo "config sync.$SYNC_TARGET.password 111111" >> "$CMD_FILE"
|
||||
|
||||
# echo "config sync.target 2" >> "$CMD_FILE"
|
||||
# echo "config sync.2.path \"$HOME/Temp/SyncTestE2EE copy/\"" >> "$CMD_FILE"
|
||||
if [[ $SYNC_TARGET = 9 ]]; then
|
||||
echo "config sync.$SYNC_TARGET.path http://api.joplincloud.local:22300" >> "$CMD_FILE"
|
||||
echo "config sync.$SYNC_TARGET.userContentPath http://joplinusercontent.local:22300" >> "$CMD_FILE"
|
||||
fi
|
||||
|
||||
elif [[ $CMD == "resetTeam" ]]; then
|
||||
|
||||
USER_EMAIL="teamuser1-$USER_NUM@example.com"
|
||||
rm -rf "$PROFILE_DIR"
|
||||
|
||||
echo "config keychain.supported 0" >> "$CMD_FILE"
|
||||
echo "config sync.target 10" >> "$CMD_FILE"
|
||||
# echo "config sync.10.path http://api.joplincloud.local:22300" >> "$CMD_FILE"
|
||||
echo "config sync.10.username $USER_EMAIL" >> "$CMD_FILE"
|
||||
echo "config sync.10.password 111111" >> "$CMD_FILE"
|
||||
|
||||
echo "config sync.target $SYNC_TARGET" >> "$CMD_FILE"
|
||||
echo "config sync.$SYNC_TARGET.username $USER_EMAIL" >> "$CMD_FILE"
|
||||
echo "config sync.$SYNC_TARGET.password 111111" >> "$CMD_FILE"
|
||||
|
||||
elif [[ $CMD == "e2ee" ]]; then
|
||||
|
||||
echo "e2ee enable --password 111111" >> "$CMD_FILE"
|
||||
@@ -104,11 +135,6 @@ do
|
||||
|
||||
echo "sync --use-lock 0" >> "$CMD_FILE"
|
||||
|
||||
# elif [[ $CMD == "generatePpk" ]]; then
|
||||
|
||||
# echo "e2ee generate-ppk --password 111111" >> "$CMD_FILE"
|
||||
# echo "sync" >> "$CMD_FILE"
|
||||
|
||||
else
|
||||
|
||||
echo "Unknown command: $CMD"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user