1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-12-14 23:26:58 +02:00

Compare commits

...

147 Commits

Author SHA1 Message Date
Laurent Cozic
8390d75293 Merge branch 'dev' into ui_update 2020-09-14 13:07:50 +01:00
Laurent Cozic
40e24102ce Merge branch 'release-1.1' into dev 2020-09-14 13:06:56 +01:00
Laurent Cozic
7614a795e9 Fixed tests 2020-09-14 13:06:33 +01:00
Laurent Cozic
75e62b86a1 Fixed search field hover styling 2020-09-14 12:43:21 +01:00
Laurent Cozic
840d3e9c60 Fixed hiding and showing note list 2020-09-14 12:39:32 +01:00
Laurent Cozic
a2b747c63d Merge branch 'dev' into ui_update 2020-09-14 12:13:07 +01:00
Laurent Cozic
1273a1dc5f Merge branch 'dev' of github.com:laurent22/joplin into dev 2020-09-14 11:26:41 +01:00
Laurent Cozic
10909fe4fc Merge branch 'release-1.1' into dev 2020-09-14 11:26:27 +01:00
Laurent Cozic
9b3d3026bf Merge branch 'release-1.0' into dev 2020-09-14 11:26:18 +01:00
Laurent Cozic
96076c84f4 CLI v1.0.168 2020-09-14 09:50:09 +01:00
Helmut K. C. Tessarek
2c553db45a Update translations 2020-09-14 02:22:27 -04:00
Laurent Cozic
7d7005596f Desktop: Security: Upgrade packages to fix vulnerabilities 2020-09-13 17:25:46 +01:00
Laurent Cozic
998dd52adc Desktop: Clarifies labels of certain actions, and added shortcut for note list toggle 2020-09-13 17:21:11 +01:00
DarinDev1000
374ee3baf5 Desktop: Fixes #3628: Add scroll offset for dragging notes (#3651)
The note draging was not taking into account the scroll distance.
This caused the notes to be dragged to a different location than the mouse.
This scroll offset should fix that issue.
2020-09-13 16:23:49 +01:00
Laurent Cozic
58574a2d0e Disable randomly failing test 2020-09-13 12:15:53 +01:00
Laurent Cozic
96ac6887ce restored fuzzy seach behaviour 2020-09-13 12:07:26 +01:00
Laurent Cozic
d4cc7ba85b Added + button to sidebar 2020-09-13 11:23:59 +01:00
Patryk Długajczyk
2a1c6d6475 Linux: Fixes #3720: Fix icons path in AppImage build (#3721) 2020-09-12 00:45:44 +01:00
Laurent Cozic
6919be2908 Merge branch 'dev' into ui_update 2020-09-12 00:39:38 +01:00
Laurent Cozic
cc6d7cebfa Apply linter 2020-09-12 00:39:23 +01:00
Laurent Cozic
1ba0644142 Merge branch 'release-1.1' of github.com:laurent22/joplin into release-1.1 2020-09-12 00:24:10 +01:00
Laurent Cozic
88ac57d7f3 Tools: Fixed handling of security vulnerabilities in git-changelog 2020-09-12 00:22:17 +01:00
Laurent Cozic
314686bede Android release v1.1.1 2020-09-12 00:18:03 +01:00
Laurent Cozic
af8845f209 Tools: Fixed Android version handling 2020-09-12 00:10:18 +01:00
Laurent Cozic
c95d7f9d37 Electron release v1.1.1 2020-09-12 00:06:59 +01:00
Laurent Cozic
2510c659e6 Clear build number 2020-09-12 00:06:25 +01:00
Laurent Cozic
b7523e1b21 Merge branch 'dev' into release-1.1 2020-09-12 00:03:29 +01:00
Laurent Cozic
e4e9e801a2 Android: Fix build 2020-09-11 23:57:06 +01:00
Laurent Cozic
524ec12d8a Android: Remove option for new editor as it crashes the app 2020-09-11 23:56:45 +01:00
Laurent Cozic
1108e8c28a Merge branch 'release-1.0' into dev 2020-09-11 23:34:44 +01:00
Laurent Cozic
0f1156ab9c Desktop: Fixed clock sync logic when creating new sync target 2020-09-11 23:33:34 +01:00
Laurent Cozic
2a08cc332a Merge branch 'dev' of github.com:laurent22/joplin into dev 2020-09-11 23:02:53 +01:00
Naveen M V
5d2baa872e Desktop: Fix wildcard search (#3713) 2020-09-11 22:52:32 +01:00
Laurent Cozic
7ac224df52 Updated all themes 2020-09-11 17:44:07 +01:00
Laurent Cozic
a2861e476b temp file 2020-09-11 17:26:05 +01:00
Laurent Cozic
76f44fe09f Fixing up dark theme 2020-09-11 17:25:26 +01:00
Laurent Cozic
6f1e8fba2c Fixing up dark theme 2020-09-11 16:58:32 +01:00
Laurent Cozic
fa65e29fb0 Fixing up dark theme 2020-09-11 16:57:50 +01:00
Laurent Cozic
277fa0827e Added comments for light theme 2020-09-11 15:44:04 +01:00
Laurent Cozic
0907cf6e88 Updated dropbox screen 2020-09-11 15:25:29 +01:00
Laurent Cozic
85296a8c09 Updated resource screen 2020-09-11 15:13:50 +01:00
Laurent Cozic
b9a88c9c44 Updated sync status screeen 2020-09-11 15:07:58 +01:00
Laurent Cozic
e4ffebbbc4 Moved button bar to own component 2020-09-11 14:46:29 +01:00
Laurent Cozic
427e90fbf7 Fixed config button bar 2020-09-11 14:27:40 +01:00
Laurent Cozic
204be519c1 Fix button style 2020-09-11 12:53:25 +01:00
Naveen M V
4b377589aa Desktop: Fix bug with quotes when searching (#3735) 2020-09-11 11:30:57 +01:00
Laurent Cozic
cf78204c85 Doc: Added more info about sync lock refresh mechanism 2020-09-11 11:26:07 +01:00
Laurent Cozic
20bd001878 Applying new style to config screen 2020-09-11 00:43:01 +01:00
Laurent Cozic
f016d6d6e5 Added config sidebar 2020-09-10 23:08:13 +01:00
Laurent Cozic
96960a7407 Converted config screen to TypeScript 2020-09-10 22:10:50 +01:00
Laurent Cozic
7b233084fe Moved config screen 2020-09-10 22:02:23 +01:00
Laurent Cozic
74355d5320 Reset search when parent type changes 2020-09-10 21:40:32 +01:00
Laurent Cozic
fbfd5942ce Restored showing folder when doing search 2020-09-10 12:17:48 +01:00
Laurent Cozic
eaca80d6c8 Revert "Improved displaying search results"
This reverts commit 1cc348d620.
2020-09-10 11:24:27 +01:00
Laurent Cozic
68f5494e3c Search improvements 2020-09-10 11:22:19 +01:00
Laurent Cozic
cf462b7e03 Fixed resizing window 2020-09-09 18:13:47 +01:00
Laurent Cozic
73a7b683d1 Fixed setTags command 2020-09-09 17:52:33 +01:00
Laurent Cozic
1cc348d620 Improved displaying search results 2020-09-09 17:44:15 +01:00
Laurent Cozic
25ab1704c6 Fixed toolbar buttons with label 2020-09-09 16:34:46 +01:00
Laurent Cozic
cb12c54eb7 Build files 2020-09-09 15:29:56 +01:00
Laurent Cozic
3959a441da Fix sidebar min width 2020-09-09 15:27:33 +01:00
Laurent Cozic
ab26949ad4 Merge branch 'dev' into ui_update 2020-09-09 15:03:13 +01:00
Laurent Cozic
c513cdd4eb Desktop: Sync immediately on startup 2020-09-09 14:45:26 +01:00
Laurent Cozic
5f410e80e6 Merge branch 'release-1.0' into dev 2020-09-09 13:59:36 +01:00
Laurent Cozic
2aa7eaa192 Electron release v1.0.245 2020-09-09 12:39:06 +01:00
Laurent Cozic
b24d060281 All: Got clock sync to work on mobile 2020-09-09 12:25:31 +01:00
Laurent Cozic
a014b9347e Merge branch 'release-1.0' of github.com:laurent22/joplin into release-1.0 2020-09-09 11:39:57 +01:00
Laurent Cozic
582ab4ac13 All: Implemented more reliable way to sync device and server clocks that would work with filesystem sync too 2020-09-09 11:39:13 +01:00
Laurent Cozic
c9adccad4a Get NTP time working on Android 2020-09-09 10:56:17 +01:00
Laurent Cozic
f41ba67e15 Improved ntp time 2020-09-09 00:34:27 +01:00
Laurent Cozic
1f70a76c7e Desktop: Fixes #3729: Fix lock issue when device does not have the right time 2020-09-08 23:57:48 +01:00
Cristi
5fe3732a38 All: Translation: Update ro.po (#3728) 2020-09-08 18:29:07 -04:00
Harris Arvanitis
445533cfcc All: Translation: Update el_GR.po (#3718) 2020-09-08 18:28:42 -04:00
Laurent Cozic
a8e29249d6 Electron release v1.1.244 2020-09-08 01:03:29 +01:00
Laurent Cozic
e4a3cbd2ff Increase minor version 2020-09-08 01:03:12 +01:00
Laurent Cozic
96b7ce9d50 Electron release v1.0.243 2020-09-08 00:57:35 +01:00
Laurent Cozic
2bbc1e7ecd Desktop: Fixes #3710: Fix applying tags to multiple notes 2020-09-08 00:49:58 +01:00
Laurent Cozic
83619b279d Desktop: Fixes #3697: Fixed copying link in Rich Text editor 2020-09-08 00:29:31 +01:00
Laurent Cozic
8b5a99d494 Desktop: Fixes #3553: Fixed viewer font size, in particular for inline code 2020-09-08 00:00:43 +01:00
Laurent Cozic
67d4123608 Desktop: Add log statement to try to fix issue #3536 2020-09-07 23:55:37 +01:00
Laurent Cozic
a424e3c899 Desktop, Cli: Fixes #3689: Fixed note export when there are folders with non-existing parents. Also fixed long path issue on Windows. 2020-09-07 22:12:51 +01:00
Laurent
08d4b5a714 Mobile: Fixes #3022: Fix issue with action button disappearing in some contexts (#3702) 2020-09-07 17:42:16 +01:00
Laurent Cozic
68aefd5e4c Desktop: Rename menu item from "Export" to "Export all" to clarify what it does 2020-09-07 17:33:51 +01:00
Laurent Cozic
57d750bc9a All: Security: Disallow EMBED tags to prevent XSS vulnerability 2020-09-06 19:29:42 +01:00
Laurent Cozic
af4a93c9d1 Update ignore files 2020-09-06 16:48:50 +01:00
Laurent Cozic
e364ae9133 delete temp files 2020-09-06 16:46:51 +01:00
Laurent Cozic
a66c40e999 Merge branch 'dev' into ui_update 2020-09-06 16:45:53 +01:00
Caleb John
fbe966903b Desktop: Resolves #3560: Make codemirror the default code editor (#3703) 2020-09-06 16:28:23 +01:00
Jose Esteve
652748f969 Cli: Resolves #3711: Fix keytar library being loaded up in FreeBSD. (#3712)
Issue https://github.com/laurent22/joplin/issues/3711

This patch replaces the 'isLinux' check by a more restrictive version
which fixes the false positive in BSD systems. This was causing Joplin
not to load due to the lack of X11 in headless mode.
2020-09-06 15:20:38 +01:00
Naveen M V
e108fdb1d8 Desktop: Fuzzy search (#3632) 2020-09-06 13:07:00 +01:00
Anjula Karunarathne
a8296e2e37 Desktop: Add keyboard shortcut editor (#3525) 2020-09-06 13:00:25 +01:00
Laurent Cozic
0998fc0ad7 Doc: Update dontate page 2020-09-05 22:49:40 +01:00
Laurent Cozic
d5f3e860b9 Merge branch 'dev' of github.com:laurent22/joplin into dev 2020-09-05 22:48:42 +01:00
Laurent Cozic
4e624f7db5 Doc: Added new sponsor 2020-09-05 22:28:28 +01:00
Anton Deriabin
5b697b7e16 Doc: Fixed wrong e2ee spec link (#3655) 2020-09-05 00:14:49 +01:00
Caleb John
30e0d69a74 Desktop: Load Codemirror css in index.html (#3673) 2020-09-05 00:02:20 +01:00
Caleb John
652816fd26 Desktop: Change codemirror default home and end to be visual line based (#3672) 2020-09-05 00:01:06 +01:00
Laurent Cozic
3a33e5f416 Electron release v1.0.242 2020-09-04 22:46:26 +01:00
Laurent Cozic
277dac5512 Desktop: Fixes sync target upgrade issue when custom TLS settings are used 2020-09-04 22:46:09 +01:00
Laurent Cozic
81d97d9f9d Update website 2020-09-04 19:34:43 +01:00
Laurent Cozic
a4873cd40d Android release v1.0.340 2020-09-04 19:22:28 +01:00
Laurent Cozic
20cb2daf43 Merge branch 'dev' of github.com:laurent22/joplin into dev 2020-09-04 19:15:04 +01:00
Laurent Cozic
e5b5250a91 Tools: Make it easier to create Android pre-releases 2020-09-04 19:11:46 +01:00
Laurent Cozic
db7d617e2b Update website 2020-09-04 19:06:36 +01:00
Laurent Cozic
a627884876 Merge branch 'dev' of github.com:laurent22/joplin into dev 2020-09-04 18:31:01 +01:00
Laurent Cozic
ed30d09e07 ios-v10.0.53 2020-09-04 18:30:43 +01:00
Laurent Cozic
179e3f9aee Electron release v1.0.241 2020-09-04 18:25:04 +01:00
Laurent Cozic
a67aedba35 Tools: Fixed changelog script 2020-09-04 18:24:53 +01:00
Laurent Cozic
199c411a7d CLI v1.0.167 2020-09-04 18:17:24 +01:00
Laurent Cozic
016943f7eb redraw gui while sidebars are being resized 2020-08-21 00:43:19 +01:00
Laurent Cozic
2dee827bb8 Convert main screen to TypeScript 2020-08-20 23:21:27 +01:00
Laurent Cozic
27700028ee sidebar 2020-08-20 22:53:43 +01:00
Laurent Cozic
56ba7663fd Merge branch 'dev' into ui_update 2020-08-20 19:36:06 +01:00
Laurent Cozic
64413405d7 gitignored 2020-08-20 19:35:42 +01:00
Laurent Cozic
f2469c9bf7 sidebar 2020-08-20 19:34:32 +01:00
Laurent Cozic
81140debdd Merge branch 'dev' into ui_update 2020-08-19 18:31:56 +00:00
Laurent Cozic
274861fdeb Fixed build 2020-08-08 10:30:52 +01:00
Laurent Cozic
8b76699949 Merge branch 'dev' into ui_update 2020-08-08 10:21:41 +01:00
Laurent Cozic
1f301cc841 Tools: Do not display linter warnings on CI 2020-08-08 10:20:48 +01:00
Laurent Cozic
8bcf096840 Merge branch 'dev' into ui_update 2020-08-08 10:16:40 +01:00
Laurent Cozic
d2a31f0ef2 Merge branch 'dev' into ui_update 2020-08-08 00:36:26 +01:00
Laurent Cozic
02a8b22163 sidebar 2020-08-07 23:51:01 +01:00
Laurent Cozic
15d55d537e Refactor SideBar component in TypeScript 2020-08-07 20:43:02 +00:00
Laurent Cozic
488ba01f60 Moved All Notes under Notebook section 2020-08-07 20:04:32 +00:00
Laurent Cozic
d7efc4aaca Remove header component 2020-08-07 19:41:51 +00:00
Laurent Cozic
19ed685a36 Styling 2020-08-07 19:21:37 +00:00
Laurent Cozic
184e22937a Make use of ThemeProvider to simplify code 2020-08-07 18:54:53 +00:00
Laurent Cozic
5b81aa1fdb Renamed theme => themeId 2020-08-07 02:01:59 +00:00
Laurent Cozic
7bb3ba9f3e Adding buttons 2020-08-07 01:24:04 +01:00
Laurent Cozic
54ef47120b Searh bar 2020-08-07 00:05:00 +01:00
Laurent Cozic
f83129cf2f Improve resizable layout 2020-08-06 19:17:28 +00:00
Laurent Cozic
9ec5030830 Merge branch 'dev' into ui_update 2020-08-06 15:30:26 +01:00
Laurent Cozic
4758035b45 toolbar 2020-08-04 23:53:55 +01:00
Laurent Cozic
33895bbc4e Merge branch 'dev' into ui_update 2020-08-04 23:02:22 +01:00
Laurent Cozic
3b36cac7f5 Merge branch 'dev' into ui_update 2020-08-04 22:33:20 +01:00
Laurent Cozic
3acb1a2836 note list 2020-08-04 19:02:15 +01:00
Laurent Cozic
9348499b63 note list 2020-08-04 18:56:54 +00:00
Laurent Cozic
9c61cfd39b Toolbar 2020-08-04 18:32:46 +00:00
Laurent Cozic
6445361bd9 Merge branch 'dev' into ui_update 2020-08-04 16:40:06 +01:00
Laurent Cozic
7ad0c0b9bd Added styled-component package 2020-08-04 00:11:45 +00:00
Laurent Cozic
a405a67367 Toolbar 2020-08-03 23:29:50 +01:00
Laurent Cozic
fc6f29636a Toolbars 2020-08-03 22:41:00 +01:00
Laurent Cozic
ac4e885748 Toolbar 2020-08-03 00:41:44 +00:00
Laurent Cozic
c120c6095a Started updating toolbar 2020-08-02 23:44:52 +01:00
Laurent Cozic
af762f7839 Merge branch 'dev' into ui_update 2020-08-02 16:36:26 +01:00
Laurent Cozic
31a44ac319 Save note list and sidebar width 2020-07-30 20:38:41 +01:00
Laurent Cozic
3ff8fa87a8 Refactoring main screen layout to make it easier to add or remove views and make them resizable. 2020-07-29 23:51:44 +00:00
371 changed files with 30486 additions and 23436 deletions

View File

@@ -62,20 +62,31 @@ Modules/TinyMCE/langs/
# AUTO-GENERATED - EXCLUDED TYPESCRIPT BUILD
CliClient/app/LinkSelector.js
CliClient/build/LinkSelector.js
CliClient/tests/synchronizer_LockHandler.js
CliClient/tests/synchronizer_MigrationHandler.js
ElectronClient/commands/focusElement.js
ElectronClient/commands/startExternalEditing.js
ElectronClient/commands/stopExternalEditing.js
ElectronClient/global.d.js
ElectronClient/gui/Button/Button.js
ElectronClient/gui/ConfigScreen/ButtonBar.js
ElectronClient/gui/ConfigScreen/ConfigScreen.js
ElectronClient/gui/ConfigScreen/SideBar.js
ElectronClient/gui/DropboxLoginScreen.js
ElectronClient/gui/ErrorBoundary.js
ElectronClient/gui/Header/commands/focusSearch.js
ElectronClient/gui/KeymapConfig/KeymapConfigScreen.js
ElectronClient/gui/KeymapConfig/ShortcutRecorder.js
ElectronClient/gui/KeymapConfig/styles/index.js
ElectronClient/gui/KeymapConfig/utils/getLabel.js
ElectronClient/gui/KeymapConfig/utils/useCommandStatus.js
ElectronClient/gui/KeymapConfig/utils/useKeymap.js
ElectronClient/gui/MainScreen/commands/editAlarm.js
ElectronClient/gui/MainScreen/commands/exportPdf.js
ElectronClient/gui/MainScreen/commands/hideModalMessage.js
ElectronClient/gui/MainScreen/commands/moveToFolder.js
ElectronClient/gui/MainScreen/commands/newFolder.js
ElectronClient/gui/MainScreen/commands/newNote.js
ElectronClient/gui/MainScreen/commands/newNotebook.js
ElectronClient/gui/MainScreen/commands/newTodo.js
ElectronClient/gui/MainScreen/commands/print.js
ElectronClient/gui/MainScreen/commands/renameFolder.js
@@ -87,9 +98,11 @@ ElectronClient/gui/MainScreen/commands/showModalMessage.js
ElectronClient/gui/MainScreen/commands/showNoteContentProperties.js
ElectronClient/gui/MainScreen/commands/showNoteProperties.js
ElectronClient/gui/MainScreen/commands/showShareNoteDialog.js
ElectronClient/gui/MainScreen/commands/toggleEditors.js
ElectronClient/gui/MainScreen/commands/toggleNoteList.js
ElectronClient/gui/MainScreen/commands/toggleSidebar.js
ElectronClient/gui/MainScreen/commands/toggleVisiblePanes.js
ElectronClient/gui/MainScreen/MainScreen.js
ElectronClient/gui/MultiNoteActions.js
ElectronClient/gui/NoteContentPropertiesDialog.js
ElectronClient/gui/NoteEditor/commands/editorCommandDeclarations.js
@@ -97,12 +110,6 @@ ElectronClient/gui/NoteEditor/commands/focusElementNoteBody.js
ElectronClient/gui/NoteEditor/commands/focusElementNoteTitle.js
ElectronClient/gui/NoteEditor/commands/showLocalSearch.js
ElectronClient/gui/NoteEditor/commands/showRevisions.js
ElectronClient/gui/NoteEditor/NoteBody/AceEditor/AceEditor.js
ElectronClient/gui/NoteEditor/NoteBody/AceEditor/styles/index.js
ElectronClient/gui/NoteEditor/NoteBody/AceEditor/Toolbar.js
ElectronClient/gui/NoteEditor/NoteBody/AceEditor/utils/index.js
ElectronClient/gui/NoteEditor/NoteBody/AceEditor/utils/types.js
ElectronClient/gui/NoteEditor/NoteBody/AceEditor/utils/useListIdent.js
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/CodeMirror.js
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/Editor.js
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/styles/index.js
@@ -115,6 +122,7 @@ ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useJoplinMode.js
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useLineSorting.js
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useListIdent.js
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useScrollUtils.js
ElectronClient/gui/NoteEditor/NoteBody/TinyMCE/styles/index.js
ElectronClient/gui/NoteEditor/NoteBody/TinyMCE/TinyMCE.js
ElectronClient/gui/NoteEditor/NoteBody/TinyMCE/utils/useScroll.js
ElectronClient/gui/NoteEditor/NoteEditor.js
@@ -124,19 +132,40 @@ ElectronClient/gui/NoteEditor/utils/index.js
ElectronClient/gui/NoteEditor/utils/resourceHandling.js
ElectronClient/gui/NoteEditor/utils/types.js
ElectronClient/gui/NoteEditor/utils/useDropHandler.js
ElectronClient/gui/NoteEditor/utils/useFolder.js
ElectronClient/gui/NoteEditor/utils/useFormNote.js
ElectronClient/gui/NoteEditor/utils/useMarkupToHtml.js
ElectronClient/gui/NoteEditor/utils/useMessageHandler.js
ElectronClient/gui/NoteEditor/utils/useNoteSearchBar.js
ElectronClient/gui/NoteEditor/utils/useNoteToolbarButtons.js
ElectronClient/gui/NoteEditor/utils/useSearchMarkers.js
ElectronClient/gui/NoteEditor/utils/useWindowCommandHandler.js
ElectronClient/gui/NoteList/commands/focusElementNoteList.js
ElectronClient/gui/NoteList/NoteList.js
ElectronClient/gui/NoteListControls/commands/focusSearch.js
ElectronClient/gui/NoteListControls/NoteListControls.js
ElectronClient/gui/NoteListItem.js
ElectronClient/gui/NoteToolbar/NoteToolbar.js
ElectronClient/gui/OneDriveLoginScreen.js
ElectronClient/gui/ResizableLayout/hooks/useLayoutItemSizes.js
ElectronClient/gui/ResizableLayout/hooks/useWindowResizeEvent.js
ElectronClient/gui/ResizableLayout/ResizableLayout.js
ElectronClient/gui/ResourceScreen.js
ElectronClient/gui/Root_UpgradeSyncTarget.js
ElectronClient/gui/SearchBar/hooks/useSearch.js
ElectronClient/gui/SearchBar/SearchBar.js
ElectronClient/gui/SearchBar/styles/index.js
ElectronClient/gui/ShareNoteDialog.js
ElectronClient/gui/SideBar/commands/focusElementSideBar.js
ElectronClient/gui/SideBar/SideBar.js
ElectronClient/gui/SideBar/styles/index.js
ElectronClient/gui/StatusScreen/StatusScreen.js
ElectronClient/gui/style/StyledInput.js
ElectronClient/gui/style/StyledTextInput.js
ElectronClient/gui/ToggleEditorsButton/styles/index.js
ElectronClient/gui/ToggleEditorsButton/ToggleEditorsButton.js
ElectronClient/gui/ToolbarButton/styles/index.js
ElectronClient/gui/ToolbarButton/ToolbarButton.js
ReactNativeClient/lib/AsyncActionQueue.js
ReactNativeClient/lib/checkPermissions.js
ReactNativeClient/lib/commands/historyBackward.js
@@ -151,6 +180,7 @@ ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/fence.js
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/mermaid.js
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/sanitize_html.js
ReactNativeClient/lib/JoplinServerApi.js
ReactNativeClient/lib/ntpDate.js
ReactNativeClient/lib/services/CommandService.js
ReactNativeClient/lib/services/keychain/KeychainService.js
ReactNativeClient/lib/services/keychain/KeychainServiceDriver.dummy.js
@@ -174,6 +204,16 @@ ReactNativeClient/lib/services/synchronizer/utils/types.js
ReactNativeClient/lib/services/UndoRedoService.js
ReactNativeClient/lib/ShareExtension.js
ReactNativeClient/lib/shareHandler.js
ReactNativeClient/lib/theme.js
ReactNativeClient/lib/themes/aritimDark.js
ReactNativeClient/lib/themes/dark.js
ReactNativeClient/lib/themes/dracula.js
ReactNativeClient/lib/themes/light.js
ReactNativeClient/lib/themes/nord.js
ReactNativeClient/lib/themes/oledDark.js
ReactNativeClient/lib/themes/solarizedDark.js
ReactNativeClient/lib/themes/solarizedLight.js
ReactNativeClient/lib/themes/type.js
ReactNativeClient/lib/versionInfo.js
ReactNativeClient/PluginAssetsLoader.js
ReactNativeClient/setUpQuickActions.js

58
.gitignore vendored
View File

@@ -50,23 +50,36 @@ joplin-webclipper-source.zip
Tools/commit_hook.txt
.vscode/*
*.map
ReactNativeClient/lib/sql-extensions/
!ReactNativeClient/lib/sql-extensions/spellfix.dll
# AUTO-GENERATED - EXCLUDED TYPESCRIPT BUILD
CliClient/app/LinkSelector.js
CliClient/build/LinkSelector.js
CliClient/tests/synchronizer_LockHandler.js
CliClient/tests/synchronizer_MigrationHandler.js
ElectronClient/commands/focusElement.js
ElectronClient/commands/startExternalEditing.js
ElectronClient/commands/stopExternalEditing.js
ElectronClient/global.d.js
ElectronClient/gui/Button/Button.js
ElectronClient/gui/ConfigScreen/ButtonBar.js
ElectronClient/gui/ConfigScreen/ConfigScreen.js
ElectronClient/gui/ConfigScreen/SideBar.js
ElectronClient/gui/DropboxLoginScreen.js
ElectronClient/gui/ErrorBoundary.js
ElectronClient/gui/Header/commands/focusSearch.js
ElectronClient/gui/KeymapConfig/KeymapConfigScreen.js
ElectronClient/gui/KeymapConfig/ShortcutRecorder.js
ElectronClient/gui/KeymapConfig/styles/index.js
ElectronClient/gui/KeymapConfig/utils/getLabel.js
ElectronClient/gui/KeymapConfig/utils/useCommandStatus.js
ElectronClient/gui/KeymapConfig/utils/useKeymap.js
ElectronClient/gui/MainScreen/commands/editAlarm.js
ElectronClient/gui/MainScreen/commands/exportPdf.js
ElectronClient/gui/MainScreen/commands/hideModalMessage.js
ElectronClient/gui/MainScreen/commands/moveToFolder.js
ElectronClient/gui/MainScreen/commands/newFolder.js
ElectronClient/gui/MainScreen/commands/newNote.js
ElectronClient/gui/MainScreen/commands/newNotebook.js
ElectronClient/gui/MainScreen/commands/newTodo.js
ElectronClient/gui/MainScreen/commands/print.js
ElectronClient/gui/MainScreen/commands/renameFolder.js
@@ -78,9 +91,11 @@ ElectronClient/gui/MainScreen/commands/showModalMessage.js
ElectronClient/gui/MainScreen/commands/showNoteContentProperties.js
ElectronClient/gui/MainScreen/commands/showNoteProperties.js
ElectronClient/gui/MainScreen/commands/showShareNoteDialog.js
ElectronClient/gui/MainScreen/commands/toggleEditors.js
ElectronClient/gui/MainScreen/commands/toggleNoteList.js
ElectronClient/gui/MainScreen/commands/toggleSidebar.js
ElectronClient/gui/MainScreen/commands/toggleVisiblePanes.js
ElectronClient/gui/MainScreen/MainScreen.js
ElectronClient/gui/MultiNoteActions.js
ElectronClient/gui/NoteContentPropertiesDialog.js
ElectronClient/gui/NoteEditor/commands/editorCommandDeclarations.js
@@ -88,12 +103,6 @@ ElectronClient/gui/NoteEditor/commands/focusElementNoteBody.js
ElectronClient/gui/NoteEditor/commands/focusElementNoteTitle.js
ElectronClient/gui/NoteEditor/commands/showLocalSearch.js
ElectronClient/gui/NoteEditor/commands/showRevisions.js
ElectronClient/gui/NoteEditor/NoteBody/AceEditor/AceEditor.js
ElectronClient/gui/NoteEditor/NoteBody/AceEditor/styles/index.js
ElectronClient/gui/NoteEditor/NoteBody/AceEditor/Toolbar.js
ElectronClient/gui/NoteEditor/NoteBody/AceEditor/utils/index.js
ElectronClient/gui/NoteEditor/NoteBody/AceEditor/utils/types.js
ElectronClient/gui/NoteEditor/NoteBody/AceEditor/utils/useListIdent.js
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/CodeMirror.js
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/Editor.js
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/styles/index.js
@@ -106,6 +115,7 @@ ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useJoplinMode.js
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useLineSorting.js
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useListIdent.js
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useScrollUtils.js
ElectronClient/gui/NoteEditor/NoteBody/TinyMCE/styles/index.js
ElectronClient/gui/NoteEditor/NoteBody/TinyMCE/TinyMCE.js
ElectronClient/gui/NoteEditor/NoteBody/TinyMCE/utils/useScroll.js
ElectronClient/gui/NoteEditor/NoteEditor.js
@@ -115,19 +125,40 @@ ElectronClient/gui/NoteEditor/utils/index.js
ElectronClient/gui/NoteEditor/utils/resourceHandling.js
ElectronClient/gui/NoteEditor/utils/types.js
ElectronClient/gui/NoteEditor/utils/useDropHandler.js
ElectronClient/gui/NoteEditor/utils/useFolder.js
ElectronClient/gui/NoteEditor/utils/useFormNote.js
ElectronClient/gui/NoteEditor/utils/useMarkupToHtml.js
ElectronClient/gui/NoteEditor/utils/useMessageHandler.js
ElectronClient/gui/NoteEditor/utils/useNoteSearchBar.js
ElectronClient/gui/NoteEditor/utils/useNoteToolbarButtons.js
ElectronClient/gui/NoteEditor/utils/useSearchMarkers.js
ElectronClient/gui/NoteEditor/utils/useWindowCommandHandler.js
ElectronClient/gui/NoteList/commands/focusElementNoteList.js
ElectronClient/gui/NoteList/NoteList.js
ElectronClient/gui/NoteListControls/commands/focusSearch.js
ElectronClient/gui/NoteListControls/NoteListControls.js
ElectronClient/gui/NoteListItem.js
ElectronClient/gui/NoteToolbar/NoteToolbar.js
ElectronClient/gui/OneDriveLoginScreen.js
ElectronClient/gui/ResizableLayout/hooks/useLayoutItemSizes.js
ElectronClient/gui/ResizableLayout/hooks/useWindowResizeEvent.js
ElectronClient/gui/ResizableLayout/ResizableLayout.js
ElectronClient/gui/ResourceScreen.js
ElectronClient/gui/Root_UpgradeSyncTarget.js
ElectronClient/gui/SearchBar/hooks/useSearch.js
ElectronClient/gui/SearchBar/SearchBar.js
ElectronClient/gui/SearchBar/styles/index.js
ElectronClient/gui/ShareNoteDialog.js
ElectronClient/gui/SideBar/commands/focusElementSideBar.js
ElectronClient/gui/SideBar/SideBar.js
ElectronClient/gui/SideBar/styles/index.js
ElectronClient/gui/StatusScreen/StatusScreen.js
ElectronClient/gui/style/StyledInput.js
ElectronClient/gui/style/StyledTextInput.js
ElectronClient/gui/ToggleEditorsButton/styles/index.js
ElectronClient/gui/ToggleEditorsButton/ToggleEditorsButton.js
ElectronClient/gui/ToolbarButton/styles/index.js
ElectronClient/gui/ToolbarButton/ToolbarButton.js
ReactNativeClient/lib/AsyncActionQueue.js
ReactNativeClient/lib/checkPermissions.js
ReactNativeClient/lib/commands/historyBackward.js
@@ -142,6 +173,7 @@ ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/fence.js
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/mermaid.js
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/sanitize_html.js
ReactNativeClient/lib/JoplinServerApi.js
ReactNativeClient/lib/ntpDate.js
ReactNativeClient/lib/services/CommandService.js
ReactNativeClient/lib/services/keychain/KeychainService.js
ReactNativeClient/lib/services/keychain/KeychainServiceDriver.dummy.js
@@ -165,6 +197,16 @@ ReactNativeClient/lib/services/synchronizer/utils/types.js
ReactNativeClient/lib/services/UndoRedoService.js
ReactNativeClient/lib/ShareExtension.js
ReactNativeClient/lib/shareHandler.js
ReactNativeClient/lib/theme.js
ReactNativeClient/lib/themes/aritimDark.js
ReactNativeClient/lib/themes/dark.js
ReactNativeClient/lib/themes/dracula.js
ReactNativeClient/lib/themes/light.js
ReactNativeClient/lib/themes/nord.js
ReactNativeClient/lib/themes/oledDark.js
ReactNativeClient/lib/themes/solarizedDark.js
ReactNativeClient/lib/themes/solarizedLight.js
ReactNativeClient/lib/themes/type.js
ReactNativeClient/lib/versionInfo.js
ReactNativeClient/PluginAssetsLoader.js
ReactNativeClient/setUpQuickActions.js

View File

@@ -11,6 +11,7 @@ Note that all the applications share the same library, which, for historical rea
- macOS, Linux: Install rsync - https://nodejs.org/en/
- macOS: Install Cocoapods - `brew install cocoapods`
- Windows: Install Windows Build Tools - `npm install -g windows-build-tools`
- Linux: Install dependencies - `sudo apt install libnss3 libsecret-1-dev`
## Building
@@ -25,6 +26,8 @@ Then you can test the various applications:
cd ElectronClient
npm start
You can also run it under WSL 2. To do so, [follow these instructions](https://www.beekeeperstudio.io/blog/building-electron-windows-ubuntu-wsl2) to setup your environment.
## Testing the Terminal application
cd CliClient

View File

@@ -2,6 +2,9 @@ const gulp = require('gulp');
const fs = require('fs-extra');
const utils = require('../Tools/gulp/utils');
const tasks = {
compileExtensions: {
fn: require('../Tools/gulp/tasks/compileExtensions.js'),
},
copyLib: require('../Tools/gulp/tasks/copyLib'),
tsc: require('../Tools/gulp/tasks/tsc'),
updateIgnoredTypeScriptBuild: require('../Tools/gulp/tasks/updateIgnoredTypeScriptBuild'),
@@ -53,10 +56,12 @@ utils.registerGulpTasks(gulp, tasks);
gulp.task('build', gulp.series([
'prepareBuild',
'compileExtensions',
'copyLib',
]));
gulp.task('buildTests', gulp.series([
'prepareTestBuild',
'compileExtensions',
'copyLib',
]));

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -38,42 +38,42 @@ locales['tr_TR'] = require('./tr_TR.json');
locales['vi'] = require('./vi.json');
locales['zh_CN'] = require('./zh_CN.json');
locales['zh_TW'] = require('./zh_TW.json');
stats['ar'] = {"percentDone":82};
stats['eu'] = {"percentDone":35};
stats['bs_BA'] = {"percentDone":85};
stats['bg_BG'] = {"percentDone":68};
stats['ca'] = {"percentDone":54};
stats['ar'] = {"percentDone":80};
stats['eu'] = {"percentDone":34};
stats['bs_BA'] = {"percentDone":83};
stats['bg_BG'] = {"percentDone":66};
stats['ca'] = {"percentDone":53};
stats['hr_HR'] = {"percentDone":28};
stats['cs_CZ'] = {"percentDone":84};
stats['da_DK'] = {"percentDone":76};
stats['de_DE'] = {"percentDone":99};
stats['et_EE'] = {"percentDone":68};
stats['cs_CZ'] = {"percentDone":82};
stats['da_DK'] = {"percentDone":74};
stats['de_DE'] = {"percentDone":95};
stats['et_EE'] = {"percentDone":66};
stats['en_GB'] = {"percentDone":100};
stats['en_US'] = {"percentDone":100};
stats['es_ES'] = {"percentDone":91};
stats['eo'] = {"percentDone":39};
stats['fr_FR'] = {"percentDone":97};
stats['gl_ES'] = {"percentDone":44};
stats['id_ID'] = {"percentDone":95};
stats['it_IT'] = {"percentDone":93};
stats['nl_NL'] = {"percentDone":99};
stats['nl_BE'] = {"percentDone":35};
stats['nb_NO'] = {"percentDone":91};
stats['fa'] = {"percentDone":34};
stats['pl_PL'] = {"percentDone":87};
stats['pt_PT'] = {"percentDone":91};
stats['pt_BR'] = {"percentDone":98};
stats['ro'] = {"percentDone":35};
stats['sl_SI'] = {"percentDone":44};
stats['sv'] = {"percentDone":73};
stats['th_TH'] = {"percentDone":54};
stats['vi'] = {"percentDone":88};
stats['tr_TR'] = {"percentDone":99};
stats['el_GR'] = {"percentDone":93};
stats['ru_RU'] = {"percentDone":90};
stats['sr_RS'] = {"percentDone":74};
stats['zh_CN'] = {"percentDone":99};
stats['zh_TW'] = {"percentDone":98};
stats['ja_JP'] = {"percentDone":99};
stats['ko'] = {"percentDone":89};
stats['es_ES'] = {"percentDone":95};
stats['eo'] = {"percentDone":38};
stats['fr_FR'] = {"percentDone":94};
stats['gl_ES'] = {"percentDone":43};
stats['id_ID'] = {"percentDone":93};
stats['it_IT'] = {"percentDone":91};
stats['nl_NL'] = {"percentDone":96};
stats['nl_BE'] = {"percentDone":34};
stats['nb_NO'] = {"percentDone":88};
stats['fa'] = {"percentDone":80};
stats['pl_PL'] = {"percentDone":96};
stats['pt_PT'] = {"percentDone":89};
stats['pt_BR'] = {"percentDone":96};
stats['ro'] = {"percentDone":78};
stats['sl_SI'] = {"percentDone":42};
stats['sv'] = {"percentDone":71};
stats['th_TH'] = {"percentDone":52};
stats['vi'] = {"percentDone":85};
stats['tr_TR'] = {"percentDone":96};
stats['el_GR'] = {"percentDone":96};
stats['ru_RU'] = {"percentDone":95};
stats['sr_RS'] = {"percentDone":72};
stats['zh_CN'] = {"percentDone":96};
stats['zh_TW'] = {"percentDone":95};
stats['ja_JP'] = {"percentDone":96};
stats['ko'] = {"percentDone":86};
module.exports = { locales: locales, stats: stats };

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "joplin",
"version": "1.0.166",
"version": "1.0.168",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View File

@@ -28,7 +28,7 @@
],
"owner": "Laurent Cozic"
},
"version": "1.0.166",
"version": "1.0.168",
"bin": {
"joplin": "./main.js"
},

View File

@@ -4,7 +4,12 @@ require('app-module-path').addPath(__dirname);
const filterParser = require('lib/services/searchengine/filterParser.js').default;
// import filterParser from 'lib/services/searchengine/filterParser.js';
const makeTerm = (name, value, negated) => { return { name, value, negated }; };
const makeTerm = (name, value, negated, quoted = false, wildcard = false) => {
if (name === 'text') { return { name, value, negated, quoted, wildcard }; }
if (name === 'title' | name === 'body') { return { name, value, negated, wildcard }; }
return { name, value, negated };
};
describe('filterParser should be correct filter for keyword', () => {
it('title', () => {
const searchString = 'title: something';
@@ -65,7 +70,7 @@ describe('filterParser should be correct filter for keyword', () => {
it('phrase text search', () => {
const searchString = '"scott joplin"';
expect(filterParser(searchString)).toContain(makeTerm('text', '"scott joplin"', false));
expect(filterParser(searchString)).toContain(makeTerm('text', '"scott joplin"', false, true));
});
it('multi word body', () => {
@@ -105,6 +110,9 @@ describe('filterParser should be correct filter for keyword', () => {
searchString = 'tag:bl*sphemy';
expect(filterParser(searchString)).toContain(makeTerm('tag', 'bl%sphemy', false));
searchString = 'tag:"space travel"';
expect(filterParser(searchString)).toContain(makeTerm('tag', 'space travel', false));
});
it('wildcard notebooks', () => {

View File

@@ -24,7 +24,7 @@ describe('pathUtils', function() {
['no space at the end ', 'no space at the end'],
['nor dots...', 'nor dots'],
[' no space before either', 'no space before either'],
['thatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylong', 'thatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylong'],
['thatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylongthatsreallylong', 'thatsreallylongthatsreallylongthatsreallylongthats'],
];
for (let i = 0; i < testCases.length; i++) {

View File

@@ -3,7 +3,7 @@
require('app-module-path').addPath(__dirname);
const { time } = require('lib/time-utils.js');
const { asyncTest, fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('test-utils.js');
const { asyncTest, fileContentEqual, expectNotThrow, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('test-utils.js');
const InteropService = require('lib/services/InteropService.js');
const Folder = require('lib/models/Folder.js');
const Note = require('lib/models/Note.js');
@@ -442,4 +442,26 @@ describe('services_InteropService', function() {
expect(await shim.fsDriver().exists(`${exportDir()}/testexportfolder/textexportnote2.md`)).toBe(true);
}));
it('should not try to export folders with a non-existing parent', asyncTest(async () => {
// Handles and edge case where user has a folder but this folder with a parent
// that doesn't exist. Can happen for example in this case:
//
// - folder1/folder2
// - Client 1 sync folder2, but not folder1
// - Client 2 sync and get folder2 only
// - Client 2 export data
// => Crash if we don't handle this case
await Folder.save({ title: 'orphan', parent_id: '0c5bbd8a1b5a48189484a412a7e534cc' });
const service = new InteropService();
const result = await service.export({
path: exportDir(),
format: 'md',
});
expect(result.warnings.length).toBe(0);
}));
});

View File

@@ -115,6 +115,7 @@ describe('services_KeymapService', () => {
{ command: 'focusElementNoteTitle', accelerator: 'Option+Shift+Cmd+T' },
{ command: 'focusElementNoteBody', accelerator: 'Ctrl+Option+Shift+Cmd+B' },
];
testCases_Darwin.forEach(({ command, accelerator }) => {
keymapService.setAccelerator(command, accelerator);
expect(keymapService.getAccelerator(command)).toEqual(accelerator);
@@ -131,6 +132,7 @@ describe('services_KeymapService', () => {
{ command: 'focusElementNoteTitle', accelerator: 'Ctrl+Alt+Shift+T' },
{ command: 'focusElementNoteBody', accelerator: 'Ctrl+Alt+Shift+B' },
];
testCases_Linux.forEach(({ command, accelerator }) => {
keymapService.setAccelerator(command, accelerator);
expect(keymapService.getAccelerator(command)).toEqual(accelerator);
@@ -138,10 +140,10 @@ describe('services_KeymapService', () => {
});
});
describe('resetAccelerator', () => {
describe('getDefaultAccelerator', () => {
beforeEach(() => keymapService.initialize());
it('should reset the Accelerator', () => {
it('should return the default accelerator', () => {
const testCases = [
{ command: 'newNote', accelerator: 'Ctrl+Alt+Shift+N' },
{ command: 'synchronize', accelerator: null /* Disabled */ },
@@ -154,28 +156,24 @@ describe('services_KeymapService', () => {
];
testCases.forEach(({ command, accelerator }) => {
// Remember the default Accelerator value
const prevAccelerator = keymapService.getAccelerator(command);
// Remember the real default Accelerator value
const defaultAccelerator = keymapService.getAccelerator(command);
// Update the Accelerator,
// Update the Accelerator and then retrieve the default accelerator
keymapService.setAccelerator(command, accelerator);
expect(keymapService.getAccelerator(command)).toEqual(accelerator);
// and then reset it..
keymapService.resetAccelerator(command);
expect(keymapService.getAccelerator(command)).toEqual(prevAccelerator);
expect(keymapService.getDefaultAccelerator(command)).toEqual(defaultAccelerator);
});
});
});
describe('setKeymap', () => {
describe('overrideKeymap', () => {
beforeEach(() => keymapService.initialize());
it('should update the keymap', () => {
keymapService.initialize('darwin');
const customKeymap_Darwin = [
const customKeymapItems_Darwin = [
{ command: 'newNote', accelerator: 'Option+Shift+Cmd+N' },
{ command: 'synchronize', accelerator: 'F11' },
{ command: 'synchronize', accelerator: 'Ctrl+F11' },
{ command: 'textBold', accelerator: 'Shift+F5' },
{ command: 'showLocalSearch', accelerator: 'Ctrl+Option+S' },
{ command: 'gotoAnything', accelerator: 'Ctrl+Shift+G' },
@@ -187,16 +185,16 @@ describe('services_KeymapService', () => {
{ command: 'focusElementNoteList', accelerator: 'Shift+Cmd+S' /* Default of focusElementSideBar */ },
];
expect(() => keymapService.setKeymap(customKeymap_Darwin)).not.toThrow();
customKeymap_Darwin.forEach(({ command, accelerator }) => {
expect(() => keymapService.overrideKeymap(customKeymapItems_Darwin)).not.toThrow();
customKeymapItems_Darwin.forEach(({ command, accelerator }) => {
// Also check if keymap is updated or not
expect(keymapService.getAccelerator(command)).toEqual(accelerator);
});
keymapService.initialize('win32');
const customKeymap_Win32 = [
const customKeymapItems_Win32 = [
{ command: 'newNote', accelerator: 'Ctrl+Alt+Shift+N' },
{ command: 'synchronize', accelerator: 'F11' },
{ command: 'synchronize', accelerator: 'Ctrl+F11' },
{ command: 'textBold', accelerator: 'Shift+F5' },
{ command: 'showLocalSearch', accelerator: 'Ctrl+Alt+S' },
{ command: 'gotoAnything', accelerator: 'Ctrl+Shift+G' },
@@ -208,8 +206,8 @@ describe('services_KeymapService', () => {
{ command: 'focusElementNoteList', accelerator: 'Ctrl+Shift+S' /* Default of focusElementSideBar */ },
];
expect(() => keymapService.setKeymap(customKeymap_Win32)).not.toThrow();
customKeymap_Win32.forEach(({ command, accelerator }) => {
expect(() => keymapService.overrideKeymap(customKeymapItems_Win32)).not.toThrow();
customKeymapItems_Win32.forEach(({ command, accelerator }) => {
// Also check if keymap is updated or not
expect(keymapService.getAccelerator(command)).toEqual(accelerator);
});
@@ -240,30 +238,30 @@ describe('services_KeymapService', () => {
];
for (let i = 0; i < customKeymaps.length; i++) {
const customKeymap = customKeymaps[i];
expect(() => keymapService.setKeymap(customKeymap)).toThrow();
const customKeymapItems = customKeymaps[i];
expect(() => keymapService.overrideKeymap(customKeymapItems)).toThrow();
}
});
it('should throw when the provided Accelerators are invalid', () => {
// Only one test case is provided since KeymapService.validateAccelerator() is already tested
const customKeymap = [
const customKeymapItems = [
{ command: 'gotoAnything', accelerator: 'Ctrl+Shift+G' },
{ command: 'print', accelerator: 'Alt+P' },
{ command: 'focusElementNoteTitle', accelerator: 'Ctrl+Alt+Shift+J+O+P+L+I+N' },
];
expect(() => keymapService.setKeymap(customKeymap)).toThrow();
expect(() => keymapService.overrideKeymap(customKeymapItems)).toThrow();
});
it('should throw when the provided commands are invalid', () => {
const customKeymap = [
const customKeymapItems = [
{ command: 'totallyInvalidCommand', accelerator: 'Ctrl+Shift+G' },
{ command: 'print', accelerator: 'Alt+P' },
{ command: 'focusElementNoteTitle', accelerator: 'Ctrl+Alt+Shift+J' },
];
expect(() => keymapService.setKeymap(customKeymap)).toThrow();
expect(() => keymapService.overrideKeymap(customKeymapItems)).toThrow();
});
it('should throw when duplicate accelerators are provided', () => {
@@ -281,14 +279,8 @@ describe('services_KeymapService', () => {
];
for (let i = 0; i < customKeymaps_Darwin.length; i++) {
const customKeymap = customKeymaps_Darwin[i];
const defaultAccelerators = customKeymap.map(({ command }) => keymapService.getAccelerator(command));
expect(() => keymapService.setKeymap(customKeymap)).toThrow();
// All items should be reset to default values
for (let j = 0; j < customKeymap.length; j++) {
expect(keymapService.getAccelerator(customKeymap[j].command)).toEqual(defaultAccelerators[j]);
}
const customKeymapItems = customKeymaps_Darwin[i];
expect(() => keymapService.overrideKeymap(customKeymapItems)).toThrow();
}
const customKeymaps_Linux = [
@@ -305,14 +297,8 @@ describe('services_KeymapService', () => {
];
for (let i = 0; i < customKeymaps_Linux.length; i++) {
const customKeymap = customKeymaps_Linux[i];
const defaultAccelerators = customKeymap.map(({ command }) => keymapService.getAccelerator(command));
expect(() => keymapService.setKeymap(customKeymap)).toThrow();
for (let j = 0; j < customKeymap.length; j++) {
expect(keymapService.getAccelerator(customKeymap[j].command)).toEqual(defaultAccelerators[j]);
}
const customKeymapItems = customKeymaps_Linux[i];
expect(() => keymapService.overrideKeymap(customKeymapItems)).toThrow();
}
});
});

View File

@@ -426,7 +426,7 @@ describe('services_SearchEngine', function() {
const t = testCases[i];
const input = t[0];
const expected = t[1];
const actual = engine.parseQuery(input);
const actual = await engine.parseQuery(input);
const _Values = actual.terms._ ? actual.terms._.map(v => v.value) : undefined;
const titleValues = actual.terms.title ? actual.terms.title.map(v => v.value) : undefined;

View File

@@ -268,7 +268,7 @@ describe('services_SearchFilter', function() {
await Tag.setNoteTagsByTitles(n1.id, ['tag1', 'tag2']);
await Tag.setNoteTagsByTitles(n2.id, ['tag2', 'tag3']);
await Tag.setNoteTagsByTitles(n3.id, ['tag3', 'tag4']);
await Tag.setNoteTagsByTitles(n3.id, ['tag3', 'tag4', 'space travel']);
await engine.syncTables();
@@ -304,6 +304,10 @@ describe('services_SearchFilter', function() {
expect(rows.length).toBe(2);
expect(ids(rows)).toContain(n1.id);
expect(ids(rows)).toContain(n3.id);
rows = await engine.search('tag:"space travel"');
expect(rows.length).toBe(1);
expect(ids(rows)).toContain(n3.id);
}));
it('should support filtering by notebook', asyncTest(async () => {

View File

@@ -0,0 +1,163 @@
/* eslint-disable no-unused-vars */
/* eslint prefer-const: 0*/
require('app-module-path').addPath(__dirname);
const { time } = require('lib/time-utils.js');
const { fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, asyncTest, db, synchronizer, fileApi, sleep, createNTestNotes, switchClient, createNTestFolders } = require('test-utils.js');
const SearchEngine = require('lib/services/searchengine/SearchEngine');
const Note = require('lib/models/Note');
const Folder = require('lib/models/Folder');
const Tag = require('lib/models/Tag');
const ItemChange = require('lib/models/ItemChange');
const Setting = require('lib/models/Setting');
const Resource = require('lib/models/Resource.js');
const { shim } = require('lib/shim');
const ResourceService = require('lib/services/ResourceService.js');
process.on('unhandledRejection', (reason, p) => {
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
});
let engine = null;
const ids = (array) => array.map(a => a.id);
describe('services_SearchFuzzy', function() {
beforeEach(async (done) => {
await setupDatabaseAndSynchronizer(1);
await switchClient(1);
engine = new SearchEngine();
engine.setDb(db());
Setting.setValue('db.fuzzySearchEnabled', 1);
done();
});
it('should return note almost matching title', asyncTest(async () => {
let rows;
const n1 = await Note.save({ title: 'If It Ain\'t Baroque, Don\'t Fix It' });
const n2 = await Note.save({ title: 'Important note' });
await engine.syncTables();
rows = await engine.search('Broke', { fuzzy: false });
expect(rows.length).toBe(0);
rows = await engine.search('Broke', { fuzzy: true });
expect(rows.length).toBe(1);
expect(rows[0].id).toBe(n1.id);
rows = await engine.search('title:Broke', { fuzzy: true });
expect(rows.length).toBe(1);
expect(rows[0].id).toBe(n1.id);
rows = await engine.search('title:"Broke"', { fuzzy: true });
expect(rows.length).toBe(1);
expect(rows[0].id).toBe(n1.id);
rows = await engine.search('Imprtant', { fuzzy: true });
expect(rows.length).toBe(1);
expect(rows[0].id).toBe(n2.id);
}));
it('should order results by min fuzziness', asyncTest(async () => {
let rows;
const n1 = await Note.save({ title: 'I demand you take me to him' });
const n2 = await Note.save({ title: 'He demanded an answer' });
const n3 = await Note.save({ title: 'Don\'t you make demands of me' });
const n4 = await Note.save({ title: 'No drama for me' });
const n5 = await Note.save({ title: 'Just minding my own business' });
await engine.syncTables();
rows = await engine.search('demand', { fuzzy: false });
expect(rows.length).toBe(1);
expect(rows[0].id).toBe(n1.id);
rows = await engine.search('demand', { fuzzy: true });
expect(rows.length).toBe(3);
expect(rows[0].id).toBe(n1.id);
expect(rows[1].id).toBe(n3.id);
expect(rows[2].id).toBe(n2.id);
}));
it('should consider any:1', asyncTest(async () => {
let rows;
const n1 = await Note.save({ title: 'cat' });
const n2 = await Note.save({ title: 'cats' });
const n3 = await Note.save({ title: 'cot' });
const n4 = await Note.save({ title: 'defenestrate' });
const n5 = await Note.save({ title: 'defenstrate' });
const n6 = await Note.save({ title: 'defenestrated' });
const n7 = await Note.save({ title: 'he defenestrated the cat' });
await engine.syncTables();
rows = await engine.search('defenestrated cat', { fuzzy: true });
expect(rows.length).toBe(1);
rows = await engine.search('any:1 defenestrated cat', { fuzzy: true });
expect(rows.length).toBe(7);
}));
it('should leave phrase searches alone', asyncTest(async () => {
let rows;
const n1 = await Note.save({ title: 'abc def' });
const n2 = await Note.save({ title: 'def ghi' });
const n3 = await Note.save({ title: 'ghi jkl' });
const n4 = await Note.save({ title: 'def abc' });
const n5 = await Note.save({ title: 'mno pqr ghi jkl' });
await engine.syncTables();
rows = await engine.search('abc def', { fuzzy: true });
expect(rows.length).toBe(2);
expect(rows.map(r=>r.id)).toContain(n1.id);
expect(rows.map(r=>r.id)).toContain(n4.id);
rows = await engine.search('"abc def"', { fuzzy: true });
expect(rows.length).toBe(1);
expect(rows.map(r=>r.id)).toContain(n1.id);
rows = await engine.search('"ghi jkl"', { fuzzy: true });
expect(rows.length).toBe(2);
expect(rows.map(r=>r.id)).toContain(n3.id);
expect(rows.map(r=>r.id)).toContain(n5.id);
rows = await engine.search('"ghi jkl" mno', { fuzzy: true });
expect(rows.length).toBe(1);
expect(rows.map(r=>r.id)).toContain(n5.id);
rows = await engine.search('any:1 "ghi jkl" mno', { fuzzy: true });
expect(rows.length).toBe(2);
expect(rows.map(r=>r.id)).toContain(n3.id);
expect(rows.map(r=>r.id)).toContain(n5.id);
}));
it('should leave wild card searches alone', asyncTest(async () => {
let rows;
const n1 = await Note.save({ title: 'abc def' });
const n2 = await Note.save({ title: 'abcc ghi' });
const n3 = await Note.save({ title: 'abccc ghi' });
const n4 = await Note.save({ title: 'abcccc ghi' });
const n5 = await Note.save({ title: 'wxy zzz' });
await engine.syncTables();
rows = await engine.search('abc*', { fuzzy: true });
expect(rows.length).toBe(4);
expect(rows.map(r=>r.id)).toContain(n1.id);
expect(rows.map(r=>r.id)).toContain(n2.id);
expect(rows.map(r=>r.id)).toContain(n3.id);
expect(rows.map(r=>r.id)).toContain(n4.id);
}));
});

View File

@@ -1,5 +1,6 @@
import LockHandler from 'lib/services/synchronizer/LockHandler';
import MigrationHandler from 'lib/services/synchronizer/MigrationHandler';
import { Dirnames } from 'lib/services/synchronizer/utils/types';
// To create a sync target snapshot for the current syncVersion:
// - In test-utils, set syncTargetName_ to "filesystem"
@@ -70,6 +71,14 @@ describe('synchronizer_MigrationHandler', function() {
done();
});
it('should init a new sync target', asyncTest(async () => {
// Check that basic folders "locks" and "temp" are created for new sync targets.
await migrationHandler().upgrade(1);
const result = await fileApi().list();
expect(result.items.filter((i:any) => i.path === Dirnames.Locks).length).toBe(1);
expect(result.items.filter((i:any) => i.path === Dirnames.Temp).length).toBe(1);
}), specTimeout);
it('should not allow syncing if the sync target is out-dated', asyncTest(async () => {
await synchronizer().start();
await fileApi().put('info.json', `{"version":${Setting.value('syncVersion') - 1}}`);

View File

@@ -50,6 +50,7 @@ const KeychainServiceDriver = require('lib/services/keychain/KeychainServiceDriv
const KeychainServiceDriverDummy = require('lib/services/keychain/KeychainServiceDriver.dummy').default;
const md5 = require('md5');
const S3 = require('aws-sdk/clients/s3');
const { Dirnames } = require('lib/services/synchronizer/utils/types');
const databases_ = [];
let synchronizers_ = [];
@@ -438,6 +439,7 @@ async function initFileApi() {
fileApi.setLogger(logger);
fileApi.setSyncTargetId(syncTargetId_);
fileApi.setTempDirName(Dirnames.Temp);
fileApi.requestRepeatCount_ = isNetworkSyncTarget_ ? 1 : 0;
fileApis_[syncTargetId_] = fileApi;

View File

@@ -26,10 +26,11 @@ describe('timeUtils', function() {
startDate = new Date('3 Aug 2020 07:30:20');
expect(time.goBackInTime(startDate, 1, 'day')).toBe(endDate.getTime().toString());
// Note: this test randomly fails - https://github.com/laurent22/joplin/issues/3722
startDate = new Date('11 Aug 2020');
endDate = new Date('9 Aug 2020'); // week start;
expect(time.goBackInTime(startDate, 0, 'week')).toBe(endDate.getTime().toString());
// startDate = new Date('11 Aug 2020');
// endDate = new Date('9 Aug 2020'); // week start;
// expect(time.goBackInTime(startDate, 0, 'week')).toBe(endDate.getTime().toString());
startDate = new Date('02 Feb 2020');
endDate = new Date('01 Jan 2020');

View File

@@ -105,7 +105,17 @@ class ElectronAppWrapper {
// Waiting for one of the ready events might work but they might not be triggered if there's an error, so
// the easiest is to use a timeout. Keep in mind that if you get a white window on Windows it might be due
// to this line though.
if (debugEarlyBugs) setTimeout(() => this.win_.webContents.openDevTools(), 3000);
if (debugEarlyBugs) {
setTimeout(() => {
try {
this.win_.webContents.openDevTools();
} catch (error) {
// This will throw an exception "Object has been destroyed" if the app is closed
// in less that the timeout interval. It can be ignored.
console.warn('Error opening dev tools', error);
}
}, 3000);
}
this.win_.on('close', (event) => {
// If it's on macOS, the app is completely closed only if the user chooses to close the app (willQuitApp_ will be true)

View File

@@ -30,20 +30,20 @@ const PluginManager = require('lib/services/PluginManager');
const RevisionService = require('lib/services/RevisionService');
const MigrationService = require('lib/services/MigrationService');
const CommandService = require('lib/services/CommandService').default;
const KeymapService = require('lib/services/KeymapService.js').default;
const KeymapService = require('lib/services/KeymapService').default;
const TemplateUtils = require('lib/TemplateUtils');
const CssUtils = require('lib/CssUtils');
const resourceEditWatcherReducer = require('lib/services/ResourceEditWatcher/reducer').default;
const versionInfo = require('lib/versionInfo').default;
const commands = [
require('./gui/Header/commands/focusSearch'),
require('./gui/NoteListControls/commands/focusSearch'),
require('./gui/MainScreen/commands/editAlarm'),
require('./gui/MainScreen/commands/exportPdf'),
require('./gui/MainScreen/commands/hideModalMessage'),
require('./gui/MainScreen/commands/moveToFolder'),
require('./gui/MainScreen/commands/newNote'),
require('./gui/MainScreen/commands/newNotebook'),
require('./gui/MainScreen/commands/newFolder'),
require('./gui/MainScreen/commands/newTodo'),
require('./gui/MainScreen/commands/print'),
require('./gui/MainScreen/commands/renameFolder'),
@@ -58,6 +58,7 @@ const commands = [
require('./gui/MainScreen/commands/toggleNoteList'),
require('./gui/MainScreen/commands/toggleSidebar'),
require('./gui/MainScreen/commands/toggleVisiblePanes'),
require('./gui/MainScreen/commands/toggleEditors'),
require('./gui/NoteEditor/commands/focusElementNoteBody'),
require('./gui/NoteEditor/commands/focusElementNoteTitle'),
require('./gui/NoteEditor/commands/showLocalSearch'),
@@ -110,6 +111,8 @@ class Application extends BaseApplication {
this.commandService_commandsEnabledStateChange = this.commandService_commandsEnabledStateChange.bind(this);
CommandService.instance().on('commandsEnabledStateChange', this.commandService_commandsEnabledStateChange);
KeymapService.instance().on('keymapChange', this.refreshMenu.bind(this));
}
commandService_commandsEnabledStateChange() {
@@ -284,10 +287,11 @@ class Application extends BaseApplication {
}
newState = resourceEditWatcherReducer(newState, action);
newState = super.reducer(newState, action);
CommandService.instance().scheduleMapStateToProps(newState);
return super.reducer(newState, action);
return newState;
}
toggleDevTools(visible) {
@@ -517,7 +521,7 @@ class Application extends BaseApplication {
const newNoteItem = cmdService.commandToMenuItem('newNote');
const newTodoItem = cmdService.commandToMenuItem('newTodo');
const newNotebookItem = cmdService.commandToMenuItem('newNotebook');
const newFolderItem = cmdService.commandToMenuItem('newFolder');
const printItem = cmdService.commandToMenuItem('print');
toolsItemsFirst.push(syncStatusItem, {
@@ -569,7 +573,7 @@ class Application extends BaseApplication {
const toolsItemsWindowsLinux = toolsItemsFirst.concat([{
label: _('Options'),
visible: !shim.isMac(),
accelerator: shim.isMac() ? null : keymapService.getAccelerator('config'),
accelerator: !shim.isMac() && keymapService.getAccelerator('config'),
click: () => {
this.dispatch({
type: 'NAV_GO',
@@ -631,7 +635,7 @@ class Application extends BaseApplication {
}, {
label: _('Preferences...'),
visible: shim.isMac() ? true : false,
accelerator: shim.isMac() ? keymapService.getAccelerator('config') : null,
accelerator: shim.isMac() && keymapService.getAccelerator('config'),
click: () => {
this.dispatch({
type: 'NAV_GO',
@@ -648,7 +652,7 @@ class Application extends BaseApplication {
},
shim.isMac() ? noItem : newNoteItem,
shim.isMac() ? noItem : newTodoItem,
shim.isMac() ? noItem : newNotebookItem, {
shim.isMac() ? noItem : newFolderItem, {
type: 'separator',
visible: shim.isMac() ? false : true,
}, {
@@ -663,7 +667,7 @@ class Application extends BaseApplication {
visible: shim.isMac() ? false : true,
submenu: importItems,
}, {
label: _('Export'),
label: _('Export all'),
visible: shim.isMac() ? false : true,
submenu: exportItems,
}, {
@@ -680,7 +684,7 @@ class Application extends BaseApplication {
}, {
label: _('Hide %s', 'Joplin'),
platforms: ['darwin'],
accelerator: shim.isMac() ? keymapService.getAccelerator('hideApp') : null,
accelerator: shim.isMac() && keymapService.getAccelerator('hideApp'),
click: () => { bridge().electronApp().hide(); },
}, {
type: 'separator',
@@ -697,10 +701,10 @@ class Application extends BaseApplication {
submenu: [
newNoteItem,
newTodoItem,
newNotebookItem, {
newFolderItem, {
label: _('Close Window'),
platforms: ['darwin'],
accelerator: shim.isMac() ? keymapService.getAccelerator('closeWindow') : null,
accelerator: shim.isMac() && keymapService.getAccelerator('closeWindow'),
selector: 'performClose:',
}, {
type: 'separator',
@@ -1040,11 +1044,9 @@ class Application extends BaseApplication {
// https://github.com/laurent22/joplin/issues/155
const css = `.CodeMirror * { font-family: ${fontFamilies.join(', ')} !important; }`;
const ace_css = `.ace_editor * { font-family: ${fontFamilies.join(', ')} !important; }`;
const styleTag = document.createElement('style');
styleTag.type = 'text/css';
styleTag.appendChild(document.createTextNode(css));
styleTag.appendChild(document.createTextNode(ace_css));
document.head.appendChild(styleTag);
}
@@ -1074,6 +1076,8 @@ class Application extends BaseApplication {
argv = await super.start(argv);
await this.applySettingsSideEffects();
if (Setting.value('sync.upgradeState') === Setting.SYNC_UPGRADE_STATE_MUST_DO) {
reg.logger().info('app.start: doing upgradeSyncTarget action');
bridge().window().show();
@@ -1091,7 +1095,7 @@ class Application extends BaseApplication {
const keymapService = KeymapService.instance();
try {
await KeymapService.instance().loadKeymap(`${dir}/keymap-desktop.json`);
await keymapService.loadCustomKeymap(`${dir}/keymap-desktop.json`);
} catch (err) {
bridge().showErrorMessageBox(err.message);
}
@@ -1210,7 +1214,7 @@ class Application extends BaseApplication {
if (Setting.value('env') === 'dev') {
AlarmService.updateAllNotifications();
} else {
reg.scheduleSync().then(() => {
reg.scheduleSync(1000).then(() => {
// Wait for the first sync before updating the notifications, since synchronisation
// might change the notifications.
AlarmService.updateAllNotifications();

View File

@@ -11,7 +11,7 @@ interface Props {
export const declaration:CommandDeclaration = {
name: 'startExternalEditing',
label: () => _('Edit in external editor'),
iconName: 'fa-share-square',
iconName: 'icon-share',
};
export const runtime = ():CommandRuntime => {

View File

@@ -0,0 +1,195 @@
import * as React from 'react';
const styled = require('styled-components').default;
const { space } = require('styled-system');
export enum ButtonLevel {
Primary = 'primary',
Secondary = 'secondary',
Tertiary = 'tertiary',
SideBarSecondary = 'sideBarSecondary',
}
interface Props {
title?: string,
iconName?: string,
level?: ButtonLevel,
className?:string,
onClick:Function,
color?: string,
iconAnimation?: string,
tooltip?: string,
disabled?: boolean,
style?:any,
}
const StyledTitle = styled.span`
`;
const StyledButtonBase = styled.button`
display: flex;
align-items: center;
flex-direction: row;
height: ${(props:any) => `${props.theme.toolbarHeight}px`};
min-height: ${(props:any) => `${props.theme.toolbarHeight}px`};
max-height: ${(props:any) => `${props.theme.toolbarHeight}px`};
width: ${(props:any) => props.iconOnly ? `${props.theme.toolbarHeight}px` : 'auto'};
${(props:any) => props.iconOnly ? `min-width: ${props.theme.toolbarHeight}px;` : ''}
${(props:any) => !props.iconOnly ? 'min-width: 100px;' : ''}
${(props:any) => props.iconOnly ? `max-width: ${props.theme.toolbarHeight}px;` : ''}
box-sizing: border-box;
border-radius: 3px;
border-style: solid;
border-width: 1px;
font-size: ${(props:any) => props.theme.fontSize}px;
padding: 0 ${(props:any) => props.iconOnly ? 4 : 8}px;
justify-content: center;
opacity: ${(props:any) => props.disabled ? 0.5 : 1};
user-select: none;
`;
const StyledIcon = styled(styled.span(space))`
font-size: ${(props:any) => props.theme.toolbarIconSize}px;
${(props:any) => props.animation ? `animation: ${props.animation}` : ''};
`;
const StyledButtonPrimary = styled(StyledButtonBase)`
border: none;
background-color: ${(props:any) => props.theme.backgroundColor5};
&:hover {
background-color: ${(props:any) => props.theme.backgroundColorHover5};
}
&:active {
background-color: ${(props:any) => props.theme.backgroundColorActive5};
}
${StyledIcon} {
color: ${(props:any) => props.theme.color5};
}
${StyledTitle} {
color: ${(props:any) => props.theme.color5};
}
`;
const StyledButtonSecondary = styled(StyledButtonBase)`
border: 1px solid ${(props:any) => props.theme.borderColor4};
background-color: ${(props:any) => props.theme.backgroundColor4};
&:hover {
background-color: ${(props:any) => props.theme.backgroundColorHover4};
}
&:active {
background-color: ${(props:any) => props.theme.backgroundColorActive4};
}
${StyledIcon} {
color: ${(props:any) => props.theme.color4};
}
${StyledTitle} {
color: ${(props:any) => props.theme.color4};
}
`;
const StyledButtonTertiary = styled(StyledButtonBase)`
border: 1px solid ${(props:any) => props.theme.color3};
background-color: ${(props:any) => props.theme.backgroundColor3};
&:hover {
background-color: ${(props:any) => props.theme.backgroundColorHoverDim3};
}
&:active {
background-color: ${(props:any) => props.theme.backgroundColorActive3};
}
${StyledIcon} {
color: ${(props:any) => props.theme.color};
}
${StyledTitle} {
color: ${(props:any) => props.theme.color};
opacity: 0.9;
}
`;
const StyledButtonSideBarSecondary = styled(StyledButtonBase)`
background: none;
border-color: ${(props:any) => props.theme.color2};
color: ${(props:any) => props.theme.color2};
&:hover {
color: ${(props:any) => props.theme.colorHover2};
border-color: ${(props:any) => props.theme.colorHover2};
background: none;
${StyledTitle} {
color: ${(props:any) => props.theme.colorHover2};
}
${StyledIcon} {
color: ${(props:any) => props.theme.colorHover2};
}
}
&:active {
color: ${(props:any) => props.theme.colorActive2};
border-color: ${(props:any) => props.theme.colorActive2};
background: none;
${StyledTitle} {
color: ${(props:any) => props.theme.colorActive2};
}
${StyledIcon} {
color: ${(props:any) => props.theme.colorActive2};
}
}
${StyledTitle} {
color: ${(props:any) => props.theme.color2};
}
${StyledIcon} {
color: ${(props:any) => props.theme.color2};
}
`;
function buttonClass(level:ButtonLevel) {
if (level === ButtonLevel.Primary) return StyledButtonPrimary;
if (level === ButtonLevel.Tertiary) return StyledButtonTertiary;
if (level === ButtonLevel.SideBarSecondary) return StyledButtonSideBarSecondary;
return StyledButtonSecondary;
}
export default function Button(props:Props) {
const iconOnly = props.iconName && !props.title;
const StyledButton = buttonClass(props.level);
function renderIcon() {
if (!props.iconName) return null;
return <StyledIcon animation={props.iconAnimation} mr={iconOnly ? '0' : '6px'} color={props.color} className={props.iconName}/>;
}
function renderTitle() {
if (!props.title) return null;
return <StyledTitle color={props.color}>{props.title}</StyledTitle>;
}
function onClick() {
if (props.disabled) return;
props.onClick();
}
return (
<StyledButton style={props.style} disabled={props.disabled} title={props.tooltip} className={props.className} iconOnly={iconOnly} onClick={onClick}>
{renderIcon()}
{renderTitle()}
</StyledButton>
);
}

View File

@@ -40,10 +40,12 @@ class ClipperConfigScreenComponent extends React.Component {
}
render() {
const theme = themeStyle(this.props.theme);
const theme = themeStyle(this.props.themeId);
const containerStyle = Object.assign({}, theme.containerStyle, {
overflowY: 'scroll',
padding: theme.configScreenPadding,
backgroundColor: theme.backgroundColor3,
});
const buttonStyle = Object.assign({}, theme.buttonStyle, { marginRight: 10 });
@@ -106,8 +108,8 @@ class ClipperConfigScreenComponent extends React.Component {
return (
<div>
<div style={containerStyle}>
<div style={{ padding: theme.margin }}>
<p style={theme.textStyle}>{_('Joplin Web Clipper allows saving web pages and screenshots from your browser to Joplin.')}</p>
<div>
<p style={Object.assign({}, theme.textStyle, { marginTop: 0 })}>{_('Joplin Web Clipper allows saving web pages and screenshots from your browser to Joplin.')}</p>
<p style={theme.textStyle}>{_('In order to use the web clipper, you need to do the following:')}</p>
<div style={stepBoxStyle}>
@@ -120,8 +122,8 @@ class ClipperConfigScreenComponent extends React.Component {
<p style={theme.h1Style}>{_('Step 2: Install the extension')}</p>
<p style={theme.textStyle}>{_('Download and install the relevant extension for your browser:')}</p>
<div style={{ display: 'flex', flexDirection: 'row' }}>
<ExtensionBadge theme={this.props.theme} type="firefox" url="https://addons.mozilla.org/en-US/firefox/addon/joplin-web-clipper/"/>
<ExtensionBadge style={{ marginLeft: 10 }} theme={this.props.theme} type="chrome" url="https://chrome.google.com/webstore/detail/joplin-web-clipper/alofnhikmmkdbbbgpnglcpdollgjjfek"/>
<ExtensionBadge themeId={this.props.themeId} type="firefox" url="https://addons.mozilla.org/en-US/firefox/addon/joplin-web-clipper/"/>
<ExtensionBadge style={{ marginLeft: 10 }} themeId={this.props.themeId} type="chrome" url="https://chrome.google.com/webstore/detail/joplin-web-clipper/alofnhikmmkdbbbgpnglcpdollgjjfek"/>
</div>
</div>
@@ -145,7 +147,7 @@ class ClipperConfigScreenComponent extends React.Component {
const mapStateToProps = state => {
return {
theme: state.settings.theme,
themeId: state.settings.theme,
clipperServer: state.clipperServer,
clipperServerAutoStart: state.settings['clipperServer.autoStart'],
apiToken: state.settings['api.token'],

View File

@@ -1,44 +0,0 @@
const React = require('react');
const styleSelector = require('./style/ConfigMenuBar');
const Setting = require('lib/models/Setting');
function ConfigMenuBarButton(props) {
const style = styleSelector(null, props);
const iconStyle = props.selected ? style.buttonIconSelected : style.buttonIcon;
const labelStyle = props.selected ? style.buttonLabelSelected : style.buttonLabel;
return (
<button style={style.button} onClick={props.onClick}>
<i style={iconStyle} className={props.iconName}></i>
<span style={labelStyle}>{props.label}</span>
</button>
);
}
function ConfigMenuBar(props) {
const buttons = [];
const style = styleSelector(null, props);
for (const section of props.sections) {
buttons.push(<ConfigMenuBarButton
selected={props.selection === section.name}
theme={props.theme}
key={section.name}
iconName={Setting.sectionNameToIcon(section.name)}
label={Setting.sectionNameToLabel(section.name)}
onClick={() => { props.onSelectionChange({ section: section }); }}
/>);
}
return (
<div style={style.root} className="config-menu-bar">
<div style={style.barButtons}>
{buttons}
</div>
</div>
);
}
module.exports = ConfigMenuBar;

View File

@@ -0,0 +1,52 @@
import * as React from 'react';
import Button, { ButtonLevel } from '../Button/Button';
const styled = require('styled-components').default;
const { _ } = require('lib/locale.js');
interface Props {
backButtonTitle?: string,
hasChanges?: boolean,
onCancelClick: Function,
onSaveClick?: Function,
onApplyClick?: Function,
}
export const StyledRoot = styled.div`
display: flex;
align-items: center;
padding: 10px;
background-color: ${(props:any) => props.theme.backgroundColor3};
padding-left: ${(props:any) => props.theme.configScreenPadding}px;
border-top-width: 1px;
border-top-style: solid;
border-top-color: ${(props:any) => props.theme.dividerColor};
`;
export default function ButtonBar(props:Props) {
function renderOkButton() {
if (!props.onSaveClick) return null;
return <Button style={{ marginRight: 10 }} level={ButtonLevel.Primary} disabled={!props.hasChanges} onClick={props.onSaveClick} title={_('OK')}/>;
}
function renderApplyButton() {
if (!props.onApplyClick) return null;
return <Button level={ButtonLevel.Primary} disabled={!props.hasChanges} onClick={props.onApplyClick} title={_('Apply')}/>;
}
return (
<StyledRoot>
<Button
onClick={props.onCancelClick}
level={ButtonLevel.Secondary}
iconName="fa fa-chevron-left"
title={props.backButtonTitle ? props.backButtonTitle : _('Back')}
/>
{ (props.onApplyClick || props.onSaveClick) && (
<div style={{ display: 'flex', flexDirection: 'row', marginLeft: 30 }}>
{renderOkButton()}
{renderApplyButton()}
</div>
)}
</StyledRoot>
);
}

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