Compare commits

...

227 Commits

Author SHA1 Message Date
alihamuh
7ee4d3f20d web: refactored code 2025-06-27 12:21:17 +05:00
alihamuh
abd254d952 web: added core functions for search 2025-06-27 12:21:04 +05:00
alihamuh
797d8b86ab web: filter search completed 2025-06-27 12:20:35 +05:00
alihamuh
3b7cb039bf web: started buidling search engine 2025-06-27 12:20:14 +05:00
alihamuh
81f252a6de web: some minor bug-fixes 2025-06-27 12:20:08 +05:00
alihamuh
9beb506bbf web: ui and some functuanality is added. 2025-06-27 12:20:00 +05:00
01zulfi
0c6180e78c web: fix note create option in quick open dialog (#8263)
* open new tab when query empty
* use editor-store methods for note creation

Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-27 11:51:00 +05:00
01zulfi
21afb28006 core: don't generate headline title if title was set during note creation (#8266)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-27 11:50:43 +05:00
01zulfi
510f4cfb35 web: fix update status height (#8267)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-27 11:40:07 +05:00
Ammar Ahmed
7ed4eee94e mobile: fix android toolbar 2025-06-27 09:42:28 +05:00
Ammar Ahmed
1ff4b9f946 mobile: convert sheets with input to screens or simple modals 2025-06-27 09:42:28 +05:00
Ammar Ahmed
78f430a9ad mobile: fix sqlite fts5 2025-06-27 09:42:16 +05:00
01zulfi
63a0965cdd web: fix scrolling toolbar also scrolling editor (#8256)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-27 09:30:53 +05:00
Abdullah Atta
ed60fe469c web: update sqlite3-fts5-html to 0.0.4 2025-06-27 09:30:14 +05:00
Abdullah Atta
681fe20604 desktop: update sqlite3-fts5-html to 0.0.4 2025-06-27 09:30:14 +05:00
Abdullah Atta
2e0cc81737 core: update sqlite3-fts5-html to 0.0.4 2025-06-27 09:30:14 +05:00
01zulfi
adf4e0e7a4 editor: don't clear nodes in clear formatting option (#8260)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-27 09:29:39 +05:00
Abdullah Atta
2f13ec51f3 web: only subscribe to note title if its generated 2025-06-26 10:50:41 +05:00
01zulfi
c7ef56a6eb web: hide monograph list for not logged in users (#8258)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-26 10:42:15 +05:00
Ammar Ahmed
c3d07d5c14 mobile: release v3.2.2 2025-06-21 13:44:20 +05:00
Abdullah Atta
befca4803e web: bump version to v3.2.2 2025-06-21 13:44:20 +05:00
Abdullah Atta
2f9e8802ab web: bump version to v3.2.1 2025-06-21 13:01:45 +05:00
Abdullah Atta
38d281fabb ci: release snap to stable track (instead of release track) 2025-06-21 13:01:45 +05:00
Ammar Ahmed
70738ab548 mobile: fix app crash on android 15 & 16 2025-06-21 13:01:45 +05:00
Ammar Ahmed
cb8dca7a52 mobile: release v3.2.1 2025-06-21 13:01:45 +05:00
Ammar Ahmed
e89e96b29a mobile: fix android toolbar hidden behind keyboard on android 15 2025-06-21 13:01:45 +05:00
Abdullah Atta
aa3ff204a7 web: make trash actions multi selectable 2025-06-21 12:27:28 +05:00
Abdullah Atta
6ae0cc37c9 common: bulk resolve notebooks & tags 2025-06-21 12:27:28 +05:00
Abdullah Atta
ada5edd0c4 core: fix hang when resolving recursive nested notebooks 2025-06-21 12:27:28 +05:00
Abdullah Atta
ece6b44053 web: register fts5 extensions after db decryption 2025-06-21 12:24:17 +05:00
Abdullah Atta
6816c9c764 web: update sqlite to v3.49.2 2025-06-21 11:02:49 +05:00
Abdullah Atta
41e7042028 desktop: update better-sqlite3-multiple-ciphers to v11.10.0 2025-06-21 10:44:19 +05:00
Abdullah Atta
2eb555bcf3 web: bump version to v3.2.1-beta.0 2025-06-18 09:27:27 +05:00
Abdullah Atta
2646ada120 ci: publish snap beta 2025-06-18 08:55:12 +05:00
Abdullah Atta
41022a9be6 desktop: change snap base to core22 2025-06-18 08:54:54 +05:00
Abdullah Atta
0ed7c2400f ci: disable snap on arm64 2025-06-18 08:52:58 +05:00
Ammar Ahmed
e021a9e7f8 mobile: release v3.2.0 2025-06-18 08:52:58 +05:00
Abdullah Atta
cbc2c066d5 desktop: fix `'environment/DISABLE_WAYLAND' property does not match the
required schema`
2025-06-18 08:52:58 +05:00
Abdullah Atta
f1e4ea4be9 web: bump version to v3.2.0 2025-06-18 08:52:58 +05:00
Abdullah Atta
d8ef54ce22 global: regenerate package-lock files to fix CI (#8212) 2025-06-17 10:48:49 +05:00
Abdullah Atta
c40528578b core: fix small tokens ignored from query 2025-06-17 10:46:14 +05:00
01zulfi
83ce9f1c21 web: fix archived notes showing in search results (#8216)
* web: fix archived notes showing in search results
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>

* core: make notes param required in lookup.notesWithHighlighting
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-17 10:19:06 +05:00
Abdullah Atta
7e88c012be web: fix tag navigation from editor 2025-06-17 10:18:19 +05:00
Abdullah Atta
0a11929c4c web: fix ui glitch in note linking dialog 2025-06-17 10:02:32 +05:00
01zulfi
3b2d853702 editor: fix failing snapshot tests (#8215)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-17 09:59:41 +05:00
01zulfi
d4410ae553 web: fix navigating to notebooks & tags from note item (#8211)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-17 09:45:34 +05:00
01zulfi
ed8d576eea core: fix notebooks parentId() tests (#8213)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-17 09:45:23 +05:00
01zulfi
17dafa330c web: fix move notebook dialog (#8214)
* also use db.notebooks.parentId()

Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-17 09:45:01 +05:00
tarynlucia
7d91cd0029 ui: correct grammar in vault creation message (issue #7497) (#8188)
Signed-off-by: Taryn Eng <taryn.eng@gmail.com>
2025-06-16 14:39:54 +05:00
Abdullah Atta
beec70211e web: update lockfile 2025-06-16 14:39:54 +05:00
Abdullah Atta
9eda07d233 web: fix infinite rerenders on checkout screen 2025-06-16 14:39:43 +05:00
Abdullah Atta
5601ab0bc3 web: fix flicker when programatically updating title 2025-06-16 14:39:15 +05:00
Abdullah Atta
42e4238aa1 core: do not allow empty titles 2025-06-16 14:39:15 +05:00
SB
b5e589ab2e docs: add missing '-' in build-steps for MacOS and Linux (AppImage) 2025-06-16 14:39:15 +05:00
Ammar Ahmed
76be2b0a5a mobile: update deps 2025-06-16 14:31:10 +05:00
Ammar Ahmed
06b895f722 mobile: fix pin and unpin from notifications 2025-06-16 13:45:57 +05:00
Ammar Ahmed
261674ce80 mobile: support android 16 2025-06-16 13:33:55 +05:00
Abdullah Atta
0bd8779144 core: fix group header for search results hidden 2025-06-16 11:16:38 +05:00
01zulfi
1a89678560 docs: add monograph size limit (#8206)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-16 10:55:03 +05:00
Abdullah Atta
0280561459 web: bump version to v3.2.0-beta.9 2025-06-13 12:51:58 +05:00
Abdullah Atta
236b015c38 core: remove search results count
it was inaccurate and confused users
2025-06-12 11:25:57 +05:00
Abdullah Atta
a6a49d5f49 web: reduce trial2pro discount to 30% 2025-06-12 09:45:53 +05:00
Abdullah Atta
717bae6968 desktop: do not use native menu for tag suggestions on macos 2025-06-12 09:08:42 +05:00
Ammar Ahmed
1826166c92 mobile: release beta 4 2025-06-11 14:07:35 +05:00
Ammar Ahmed
bf440f32c9 mobile: make adding notebook a dialog
* make manage tags sheet a screen
2025-06-11 13:57:36 +05:00
Abdullah Atta
fecda3838f editor: fix search popup removed on link hover 2025-06-11 10:40:48 +05:00
Abdullah Atta
3b54e62495 core: fix search results sorting not working 2025-06-11 08:55:20 +05:00
Abdullah Atta
3fe6cd503c web: bump version to v3.2.0-beta.8 2025-06-10 11:34:36 +05:00
Abdullah Atta
7dd581d175 core: take into account boolean parameters in query 2025-06-05 15:19:55 +05:00
Ammar Ahmed
f7d1d92613 mobile: default tag 2025-06-05 12:08:44 +05:00
01zulfi
55e1f6922e web: fix navigation commands in command palette (#8070)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-05 11:51:32 +05:00
01zulfi
f408cdff02 web: add move notebook dialog (#8099)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
Co-authored-by: Abdullah Atta <abdullahatta@streetwriters.co>
2025-06-05 11:44:04 +05:00
Ammar Ahmed
be7a140877 mobile: fix ci build 2025-06-05 10:08:28 +05:00
Abdullah Atta
00691fa43b web: bump version to v3.2.0-beta.7 2025-06-05 10:05:17 +05:00
Ammar Ahmed
8e6db4d81c mobile: fix mmkv patch 2025-06-05 09:49:46 +05:00
Ammar Ahmed
489f0d376d mobile: beta release 2025-06-04 15:09:54 +05:00
Abdullah Atta
6e6be63e7b core: fix false positives appearing in search 2025-06-04 14:55:57 +05:00
Ammar Ahmed
228951da49 mobile: update deps 2025-06-04 12:59:32 +05:00
Abdullah Atta
e806812593 core: remove porter tokenizer for stemming
it didn't work very well. It was stemming things like "one" into "on"
2025-06-04 12:59:15 +05:00
Ammar Ahmed
3b92c401f3 mobile: fix key missing warning in search-result item 2025-06-04 12:38:19 +05:00
Abdullah Atta
c1a684f14a core: fix lookup tests 2025-06-04 12:23:40 +05:00
Abdullah Atta
21cbc75b93 core: update htmlparser2 2025-06-04 12:23:40 +05:00
Ammar Ahmed
6c2d95abe1 core: skip decodine entities when parsing html 2025-06-04 12:17:49 +05:00
Ammar Ahmed
00460f84ee mobile: update lockfiles 2025-06-03 09:44:49 +05:00
Ammar Ahmed
eedbded335 mobile: fix android build 2025-06-03 09:44:49 +05:00
Ammar Ahmed
843178b8cf mobile: fix ios build on rn 77 2025-06-03 09:44:49 +05:00
Ammar Ahmed
d5ca8d70b7 mobile: update fts5-html patch 2025-06-03 09:44:49 +05:00
Ammar Ahmed
7baaeda722 mobile: remove patch 2025-06-03 09:44:49 +05:00
Ammar Ahmed
1388e77828 mobile: update patches 2025-06-03 09:44:49 +05:00
Ammar Ahmed
caca30240d mobile: upgrade to RN 0.77.2 2025-06-03 09:44:49 +05:00
Abdullah Atta
fc476828e8 core: sort content matches 2025-06-02 15:32:47 +05:00
Abdullah Atta
a76c35356d core: only expand matching callout & outline list items 2025-06-02 15:32:15 +05:00
Abdullah Atta
d6584664f3 ci: fix prerelease not setting correctly on gh release 2025-06-02 12:51:18 +05:00
Abdullah Atta
25fec5afeb web: bump version to 3.2.0-beta.6 2025-06-02 12:04:41 +05:00
01zulfi
512e412b19 web: add support for setting a tag as default (#8060)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-02 11:17:46 +05:00
01zulfi
be615b9b75 editor: remove styling for sibling elements of double spaced paragraphs (#8144)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-02 11:04:01 +05:00
Ammar Ahmed
0d6c693dd1 mobile: release new beta 2025-06-02 10:11:48 +05:00
Ammar Ahmed
ea7473f757 mobile: skip rendering if query changed during search 2025-06-02 09:42:56 +05:00
Abdullah Atta
bebb70bf23 web: discard results if query changed during search 2025-06-02 09:42:37 +05:00
Abdullah Atta
f683f63abd core: auto expand outline & callout in search result 2025-06-02 09:35:12 +05:00
Abdullah Atta
6f9ff0e427 core: fix phrase queries not getting highlighted 2025-06-02 09:10:58 +05:00
Abdullah Atta
3dbb4cd1d5 web: fix click on match no opening note at desired location 2025-06-02 09:10:58 +05:00
Ammar Ahmed
b33046a2c7 mobile: enable regexp in sqlite 2025-06-02 08:47:46 +05:00
Ammar Ahmed
53ecdd0c0f mobile: fix tab gets focused in loop 2025-06-02 08:47:46 +05:00
Abdullah Atta
971a490292 desktop: add SQLITE_ENABLE_REGEXP define to better-sqlite3 2025-05-31 13:28:00 +05:00
Abdullah Atta
c9c6ee88d8 desktop: do not gitignore *.patch 2025-05-31 13:26:58 +05:00
Abdullah Atta
3d31c7d7bb web: bump version to 3.2.0-beta.5 2025-05-30 19:28:30 +05:00
Abdullah Atta
ed079d2efb core: use intl for showing search results count 2025-05-30 19:27:10 +05:00
Abdullah Atta
6de57c79f3 core: install @notesnook/intl 2025-05-30 19:27:10 +05:00
Abdullah Atta
fc1cb19014 web: use plain list instead of tree for showing search results 2025-05-30 19:27:10 +05:00
Abdullah Atta
097963dbba web: enable regexp in sqlite 2025-05-30 19:27:10 +05:00
Abdullah Atta
6e33932a2f desktop: enable regexp in sqlite 2025-05-30 19:27:10 +05:00
Abdullah Atta
bf0d43d3a2 core: speed up search 2025-05-30 19:27:05 +05:00
Ammar Ahmed
0effa01ef7 core: fix stop-words import 2025-05-29 11:09:47 +05:00
Abdullah Atta
edacdbcbae core: filter out stop words in search query 2025-05-28 14:57:09 +05:00
Abdullah Atta
0e9953ed87 web: bump version to v3.2.0-beta.4 2025-05-28 13:02:38 +05:00
Abdullah Atta
cba713990b ci: build desktop app on ubuntu-22-04
this fixes `Error: /lib/x86_64-linux-gnu/libm.so.6: version `GLIBC_2.38'
not found` error
2025-05-28 13:01:48 +05:00
Abdullah Atta
2bce6d3b01 web: fix editor not jumping to search result 2025-05-28 12:31:57 +05:00
Abdullah Atta
4ae4376897 web: fix various type errors causing crashes 2025-05-28 11:30:35 +05:00
Abdullah Atta
2b9bcb2fe2 core: bring back limit in lookup 2025-05-28 11:30:35 +05:00
Ammar Ahmed
590c6c28c2 mobile: release v3.2.0-beta.1 2025-05-27 14:04:09 +05:00
Ammar Ahmed
29229d1372 mobile: fix note search 2025-05-27 13:10:41 +05:00
Abdullah Atta
81be2fad9d web: use notesWithHighlighting for full notes search 2025-05-27 12:38:00 +05:00
Abdullah Atta
2c45cea746 core: bring back old notes search 2025-05-27 12:38:00 +05:00
Ammar Ahmed
4c9fe1e58a mobile: release v3.2.0-beta.0 2025-05-23 15:14:38 +05:00
Abdullah Atta
b21fb195d1 web: bump version to 3.2.0-beta.3 2025-05-23 15:07:11 +05:00
Ammar Ahmed
3850ad414b mobile: search and sorting 2025-05-23 14:59:01 +05:00
Abdullah Atta
22ae09f926 web: localize search results count 2025-05-23 14:59:01 +05:00
Abdullah Atta
7fe3feef22 web: hide search results on editor focus & search cancel 2025-05-23 14:59:01 +05:00
Abdullah Atta
9b70853c57 editor: make search results style toggleable 2025-05-23 14:59:01 +05:00
Abdullah Atta
175cf92e74 web: fix note not scrolling to selected match 2025-05-23 14:59:01 +05:00
Abdullah Atta
8c6476545b web: fix note not opening from search results if its already opened 2025-05-23 14:59:01 +05:00
Abdullah Atta
a0bf06db90 web: use same search ux for notes everywhere 2025-05-23 14:59:01 +05:00
Abdullah Atta
3889aa291b web: improve search results ui 2025-05-23 14:59:01 +05:00
Abdullah Atta
c1aa727a6d core: improve prefix/suffix generation for matches 2025-05-23 14:59:01 +05:00
Abdullah Atta
23de5d2229 web: add full support for highlighting results in notes search 2025-05-23 14:59:01 +05:00
Abdullah Atta
4aab23b117 editor: add support for nn-search-result node 2025-05-23 14:59:01 +05:00
Abdullah Atta
10f6501951 core: add raw html content with highlighting in results 2025-05-23 14:59:01 +05:00
Abdullah Atta
2e8173f6ca web: add support for highlighting in search results 2025-05-23 14:59:01 +05:00
Abdullah Atta
33b6e3a19d core: add console.time tracing for notes search 2025-05-23 14:59:01 +05:00
Abdullah Atta
0fb115df0b core: improve search results highlighting 2025-05-23 14:59:01 +05:00
Abdullah Atta
f1b875b1dd core: fix title matches not merged when query contains short tokens 2025-05-23 14:59:01 +05:00
Abdullah Atta
c3604da0c1 core: bring back search result sorting for notes 2025-05-23 14:59:01 +05:00
Abdullah Atta
c61706d4f1 core: add support for highlighting search results 2025-05-23 14:59:01 +05:00
Ammar Ahmed
fa39f2e75d mobile: fix archive count not shown 2025-05-23 14:59:01 +05:00
Ammar Ahmed
8a283baeaf mobile: update fts5-html lib 2025-05-23 14:59:01 +05:00
Ammar Ahmed
4ddc21d783 mobile: support sorting search results 2025-05-23 14:59:01 +05:00
Abdullah Atta
5b828a71a9 core: add a new migration to reindex fts5 2025-05-23 14:59:01 +05:00
Abdullah Atta
c3b0d0feb9 web: update sqlite3-fts5-html to v0.0.3 2025-05-23 14:59:01 +05:00
Abdullah Atta
a4468271f4 web: show date created on search results if sort by is set to date created 2025-05-23 14:59:01 +05:00
Abdullah Atta
0127de1290 web: add support for sorting in search 2025-05-23 14:59:01 +05:00
Abdullah Atta
3e270a3906 core: add support for sortable search 2025-05-23 14:59:01 +05:00
01zulfi
76a7e9318e editor: support ctrl/cmd+click to open internal links in new tab (#8131)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-05-23 10:36:10 +05:00
01zulfi
527b6ca1a3 web: add 'move to top' for sub-notebooks (#8066)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-05-21 11:31:12 +05:00
Ammar Ahmed
d3f8b06fcb mobile: handle crash in background on device boot 2025-05-20 11:32:20 +05:00
Ammar Ahmed
7d34993d84 mobile: fix new reminder title/headline is not autofill 2025-05-17 12:42:38 +05:00
Ammar Ahmed
be5a1605b7 mobile: add line break when appending to note 2025-05-17 12:14:57 +05:00
Ammar Ahmed
3e86167842 mobile: fix crash in settings -> user subscription 2025-05-17 10:05:35 +05:00
01zulfi
93713d58d4 web: persist double spaced lines config on logout (#8097)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-05-16 15:21:26 +05:00
01zulfi
7da18de68c web: fix readonly note not locking when vault is locked (#8092)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-05-16 15:21:10 +05:00
01zulfi
fccf2a7b3e web: add support for drag/dropping notes on tab strip (#8090)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-05-16 15:20:28 +05:00
Abdullah Atta
b200180684 web: bump version to 3.2.0-beta.2 2025-05-16 15:05:40 +05:00
Abdullah Atta
0a5ea5d448 core: fix `expected previously executed migration 2 to be at index 1 but
10 was found in its place.`
2025-05-16 15:04:27 +05:00
01zulfi
739906dbe4 core: fix db.settings.getTrashCleanupInterval return type (#8076)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-05-16 14:48:28 +05:00
01zulfi
4326552ccc web: add support for removing recents in command palette using delete key (#8069)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-05-16 14:44:11 +05:00
01zulfi
1ee1ceef73 web: press shift+enter to create note in quick open (#8068)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-05-16 14:43:24 +05:00
Ammar Ahmed
4d83666fed editor: fix alignment items in callout heading (#8101)
* editor: fix alignment items in callout heading

* Update packages/editor/styles/styles.css

Signed-off-by: Abdullah Atta <thecodrr@protonmail.com>

---------

Signed-off-by: Abdullah Atta <thecodrr@protonmail.com>
Co-authored-by: Abdullah Atta <abdullahatta@streetwriters.co>
2025-05-16 14:36:29 +05:00
Abdullah Atta
86b8a2ae8c desktop: update patched better-sqlite3-multiple-ciphers to 11.6.1 2025-05-16 12:52:11 +05:00
Abdullah Atta
c8c21d210b global: regenerate package-lock.json for theme & ui packages 2025-05-16 11:22:21 +05:00
Ammar Ahmed
96343a3b1f mobile: fix error in build 2025-05-16 11:03:16 +05:00
Ammar Ahmed
74ebc4c82e mobile: add option to disable auto update check 2025-05-16 10:58:15 +05:00
Abdullah Atta
3acd3a87a9 misc: include @notesnook/theme package when generating flatpak sources 2025-05-16 10:24:54 +05:00
Abdullah Atta
94888ad94d desktop: downgrade playwright 2025-05-16 10:15:21 +05:00
Abdullah Atta
030daf12f2 desktop: fix flatpak sources generation 2025-05-15 12:17:28 +05:00
Abdullah Atta
d599a0836f desktop: regenerate package-lock.json 2025-05-15 10:36:42 +05:00
Abdullah Atta
7f901e7e75 web: update package-lock.json 2025-05-15 10:28:54 +05:00
Abdullah Atta
0a5e235e50 global: fix dependencies version differences 2025-05-15 09:59:39 +05:00
Abdullah Atta
aec3530d8a global: update package-lock.json 2025-05-15 09:47:41 +05:00
01zulfi
732e79dd60 web: fix list pane not expanding (#7963)
* web: fix list pane not expanding
* fix list pane not expanding to saved width on reload
* fix list pane not expanding to saved width on collapse

Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>

* web: collapse pane and set size to 0 when applicable
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>

---------

Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-05-15 09:25:29 +05:00
01zulfi
ca5c596158 core: segregate logic for note headline and note headline title generation (#7968)
* core: segregate logic for note headline and note headline title generation
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>

* core: minor refactor note headline title
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-05-15 09:25:29 +05:00
Ammar Ahmed
9e8e9c54d4 ci: fix build ios
Signed-off-by: Ammar Ahmed <40239442+ammarahm-ed@users.noreply.github.com>
2025-05-15 09:25:29 +05:00
Ammar Ahmed
2c2a79104b ci: fix build ios
Signed-off-by: Ammar Ahmed <40239442+ammarahm-ed@users.noreply.github.com>
2025-05-15 09:25:29 +05:00
Ammar Ahmed
27769f8682 ci: fix build ios
Signed-off-by: Ammar Ahmed <40239442+ammarahm-ed@users.noreply.github.com>
2025-05-15 09:25:29 +05:00
Ammar Ahmed
f150637e3a mobile: fix crash when going from trash -> search 2025-05-15 09:25:29 +05:00
Ammar Ahmed
f04661e32a mobile: release v3.1.1 2025-05-15 09:25:29 +05:00
Ammar Ahmed
db65e80dbc mobile: fix crash on delete item 2025-05-15 09:25:29 +05:00
Ammar Ahmed
4e65bbb7bf mobile: fix crash in list 2025-05-15 09:25:29 +05:00
Ammar Ahmed
d5ec302bf6 mobile: fix cursor bug on ios 2025-05-15 09:25:29 +05:00
Ammar Ahmed
51692a67e7 mobile: fix typing in editor title input 2025-05-15 09:25:29 +05:00
Ammar Ahmed
ee97d71f09 mobile: archive notes 2025-05-12 12:17:29 +05:00
Abdullah Atta
6d089c7332 web: bump version to 3.2.0-beta.1 2025-05-06 13:34:16 +05:00
Abdullah Atta
ab1b45bd50 core: fix query-transformer tests 2025-05-06 13:28:24 +05:00
Ammar Ahmed
fff8b61f71 mobile: add sqlite3-fts5-html module 2025-05-06 13:28:24 +05:00
Abdullah Atta
2c4f262fbc desktop: install sqlite3-fts5-html 2025-05-06 13:28:24 +05:00
Abdullah Atta
e5a7e08efb web: update wa-sqlite to use sqlite3-fts5-html for stripping html 2025-05-06 13:28:24 +05:00
Abdullah Atta
b4ef01c688 core: fix short queries search 2025-05-06 13:28:24 +05:00
Abdullah Atta
e6d6194b66 core: remove @orama/stopwords 2025-05-06 13:28:24 +05:00
Abdullah Atta
b6ee0989e5 core: strip html when searching notes
this commit also properly fixes search queries containing
words less than 3 characters in length
2025-05-06 13:28:24 +05:00
Abdullah Atta
e4230a0709 core: fix warnings in tests 2025-05-06 13:28:24 +05:00
Ammar Ahmed
0b17588e5d mobile: update better trigram 2025-05-06 13:28:24 +05:00
Abdullah Atta
8498f35b95 core: fix db migration 2025-05-06 13:28:24 +05:00
Abdullah Atta
8eecc995fc core: wrap query with invalid symbols in quotes 2025-05-06 13:28:24 +05:00
Abdullah Atta
1bbc01346b core: update sqlite-better-trigram to v0.0.3 2025-05-06 13:28:24 +05:00
01zulfi
2f3a895ddc core: fix trash cleanup interval setting retrieval (#8045)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-05-02 12:15:00 +05:00
01zulfi
5caa18543a web: add more archive test cases (#8040)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-05-02 10:11:53 +05:00
Abdullah Atta
33c493b317 desktop: no need to externalize @resvg/resvg-js 2025-05-02 10:11:08 +05:00
Abdullah Atta
ca497f3815 desktop: remove icon from native menu 2025-05-02 10:11:08 +05:00
Abdullah Atta
d796795c40 desktop: only show native menus on macos 2025-05-02 10:11:08 +05:00
Abdullah Atta
5c9d98d5d6 desktop: show native menus where possible 2025-05-02 10:11:08 +05:00
01zulfi
3b47d97314 web: assign accent color to links (#8041)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-05-01 13:14:40 +05:00
Abdullah Atta
4360d4b155 desktop: update packages 2025-05-01 13:13:38 +05:00
01zulfi
24d8bfe9bd desktop: upgrade electron to v34.0.0 (#8038)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-05-01 10:23:54 +05:00
01zulfi
832506b836 web: fix automatic backup reminder setting reverting to never (#8037)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-05-01 09:07:30 +05:00
01zulfi
795f38b4b8 web: fix focus last active tab method (#8034)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-04-30 11:30:24 +05:00
01zulfi
d42813b262 editor: improve hover link popup position (#8011)
* move it down so it doesn't block the link

Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-04-29 09:32:38 +05:00
Abdullah Atta
d522c65d49 web: bump version to 3.2.0-beta.0 2025-04-28 11:18:25 +05:00
Abdullah Atta
4b7cecccbe web: update @notesnook-imoporter/core to 2.2.2 2025-04-28 11:09:51 +05:00
01zulfi
151abb94e1 web: fix notestore is not defined error (#8012)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-04-28 11:09:05 +05:00
Abdullah Atta
b67a307453 web: update @notesnook-importer/core to 2.2.1 2025-04-28 10:31:54 +05:00
Abdullah Atta
bf83c87911 web: update @notesnook-importer/core to 2.2.0 2025-04-28 09:59:57 +05:00
Abdullah Atta
8e67d3dc23 web: open settings with importer page instead of importer.notesnook.com 2025-04-28 09:59:57 +05:00
Ammar Ahmed
4b24f2c4b6 mobile: fix default font setting not followed 2025-04-28 09:59:57 +05:00
01zulfi
6cd14a5a78 web: make nav menu header draggable (#7985)
* web: make part of nav menu header draggable
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>

* Update apps/web/src/app.css

Signed-off-by: Abdullah Atta <thecodrr@protonmail.com>

* Update apps/web/src/components/navigation-menu/index.tsx

Signed-off-by: Abdullah Atta <thecodrr@protonmail.com>

---------

Signed-off-by: Abdullah Atta <thecodrr@protonmail.com>
Co-authored-by: Abdullah Atta <thecodrr@protonmail.com>
2025-04-28 09:59:57 +05:00
Ammar Ahmed
6edae50960 mobile: remove READ_MEDIA_IMAGES permission 2025-04-28 09:59:57 +05:00
Abdullah Atta
2a6a377d06 web: refresh app after import 2025-04-28 09:59:57 +05:00
Abdullah Atta
c569dbd778 web: move importer into web/desktop app (#7472)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-04-28 09:59:57 +05:00
01zulfi
36022df189 web: add support for archiving notes (#7810)
* web: archive notes
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>

* global: arhives -> archived
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-04-28 09:45:59 +05:00
246 changed files with 28317 additions and 15870 deletions

View File

@@ -69,8 +69,6 @@ jobs:
run: |
sed -i -e 's/arguments/arguments "-DCMAKE_CXX_COMPILER_LAUNCHER=ccache",/g' apps/mobile/node_modules/react-native-mmkv-storage/android/build.gradle
sed -i -e 's/arguments/arguments "-DCMAKE_CXX_COMPILER_LAUNCHER=ccache",/g' apps/mobile/node_modules/react-native-reanimated/android/build.gradle
sed -i -e 's/defaultConfig {/ndkVersion safeExtGet('ndkVersion', "25.2.9519653")\n defaultConfig {/g' apps/mobile/node_modules/react-native-reanimated//android/build.gradle
sed -i -e 's/defaultConfig {/ndkVersion safeExtGet('ndkVersion', "25.2.9519653")\n defaultConfig {/g' apps/mobile/node_modules/react-native-mmkv-storage/android/build.gradle
- name: CCache Stats Before Build
run: ccache -sv

View File

@@ -69,8 +69,6 @@ jobs:
run: |
sed -i -e 's/arguments/arguments "-DCMAKE_CXX_COMPILER_LAUNCHER=ccache",/g' apps/mobile/node_modules/react-native-mmkv-storage/android/build.gradle
sed -i -e 's/arguments/arguments "-DCMAKE_CXX_COMPILER_LAUNCHER=ccache",/g' apps/mobile/node_modules/react-native-reanimated/android/build.gradle
sed -i -e 's/defaultConfig {/ndkVersion safeExtGet('ndkVersion', "25.2.9519653")\n defaultConfig {/g' apps/mobile/node_modules/react-native-reanimated//android/build.gradle
sed -i -e 's/defaultConfig {/ndkVersion safeExtGet('ndkVersion', "25.2.9519653")\n defaultConfig {/g' apps/mobile/node_modules/react-native-mmkv-storage/android/build.gradle
- name: CCache Stats Before Build
run: ccache -sv

View File

@@ -45,7 +45,7 @@ on:
jobs:
build:
name: Build
runs-on: ubuntu-24.04
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -107,7 +107,8 @@ jobs:
name: Notesnook Desktop v${{ steps.app_metadata.outputs.app_version }}
tag_name: v${{ steps.app_metadata.outputs.app_version }}
files: ./notesnook_build_v${{ steps.app_metadata.outputs.app_version }}.zip
prerelease: ${{ endsWith(steps.app_metadata.outputs.app_version, '-beta') }}
prerelease: ${{ inputs.release-track == 'beta' }}
target_commitish: ${{ github.ref }}
- name: Generate flatpak sources
if: inputs.publish-github && inputs.build-linux
@@ -232,8 +233,8 @@ jobs:
xcrun altool --upload-package $package -t osx --apiKey $API_KEY_ID --apiIssuer $API_KEY_ISSUER_ID --apple-id ${{ steps.app_metadata.outputs.apple_app_id }} --bundle-id ${{ steps.app_metadata.outputs.app_bundle_id }} --bundle-short-version-string ${{ steps.app_metadata.outputs.app_version }} --bundle-version ${{ steps.app_metadata.outputs.bundle_version }}
working-directory: ./apps/desktop
build-linux:
name: Build for Linux
build-linux-x64:
name: Build for Linux x64
needs: build
if: inputs.build-linux
runs-on: ubuntu-22.04
@@ -250,7 +251,7 @@ jobs:
run: echo "SNAPCRAFT_STORE_CREDENTIALS=${{ secrets.snapcraft_token }}" >> $GITHUB_ENV
- name: Install Snapcraft
uses: samuelmeuli/action-snapcraft@v1
uses: samuelmeuli/action-snapcraft@v3
if: inputs.publish-snap
- name: Download build
@@ -266,7 +267,6 @@ jobs:
- name: Install sqlite-better-trigram for all arch
run: |
npm i --cpu arm64 sqlite-better-trigram
npm i --cpu x64 sqlite-better-trigram
working-directory: ./apps/desktop
@@ -285,18 +285,86 @@ jobs:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
if [ ${{ inputs.publish-github }} == true ]; then
yarn electron-builder --config=electron-builder.config.js --linux AppImage:x64 AppImage:arm64 -p always
yarn electron-builder --config=electron-builder.config.js --linux AppImage:x64 -p always
else
yarn electron-builder --config=electron-builder.config.js --linux AppImage:x64 AppImage:arm64 -p never
yarn electron-builder --config=electron-builder.config.js --linux AppImage:x64 -p never
fi
working-directory: ./apps/desktop
- name: Publish on Snapcraft
if: inputs.publish-snap
run: |
snapcraft upload --release=stable ./output/notesnook_linux_amd64.snap
if [ ${{ inputs.release-track }} == 'beta' ]; then
snapcraft upload --release=beta ./output/notesnook_linux_amd64.snap
else
snapcraft upload --release=stable ./output/notesnook_linux_amd64.snap
fi
working-directory: ./apps/desktop
build-linux-arm64:
name: Build for Linux arm64
needs: build
if: inputs.build-linux
runs-on: ubuntu-22.04-arm
steps:
- name: Check out Git repository
uses: actions/checkout@v4
- name: Setup Node
uses: ./.github/actions/setup-node-with-cache
# - name: Setup Snapcraft Auth
# if: inputs.publish-snap
# run: echo "SNAPCRAFT_STORE_CREDENTIALS=${{ secrets.snapcraft_token }}" >> $GITHUB_ENV
# - name: Install Snapcraft
# uses: samuelmeuli/action-snapcraft@v1
# if: inputs.publish-snap
- name: Download build
uses: actions/download-artifact@v4
with:
name: build
path: ./apps/web/build
- name: Install packages
run: |
npm ci --ignore-scripts --prefer-offline --no-audit
npm run bootstrap -- --scope=desktop
- name: Install sqlite-better-trigram for all arch
run: |
npm i --cpu arm64 sqlite-better-trigram
working-directory: ./apps/desktop
- name: Build Electron wrapper
run: npx nx run release --project @notesnook/desktop
working-directory: ./apps/desktop
# - name: Build snap
# if: inputs.publish-snap
# run: |
# yarn electron-builder --config=electron-builder.config.js --linux snap:arm64 -p never
# working-directory: ./apps/desktop
- name: Build AppImage
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
if [ ${{ inputs.publish-github }} == true ]; then
yarn electron-builder --config=electron-builder.config.js --linux AppImage:arm64 -p always
else
yarn electron-builder --config=electron-builder.config.js --linux AppImage:arm64 -p never
fi
working-directory: ./apps/desktop
# - name: Publish on Snapcraft
# if: inputs.publish-snap
# run: |
# snapcraft upload --release=stable ./output/notesnook_linux_arm64.snap
# working-directory: ./apps/desktop
build-windows:
name: Build for Windows
needs: build

View File

@@ -4,7 +4,7 @@ on: workflow_dispatch
jobs:
build:
runs-on: macos-latest
runs-on: macos-14
timeout-minutes: 60
steps:
@@ -14,6 +14,11 @@ jobs:
- name: Setup Node
uses: ./.github/actions/setup-node-with-cache
- name: Setup Xcode
uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: "16.1"
- name: Install node modules
run: |
npm ci --ignore-scripts --prefer-offline --no-audit

2
.gitignore vendored
View File

@@ -11,4 +11,4 @@ nx-cloud.env
site
node_modules.backup
.nx
*.patch
/*.patch

View File

@@ -58,10 +58,10 @@ This will compile and run the app in production mode but it won't generate any p
npm run release -- --rebuild
# For macOS
npx electron-builder --config=electron-builder.config.js --mac dmg --arm64 --x64 -publish never
npx electron-builder --config=electron-builder.config.js --mac dmg --arm64 --x64 --publish never
# For Linux (AppImage)
npx electron-builder --config=electron-builder.config.js --linux AppImage:x64 AppImage:arm64 -publish never
npx electron-builder --config=electron-builder.config.js --linux AppImage:x64 AppImage:arm64 --publish never
# For Windows
npx electron-builder --config=electron-builder.config.js --win --publish never

View File

@@ -38,6 +38,9 @@ const linuxExecutableName = process.env.NN_PRODUCT_NAME
const year = new Date().getFullYear();
const isBeta = pkg.version.includes("-beta");
/**
* @type {import("app-builder-lib").Configuration}
*/
module.exports = {
appId: appId,
productName: productName,
@@ -57,6 +60,7 @@ module.exports = {
"node_modules/bindings",
"node_modules/node-gyp-build",
"node_modules/sqlite-better-trigram",
"node_modules/sqlite3-fts5-html",
"node_modules/sodium-native/prebuilds/${platform}-${arch}",
{
from: "node_modules/sqlite-better-trigram-linux-${arch}",
@@ -70,6 +74,20 @@ module.exports = {
from: "node_modules/sqlite-better-trigram-windows-${arch}",
to: "node_modules/sqlite-better-trigram-windows-${arch}"
},
{
from: "node_modules/sqlite3-fts5-html-linux-${arch}",
to: "node_modules/sqlite3-fts5-html-linux-${arch}"
},
{
from: "node_modules/sqlite3-fts5-html-darwin-${arch}",
to: "node_modules/sqlite3-fts5-html-darwin-${arch}"
},
{
from: "node_modules/sqlite3-fts5-html-windows-${arch}",
to: "node_modules/sqlite3-fts5-html-windows-${arch}"
},
"node_modules/sodium-native/index.js",
"node_modules/sodium-native/package.json"
],
@@ -160,29 +178,27 @@ module.exports = {
description: "Your private note taking space",
executableName: linuxExecutableName,
desktop: {
actions: [
{
id: "new-note",
name: "New note",
args: "new note"
desktopActions: {
"new-note": {
Name: "New note",
Exec: `${linuxExecutableName} new note`
},
{
id: "new-notebook",
name: "New notebook",
args: "new notebook"
"new-notebook": {
Name: "New notebook",
Exec: `${linuxExecutableName} new notebook`
},
{
id: "new-reminder",
name: "New reminder",
args: "new reminder"
"new-reminder": {
Name: "New reminder",
Exec: `${linuxExecutableName} new reminder`
}
]
}
}
},
snap: {
autoStart: false,
confinement: "strict",
allowNativeWayland: true
allowNativeWayland: true,
base: "core22"
},
extraResources: ["app-update.yml", "./assets/**"],
extraMetadata: {

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,7 @@
"name": "@notesnook/desktop",
"productName": "Notesnook",
"description": "Your private note taking space",
"version": "3.1.0",
"version": "3.2.2",
"appAppleId": "1544027013",
"private": true,
"main": "./dist/cjs/index.js",
@@ -27,37 +27,42 @@
"dependencies": {
"@lingui/core": "5.1.2",
"@notesnook/intl": "file:../../packages/intl",
"@notesnook/ui": "file:../../packages/ui",
"@trpc/client": "10.45.2",
"@trpc/server": "10.45.2",
"better-sqlite3-multiple-ciphers": "11.5.0",
"better-sqlite3-multiple-ciphers": "^11.10.0",
"electron-trpc": "0.7.1",
"electron-updater": "^6.3.4",
"icojs": "^0.19.4",
"sqlite-better-trigram": "0.0.2",
"electron-updater": "^6.6.2",
"icojs": "^0.19.5",
"sqlite-better-trigram": "0.0.3",
"sqlite3-fts5-html": "^0.0.4",
"typed-emitter": "^2.1.0",
"yargs": "^17.7.2",
"zod": "3.23.8"
"zod": "3.24.3"
},
"devDependencies": {
"@streetwriters/kysely": "^0.27.4",
"@types/node": "22.7.0",
"@types/node": "22.15.3",
"@types/yargs": "^17.0.33",
"chokidar": "^4.0.1",
"electron": "^31.7.4",
"electron-builder": "^25.1.8",
"chokidar": "^4.0.3",
"electron": "^34.0.0",
"electron-builder": "^26.0.12",
"esbuild": "0.21.5",
"node-abi": "^3.68.0",
"node-gyp-build": "^4.8.2",
"playwright": "^1.48.2",
"node-abi": "^4.5.0",
"node-gyp-build": "^4.8.4",
"playwright": "1.48.2",
"prebuildify": "^6.0.1",
"slugify": "1.6.6",
"tree-kill": "^1.2.2",
"undici": "^6.19.8",
"vitest": "^2.1.8"
"undici": "^7.8.0",
"vitest": "2.1.8"
},
"optionalDependencies": {
"dmg-license": "^1.0.11"
},
"overrides": {
"@electron/node-gyp": "^10.2.0-electron.2"
},
"scripts": {
"start": "node scripts/dev.mjs",
"staging": "node scripts/build.mjs --run",

View File

@@ -1,36 +0,0 @@
diff --git a/node_modules/app-builder-lib/out/targets/LinuxTargetHelper.js b/node_modules/app-builder-lib/out/targets/LinuxTargetHelper.js
index 739a48c..7a7b4af 100644
--- a/node_modules/app-builder-lib/out/targets/LinuxTargetHelper.js
+++ b/node_modules/app-builder-lib/out/targets/LinuxTargetHelper.js
@@ -117,6 +117,7 @@ class LinuxTargetHelper {
StartupWMClass: appInfo.productName,
...extra,
...targetSpecificOptions.desktop,
+ actions: undefined
};
const description = this.getDescription(targetSpecificOptions);
if (!(0, builder_util_1.isEmptyOrSpaces)(description)) {
@@ -160,6 +161,23 @@ class LinuxTargetHelper {
data += `\n${name}=${desktopMeta[name]}`;
}
data += "\n";
+
+ if (targetSpecificOptions.desktop.actions) {
+ let actionsData = "";
+ const validActions = [];
+ for (const action of targetSpecificOptions.desktop.actions) {
+ if (!action.id || !action.name || !action.args) continue;
+ actionsData += "\n";
+ actionsData += `[Desktop Action ${action.id}]
+Name=${action.name}
+Exec=${desktopMeta.Exec} ${action.args}`;
+ actionsData += "\n";
+
+ validActions.push(action.id);
+ }
+
+ data += `Actions=${validActions.join(";")};\n${actionsData}`
+ }
return Promise.resolve(data);
}
}

View File

@@ -0,0 +1,13 @@
diff --git a/node_modules/app-builder-lib/out/targets/snap.js b/node_modules/app-builder-lib/out/targets/snap.js
index 0b5405e..753f6c6 100644
--- a/node_modules/app-builder-lib/out/targets/snap.js
+++ b/node_modules/app-builder-lib/out/targets/snap.js
@@ -115,7 +115,7 @@ class SnapTarget extends core_1.Target {
else {
const archTriplet = archNameToTriplet(arch);
appDescriptor.environment = {
- DISABLE_WAYLAND: options.allowNativeWayland ? "" : "1",
+ DISABLE_WAYLAND: options.allowNativeWayland ? "0" : "1",
PATH: "$SNAP/usr/sbin:$SNAP/usr/bin:$SNAP/sbin:$SNAP/bin:$PATH",
SNAP_DESKTOP_RUNTIME: "$SNAP/gnome-platform",
LD_LIBRARY_PATH: [

View File

@@ -0,0 +1,11 @@
diff --git a/node_modules/better-sqlite3-multiple-ciphers/deps/defines.gypi b/node_modules/better-sqlite3-multiple-ciphers/deps/defines.gypi
index 1a14ecd..ff938f1 100644
--- a/node_modules/better-sqlite3-multiple-ciphers/deps/defines.gypi
+++ b/node_modules/better-sqlite3-multiple-ciphers/deps/defines.gypi
@@ -38,5 +38,6 @@
'SQLITE_TRACE_SIZE_LIMIT=32',
'SQLITE_USER_AUTHENTICATION=0',
'SQLITE_USE_URI=0',
+ 'SQLITE_ENABLE_REGEXP',
],
}

View File

@@ -1,39 +0,0 @@
diff --git a/node_modules/electron-trpc/dist/main.mjs b/node_modules/electron-trpc/dist/main.mjs
index 07971db..b67a3cf 100644
--- a/node_modules/electron-trpc/dist/main.mjs
+++ b/node_modules/electron-trpc/dist/main.mjs
@@ -537,8 +537,15 @@ class be {
attachWindow(r) {
F(this, w).includes(r) || (y("Attaching window", r.id), F(this, w).push(r), v(this, N, Z).call(this, r));
}
- detachWindow(r) {
- y("Detaching window", r.id), L(this, w, F(this, w).filter((e) => e !== r)), v(this, R, M).call(this, { webContentsId: r.webContents.id });
+ detachWindow(r, webContentsId) {
+ y("Detaching window", r.id);
+
+ if (r.isDestroyed() && webContentsId === undefined) {
+ throw new Error('webContentsId is required when calling detachWindow on a destroyed window');
+ }
+
+ L(this, w, F(this, w).filter((e) => e !== r));
+ v(this, R, M).call(this, { webContentsId: webContentsId ?? r.webContents.id });
}
}
w = new WeakMap(), E = new WeakMap(), R = new WeakSet(), M = function({
@@ -548,6 +555,7 @@ w = new WeakMap(), E = new WeakMap(), R = new WeakSet(), M = function({
for (const [i, a] of F(this, E).entries())
i.startsWith(`${r}-${e ?? ""}`) && (y("Closing subscription", i), a.unsubscribe(), F(this, E).delete(i));
}, N = new WeakSet(), Z = function(r) {
+ const webContentsId = r.webContents.id;
r.webContents.on("did-start-navigation", ({ frame: e }) => {
y(
"Handling webContents `did-start-navigation` event",
@@ -558,7 +566,7 @@ w = new WeakMap(), E = new WeakMap(), R = new WeakSet(), M = function({
frameRoutingId: e.routingId
});
}), r.webContents.on("destroyed", () => {
- y("Handling webContents `destroyed` event"), this.detachWindow(r);
+ y("Handling webContents `destroyed` event"), this.detachWindow(r, webContentsId);
});
};
const me = ({

View File

@@ -43,8 +43,7 @@ if (args.rebuild || !existsSync(path.join(webAppPath, "build"))) {
);
}
// temporary until there's support for prebuilt binaries for linux ARM
if (os.platform() === "linux") await patchBetterSQLite3();
await patchBetterSQLite3();
await fs.cp(path.join(webAppPath, "build"), path.join(root, "build"), {
recursive: true,

View File

@@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { readFile, writeFile } from "fs/promises";
import { readFile, rm, writeFile } from "fs/promises";
import path from "path";
import { fileURLToPath } from "url";
@@ -25,6 +25,8 @@ const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
export async function patchBetterSQLite3() {
console.log("Patching better-sqlite3");
const jsonPath = path.join(
__dirname,
"..",
@@ -34,15 +36,23 @@ export async function patchBetterSQLite3() {
);
const json = JSON.parse(await readFile(jsonPath, "utf-8"));
json.version = "11.5.1";
json.homepage = "https://github.com/thecodrr/better-sqlite3-multiple-ciphers";
json.repository.url =
"git://github.com/thecodrr/better-sqlite3-multiple-ciphers.git";
delete json.homepage;
delete json.repository;
await writeFile(jsonPath, JSON.stringify(json));
await rm(
path.join(
__dirname,
"..",
"node_modules",
"better-sqlite3-multiple-ciphers",
"build"
),
{ force: true, recursive: true }
);
}
if (process.argv[1] === __filename) {
console.log("Patching better-sqlite3");
patchBetterSQLite3();
}

View File

@@ -19,7 +19,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import { initTRPC } from "@trpc/server";
import { z } from "zod";
import { app, dialog, nativeTheme, Notification, shell } from "electron";
import {
app,
dialog,
Menu,
MenuItem,
nativeImage,
nativeTheme,
Notification,
shell
} from "electron";
import { AutoLaunch } from "../utils/autolaunch";
import { config, DesktopIntegration } from "../utils/config";
import { bringToFront } from "../utils/bring-to-front";
@@ -33,6 +42,7 @@ import { isFlatpak, isSnap } from "../utils";
import { setupDesktopIntegration } from "../utils/desktop-integration";
import { rm } from "fs/promises";
import { disableCustomDns, enableCustomDns } from "../utils/custom-dns";
import type { MenuItem as NNMenuItem } from "@notesnook/ui";
const t = initTRPC.create();
@@ -225,5 +235,63 @@ export const osIntegrationRouter = t.router({
nativeTheme.off("updated", updated);
};
})
)
),
showMenu: t.procedure
.input(
z.object({
menuItems: z.array(z.any())
})
)
.subscription(({ input: { menuItems } }) =>
observable<string[]>((emit) => {
const items = menuItems as NNMenuItem[];
const menu = new Menu();
for (const item of items) {
const menuItem = toMenuItem(item, (id) => emit.next(id));
if (menuItem) menu.append(menuItem);
}
if (menu.items.length > 0) menu.popup();
return () => {
menu.removeAllListeners();
menu.closePopup();
};
})
)
});
function toMenuItem(
item: NNMenuItem,
onClick: (id: string[]) => void,
parentKey?: string
): MenuItem | undefined {
switch (item.type) {
case "lazy-loader":
return undefined;
case "separator":
return new MenuItem({ type: "separator" });
case "button": {
const submenu = item.menu ? new Menu() : undefined;
if (submenu && item.menu) {
for (const subitem of item.menu.items) {
const subMenuItem = toMenuItem(subitem, onClick, item.key);
if (subMenuItem) submenu.append(subMenuItem);
}
}
return new MenuItem({
label: item.title,
enabled: !item.isDisabled,
visible: !item.isHidden,
toolTip: item.tooltip,
sublabel: item.tooltip,
checked: item.isChecked,
type: submenu ? "submenu" : item.isChecked ? "checkbox" : "normal",
id: item.key,
submenu,
click: () => onClick(parentKey ? [parentKey, item.key] : [item.key]),
accelerator: item.modifier?.replace("Mod", "CommandOrControl")
});
}
}
}

View File

@@ -33,6 +33,8 @@ export class SQLite {
initialized = false;
preparedStatements: Map<string, Statement<unknown[]>> = new Map();
retryCounter: Record<string, number> = {};
extensionsLoaded = false;
constructor() {
console.log("new sqlite worker");
}
@@ -46,8 +48,6 @@ export class SQLite {
this.sqlite = require("better-sqlite3-multiple-ciphers")(
filePath
).unsafeMode(true);
const betterTrigram = require("sqlite-better-trigram");
betterTrigram.load(this.sqlite);
}
/**
@@ -115,6 +115,20 @@ export class SQLite {
} catch (e) {
if (e instanceof Error) e.message += ` (query: ${sql})`;
throw e;
} finally {
// Since SQLite 3.48.0 (SQLite3MC v2.0.2) it's not possible to load fts5
// extensions before database has been decrypting. This is because
// executing a `SELECT` now accesses the underlying databases resulting in
// an error. Since FTS5 extensions depend on `SELECT fts5` to load the
// fts5 API, we must wait decrypt the database before we can load
// the extensions.
if (!this.extensionsLoaded && (await this.isDatabaseReady())) {
const betterTrigram = require("sqlite-better-trigram");
const fts5Html = require("sqlite3-fts5-html");
betterTrigram.load(this.sqlite);
fts5Html.load(this.sqlite);
this.extensionsLoaded = true;
}
}
}
@@ -142,4 +156,22 @@ export class SQLite {
retryDelay: 500
});
}
/**
* This just executes `SELECT 1` on the database to make sure its ready.
* On an encrypted database, this will fail until `PRAGMA key` has been
* called.
*/
private async isDatabaseReady() {
// return this.exec(`SELECT 1;`)
// .then(() => true)
// .catch(() => false);
if (!this.sqlite) return false;
try {
this.sqlite.prepare(`SELECT 1;`).run();
return true;
} catch {
return false;
}
}
}

View File

@@ -143,16 +143,44 @@ function setupMenu() {
})
);
if (params.isEditable)
if (params.isEditable) {
menu.append(
new MenuItem({
label: strings.paste(),
role: "pasteAndMatchStyle",
role: "paste",
enabled: clipboard.readText("clipboard").length > 0,
accelerator: "CommandOrControl+V"
})
);
menu.append(
new MenuItem({
label:
process.platform === "darwin"
? strings.pasteAndMatchStyle()
: strings.pasteWithoutFormatting(),
role: "pasteAndMatchStyle",
enabled: clipboard.readText("clipboard").length > 0,
accelerator:
process.platform === "darwin"
? "Option+Shift+Command+V"
: "Shift+CommandOrControl+V"
})
);
menu.append(
new MenuItem({
type: "separator"
})
);
menu.append(
new MenuItem({
label: strings.spellCheck(),
role: "toggleSpellChecker"
})
);
}
if (menu.items.length > 0) menu.popup();
});
}

View File

@@ -69,6 +69,7 @@ buck-out/
*/fastlane/report.xml
*/fastlane/Preview.html
*/fastlane/screenshots
native/vendor
# Bundle artifact
*.jsbundle

View File

@@ -167,6 +167,7 @@ const Actions = ({
setAttachments();
eSendEvent(eDBItemUpdate, attachment.id);
}
return true;
},
positiveText: strings.rename()
});

View File

@@ -17,26 +17,20 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { strings } from "@notesnook/intl";
import React, { useRef, useState } from "react";
import { View } from "react-native";
import { db } from "../../common/database";
import {
eSendEvent,
presentSheet,
ToastManager
} from "../../services/event-manager";
import BackupService from "../../services/backup";
import { eSendEvent, ToastManager } from "../../services/event-manager";
import Navigation from "../../services/navigation";
import { useUserStore } from "../../stores/use-user-store";
import { eCloseSheet, eOpenRecoveryKeyDialog } from "../../utils/events";
import DialogHeader from "../dialog/dialog-header";
import { eOpenRecoveryKeyDialog } from "../../utils/events";
import { DefaultAppStyles } from "../../utils/styles";
import { Dialog } from "../dialog";
import { Button } from "../ui/button";
import Input from "../ui/input";
import { Notice } from "../ui/notice";
import Seperator from "../ui/seperator";
import { Dialog } from "../dialog";
import BackupService from "../../services/backup";
import { sleep } from "../../utils/time";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../utils/styles";
export const ChangePassword = () => {
const passwordInputRef = useRef();
@@ -85,8 +79,7 @@ export const ChangePassword = () => {
context: "global"
});
setLoading(false);
eSendEvent(eCloseSheet);
await sleep(300);
Navigation.goBack();
eSendEvent(eOpenRecoveryKeyDialog);
} catch (e) {
setLoading(false);
@@ -108,9 +101,6 @@ export const ChangePassword = () => {
}}
>
<Dialog context="change-password-dialog" />
<DialogHeader title={strings.changePassword()} />
<Seperator />
<Input
fwdRef={oldPasswordInputRef}
onChangeText={(value) => {
@@ -160,9 +150,3 @@ export const ChangePassword = () => {
</View>
);
};
ChangePassword.present = () => {
presentSheet({
component: <ChangePassword />
});
};

View File

@@ -39,6 +39,7 @@ import { hideAuth } from "./common";
import { ForgotPassword } from "./forgot-password";
import { useLogin } from "./use-login";
import { DefaultAppStyles } from "../../utils/styles";
import { Dialog } from "../dialog";
const LoginSteps = {
emailAuth: 1,
@@ -89,7 +90,7 @@ export const Login = ({ changeMode }) => {
return (
<>
<ForgotPassword />
<SheetProvider context="two_factor_verify" />
<Dialog context="two_factor_verify" />
<View
style={{
borderRadius: DDS.isTab ? 5 : 0,

View File

@@ -24,12 +24,8 @@ import { View } from "react-native";
import { ScrollView } from "react-native-actions-sheet";
import { db } from "../../common/database/index";
import useTimer from "../../hooks/use-timer";
import {
eSendEvent,
presentSheet,
ToastManager
} from "../../services/event-manager";
import { eCloseSheet } from "../../utils/events";
import { eSendEvent, ToastManager } from "../../services/event-manager";
import { eCloseSimpleDialog } from "../../utils/events";
import { AppFontSize } from "../../utils/size";
import { Button } from "../ui/button";
import { IconButton } from "../ui/icon-button";
@@ -38,6 +34,7 @@ import { Pressable } from "../ui/pressable";
import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import { DefaultAppStyles } from "../../utils/styles";
import { presentDialog } from "../dialog/functions";
const TwoFactorVerification = ({ onMfaLogin, mfaInfo, onCancel }) => {
const { colors } = useThemeColors();
@@ -46,7 +43,7 @@ const TwoFactorVerification = ({ onMfaLogin, mfaInfo, onCancel }) => {
method: mfaInfo?.primaryMethod,
isPrimary: true
});
const { seconds, start } = useTimer(currentMethod.method);
const { seconds, start, reset } = useTimer(currentMethod.method);
const [loading, setLoading] = useState(false);
const inputRef = useRef();
const [sending, setSending] = useState(false);
@@ -62,7 +59,7 @@ const TwoFactorVerification = ({ onMfaLogin, mfaInfo, onCancel }) => {
},
(result) => {
if (result) {
eSendEvent(eCloseSheet, "two_factor_verify");
eSendEvent(eCloseSimpleDialog, "two_factor_verify");
}
setLoading(false);
}
@@ -133,6 +130,12 @@ const TwoFactorVerification = ({ onMfaLogin, mfaInfo, onCancel }) => {
<ScrollView
keyboardShouldPersistTaps="handled"
keyboardDismissMode="interactive"
style={{
width: "100%",
height: "100%",
backgroundColor: colors.primary.background,
paddingTop: 60
}}
>
<View
style={{
@@ -236,7 +239,10 @@ const TwoFactorVerification = ({ onMfaLogin, mfaInfo, onCancel }) => {
<Button
title={strings.cancel()}
type="secondaryAccented"
onPress={onCancel}
onPress={() => {
reset();
onCancel();
}}
width={250}
/>
@@ -297,7 +303,7 @@ const TwoFactorVerification = ({ onMfaLogin, mfaInfo, onCancel }) => {
};
TwoFactorVerification.present = (onMfaLogin, data, onCancel, context) => {
presentSheet({
presentDialog({
component: () => (
<TwoFactorVerification
onMfaLogin={onMfaLogin}
@@ -306,7 +312,9 @@ TwoFactorVerification.present = (onMfaLogin, data, onCancel, context) => {
/>
),
context: context || "two_factor_verify",
disableClosing: true
disableClosing: true,
transparent: false,
statusBarTranslucent: true
});
};

View File

@@ -24,7 +24,7 @@ import { clearMessage } from "../../services/message";
import PremiumService from "../../services/premium";
import SettingsService from "../../services/settings";
import { useUserStore } from "../../stores/use-user-store";
import { eCloseSheet } from "../../utils/events";
import { eCloseSimpleDialog } from "../../utils/events";
import TwoFactorVerification from "./two-factor";
import { strings } from "@notesnook/intl";
@@ -92,7 +92,7 @@ export const useLogin = (onFinishLogin, sessionExpired = false) => {
} catch (e) {
callback && callback(false);
if (e.message === "invalid_grant") {
eSendEvent(eCloseSheet, "two_factor_verify");
eSendEvent(eCloseSimpleDialog, "two_factor_verify");
setLoading(false);
setStep(LoginSteps.emailAuth);
}
@@ -100,7 +100,7 @@ export const useLogin = (onFinishLogin, sessionExpired = false) => {
},
mfaInfo,
() => {
eSendEvent(eCloseSheet, "two_factor_verify");
eSendEvent(eCloseSimpleDialog, "two_factor_verify");
setLoading(false);
setStep(LoginSteps.emailAuth);
}

View File

@@ -26,7 +26,7 @@ import { notesnook } from "../../../e2e/test.ids";
import { getColorLinearShade } from "../../utils/colors";
import { AppFontSize } from "../../utils/size";
import { DefaultAppStyles } from "../../utils/styles";
import { Button } from "../ui/button";
import { Button, ButtonProps } from "../ui/button";
import Paragraph from "../ui/typography/paragraph";
const DialogButtons = ({
@@ -37,6 +37,14 @@ const DialogButtons = ({
loading,
doneText,
positiveType
}: {
onPressPositive?: () => void;
onPressNegative: () => void;
positiveTitle: string;
negativeTitle?: string;
loading?: boolean;
doneText?: string;
positiveType?: ButtonProps["type"];
}) => {
const { colors, isDark } = useThemeColors();

View File

@@ -17,15 +17,20 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { KeyboardTypeOptions } from "react-native";
import { eSendEvent } from "../../services/event-manager";
import { eCloseSimpleDialog, eOpenSimpleDialog } from "../../utils/events";
import { ButtonProps } from "../ui/button";
type DialogInfo = {
export type DialogInfo = {
title?: string;
paragraph?: string;
positiveText?: string;
negativeText?: string;
positivePress?: (...args: any[]) => void;
positiveText: string;
negativeText: string;
background?: string;
transparent?: boolean;
statusBarTranslucent?: boolean;
positivePress?: (...args: any[]) => Promise<any>;
onClose?: () => void;
positiveType?:
| "transparent"
@@ -44,16 +49,18 @@ type DialogInfo = {
// eslint-disable-next-line @typescript-eslint/ban-types
context: "global" | "local" | (string & {});
secureTextEntry?: boolean;
keyboardType?: string;
keyboardType?: KeyboardTypeOptions;
check?: {
info: string;
type?: string;
type?: ButtonProps["type"];
defaultValue?: boolean;
};
notice: {
text: string;
type: "alert" | "information";
};
disableBackdropClosing: boolean;
component: JSX.Element | ((close?: () => void) => JSX.Element);
};
export function presentDialog(data: Partial<DialogInfo>): void {

View File

@@ -20,7 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import { strings } from "@notesnook/intl";
import { useThemeColors } from "@notesnook/theme";
import React, { useCallback, useEffect, useRef, useState } from "react";
import { View } from "react-native";
import { TextInput, View, ViewStyle } from "react-native";
import { DDS } from "../../services/device-detection";
import {
eSubscribeEvent,
@@ -40,42 +40,26 @@ import Seperator from "../ui/seperator";
import BaseDialog from "./base-dialog";
import DialogButtons from "./dialog-buttons";
import DialogHeader from "./dialog-header";
import { DialogInfo } from "./functions";
export const Dialog = ({ context = "global" }) => {
export const Dialog = ({ context = "global" }: { context?: string }) => {
const { colors } = useThemeColors();
const [visible, setVisible] = useState(false);
const [checked, setChecked] = useState(false);
const [loading, setLoading] = useState(false);
const values = useRef({
const [visible, setVisible] = useState<boolean>();
const [checked, setChecked] = useState<boolean>();
const [loading, setLoading] = useState<boolean>();
const values = useRef<{
inputValue?: string;
}>({
inputValue: undefined
});
const inputRef = useRef();
const [dialogInfo, setDialogInfo] = useState({
title: "",
paragraph: "",
positiveText: strings.done(),
negativeText: strings.cancel(),
positivePress: () => {},
onClose: () => {},
positiveType: "transparent",
icon: null,
paragraphColor: colors.primary.paragraph,
input: false,
inputPlaceholder: "Enter some text",
defaultValue: "",
disableBackdropClosing: false,
check: {
info: "Check",
type: "transparent",
defaultValue: false
}
});
const inputRef = useRef<TextInput>(null);
const [dialogInfo, setDialogInfo] = useState<DialogInfo>();
const onPressPositive = async () => {
if (dialogInfo.positivePress) {
if (dialogInfo?.positivePress) {
inputRef.current?.blur();
setLoading(true);
let result;
let result = false;
try {
result = await dialogInfo.positivePress(
values.current.inputValue || dialogInfo.defaultValue,
@@ -97,7 +81,7 @@ export const Dialog = ({ context = "global" }) => {
};
const show = useCallback(
(data) => {
(data: DialogInfo) => {
if (!data.context) data.context = "global";
if (data.context !== context) return;
setDialogInfo(data);
@@ -108,6 +92,14 @@ export const Dialog = ({ context = "global" }) => {
[context]
);
const hide = React.useCallback(() => {
setChecked(false);
values.current.inputValue = undefined;
setVisible(false);
setDialogInfo(undefined);
dialogInfo?.onClose?.();
}, [dialogInfo]);
useEffect(() => {
eSubscribeEvent(eOpenSimpleDialog, show);
eSubscribeEvent(eCloseSimpleDialog, hide);
@@ -118,21 +110,14 @@ export const Dialog = ({ context = "global" }) => {
};
}, [hide, show]);
const hide = React.useCallback(() => {
setChecked(false);
values.current.inputValue = undefined;
setVisible(false);
dialogInfo.onClose?.();
}, [dialogInfo]);
const onNegativePress = async () => {
if (dialogInfo.onClose) {
if (dialogInfo?.onClose) {
await dialogInfo.onClose();
}
hide();
};
const style = {
const style: ViewStyle = {
...getElevationStyle(5),
width: DDS.isTab ? 400 : "85%",
maxHeight: 450,
@@ -143,11 +128,19 @@ export const Dialog = ({ context = "global" }) => {
overflow: "hidden"
};
return visible ? (
return visible && dialogInfo ? (
<BaseDialog
statusBarTranslucent={false}
statusBarTranslucent={
dialogInfo.statusBarTranslucent === undefined
? false
: dialogInfo.statusBarTranslucent
}
bounce={!dialogInfo.input}
closeOnTouch={!dialogInfo.disableBackdropClosing}
background={dialogInfo.background}
transparent={
dialogInfo.transparent === undefined ? true : dialogInfo.transparent
}
onShow={async () => {
if (dialogInfo.input) {
inputRef.current?.setNativeProps({
@@ -160,89 +153,99 @@ export const Dialog = ({ context = "global" }) => {
visible={true}
onRequestClose={hide}
>
<View style={style}>
<DialogHeader
title={dialogInfo.title}
icon={dialogInfo.icon}
paragraph={dialogInfo.paragraph}
paragraphColor={dialogInfo.paragraphColor}
padding={12}
style={{
minHeight: 0
}}
/>
<Seperator half />
{typeof dialogInfo.component === "function"
? dialogInfo.component(() => hide())
: dialogInfo.component}
{dialogInfo.input ? (
<View
{dialogInfo.component ? null : (
<View style={style}>
<DialogHeader
title={dialogInfo.title}
icon={dialogInfo.icon}
paragraph={dialogInfo.paragraph}
paragraphColor={dialogInfo.paragraphColor}
padding={12}
style={{
paddingHorizontal: DefaultAppStyles.GAP
minHeight: 0
}}
>
<Input
fwdRef={inputRef}
autoCapitalize="none"
onChangeText={(value) => {
values.current.inputValue = value;
}}
testID="input-value"
secureTextEntry={dialogInfo.secureTextEntry}
//defaultValue={dialogInfo.defaultValue}
onSubmit={onPressPositive}
returnKeyLabel="Done"
returnKeyType="done"
keyboardType={dialogInfo.keyboardType || "default"}
placeholder={dialogInfo.inputPlaceholder}
/>
</View>
) : null}
/>
<Seperator half />
{dialogInfo?.notice ? (
<View
style={{
paddingHorizontal: DefaultAppStyles.GAP
}}
>
<Notice
type={dialogInfo.notice.type || "information"}
text={dialogInfo.notice.text}
/>
</View>
) : null}
{dialogInfo.check ? (
<>
<Button
onPress={() => {
setChecked(!checked);
}}
icon={
checked
? "check-circle-outline"
: "checkbox-blank-circle-outline"
}
iconColor={checked ? colors.secondary.icon : colors.primary.icon}
{dialogInfo.input ? (
<View
style={{
justifyContent: "flex-start"
paddingHorizontal: DefaultAppStyles.GAP
}}
height={35}
iconSize={20}
width="100%"
title={dialogInfo.check.info}
type={checked ? dialogInfo.check.type || "plain" : "plain"}
/>
</>
) : null}
>
<Input
fwdRef={inputRef}
autoCapitalize="none"
onChangeText={(value) => {
values.current.inputValue = value;
}}
testID="input-value"
secureTextEntry={dialogInfo.secureTextEntry}
//defaultValue={dialogInfo.defaultValue}
onSubmit={() => {
onPressPositive();
}}
returnKeyLabel="Done"
returnKeyType="done"
keyboardType={dialogInfo.keyboardType || "default"}
placeholder={dialogInfo.inputPlaceholder}
/>
</View>
) : null}
<DialogButtons
onPressNegative={onNegativePress}
onPressPositive={dialogInfo.positivePress && onPressPositive}
loading={loading}
positiveTitle={dialogInfo.positiveText}
negativeTitle={dialogInfo.negativeText}
positiveType={dialogInfo.positiveType}
/>
</View>
{dialogInfo?.notice ? (
<View
style={{
paddingHorizontal: DefaultAppStyles.GAP
}}
>
<Notice
type={dialogInfo.notice.type || "information"}
text={dialogInfo.notice.text}
/>
</View>
) : null}
{dialogInfo.check ? (
<>
<Button
onPress={() => {
setChecked(!checked);
}}
icon={
checked
? "check-circle-outline"
: "checkbox-blank-circle-outline"
}
iconColor={
checked ? colors.secondary.icon : colors.primary.icon
}
style={{
justifyContent: "flex-start"
}}
height={35}
iconSize={20}
width="100%"
title={dialogInfo.check.info}
type={checked ? dialogInfo.check.type || "plain" : "plain"}
/>
</>
) : null}
<DialogButtons
onPressNegative={onNegativePress}
onPressPositive={dialogInfo.positivePress && onPressPositive}
loading={loading}
positiveTitle={dialogInfo.positiveText}
negativeTitle={dialogInfo.negativeText}
positiveType={dialogInfo.positiveType}
/>
</View>
)}
<Toast context="local" />
</BaseDialog>
) : null;

View File

@@ -97,7 +97,6 @@ export const Header = ({
style={{
flexDirection: "row",
justifyContent: "space-between",
marginTop: DefaultAppStyles.GAP_SMALL,
borderRadius: 10,
paddingVertical: 3,
borderWidth: hasSearch ? 1 : 0,

View File

@@ -133,7 +133,9 @@ export const SectionHeader = React.memo<
<Sort
screen={screen}
type={dataType}
hideGroupOptions={screen === "Reminders"}
hideGroupOptions={
screen === "Reminders" || screen === "Search"
}
/>
)
});

View File

@@ -0,0 +1,181 @@
/*
This file is part of the Notesnook project (https://notesnook.com/)
Copyright (C) 2023 Streetwriters (Private) Limited
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import React from "react";
import { HighlightedResult } from "@notesnook/core";
import { View } from "react-native";
import { Pressable } from "../../ui/pressable";
import Paragraph from "../../ui/typography/paragraph";
import { useThemeColors } from "@notesnook/theme";
import { DefaultAppStyles } from "../../../utils/styles";
import Heading from "../../ui/typography/heading";
import { AppFontSize } from "../../../utils/size";
import { Properties } from "../../properties";
import { db } from "../../../common/database";
import { eSendEvent } from "../../../services/event-manager";
import { eOnLoadNote } from "../../../utils/events";
import { IconButton } from "../../ui/icon-button";
import { fluidTabsRef } from "../../../utils/global-refs";
type SearchResultProps = {
item: HighlightedResult;
};
export const SearchResult = (props: SearchResultProps) => {
const [expanded, setExpanded] = React.useState(true);
const { colors } = useThemeColors();
const openNote = async (index?: number) => {
const note = await db.notes.note(props.item.id);
eSendEvent(eOnLoadNote, {
item: {
...note,
content: props.item.rawContent
? {
data: props.item.rawContent || "",
type: "tiptap"
}
: undefined
},
searchResultIndex: index
});
fluidTabsRef.current?.goToPage("editor");
};
return (
<Pressable
style={{
alignSelf: "flex-start",
alignItems: "flex-start",
paddingHorizontal: DefaultAppStyles.GAP,
paddingVertical: DefaultAppStyles.GAP_VERTICAL_SMALL,
borderRadius: 0
}}
onLongPress={async () => {
const note = await db.notes.note(props.item.id);
Properties.present(note);
}}
onPress={async () => openNote()}
>
<View
style={{
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
width: "100%"
}}
>
<View
style={{
flexDirection: "row",
alignItems: "center",
gap: DefaultAppStyles.GAP_SMALL / 2,
flexShrink: 1
}}
>
{props.item.content?.length ? (
<IconButton
name={!expanded ? "chevron-right" : "chevron-down"}
onPress={() => setExpanded((prev) => !prev)}
size={AppFontSize.md + 2}
color={colors.secondary.icon}
style={{
width: 23,
height: 23
}}
/>
) : null}
<Heading
size={AppFontSize.sm}
style={{
flexShrink: 1
}}
>
{props.item.title.map((title, index) => (
<React.Fragment key={props.item.id + index + "-srt"}>
{title.prefix}
<Heading
size={AppFontSize.sm}
style={{
backgroundColor: colors.secondary.accent,
color: colors.secondary.accentForeground
}}
>
{title.match}
</Heading>
{title.suffix}
</React.Fragment>
))}
</Heading>
</View>
{props.item.content?.length ? (
<Paragraph size={AppFontSize.xxs} color={colors.secondary.paragraph}>
{props.item.content.length}
</Paragraph>
) : null}
</View>
{expanded &&
props.item.content.map((content, index) => (
<Pressable
key={props.item.id + index}
style={{
alignSelf: "flex-start",
alignItems: "flex-start",
paddingVertical: DefaultAppStyles.GAP_VERTICAL_SMALL,
borderColor: colors.primary.border,
borderWidth: 0,
borderRadius: 0,
borderBottomWidth: 1,
borderBottomColor: colors.primary.border,
width: "100%"
}}
onLongPress={async () => {
const note = await db.notes.note(props.item.id);
Properties.present(note);
}}
onPress={() => {
let activeIndex = 0;
for (let i = 0; i <= index; i++) {
activeIndex += props.item.content[i].length;
}
console.log(activeIndex);
openNote(activeIndex);
}}
>
<Paragraph>
{content.map((match, index) => (
<React.Fragment key={props.item.id + index + "src"}>
{match.prefix}
<Paragraph
size={AppFontSize.sm}
style={{
backgroundColor: colors.secondary.accent,
color: colors.secondary.accentForeground
}}
>
{match.match}
</Paragraph>
{match.suffix}
</React.Fragment>
))}
</Paragraph>
</Pressable>
))}
</Pressable>
);
};

View File

@@ -73,7 +73,7 @@ export default function List(props: ListProps) {
? "home"
: props.renderedInRoute === "Favorites"
? "favorites"
: props.renderedInRoute === "Trash"
: props.renderedInRoute === "Trash" || props.dataType === "trash"
? "trash"
: `${props.dataType}s`;
@@ -150,7 +150,7 @@ export default function List(props: ListProps) {
flex: 1
}}
>
{props.data?.placeholders?.length === 0 ? (
{props.data?.placeholders?.length === 0 || !props.data ? (
<>
{props.CustomLisHeader ? (
props.CustomLisHeader

View File

@@ -27,6 +27,7 @@ import {
GroupHeader,
GroupOptions,
GroupingKey,
HighlightedResult,
Item,
ItemType,
Note,
@@ -49,6 +50,7 @@ import { NoteWrapper } from "../list-items/note/wrapper";
import { NotebookWrapper } from "../list-items/notebook/wrapper";
import ReminderItem from "../list-items/reminder";
import TagItem from "../list-items/tag";
import { SearchResult } from "../list-items/search-result";
type ListItemWrapperProps<TItem = Item> = {
group?: GroupingKey;
@@ -153,7 +155,9 @@ export function ListItemWrapper(props: ListItemWrapperProps) {
},
items?.cacheItem(index) ? 100 : 0
);
} catch (e) {}
} catch (e) {
/** empty */
}
})();
}, [index, items, refreshItem]);
@@ -196,7 +200,7 @@ export function ListItemWrapper(props: ListItemWrapperProps) {
notebooks={notebooks.current}
reminder={reminder.current}
attachmentsCount={attachmentsCount.current}
date={getDate(item, group)}
date={getDate(item as Note, group)}
isRenderedInActionSheet={isSheet}
index={index}
locked={locked.current}
@@ -227,7 +231,7 @@ export function ListItemWrapper(props: ListItemWrapperProps) {
<NotebookWrapper
item={item as Notebook}
totalNotes={totalNotes.current}
date={getDate(item, group)}
date={getDate(item as Notebook, group)}
index={index}
/>
</>
@@ -285,12 +289,34 @@ export function ListItemWrapper(props: ListItemWrapperProps) {
/>
</>
);
case "searchResult":
return (
<>
{groupHeader && previousIndex.current === index && !isSheet ? (
<SectionHeader
screen={props.renderedInRoute}
item={groupHeader}
index={index}
dataType={item.type}
color={props.customAccentColor}
groupOptions={groupOptions}
onOpenJumpToDialog={() => {
eSendEvent(eOpenJumpToDialog, {
ref: props.scrollRef,
data: items
});
}}
/>
) : null}
<SearchResult item={item as HighlightedResult} />
</>
);
default:
return null;
}
}
function getDate(item: Item, groupType?: GroupingKey): number {
function getDate(item: Notebook | Note, groupType?: GroupingKey): number {
return (
getSortValue(
groupType

View File

@@ -58,7 +58,6 @@ const Line = ({ top = 6, bottom = 6 }) => {
export const Properties = ({ close = () => {}, item, buttons = [] }) => {
const { colors } = useThemeColors();
const isColor = !!ColorValues[item.title];
if (!item || !item.id) {
return (
<Paragraph style={{ marginVertical: 10, alignSelf: "center" }}>

View File

@@ -36,6 +36,7 @@ import Paragraph from "../ui/typography/paragraph";
const TOP_BAR_ITEMS: ActionId[] = [
"pin",
"favorite",
"archive",
"lock-unlock",
"publish",
"local-only",
@@ -66,6 +67,7 @@ const COLUMN_BAR_ITEMS: ActionId[] = [
"move-notebook",
"pin",
"default-notebook",
"default-tag",
"default-homepage",
"add-shortcut",
"reorder",

View File

@@ -24,11 +24,11 @@ import { TaggedNotes } from "../../screens/notes/tagged";
import { useThemeColors } from "@notesnook/theme";
import { AppFontSize } from "../../utils/size";
import { sleep } from "../../utils/time";
import ManageTagsSheet from "../sheets/manage-tags";
import { Button } from "../ui/button";
import { ColorTags } from "./color-tags";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../utils/styles";
import ManageTags from "../../screens/manage-tags";
export const Tags = ({ item, close }) => {
const { colors } = useThemeColors();
@@ -47,7 +47,8 @@ export const Tags = ({ item, close }) => {
>
<Button
onPress={async () => {
ManageTagsSheet.present([item.id]);
ManageTags.present([item.id]);
close();
}}
buttonType={{
text: colors.primary.accent

View File

@@ -42,10 +42,11 @@ import { DefaultAppStyles } from "../../utils/styles";
import { sleep } from "../../utils/time";
import { presentDialog } from "../dialog/functions";
import ExportNotesSheet from "../sheets/export-notes";
import ManageTagsSheet from "../sheets/manage-tags";
import { MoveNotebook } from "../../screens/move-notebook";
import { IconButton } from "../ui/icon-button";
import NativeTooltip from "../../utils/tooltip";
import ManageTags from "../../screens/manage-tags";
export const SelectionHeader = React.memo(
({
@@ -209,7 +210,7 @@ export const SelectionHeader = React.memo(
{
title: strings.manageTags(),
onPress: async () => {
ManageTagsSheet.present(selectedItemsList);
ManageTags.present(selectedItemsList);
},
visible: type === "note",
icon: "pound"

View File

@@ -24,23 +24,22 @@ import { TextInput, View } from "react-native";
import { notesnook } from "../../../../e2e/test.ids";
import { db } from "../../../common/database";
import { DDS } from "../../../services/device-detection";
import {
ToastManager,
eSendEvent,
presentSheet
} from "../../../services/event-manager";
import { ToastManager, eSendEvent } from "../../../services/event-manager";
import Navigation from "../../../services/navigation";
import { useMenuStore } from "../../../stores/use-menu-store";
import { useNotebookStore } from "../../../stores/use-notebook-store";
import { useRelationStore } from "../../../stores/use-relation-store";
import { eOnNotebookUpdated } from "../../../utils/events";
import { getParentNotebookId } from "../../../utils/notebooks";
import { AppFontSize } from "../../../utils/size";
import { Button } from "../../ui/button";
import Input from "../../ui/input";
import Seperator from "../../ui/seperator";
import Heading from "../../ui/typography/heading";
import { DefaultAppStyles } from "../../../utils/styles";
import { useSettingStore } from "../../../stores/use-setting-store";
import DialogHeader from "../../dialog/dialog-header";
import DialogButtons from "../../dialog/dialog-buttons";
import { presentDialog } from "../../dialog/functions";
import { getElevationStyle } from "../../../utils/elevation";
import { defaultBorderRadius } from "../../../utils/size";
import { useThemeColors } from "@notesnook/theme";
import { getContainerBorder } from "../../../utils/colors";
export const AddNotebookSheet = ({
notebook,
@@ -55,6 +54,7 @@ export const AddNotebookSheet = ({
showMoveNotesOnComplete: boolean;
defaultTitle?: string;
}) => {
const { colors } = useThemeColors();
const title = useRef(notebook?.title || defaultTitle);
const description = useRef(notebook?.description);
const titleInput = useRef<TextInput>(null);
@@ -124,57 +124,66 @@ export const AddNotebookSheet = ({
return (
<View
style={{
maxHeight: DDS.isTab ? "90%" : "97%",
borderRadius: DDS.isTab ? 5 : 0,
paddingHorizontal: DefaultAppStyles.GAP
...getElevationStyle(5),
width: DDS.isTab ? 400 : "85%",
maxHeight: 450,
borderRadius: defaultBorderRadius,
backgroundColor: colors.primary.background,
paddingTop: 12,
...getContainerBorder(colors.primary.border, 0.5),
overflow: "hidden"
}}
>
<Heading size={AppFontSize.lg}>
{notebook ? strings.editNotebook() : strings.newNotebook()}
</Heading>
<Seperator />
<Input
fwdRef={titleInput}
testID={notesnook.ids.dialogs.notebook.inputs.title}
onChangeText={(value) => {
title.current = value;
}}
onLayout={() => {
setImmediate(() => {
titleInput?.current?.focus();
});
}}
placeholder={strings.enterNotebookTitle()}
onSubmit={() => {
descriptionInput.current?.focus();
}}
returnKeyLabel="Next"
returnKeyType="next"
defaultValue={notebook ? notebook.title : title.current}
/>
<Input
fwdRef={descriptionInput}
testID={notesnook.ids.dialogs.notebook.inputs.description}
onChangeText={(value) => {
description.current = value;
}}
placeholder={strings.enterNotebookDescription()}
returnKeyLabel={strings.next()}
returnKeyType="next"
defaultValue={notebook ? notebook.description : ""}
/>
<Button
title={notebook ? strings.save() : strings.add()}
type="accent"
<View
style={{
paddingHorizontal: DefaultAppStyles.GAP * 2,
width: "100%"
paddingHorizontal: 12
}}
onPress={onSaveChanges}
>
<DialogHeader
title={notebook ? strings.editNotebook() : strings.newNotebook()}
/>
<Input
fwdRef={titleInput}
testID={notesnook.ids.dialogs.notebook.inputs.title}
onChangeText={(value) => {
title.current = value;
}}
onLayout={() => {
setTimeout(() => {
titleInput?.current?.focus();
}, 300);
}}
placeholder={strings.enterNotebookTitle()}
onSubmit={() => {
descriptionInput.current?.focus();
}}
returnKeyLabel="Next"
returnKeyType="next"
defaultValue={notebook ? notebook.title : title.current}
/>
<Input
fwdRef={descriptionInput}
testID={notesnook.ids.dialogs.notebook.inputs.description}
onChangeText={(value) => {
description.current = value;
}}
placeholder={strings.enterNotebookDescription()}
returnKeyLabel={strings.next()}
returnKeyType="next"
defaultValue={notebook ? notebook.description : ""}
/>
</View>
<DialogButtons
onPressNegative={() => {
title.current = undefined;
close?.(false);
useSettingStore.getState().setSheetKeyboardHandler(true);
}}
positiveTitle={notebook ? strings.save() : strings.add()}
negativeTitle={strings.cancel()}
onPressPositive={onSaveChanges}
/>
</View>
);
@@ -188,9 +197,9 @@ AddNotebookSheet.present = (
showMoveNotesOnComplete = true,
defaultTitle?: string
) => {
presentSheet({
presentDialog({
context: context,
component: (ref, close) => (
component: (close) => (
<AddNotebookSheet
notebook={notebook}
parentNotebook={parentNotebook}

View File

@@ -283,7 +283,14 @@ export default function LinkNote(props: {
width: "100%"
}}
>
<Paragraph numberOfLines={1}>{selectedNote?.title}</Paragraph>
<Paragraph
style={{
flexShrink: 1
}}
numberOfLines={1}
>
{selectedNote?.title}
</Paragraph>
<Paragraph
color={colors.secondary.paragraph}

View File

@@ -48,7 +48,7 @@ import { Dialog } from "../../dialog";
import { ReminderTime } from "../../ui/reminder-time";
import Heading from "../../ui/typography/heading";
import Paragraph from "../../ui/typography/paragraph";
import { ItemReference, Note, Reminder } from "@notesnook/core";
import { Note, Reminder } from "@notesnook/core";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../../utils/styles";
@@ -57,7 +57,7 @@ type ReminderSheetProps = {
close?: (ctx?: string) => void;
update?: (options: PresentSheetOptions) => void;
reminder?: Reminder;
reference?: ItemReference;
reference?: Note;
};
const ReminderModes =
@@ -612,7 +612,7 @@ export default function ReminderSheet({
ReminderSheet.present = (
reminder?: Reminder,
reference?: ItemReference,
reference?: Note,
isSheet?: boolean
) => {
presentSheet({

View File

@@ -52,23 +52,42 @@ const Sort = ({
hideGroupOptions?: boolean;
}) => {
const { colors } = useThemeColors();
const groupType =
screen === "Archive"
? "archive"
: screen === "Search"
? "search"
: screen === "Notes"
? "home"
: screen === "Trash" || type === "trash"
? "trash"
: ((type + "s") as GroupingKey);
const [groupOptions, setGroupOptions] = useState(
db.settings.getGroupOptions(
screen === "Notes"
? "home"
: screen === "Trash"
? "trash"
: ((type + "s") as GroupingKey)
)
db.settings.getGroupOptions(groupType)
);
const getSortButtonTitle = () => {
const { sortDirection, groupBy, sortBy } = groupOptions || {};
const isAlphabetical = groupBy === "abc" || sortBy === "title";
const isDueDate = sortBy === "dueDate";
const isRelevance = sortBy === "relevance";
if (sortDirection === "asc") {
if (isAlphabetical) return strings.aToZ();
if (isDueDate) return strings.earliestFirst();
if (isRelevance) return strings.leastRelevantFirst();
return strings.oldNew();
} else {
if (isAlphabetical) return strings.zToA();
if (isDueDate) return strings.latestFirst();
if (isRelevance) return strings.mostRelevantFirst();
return strings.newOld();
}
};
const updateGroupOptions = async (_groupOptions: GroupOptions) => {
const groupType =
screen === "Notes"
? "home"
: screen === "Trash"
? "trash"
: ((type + "s") as GroupingKey);
console.log("updateGroupOptions for group", groupType, "in", screen);
await db.settings.setGroupOptions(groupType, _groupOptions);
setGroupOptions(_groupOptions);
setTimeout(() => {
@@ -109,31 +128,10 @@ const Sort = ({
paddingHorizontal: DefaultAppStyles.GAP
}}
>
<Heading
size={AppFontSize.lg}
style={{
alignSelf: "center"
}}
>
{strings.sortBy()}
</Heading>
<Heading size={AppFontSize.lg}>{strings.sortBy()}</Heading>
<Button
title={
groupOptions?.sortDirection === "asc"
? groupOptions?.groupBy === "abc" ||
groupOptions?.sortBy === "title"
? strings.aToZ()
: groupOptions?.sortBy === "dueDate"
? strings.earliestFirst()
: strings.oldNew()
: groupOptions?.groupBy === "abc" ||
groupOptions?.sortBy === "title"
? strings.zToA()
: groupOptions?.sortBy === "dueDate"
? strings.latestFirst()
: strings.newOld()
}
title={getSortButtonTitle()}
icon={
groupOptions?.sortDirection === "asc"
? "sort-ascending"
@@ -157,13 +155,24 @@ const Sort = ({
borderBottomColor: colors.primary.border
}}
>
{Object.keys(SORT).map((item) =>
(item === "dueDate" && screen !== "Reminders") ||
(screen !== "Tags" &&
screen !== "Reminders" &&
item === "dateModified") ||
((screen === "Tags" || screen === "Reminders") &&
item === "dateEdited") ? null : (
{Object.keys(SORT).map((item) => {
const sortOptionVisibility = {
relevance: screen === "Search",
dueDate: screen === "Reminders",
dateModified: screen === "Tags" || screen === "Reminders",
dateEdited: screen !== "Tags" && screen !== "Reminders"
};
// Check if this sort option should be skipped for the current screen
const shouldSkip =
item in sortOptionVisibility &&
!sortOptionVisibility[item as keyof typeof sortOptionVisibility];
if (shouldSkip) {
return null;
}
return (
<Pressable
key={item}
type={groupOptions?.sortBy === item ? "selected" : "plain"}
@@ -201,8 +210,8 @@ const Sort = ({
/>
) : null}
</Pressable>
)
)}
);
})}
</View>
{!hideGroupOptions ? (

View File

@@ -80,6 +80,9 @@ function _MenuItem({
case "Monographs":
setItemCount(await db.monographs.all.count());
break;
case "Archive":
setItemCount(await db.notes.archived.count());
break;
case "Trash":
setItemCount((await db.trash.all()).length);
break;

View File

@@ -93,7 +93,11 @@ export const NotebookItem = ({
<View
style={{
paddingLeft:
item.depth > 0 && item.depth < 6 ? 15 * item.depth : undefined,
item.depth === 0
? undefined
: item.depth < 6
? 15 * item.depth
: 15 * 5,
width: "100%",
marginTop: 2
}}

View File

@@ -321,6 +321,9 @@ const Input = ({
bottom={10}
onPress={button.onPress}
color={button.color}
style={{
marginRight: -8
}}
/>
)}

View File

@@ -21,11 +21,7 @@ import { FeatureType } from "./components/sheets/new-feature";
export const features: FeatureType[] = [
{
title: "Notebook Tree View",
body: "Notebooks are now displayed in a tree view for better organization and user experience."
},
{
title: "New SideBar",
body: "Sidebar now contains tabs for Notebooks and Tags for easy navigation."
title: "Improved Search",
body: "Improved search results with better relevance and highlighting."
}
];

View File

@@ -66,9 +66,11 @@ import { convertNoteToText } from "../utils/note-to-text";
import { sleep } from "../utils/time";
import SettingsService from "../services/settings";
import { useSettingStore } from "../stores/use-setting-store";
import { useArchivedStore } from "../stores/use-archived-store";
export type ActionId =
| "select"
| "archive"
| "restore"
| "delete"
| "reorder"
@@ -108,7 +110,8 @@ export type ActionId =
| "favorite"
| "remove-from-notebook"
| "trash"
| "default-homepage";
| "default-homepage"
| "default-tag";
export type Action = {
id: ActionId;
@@ -156,6 +159,8 @@ export const useActions = ({
const [defaultNotebook, setDefaultNotebook] = useState(
db.settings.getDefaultNotebook()
);
const [defaultTag, setDefaultTag] = useState(db.settings.getDefaultTag());
const [noteInCurrentNotebook, setNoteInCurrentNotebook] = useState(false);
const [locked, setLocked] = useState(false);
const isHomepage = useSettingStore(
@@ -467,15 +472,39 @@ export const useActions = ({
}
if (item.type === "tag" || item.type === "notebook") {
actions.push({
id: "add-shortcut",
title: isPinnedToMenu ? strings.removeShortcut() : strings.addShortcut(),
icon: isPinnedToMenu ? "link-variant-remove" : "link-variant",
onPress: createMenuShortcut,
isToggle: true,
checked: isPinnedToMenu,
activeColor: colors.error.paragraph
});
actions.push(
{
id: "add-shortcut",
title: isPinnedToMenu
? strings.removeShortcut()
: strings.addShortcut(),
icon: isPinnedToMenu ? "link-variant-remove" : "link-variant",
onPress: createMenuShortcut,
isToggle: true,
checked: isPinnedToMenu,
activeColor: colors.error.paragraph
},
{
id: "default-tag",
title:
defaultTag === item.id
? strings.removeAsDefault()
: strings.setAsDefault(),
hidden: item.type !== "tag",
icon: "pound",
onPress: async () => {
if (defaultTag === item.id) {
await db.settings.setDefaultTag(undefined);
setDefaultTag(undefined);
} else {
await db.settings.setDefaultTag(item.id);
setDefaultTag(item.id);
}
close();
},
checked: defaultTag === item.id
}
);
}
if (item.type === "notebook") {
@@ -651,7 +680,8 @@ export const useActions = ({
async function pinToNotifications() {
if (notifPinned) {
Notifications.remove(item.id);
await Notifications.remove(item.id);
await sleep(500);
await Notifications.get();
setNotifPinned(isNotePinnedInNotifications(item));
return;
@@ -665,7 +695,8 @@ export const useActions = ({
return;
}
Notifications.pinNote(item.id);
await Notifications.pinNote(item.id);
await sleep(500);
await Notifications.get();
setNotifPinned(isNotePinnedInNotifications(item));
}
@@ -926,7 +957,7 @@ export const useActions = ({
title: strings.remindMe(),
icon: "clock-plus-outline",
onPress: () => {
ReminderSheet.present(undefined, { id: item.id, type: "note" });
ReminderSheet.present(undefined, item);
}
},
{
@@ -972,6 +1003,19 @@ export const useActions = ({
reference: item as ItemReference
});
}
},
{
id: "archive",
title: !item.archived ? strings.archive() : strings.unarchive(),
icon: "archive",
onPress: async () => {
db.notes.archive(!item.archived, item.id);
setItem((await db.notes.note(item.id)) as Item);
Navigation.queueRoutesForUpdate();
useArchivedStore.getState().refresh();
},
checked: item.archived,
isToggle: true
}
);

View File

@@ -341,8 +341,15 @@ const doAppLoadActions = async () => {
};
const checkAppUpdateAvailable = async () => {
if (__DEV__ || Config.isTesting === "true" || Config.FDROID_BUILD || BETA)
if (
__DEV__ ||
Config.isTesting === "true" ||
Config.FDROID_BUILD ||
BETA ||
!SettingsService.getProperty("checkForUpdates")
)
return;
try {
const version =
Config.GITHUB_RELEASE === "true"

View File

@@ -32,7 +32,7 @@ export function useGroupOptions(type: any) {
const onUpdate = (groupType: string) => {
if (groupType !== type) return;
const options = db.settings?.getGroupOptions(type) as any;
if (!options) return;
if (
groupOptions?.groupBy !== options.groupBy ||
groupOptions?.sortBy !== options.sortBy ||

View File

@@ -52,7 +52,14 @@ const useTimer = (initialId?: string) => {
};
}, [seconds, id]);
return { seconds, setId, start };
const reset = () => {
if (id) {
timers[id] = 0;
setSeconds(0);
}
};
return { seconds, setId, start, reset };
};
export default useTimer;

View File

@@ -43,7 +43,7 @@ let Reminders: any = null;
let Monographs: any = null;
let TaggedNotes: any = null;
let ColoredNotes: any = null;
let Archive: any = null;
const AppNavigation = React.memo(
() => {
const { colors } = useThemeColors();
@@ -192,6 +192,14 @@ const AppNavigation = React.memo(
initialParams={home.name === "ColoredNotes" ? home.params : undefined}
/>
<AppStack.Screen
name="Archive"
getComponent={() => {
Archive = Archive || require("../screens/archive").default;
return Archive;
}}
/>
<AppStack.Screen
name="Reminders"
getComponent={() => {
@@ -239,6 +247,7 @@ let LinkNotebooks: any = null;
let MoveNotebook: any = null;
let MoveNotes: any = null;
let Settings: any = null;
let ManageTags: any = null;
export const RootNavigation = () => {
const introCompleted = useSettingStore(
@@ -318,6 +327,15 @@ export const RootNavigation = () => {
return Settings;
}}
/>
<RootStack.Screen
name="ManageTags"
getComponent={() => {
ManageTags =
ManageTags || require("../screens/manage-tags").default;
return ManageTags;
}}
/>
</RootStack.Navigator>
</NavigationContainer>
);

View File

@@ -0,0 +1,88 @@
/*
This file is part of the Notesnook project (https://notesnook.com/)
Copyright (C) 2023 Streetwriters (Private) Limited
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import React from "react";
import DelayLayout from "../../components/delay-layout";
import { Header } from "../../components/header";
import List from "../../components/list";
import SelectionHeader from "../../components/selection-header";
import { useNavigationFocus } from "../../hooks/use-navigation-focus";
import Navigation, { NavigationProps } from "../../services/navigation";
import SettingsService from "../../services/settings";
import useNavigationStore from "../../stores/use-navigation-store";
import { db } from "../../common/database";
import { strings } from "@notesnook/intl";
import { useArchived } from "../../stores/use-archived-store";
export const Archive = ({ navigation, route }: NavigationProps<"Archive">) => {
const [archive, loading, refresh] = useArchived();
const isFocused = useNavigationFocus(navigation, {
onFocus: (prev) => {
Navigation.routeNeedsUpdate(
route.name,
Navigation.routeUpdateFunctions[route.name]
);
useNavigationStore.getState().setFocusedRouteId(route?.name);
return false;
},
onBlur: () => false,
delay: SettingsService.get().homepage === route.name ? 1 : -1
});
return (
<>
<SelectionHeader id={route.name} items={archive} type="note" />
<Header
renderedInRoute={route.name}
title={strings.routes[route.name]()}
canGoBack={false}
hasSearch={true}
id={route.name}
onSearch={() => {
Navigation.push("Search", {
placeholder: strings.searchInRoute(route.name),
type: "note",
title: route.name,
route: route.name,
items: db.notes.archived
});
}}
/>
<DelayLayout wait={loading}>
<List
data={archive}
dataType="note"
onRefresh={() => {
refresh();
}}
renderedInRoute="Archive"
loading={loading}
placeholder={{
title: strings.yourArchive(),
paragraph: strings.yourArchiveIsEmpty(),
loading: strings.loadingArchive()
}}
headerTitle={strings.routes.Archive()}
/>
</DelayLayout>
</>
);
};
export default Archive;

View File

@@ -236,6 +236,11 @@ class Commands {
const tabId = useTabStore.getState().currentTab;
return this.sendCommand("scrollIntoViewById", id, tabId);
};
scrollToSearchResult = (index: number) => {
const tabId = useTabStore.getState().currentTab;
return this.sendCommand("scrollToSearchResult", index, tabId);
};
}
export default Commands;

View File

@@ -41,7 +41,6 @@ import { AuthMode } from "../../../components/auth/common";
import EditorTabs from "../../../components/sheets/editor-tabs";
import { Issue } from "../../../components/sheets/github/issue";
import LinkNote from "../../../components/sheets/link-note";
import ManageTagsSheet from "../../../components/sheets/manage-tags";
import { RelationsList } from "../../../components/sheets/relations-list";
import ReminderSheet from "../../../components/sheets/reminder";
import TableOfContents from "../../../components/sheets/toc";
@@ -79,6 +78,8 @@ import { EditorMessage, EditorProps, useEditorType } from "./types";
import { useTabStore } from "./use-tab-store";
import { editorState, openInternalLink } from "./utils";
import { Properties } from "../../../components/properties";
import { sleep } from "../../../utils/time";
import ManageTags from "../../manage-tags";
const publishNote = async () => {
const user = useUserStore.getState().user;
@@ -177,7 +178,7 @@ export const useEditorEvents = (
useEffect(() => {
const handleKeyboardDidShow: KeyboardEventListener = () => {
editor.commands.keyboardShown(true);
//editor.postMessage(NativeEvents.keyboardShown, undefined);
editor.postMessage(NativeEvents.keyboardShown, undefined);
};
const handleKeyboardDidHide: KeyboardEventListener = () => {
editor.commands.keyboardShown(false);
@@ -448,7 +449,7 @@ export const useEditorEvents = (
});
return;
}
ManageTagsSheet.present([noteId]);
ManageTags.present([noteId]);
break;
case EditorEvents.tag:
if (editorMessage.value) {
@@ -613,6 +614,10 @@ export const useEditorEvents = (
eSendEvent(eEditorTabFocused, editorMessage.tabId);
if (!editor.state.current.initialLoadCalled) break;
if (editorMessage.noteId) {
// Wait for next tick to ensure the tab is not changed.
await sleep(1);
if (useTabStore.getState().currentTab !== editorMessage.tabId)
return;
if (!useSettingStore.getState().isAppLoading) {
const note = await db.notes.note(editorMessage.noteId);
if (note) {

View File

@@ -352,7 +352,7 @@ export const useEditor = (
DatabaseLogger.log(`Note saved: ${id}...`);
clearTimeout(saveTimer);
const oldNote = currentNotes.current[id];
if (id) {
currentNotes.current[id] = await db.notes?.note(id);
}
@@ -365,22 +365,37 @@ export const useEditor = (
}
});
const defaultNotebook = db.settings.getDefaultNotebook();
if (!state.current.onNoteCreated && defaultNotebook) {
onNoteCreated(id, {
type: "notebook",
id: defaultNotebook
});
if (!state.current.onNoteCreated) {
const defaultNotebook = db.settings.getDefaultNotebook();
if (defaultNotebook) {
onNoteCreated(id, {
type: "notebook",
id: defaultNotebook
});
}
const defaultTag = db.settings.getDefaultTag();
if (defaultTag) {
onNoteCreated(id, {
type: "tag",
id: defaultTag
});
}
} else {
state.current?.onNoteCreated && state.current.onNoteCreated(id);
state.current.onNoteCreated(id);
}
}
postMessage(
NativeEvents.title,
currentNotes.current[id]?.title,
tabId
);
if (
oldNote?.title !== currentNotes.current[id]?.title &&
!noteData.title
) {
postMessage(
NativeEvents.title,
currentNotes.current[id]?.title,
tabId
);
}
if (Notifications.isNotePinned(id as string)) {
Notifications.pinNote(id as string);
@@ -464,8 +479,7 @@ export const useEditor = (
}
) => {
currentNotes.current[note.id] = note;
const locked = note && (await db.vaults.itemExists(note));
if ((locked || note.content) && note.content?.data) {
if (note.content && note.content?.data) {
currentContents.current[note.id] = {
data: note.content?.data,
type: note.content?.type || "tiptap",
@@ -493,6 +507,7 @@ export const useEditor = (
session?: TabSessionItem;
newTab?: boolean;
refresh?: boolean;
searchResultIndex?: number;
}) => {
loadNoteMutex.runExclusive(async () => {
if (!event) return;
@@ -678,13 +693,17 @@ export const useEditor = (
{
data: currentContents.current[item.id]?.data || "",
scrollTop: tab?.session?.scrollTop,
selection: tab?.session?.selection
selection: tab?.session?.selection,
searchResultIndex: event.searchResultIndex
},
tabId,
10000
);
setTimeout(() => {
if (event.searchResultIndex !== undefined) {
commands.scrollToSearchResult(event.searchResultIndex);
}
if (blockIdRef.current) {
commands.scrollIntoViewById(blockIdRef.current);
blockIdRef.current = undefined;

View File

@@ -29,27 +29,30 @@ import React, {
useRef,
useState
} from "react";
import { SafeAreaView } from "react-native-safe-area-context";
import { TextInput, View, useWindowDimensions } from "react-native";
import { ActionSheetRef } from "react-native-actions-sheet";
import { FlashList } from "react-native-actions-sheet/dist/src/views/FlashList";
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
import { db } from "../../../common/database";
import { useDBItem } from "../../../hooks/use-db-item";
import { ToastManager, presentSheet } from "../../../services/event-manager";
import Navigation from "../../../services/navigation";
import { db } from "../../common/database";
import { useDBItem } from "../../hooks/use-db-item";
import { ToastManager } from "../../services/event-manager";
import Navigation, { NavigationProps } from "../../services/navigation";
import {
ItemSelection,
createItemSelectionStore
} from "../../../stores/item-selection-store";
import { useRelationStore } from "../../../stores/use-relation-store";
import { useTagStore } from "../../../stores/use-tag-store";
import { defaultBorderRadius, AppFontSize } from "../../../utils/size";
import Input from "../../ui/input";
import { Pressable } from "../../ui/pressable";
import Heading from "../../ui/typography/heading";
import Paragraph from "../../ui/typography/paragraph";
} from "../../stores/item-selection-store";
import { useRelationStore } from "../../stores/use-relation-store";
import { useTagStore } from "../../stores/use-tag-store";
import { defaultBorderRadius, AppFontSize } from "../../utils/size";
import Input from "../../components/ui/input";
import { Pressable } from "../../components/ui/pressable";
import Heading from "../../components/ui/typography/heading";
import Paragraph from "../../components/ui/typography/paragraph";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../../utils/styles";
import { DefaultAppStyles } from "../../utils/styles";
import { Header } from "../../components/header";
import { useNavigationFocus } from "../../hooks/use-navigation-focus";
async function updateInitialSelectionState(items: string[]) {
const relations = await db.relations
@@ -85,16 +88,14 @@ async function updateInitialSelectionState(items: string[]) {
const useTagItemSelection = createItemSelectionStore(true);
const ManageTagsSheet = (props: {
ids?: string[];
actionSheetRef: RefObject<ActionSheetRef>;
}) => {
const ManageTags = (props: NavigationProps<"ManageTags">) => {
const { colors } = useThemeColors();
const ids = useMemo(() => props.ids || [], [props.ids]);
const ids = props.route.params.ids || [];
const [tags, setTags] = useState<VirtualizedGrouping<Tag>>();
const [query, setQuery] = useState<string>();
const inputRef = useRef<TextInput>(null);
const [focus, setFocus] = useState(false);
useNavigationFocus(props.navigation, { focusOnInit: true });
const [queryExists, setQueryExists] = useState(false);
const dimensions = useWindowDimensions();
const refreshSelection = useCallback(() => {
@@ -239,112 +240,117 @@ const ManageTagsSheet = (props: {
);
return (
<View
<SafeAreaView
style={{
width: "100%",
alignSelf: "center",
paddingHorizontal: DefaultAppStyles.GAP,
maxHeight: dimensions.height * 0.85
backgroundColor: colors.primary.background,
gap: DefaultAppStyles.GAP_VERTICAL
}}
>
<Input
button={{
icon: "magnify",
color: colors.primary.accent,
size: AppFontSize.lg,
onPress: () => {}
}}
testID="tag-input"
fwdRef={inputRef}
autoCapitalize="none"
onChangeText={(v) => {
setQuery(sanitizeTag(v));
checkQueryExists(sanitizeTag(v));
}}
onFocusInput={() => {
setFocus(true);
}}
onBlurInput={() => {
setFocus(false);
}}
onSubmit={() => {
onSubmit();
}}
placeholder={strings.searchForTags()}
/>
{query && !queryExists ? (
<Pressable
key={"query_item"}
style={{
flexDirection: "row",
marginVertical: 5,
justifyContent: "space-between",
padding: DefaultAppStyles.GAP
}}
onPress={onSubmit}
type="selected"
>
<Heading size={AppFontSize.sm} color={colors.selected.heading}>
{strings.add()} {'"' + "#" + query + '"'}
</Heading>
<Icon
name="plus"
color={colors.selected.icon}
size={AppFontSize.lg}
/>
</Pressable>
) : null}
<Header title={strings.manageTags()} canGoBack />
<View
style={{
width: "100%",
flexGrow: 1,
height: "100%"
paddingHorizontal: DefaultAppStyles.GAP
}}
>
<FlashList
data={tags?.placeholders}
keyboardShouldPersistTaps
keyboardDismissMode="interactive"
estimatedItemSize={50}
renderItem={renderTag}
ListEmptyComponent={
<View
style={{
width: "100%",
height: 200,
justifyContent: "center",
alignItems: "center"
}}
>
<Heading size={50} color={colors.secondary.heading}>
#
</Heading>
<Paragraph
textBreakStrategy="balanced"
color={colors.secondary.paragraph}
>
{strings.emptyPlaceholders("tag")}
</Paragraph>
</View>
}
ListFooterComponent={<View style={{ height: 50 }} />}
<Input
button={{
icon: "magnify",
color: colors.primary.accent,
size: AppFontSize.lg,
onPress: () => {}
}}
testID="tag-input"
fwdRef={inputRef}
autoCapitalize="none"
onChangeText={(v) => {
setQuery(sanitizeTag(v));
checkQueryExists(sanitizeTag(v));
}}
onFocusInput={() => {
setFocus(true);
}}
onBlurInput={() => {
setFocus(false);
}}
onSubmit={() => {
onSubmit();
}}
placeholder={strings.searchForTags()}
/>
{query && !queryExists ? (
<Pressable
key={"query_item"}
style={{
flexDirection: "row",
justifyContent: "space-between",
paddingHorizontal: DefaultAppStyles.GAP,
paddingVertical: DefaultAppStyles.GAP_VERTICAL
}}
onPress={onSubmit}
type="selected"
>
<Heading size={AppFontSize.sm} color={colors.selected.heading}>
{strings.add()} {'"' + "#" + query + '"'}
</Heading>
<Icon
name="plus"
color={colors.selected.icon}
size={AppFontSize.lg}
/>
</Pressable>
) : null}
<View
style={{
width: "100%",
flexGrow: 1,
height: "100%"
}}
>
<FlashList
data={tags?.placeholders}
keyboardShouldPersistTaps
keyboardDismissMode="interactive"
estimatedItemSize={50}
renderItem={renderTag}
ListEmptyComponent={
<View
style={{
width: "100%",
height: 200,
justifyContent: "center",
alignItems: "center"
}}
>
<Heading size={50} color={colors.secondary.heading}>
#
</Heading>
<Paragraph
textBreakStrategy="balanced"
color={colors.secondary.paragraph}
>
{strings.emptyPlaceholders("tag")}
</Paragraph>
</View>
}
ListFooterComponent={<View style={{ height: 50 }} />}
/>
</View>
</View>
</View>
</SafeAreaView>
);
};
ManageTagsSheet.present = (ids?: string[]) => {
presentSheet({
component: (ref) => {
return <ManageTagsSheet actionSheetRef={ref} ids={ids} />;
}
ManageTags.present = (ids?: string[]) => {
Navigation.push("ManageTags", {
ids: ids
});
};
export default ManageTagsSheet;
export default ManageTags;
const TagItem = ({
id,

View File

@@ -248,7 +248,13 @@ const SelectableNoteItem = React.memo(
flexGrow: 1
}}
>
<Heading size={AppFontSize.sm} numberOfLines={1}>
<Heading
size={AppFontSize.sm}
numberOfLines={1}
style={{
maxWidth: "93%"
}}
>
{item?.title}
</Heading>
{item.type == "note" && item.headline ? (
@@ -256,6 +262,9 @@ const SelectableNoteItem = React.memo(
numberOfLines={1}
color={colors?.secondary.paragraph}
size={AppFontSize.sm}
style={{
maxWidth: "93%"
}}
>
{item.headline}
</Paragraph>

View File

@@ -29,6 +29,7 @@ import useGlobalSafeAreaInsets from "../../hooks/use-global-safe-area-insets";
import { useSettingStore } from "../../stores/use-setting-store";
import { NotesnookModule } from "../../utils/notesnook-module";
import { DefaultAppStyles } from "../../utils/styles";
import { SafeAreaView } from "react-native-safe-area-context";
const NoteItem = (props: {
id: string | number;
@@ -111,7 +112,7 @@ export const NotePreviewConfigure = () => {
);
return (
<View
<SafeAreaView
style={{
backgroundColor: colors.primary.background,
flex: 1
@@ -165,6 +166,6 @@ export const NotePreviewConfigure = () => {
ListFooterComponent={<View style={{ height: 200 }} />}
/>
</View>
</View>
</SafeAreaView>
);
};

View File

@@ -17,35 +17,37 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { Item, Note, VirtualizedGrouping } from "@notesnook/core";
import {
FilteredSelector,
Item,
Note,
VirtualizedGrouping
} from "@notesnook/core";
import { strings } from "@notesnook/intl";
import React, { useEffect, useRef, useState } from "react";
import { DatabaseLogger, db } from "../../common/database";
import List from "../../components/list";
import SelectionHeader from "../../components/selection-header";
import { useNavigationFocus } from "../../hooks/use-navigation-focus";
import {
ToastManager,
eSubscribeEvent,
eUnSubscribeEvent
} from "../../services/event-manager";
import { ToastManager, eSubscribeEvent } from "../../services/event-manager";
import { NavigationProps } from "../../services/navigation";
import useNavigationStore from "../../stores/use-navigation-store";
import { eOnRefreshSearch } from "../../utils/events";
import { eGroupOptionsUpdated, eOnRefreshSearch } from "../../utils/events";
import { SearchBar } from "./search-bar";
import { FilteredSelector } from "@notesnook/core";
import { strings } from "@notesnook/intl";
export const Search = ({ route, navigation }: NavigationProps<"Search">) => {
const [results, setResults] = useState<VirtualizedGrouping<Item>>();
const [loading, setLoading] = useState(false);
const [searchStatus, setSearchStatus] = useState<string>();
const currentQuery = useRef<string>();
const timer = useRef<NodeJS.Timeout>();
const isFocused = useNavigationFocus(navigation, {
useNavigationFocus(navigation, {
onFocus: (prev) => {
useNavigationStore.getState().setFocusedRouteId(route.name);
return !prev?.current;
},
onBlur: () => false
onBlur: () => {
return false;
}
});
const onSearch = React.useCallback(
@@ -60,32 +62,35 @@ export const Search = ({ route, navigation }: NavigationProps<"Search">) => {
try {
setLoading(true);
let results: VirtualizedGrouping<Item> | undefined;
const groupOptions = db.settings.getGroupOptions("search");
switch (route.params.type) {
case "note":
results = await db.lookup
.notes(query, route.params.items as FilteredSelector<Note>)
.sorted();
results = await db.lookup.notesWithHighlighting(
query,
route.params.items as FilteredSelector<Note>,
groupOptions
);
break;
case "notebook":
results = await db.lookup.notebooks(query).sorted();
results = await db.lookup.notebooks(query).sorted(groupOptions);
break;
case "tag":
results = await db.lookup.tags(query).sorted();
results = await db.lookup.tags(query).sorted(groupOptions);
break;
case "reminder":
results = await db.lookup.reminders(query).sorted();
results = await db.lookup.reminders(query).sorted(groupOptions);
break;
case "trash":
results = await db.lookup.trash(query).sorted();
results = await db.lookup.trash(query).sorted(groupOptions);
break;
case "attachment":
results = await db.lookup.attachments(query).sorted();
results = await db.lookup.attachments(query).sorted(groupOptions);
break;
default:
results = undefined;
}
if (currentQuery.current !== query) return;
if (!results) {
setSearchStatus(strings.noResultsFound(query));
setLoading(false);
@@ -97,6 +102,7 @@ export const Search = ({ route, navigation }: NavigationProps<"Search">) => {
);
if (currentQuery.current !== query) return;
await results.item(0);
if (currentQuery.current !== query) return;
setResults(results);
if (results.placeholders?.length === 0) {
setSearchStatus(strings.noResultsFound(query));
@@ -118,9 +124,18 @@ export const Search = ({ route, navigation }: NavigationProps<"Search">) => {
onSearch(currentQuery.current);
}
};
eSubscribeEvent(eOnRefreshSearch, onRefreshSearch);
const subs = [
eSubscribeEvent(eGroupOptionsUpdated, (groupType) => {
if (groupType === "search") {
onSearch(currentQuery.current);
}
}),
eSubscribeEvent(eOnRefreshSearch, onRefreshSearch)
];
return () => {
eUnSubscribeEvent(eOnRefreshSearch, onRefreshSearch);
subs.forEach((sub) => sub?.unsubscribe());
};
}, [onSearch, route.params?.type]);
@@ -137,7 +152,7 @@ export const Search = ({ route, navigation }: NavigationProps<"Search">) => {
clearTimeout(timer.current);
timer.current = setTimeout(() => {
onSearch(query);
}, 300);
}, 500);
}}
loading={loading}
/>

View File

@@ -16,35 +16,22 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import React, { RefObject, useRef, useState } from "react";
import React, { useRef, useState } from "react";
import { TextInput, View } from "react-native";
import { ActionSheetRef } from "react-native-actions-sheet";
import { db } from "../../../common/database";
import {
eSendEvent,
presentSheet,
PresentSheetOptions,
ToastManager
} from "../../../services/event-manager";
import DialogHeader from "../../dialog/dialog-header";
import { Button } from "../../ui/button";
import Input from "../../ui/input";
import { eSendEvent, ToastManager } from "../../../services/event-manager";
import { eUserLoggedIn } from "../../../utils/events";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../../utils/styles";
type ChangeEmailProps = {
actionSheetRef: RefObject<ActionSheetRef>;
close?: () => void;
update?: (options: PresentSheetOptions) => void;
};
import Input from "../../../components/ui/input";
import { Button } from "../../../components/ui/button";
enum EmailChangeSteps {
verify,
changeEmail
}
export const ChangeEmail = ({ close }: ChangeEmailProps) => {
export const ChangeEmail = () => {
const [step, setStep] = useState(EmailChangeSteps.verify);
const emailChangeData = useRef<{
email?: string;
@@ -103,10 +90,6 @@ export const ChangeEmail = ({ close }: ChangeEmailProps) => {
return (
<View style={{ paddingHorizontal: DefaultAppStyles.GAP }}>
<DialogHeader
title={strings.changeEmail()}
paragraph={strings.changeEmailDesc()}
/>
<View
style={{
marginTop: DefaultAppStyles.GAP_VERTICAL
@@ -156,23 +139,12 @@ export const ChangeEmail = ({ close }: ChangeEmailProps) => {
: strings.changeEmail()
}
type="accent"
width={250}
style={{
width: "100%"
}}
loading={loading}
onPress={onSubmit}
style={{
borderRadius: 100,
height: 45,
marginTop: 2
}}
/>
</View>
);
};
ChangeEmail.present = () => {
presentSheet({
component: (ref, close, update) => (
<ChangeEmail actionSheetRef={ref} close={close} update={update} />
)
});
};

View File

@@ -43,6 +43,8 @@ import ThemeSelector from "./theme-selector";
import { TitleFormat } from "./title-format";
import { View } from "react-native";
import { DefaultAppStyles } from "../../utils/styles";
import { ChangePassword } from "../../components/auth/change-password";
import { ChangeEmail } from "./change-email";
export const components: { [name: string]: ReactElement } = {
colorpicker: <AccentColorPicker />,
@@ -69,5 +71,7 @@ export const components: { [name: string]: ReactElement } = {
<AttachmentGroupProgress groupId="offline-mode" />
</View>
),
"sidebar-tab-selector": <SidebarTabPicker />
"sidebar-tab-selector": <SidebarTabPicker />,
"change-password": <ChangePassword />,
"change-email": <ChangeEmail />
};

View File

@@ -32,11 +32,9 @@ import { enabled } from "react-native-privacy-snapshot";
import ScreenGuardModule from "react-native-screenguard";
import { db } from "../../common/database";
import filesystem from "../../common/filesystem";
import { ChangePassword } from "../../components/auth/change-password";
import { presentDialog } from "../../components/dialog/functions";
import { AppLockPassword } from "../../components/dialogs/applock-password";
import { endProgress, startProgress } from "../../components/dialogs/progress";
import { ChangeEmail } from "../../components/sheets/change-email";
import ExportNotesSheet from "../../components/sheets/export-notes";
import { Issue } from "../../components/sheets/github/issue";
import { Progress } from "../../components/sheets/progress";
@@ -82,7 +80,8 @@ export const settingsGroups: SettingSection[] = [
useHook: () => useUserStore((state) => state.user),
hidden: (current) => !current,
name: (current) => {
const user = current as User;
const user = (current as User) || useUserStore.getState().user;
if (!user) return strings.subscribeToPro();
const isBasic = user.subscription?.type === SUBSCRIPTION_STATUS.BASIC;
const isTrial = user.subscription?.type === SUBSCRIPTION_STATUS.TRIAL;
return isBasic || !user.subscription?.type
@@ -96,6 +95,7 @@ export const settingsGroups: SettingSection[] = [
icon: "crown",
description: (current) => {
const user = current as User;
if (!user) return strings.neverHesitate();
const subscriptionDaysLeft =
user &&
getTimeLeft(
@@ -241,17 +241,15 @@ export const settingsGroups: SettingSection[] = [
{
id: "change-password",
name: strings.changePassword(),
modifer: async () => {
ChangePassword.present();
},
description: strings.changePasswordDesc()
type: "screen",
description: strings.changePasswordDesc(),
component: "change-password"
},
{
id: "change-email",
name: strings.changeEmail(),
modifer: async () => {
ChangeEmail.present();
},
type: "screen",
component: "change-email",
description: strings.changeEmailDesc()
},
{
@@ -670,6 +668,13 @@ export const settingsGroups: SettingSection[] = [
});
},
disabled: () => !db.settings.getDefaultNotebook()
},
{
id: "disable-update-check",
type: "switch",
name: strings.autoUpdateCheck(),
description: strings.autoUpdateCheckDesc(),
property: "checkForUpdates"
}
]
},

View File

@@ -37,6 +37,7 @@ import {
rootNavigatorRef
} from "../utils/global-refs";
import { eSendEvent } from "./event-manager";
import { useArchivedStore } from "../stores/use-archived-store";
/**
* Routes that should be updated on focus
@@ -66,7 +67,9 @@ const routeNames = {
Reminders: "Reminders",
MoveNotebook: "MoveNotebook",
LinkNotebooks: "LinkNotebooks",
MoveNotes: "MoveNotes"
MoveNotes: "MoveNotes",
Archive: "Archive",
ManageTags: "ManageTags"
};
export type NavigationProps<T extends RouteName> = NativeStackScreenProps<
@@ -92,7 +95,8 @@ const routeUpdateFunctions: {
TopicNotes: (params) => eSendEvent("TopicNotes", params),
Monographs: (params) => eSendEvent("Monographs", params),
Reminders: () => useReminderStore.getState().refresh(),
Search: () => eSendEvent(eOnRefreshSearch)
Search: () => eSendEvent(eOnRefreshSearch),
Archive: () => useArchivedStore.getState().refresh()
};
function clearRouteFromQueue(routeName: RouteName) {

View File

@@ -0,0 +1,30 @@
/*
This file is part of the Notesnook project (https://notesnook.com/)
Copyright (C) 2023 Streetwriters (Private) Limited
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { db } from "../common/database";
import createDBCollectionStore from "./create-db-collection-store";
const { useStore: useArchivedStore, useCollection: useArchived } =
createDBCollectionStore({
getCollection: () =>
db.notes.archived.grouped(db.settings.getGroupOptions("archive")),
eagerlyFetchFirstBatch: true
});
export { useArchivedStore, useArchived };

View File

@@ -74,6 +74,7 @@ export interface RouteParams extends ParamListBase {
TaggedNotes: NotesScreenParams;
ColoredNotes: NotesScreenParams;
TopicNotes: NotesScreenParams;
Archive: GenericRouteParam;
Monographs: NotesScreenParams;
Reminders: GenericRouteParam;
SettingsGroup: GenericRouteParam;
@@ -90,6 +91,9 @@ export interface RouteParams extends ParamListBase {
MoveNotes: {
notebook: Notebook;
};
ManageTags: {
ids?: string[];
};
}
export type RouteName = keyof RouteParams;

View File

@@ -98,6 +98,7 @@ export type Settings = {
lastFullBackupDate?: number;
serverUrls?: Record<HostId, string>;
defaultSidebarTab: number;
checkForUpdates?: boolean;
};
type DimensionsType = {
@@ -196,7 +197,8 @@ export const defaultSettings: SettingStore["settings"] = {
settingsVersion: 0,
backupType: "partial",
fullBackupReminder: "never",
lastFullBackupDate: 0
lastFullBackupDate: 0,
checkForUpdates: true
};
export const useSettingStore = create<SettingStore>((set, get) => ({

View File

@@ -45,7 +45,8 @@ export const SORT = {
dateEdited: "Date edited",
dateCreated: "Date created",
title: "Title",
dueDate: "Due date"
dueDate: "Due date",
relevance: "Relevance"
};
export const itemSkus = [

View File

@@ -77,12 +77,13 @@ export const MenuItemsList: SideMenuItem[] = [
},
type: "side-menu-item"
},
// {
// dataType: "note",
// id: "Archive",
// title: "Archive",
// icon: "archive"
// },
{
dataType: "note",
id: "Archive",
title: "Archive",
icon: "archive",
type: "side-menu-item"
},
{
dataType: "note",
id: "Trash",

View File

@@ -1,7 +1,10 @@
source 'https://rubygems.org'
# You may use http://rbenv.org/ or https://rvm.io/ to install and use this version
ruby ">= 2.6.10"
# Cocoapods 1.15 introduced a bug which break the build. We will remove the upper
# bound in the template on Cocoapods with next React Native release.
gem 'cocoapods', '>= 1.13', '< 1.15'
gem 'activesupport', '>= 6.1.7.5', '< 7.1.0'
# Exclude problematic versions of cocoapods and activesupport that causes build failures.
gem 'cocoapods', '>= 1.13', '!= 1.15.0', '!= 1.15.1'
gem 'activesupport', '>= 6.1.7.5', '!= 7.1.0'
gem 'xcodeproj', '< 1.26.0'
gem 'concurrent-ruby', '< 1.3.4'

View File

@@ -1,30 +1,41 @@
GEM
remote: https://rubygems.org/
specs:
CFPropertyList (3.0.5)
CFPropertyList (3.0.7)
base64
nkf
rexml
activesupport (6.1.5)
concurrent-ruby (~> 1.0, >= 1.0.2)
activesupport (7.2.2.1)
base64
benchmark (>= 0.3)
bigdecimal
concurrent-ruby (~> 1.0, >= 1.3.1)
connection_pool (>= 2.2.5)
drb
i18n (>= 1.6, < 2)
logger (>= 1.4.2)
minitest (>= 5.1)
tzinfo (~> 2.0)
zeitwerk (~> 2.3)
addressable (2.8.0)
public_suffix (>= 2.0.2, < 5.0)
securerandom (>= 0.3)
tzinfo (~> 2.0, >= 2.0.5)
addressable (2.8.7)
public_suffix (>= 2.0.2, < 7.0)
algoliasearch (1.27.5)
httpclient (~> 2.8, >= 2.8.3)
json (>= 1.5.1)
atomos (0.1.3)
base64 (0.3.0)
benchmark (0.4.1)
bigdecimal (3.2.1)
claide (1.1.0)
cocoapods (1.11.3)
cocoapods (1.15.2)
addressable (~> 2.8)
claide (>= 1.0.2, < 2.0)
cocoapods-core (= 1.11.3)
cocoapods-core (= 1.15.2)
cocoapods-deintegrate (>= 1.0.3, < 2.0)
cocoapods-downloader (>= 1.4.0, < 2.0)
cocoapods-downloader (>= 2.1, < 3.0)
cocoapods-plugins (>= 1.0.0, < 2.0)
cocoapods-search (>= 1.0.0, < 2.0)
cocoapods-trunk (>= 1.4.0, < 2.0)
cocoapods-trunk (>= 1.6.0, < 2.0)
cocoapods-try (>= 1.1.0, < 2.0)
colored2 (~> 3.1)
escape (~> 0.0.4)
@@ -32,10 +43,10 @@ GEM
gh_inspector (~> 1.0)
molinillo (~> 0.8.0)
nap (~> 1.0)
ruby-macho (>= 1.0, < 3.0)
xcodeproj (>= 1.21.0, < 2.0)
cocoapods-core (1.11.3)
activesupport (>= 5.0, < 7)
ruby-macho (>= 2.3.0, < 3.0)
xcodeproj (>= 1.23.0, < 2.0)
cocoapods-core (1.15.2)
activesupport (>= 5.0, < 8)
addressable (~> 2.8)
algoliasearch (~> 1.0)
concurrent-ruby (~> 1.1)
@@ -45,7 +56,7 @@ GEM
public_suffix (~> 4.0)
typhoeus (~> 1.0)
cocoapods-deintegrate (1.0.5)
cocoapods-downloader (1.6.3)
cocoapods-downloader (2.1)
cocoapods-plugins (1.0.0)
nap
cocoapods-search (1.0.1)
@@ -54,47 +65,56 @@ GEM
netrc (~> 0.11)
cocoapods-try (1.2.0)
colored2 (3.1.2)
concurrent-ruby (1.1.10)
concurrent-ruby (1.3.3)
connection_pool (2.5.3)
drb (2.2.3)
escape (0.0.4)
ethon (0.15.0)
ethon (0.16.0)
ffi (>= 1.15.0)
ffi (1.15.5)
ffi (1.17.2)
fourflusher (2.3.1)
fuzzy_match (2.0.4)
gh_inspector (1.1.3)
httpclient (2.8.3)
i18n (1.10.0)
httpclient (2.9.0)
mutex_m
i18n (1.14.7)
concurrent-ruby (~> 1.0)
json (2.6.1)
minitest (5.15.0)
json (2.12.2)
logger (1.7.0)
minitest (5.25.5)
molinillo (0.8.0)
mutex_m (0.3.0)
nanaimo (0.3.0)
nap (1.1.0)
netrc (0.11.0)
nkf (0.2.0)
public_suffix (4.0.7)
rexml (3.2.5)
rexml (3.4.1)
ruby-macho (2.5.1)
typhoeus (1.4.0)
securerandom (0.4.1)
typhoeus (1.4.1)
ethon (>= 0.9.0)
tzinfo (2.0.4)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
xcodeproj (1.21.0)
xcodeproj (1.25.1)
CFPropertyList (>= 2.3.3, < 4.0)
atomos (~> 0.1.3)
claide (>= 1.0.2, < 2.0)
colored2 (~> 3.1)
nanaimo (~> 0.3.0)
rexml (~> 3.2.4)
zeitwerk (2.5.4)
rexml (>= 3.3.6, < 4.0)
PLATFORMS
ruby
DEPENDENCIES
cocoapods (~> 1.11, >= 1.11.2)
activesupport (>= 6.1.7.5, != 7.1.0)
cocoapods (>= 1.13, != 1.15.1, != 1.15.0)
concurrent-ruby (< 1.3.4)
xcodeproj (< 1.26.0)
RUBY VERSION
ruby 2.7.4p191
ruby 3.4.1p0
BUNDLED WITH
2.2.27
2.6.2

View File

@@ -48,6 +48,9 @@ react {
//
// The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map"
hermesFlags = ["-O", "-output-source-map"]
/* Autolinking */
autolinkLibrariesWithApp()
}
/**
@@ -121,7 +124,7 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
multiDexEnabled true
versionCode 3049
versionCode 3058
versionName getNpmVersion()
testBuildType System.getProperty('testBuildType', 'debug')
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
@@ -258,7 +261,3 @@ copyFontFiles.dependsOn(copyEditorBundle);
copyPlainEditorBundle.dependsOn(copyFontFiles);
preBuild.dependsOn(copyPlainEditorBundle)
apply from: file("../../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)

View File

@@ -15,7 +15,6 @@
<uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" tools:node="remove"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" tools:node="remove"/>
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" tools:node="remove" />
@@ -59,18 +58,8 @@
android:requestLegacyExternalStorage="true"
android:theme="@style/BootTheme"
android:largeHeap="true"
android:supportsRtl="false"
android:networkSecurityConfig="@xml/network_security_config"
tools:replace="android:supportsRtl">
<receiver android:exported="false" android:label="@string/reminders_title" android:name=".ReminderWidgetProvider">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/widget_reminders_info" />
</receiver>
android:supportsRtl="true"
android:networkSecurityConfig="@xml/network_security_config">
<receiver android:exported="false" android:label="@string/quick_note" android:name=".NoteWidget">
<intent-filter>
@@ -92,6 +81,15 @@
android:resource="@xml/note_widget_info" />
</receiver>
<receiver android:exported="false" android:label="@string/reminders_title" android:name=".ReminderWidgetProvider">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/widget_reminders_info" />
</receiver>
<activity android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode"
android:label="NotePreviewConfigure"
android:launchMode="singleTask"

View File

@@ -14,19 +14,21 @@ public class BootRecieverService extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (!isAppOnForeground((context))) {
/**
We will start our service and send extra info about
network connections
**/
Intent serviceIntent = new Intent(context, BootTaskService.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(serviceIntent);
} else {
context.startService(serviceIntent);
}
HeadlessJsTaskService.acquireWakeLockNow(context);
}
try {
if (!isAppOnForeground((context))) {
/**
We will start our service and send extra info about
network connections
**/
Intent serviceIntent = new Intent(context, BootTaskService.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(serviceIntent);
} else {
context.startService(serviceIntent);
}
HeadlessJsTaskService.acquireWakeLockNow(context);
}
} catch (Exception ignored) {}
}
private boolean isAppOnForeground(Context context) {

View File

@@ -3,8 +3,16 @@ package com.streetwriters.notesnook;
import com.facebook.react.ReactActivity;
import android.content.Intent;
import android.content.res.Configuration;
import androidx.core.graphics.Insets;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.webkit.WebView;
import androidx.core.view.OnApplyWindowInsetsListener;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import com.facebook.react.ReactActivityDelegate;
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
import com.facebook.react.defaults.DefaultReactActivityDelegate;
@@ -22,6 +30,20 @@ public class MainActivity extends ReactActivity {
try {
startService(new Intent(getBaseContext(), OnClearFromRecentService.class));
} catch (Exception ignored) {}
if (Build.VERSION.SDK_INT >= 35) {
final View rootView = findViewById(android.R.id.content);
ViewCompat.setOnApplyWindowInsetsListener(rootView, (v, insets) -> {
Insets innerPadding = insets.getInsets(WindowInsetsCompat.Type.ime());
rootView.setPadding(
innerPadding.left,
innerPadding.top,
innerPadding.right,
innerPadding.bottom
);
return insets;
});
}
}
/**

View File

@@ -10,6 +10,7 @@ import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load
import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
import com.facebook.react.defaults.DefaultReactNativeHost
import com.facebook.soloader.SoLoader
import com.facebook.react.soloader.OpenSourceMergedSoMapping
class MainApplication : Application(), ReactApplication {
@@ -36,7 +37,7 @@ class MainApplication : Application(), ReactApplication {
override fun onCreate() {
super.onCreate()
SoLoader.init(this, false)
SoLoader.init(this, OpenSourceMergedSoMapping)
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
// If you opted-in for the New Architecture, we load the native entry point for this app.
load()

View File

@@ -48,7 +48,8 @@ public class NotePreviewWidget extends AppWidgetProvider {
private static Bundle getActivityOptionsBundle() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
ActivityOptions activityOptions = ActivityOptions.makeBasic();
activityOptions.setPendingIntentBackgroundActivityStartMode(ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED);
activityOptions.setPendingIntentCreatorBackgroundActivityStartMode(
ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED);
return activityOptions.toBundle();
} else
return null;

View File

@@ -31,7 +31,8 @@ public class NoteWidget extends AppWidgetProvider {
private static Bundle getActivityOptionsBundle() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
ActivityOptions activityOptions = ActivityOptions.makeBasic();
activityOptions.setPendingIntentBackgroundActivityStartMode(ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED);
activityOptions.setPendingIntentCreatorBackgroundActivityStartMode(
ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED);
return activityOptions.toBundle();
} else
return null;

View File

@@ -26,7 +26,8 @@ public class ReminderWidgetProvider extends AppWidgetProvider {
private static Bundle getActivityOptionsBundle() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
ActivityOptions activityOptions = ActivityOptions.makeBasic();
activityOptions.setPendingIntentBackgroundActivityStartMode(ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED);
activityOptions.setPendingIntentCreatorBackgroundActivityStartMode(
ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED);
return activityOptions.toBundle();
} else
return null;

View File

@@ -3,16 +3,16 @@ import org.apache.tools.ant.taskdefs.condition.Os
buildscript {
ext {
buildToolsVersion = "34.0.0"
minSdkVersion = 23
compileSdkVersion = 34
buildToolsVersion = "35.0.0"
minSdkVersion = 24
compileSdkVersion = 35
targetSdkVersion = 34
kotlinVersion = '1.9.22'
kotlinVersion = '2.0.21'
androidXAnnotation = "1.1.0"
androidXCoreVersion = "1.7.0"
androidXCore = "1.7.0"
androidXBrowser = "1.0.0"
ndkVersion = "23.2.8568313"
ndkVersion = "27.1.12297006"
}
repositories {

View File

@@ -23,7 +23,7 @@ org.gradle.jvmargs=-Xmx4096m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
# Automatically convert third-party libraries to use AndroidX
android.enableJetifier=true
# android.enableJetifier=true
# Use this property to specify which architecture you want to build.
# You can also override it from the CLI using
@@ -45,6 +45,6 @@ hermesEnabled=true
# v8.android.tools.dir=/home/ammarahm-ed/Repos/notesnook-mobile/node_modules/v8-android-jit-nointl/dist/tools/android
# fdroid
fdroidBuild=false
fdroidBuild=true
# -DSQLITE_USER_AUTHENTICATION=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS=1 -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_OMIT_DEPRECATED=1 -DSQLITE_OMIT_PROGRESS_CALLBACK=1
quickSqliteFlags=-DSQLITE3MC_OMIT_AES_HARDWARE_SUPPORT -DHAVE_CIPHER_AES_128_CBC=0 -DHAVE_CIPHER_AES_256_CBC=0 -DHAVE_CIPHER_SQLCIPHER=0 -DHAVE_CIPHER_RC4=0 -DHAVE_CIPHER_CHACHA20=1 -DSQLITE_ENABLE_FTS5 -DSQLITE_OMIT_PROGRESS_CALLBACK=1 -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_OMIT_DEPRECATED=1 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS=1 -DSQLITE_DQS=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_USE_ALLOCA=1
quickSqliteFlags=-DSQLITE3MC_OMIT_AES_HARDWARE_SUPPORT -DHAVE_CIPHER_AES_128_CBC=0 -DHAVE_CIPHER_AES_256_CBC=0 -DHAVE_CIPHER_SQLCIPHER=0 -DHAVE_CIPHER_RC4=0 -DHAVE_CIPHER_CHACHA20=1 -DSQLITE_ENABLE_FTS5 -DSQLITE_OMIT_PROGRESS_CALLBACK=1 -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_OMIT_DEPRECATED=1 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS=1 -DSQLITE_DQS=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_USE_ALLOCA=1 -DSQLITE_ENABLE_REGEXP=1

View File

@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME

View File

@@ -15,6 +15,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#
##############################################################################
#
@@ -55,7 +57,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
@@ -84,7 +86,8 @@ done
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum

View File

@@ -13,6 +13,8 @@
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@rem SPDX-License-Identifier: Apache-2.0
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################

View File

@@ -1,8 +1,5 @@
- v3.1.0 brings new features and improvements to enhance your Notesnook experience.
- Notebooks and Tags are not located in the Sidebar
- Tree view for notebooks
- Improved list view UI for better user experience
- Improved notebook related actions by integrating tree view in most places
- You can set any notebook, tag or colors as home screen
- New and improved search with highlighting
- Fixed app crashing on android 16 devices
- Many bug fixes and improvements
Thank you for using Notesnook!

View File

@@ -1,4 +1,9 @@
pluginManagement { includeBuild("../../node_modules/@react-native/gradle-plugin") }
plugins { id("com.facebook.react.settings") }
extensions.configure(com.facebook.react.ReactSettingsExtension){ ex -> ex.autolinkLibrariesFromCommand() }
rootProject.name = 'Notesnook'
apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
include ':app'
includeBuild('../../node_modules/@react-native/gradle-plugin')
include ":lazysodium"
project(':lazysodium').projectDir = new File(rootProject.projectDir, '../../node_modules/@ammarahmed/react-native-sodium/android/lazysodium')

View File

@@ -6,7 +6,7 @@ module.exports = function (api, opts) {
if (!PROCESS_ENV) PROCESS_ENV = 'production';
const env = {
presets: ['module:metro-react-native-babel-preset'],
presets: ['module:@react-native/babel-preset'],
plugins: [
'@babel/plugin-transform-named-capturing-groups-regex',
'react-native-reanimated/plugin',

View File

@@ -20,6 +20,10 @@
6517B7C12B6838EB0079FF37 /* OpenSans-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 6517B7BE2B6838EB0079FF37 /* OpenSans-Regular.ttf */; };
6517B7C22B6838EB0079FF37 /* OpenSans-SemiBold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 6517B7BF2B6838EB0079FF37 /* OpenSans-SemiBold.ttf */; };
6517B7C32B6838EB0079FF37 /* OpenSans-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 6517B7C02B6838EB0079FF37 /* OpenSans-Bold.ttf */; };
651F09DA2E0D262B00495DED /* fts5-html.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 651F09D92E0D262B00495DED /* fts5-html.xcframework */; };
651F09DB2E0D262B00495DED /* fts5-html.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 651F09D92E0D262B00495DED /* fts5-html.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
651F09DD2E0D263300495DED /* fts5-html.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 651F09D92E0D262B00495DED /* fts5-html.xcframework */; };
651F09DE2E0D263300495DED /* fts5-html.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 651F09D92E0D262B00495DED /* fts5-html.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
6529A13E279BC4C70048D4A8 /* BootSplash.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6529A13D279BC4C70048D4A8 /* BootSplash.storyboard */; };
656835812BB29A9800144BAB /* OpenSans-Italic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 656835802BB29A8300144BAB /* OpenSans-Italic.ttf */; };
6569927F2C5754F10041CD41 /* OpenSans-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 6517B7C02B6838EB0079FF37 /* OpenSans-Bold.ttf */; };
@@ -79,6 +83,28 @@
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
651F09DC2E0D262C00495DED /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
651F09DB2E0D262B00495DED /* fts5-html.xcframework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
651F09DF2E0D263300495DED /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
651F09DE2E0D263300495DED /* fts5-html.xcframework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
65A7F34B255687E600699170 /* Embed App Extensions */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
@@ -120,11 +146,11 @@
6517B7BE2B6838EB0079FF37 /* OpenSans-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "OpenSans-Regular.ttf"; path = "../../../../packages/editor-mobile/public/fonts/OpenSans-Regular.ttf"; sourceTree = "<group>"; };
6517B7BF2B6838EB0079FF37 /* OpenSans-SemiBold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "OpenSans-SemiBold.ttf"; path = "../../../../packages/editor-mobile/public/fonts/OpenSans-SemiBold.ttf"; sourceTree = "<group>"; };
6517B7C02B6838EB0079FF37 /* OpenSans-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "OpenSans-Bold.ttf"; path = "../../../../packages/editor-mobile/public/fonts/OpenSans-Bold.ttf"; sourceTree = "<group>"; };
651F09D92E0D262B00495DED /* fts5-html.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = "fts5-html.xcframework"; sourceTree = "<group>"; };
6529A13D279BC4C70048D4A8 /* BootSplash.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = BootSplash.storyboard; path = Notesnook/BootSplash.storyboard; sourceTree = "<group>"; };
6529D2B0257B4A2900B49BC3 /* NotesnookDebug.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = NotesnookDebug.entitlements; path = Notesnook/NotesnookDebug.entitlements; sourceTree = "<group>"; };
656835802BB29A8300144BAB /* OpenSans-Italic.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "OpenSans-Italic.ttf"; path = "../../../../packages/editor-mobile/public/fonts/OpenSans-Italic.ttf"; sourceTree = "<group>"; };
6593E4A2281C345400492C50 /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = Notesnook/AppDelegate.mm; sourceTree = "<group>"; };
6594DDF22CD8BFE8007F5EC2 /* BetterTrigram.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = BetterTrigram.xcframework; sourceTree = "<group>"; };
659BE46625E11A5100E05671 /* notesnook-text.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "notesnook-text.png"; path = "Notesnook/Images.xcassets/notesnook-text.png"; sourceTree = "<group>"; };
65A7F34F255689AD00699170 /* Notesnook.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = Notesnook.entitlements; path = Notesnook/Notesnook.entitlements; sourceTree = "<group>"; };
65AA857725E6DDEC00772A01 /* NotesWidgetExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = NotesWidgetExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -177,6 +203,7 @@
files = (
2B3F87EC6B2264CD8ABA5DA8 /* libPods-Notesnook.a in Frameworks */,
6515C42F2580AA3000E83E39 /* StoreKit.framework in Frameworks */,
651F09DA2E0D262B00495DED /* fts5-html.xcframework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -209,6 +236,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
651F09DD2E0D263300495DED /* fts5-html.xcframework in Frameworks */,
C619D096A9DE2070DBEAC70F /* libPods-Make Note.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -256,7 +284,7 @@
2D16E6871FA4F8E400B85C8A /* Frameworks */ = {
isa = PBXGroup;
children = (
6594DDF22CD8BFE8007F5EC2 /* BetterTrigram.xcframework */,
651F09D92E0D262B00495DED /* fts5-html.xcframework */,
6515C42E2580AA2F00E83E39 /* StoreKit.framework */,
ED297162215061F000B7C4FE /* JavaScriptCore.framework */,
ED2971642150620600B7C4FE /* JavaScriptCore.framework */,
@@ -400,6 +428,7 @@
240525450DF9ABA0F332B52E /* [CP] Copy Pods Resources */,
65A7F34B255687E600699170 /* Embed App Extensions */,
48C834D962D612F18A0388B3 /* [CP] Embed Pods Frameworks */,
651F09DC2E0D262C00495DED /* Embed Frameworks */,
);
buildRules = (
);
@@ -478,6 +507,7 @@
65B5013E25A672B200E2D264 /* Resources */,
658D06A625A7446E008C70C0 /* Run Script */,
E81EC4451F76606456BCA61F /* [CP] Copy Pods Resources */,
651F09DF2E0D263300495DED /* Embed Frameworks */,
);
buildRules = (
);
@@ -653,15 +683,25 @@
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Notesnook/Pods-Notesnook-resources.sh",
"${PODS_CONFIGURATION_BUILD_DIR}/RCT-Folly/RCT-Folly_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/RNImageCropPicker/QBImagePicker.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/RCTI18nStrings.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/RNSVG/RNSVGFilters.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/React-Core_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/React-cxxreact/React-cxxreact_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/TOCropViewController/TOCropViewControllerBundle.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/boost/boost_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/glog/glog_privacy.bundle",
);
name = "[CP] Copy Pods Resources";
outputPaths = (
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RCT-Folly_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/QBImagePicker.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RCTI18nStrings.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RNSVGFilters.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/React-Core_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/React-cxxreact_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/TOCropViewControllerBundle.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/boost_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/glog_privacy.bundle",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
@@ -810,15 +850,25 @@
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Notesnook-NotesnookTests/Pods-Notesnook-NotesnookTests-resources.sh",
"${PODS_CONFIGURATION_BUILD_DIR}/RCT-Folly/RCT-Folly_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/RNImageCropPicker/QBImagePicker.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/RCTI18nStrings.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/RNSVG/RNSVGFilters.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/React-Core_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/React-cxxreact/React-cxxreact_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/TOCropViewController/TOCropViewControllerBundle.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/boost/boost_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/glog/glog_privacy.bundle",
);
name = "[CP] Copy Pods Resources";
outputPaths = (
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RCT-Folly_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/QBImagePicker.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RCTI18nStrings.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RNSVGFilters.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/React-Core_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/React-cxxreact_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/TOCropViewControllerBundle.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/boost_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/glog_privacy.bundle",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
@@ -854,11 +904,19 @@
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Make Note/Pods-Make Note-resources.sh",
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/RCTI18nStrings.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/RCT-Folly/RCT-Folly_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/React-Core_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/React-cxxreact/React-cxxreact_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/boost/boost_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/glog/glog_privacy.bundle",
);
name = "[CP] Copy Pods Resources";
outputPaths = (
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RCTI18nStrings.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RCT-Folly_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/React-Core_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/React-cxxreact_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/boost_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/glog_privacy.bundle",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
@@ -1063,7 +1121,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2132;
CURRENT_PROJECT_VERSION = 2136;
DEVELOPMENT_TEAM = 53CWBG3QUC;
ENABLE_BITCODE = NO;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
@@ -1137,7 +1195,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 3.1.0;
MARKETING_VERSION = 3.2.2;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
@@ -1168,7 +1226,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 2132;
CURRENT_PROJECT_VERSION = 2136;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 53CWBG3QUC;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
@@ -1242,7 +1300,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 3.1.0;
MARKETING_VERSION = 3.2.2;
ONLY_ACTIVE_ARCH = NO;
OTHER_LDFLAGS = (
"$(inherited)",
@@ -1401,7 +1459,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2132;
CURRENT_PROJECT_VERSION = 2136;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = 53CWBG3QUC;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
@@ -1413,7 +1471,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 3.1.0;
MARKETING_VERSION = 3.2.2;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.notewidget;
@@ -1444,7 +1502,7 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 2132;
CURRENT_PROJECT_VERSION = 2136;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 53CWBG3QUC;
@@ -1457,7 +1515,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 3.1.0;
MARKETING_VERSION = 3.2.2;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.notewidget;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -1487,7 +1545,7 @@
CODE_SIGN_ENTITLEMENTS = "Make Note/Make Note.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2132;
CURRENT_PROJECT_VERSION = 2136;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = 53CWBG3QUC;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
@@ -1561,7 +1619,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 3.1.0;
MARKETING_VERSION = 3.2.2;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.share;
@@ -1592,7 +1650,7 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 2132;
CURRENT_PROJECT_VERSION = 2136;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 53CWBG3QUC;
@@ -1667,7 +1725,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 3.1.0;
MARKETING_VERSION = 3.2.2;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.share;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -1744,12 +1802,10 @@
ONLY_ACTIVE_ARCH = YES;
OTHER_CFLAGS = "$(inherited)";
OTHER_CPLUSPLUSFLAGS = "$(inherited)";
OTHER_LDFLAGS = (
"$(inherited)",
" ",
);
OTHER_LDFLAGS = "$(inherited) ";
REACT_NATIVE_PATH = "${PODS_ROOT}/../../../node_modules/react-native";
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG";
USE_HERMES = true;
};
name = Debug;
@@ -1811,10 +1867,7 @@
ONLY_ACTIVE_ARCH = NO;
OTHER_CFLAGS = "$(inherited)";
OTHER_CPLUSPLUSFLAGS = "$(inherited)";
OTHER_LDFLAGS = (
"$(inherited)",
" ",
);
OTHER_LDFLAGS = "$(inherited) ";
REACT_NATIVE_PATH = "${PODS_ROOT}/../../../node_modules/react-native";
SDKROOT = iphoneos;
USE_HERMES = true;

View File

@@ -4,12 +4,14 @@
#import <React/RCTLinkingManager.h>
#import "RNShortcuts.h"
#import "RNBootSplash.h"
#import <ReactAppDependencyProvider/RCTAppDependencyProvider.h>
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.dependencyProvider = [RCTAppDependencyProvider new];
self.moduleName = @"Notesnook";
// You can add your custom initial props in the dictionary below.
// They will be passed down to the ViewController used by React Native.

View File

@@ -114,7 +114,7 @@ post_install do |installer|
installer.pods_project.targets.each do |target|
if target.name == "react-native-quick-sqlite" then
target.build_configurations.each do |config|
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] = 'SQLITE_CORE=1 SQLITE_ENABLE_FTS5=1 SQLITE3MC_OMIT_AES_HARDWARE_SUPPORT=1 HAVE_CIPHER_AES_128_CBC=0 HAVE_CIPHER_AES_256_CBC=0 HAVE_CIPHER_SQLCIPHER=0 HAVE_CIPHER_RC4=0 HAVE_CIPHER_CHACHA20=1 SQLITE_OMIT_PROGRESS_CALLBACK=1 SQLITE_MAX_EXPR_DEPTH=0 SQLITE_OMIT_DEPRECATED=1 SQLITE_LIKE_DOESNT_MATCH_BLOBS=1 SQLITE_DQS=0 SQLITE_DEFAULT_MEMSTATUS=0 SQLITE_USE_ALLOCA=1'
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] = 'SQLITE_CORE=1 SQLITE_ENABLE_FTS5=1 SQLITE3MC_OMIT_AES_HARDWARE_SUPPORT=1 HAVE_CIPHER_AES_128_CBC=0 HAVE_CIPHER_AES_256_CBC=0 HAVE_CIPHER_SQLCIPHER=0 HAVE_CIPHER_RC4=0 HAVE_CIPHER_CHACHA20=1 SQLITE_OMIT_PROGRESS_CALLBACK=1 SQLITE_MAX_EXPR_DEPTH=0 SQLITE_OMIT_DEPRECATED=1 SQLITE_LIKE_DOESNT_MATCH_BLOBS=1 SQLITE_DQS=0 SQLITE_DEFAULT_MEMSTATUS=0 SQLITE_USE_ALLOCA=1 SQLITE_ENABLE_REGEXP=1'
end
end
end

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>AvailableLibraries</key>
<array>
<dict>
<key>BinaryPath</key>
<string>fts5-html.dylib</string>
<key>LibraryIdentifier</key>
<string>ios-arm64</string>
<key>LibraryPath</key>
<string>fts5-html.dylib</string>
<key>SupportedArchitectures</key>
<array>
<string>arm64</string>
</array>
<key>SupportedPlatform</key>
<string>ios</string>
</dict>
<dict>
<key>BinaryPath</key>
<string>fts5-html.dylib</string>
<key>LibraryIdentifier</key>
<string>ios-arm64_x86_64-simulator</string>
<key>LibraryPath</key>
<string>fts5-html.dylib</string>
<key>SupportedArchitectures</key>
<array>
<string>arm64</string>
<string>x86_64</string>
</array>
<key>SupportedPlatform</key>
<string>ios</string>
<key>SupportedPlatformVariant</key>
<string>simulator</string>
</dict>
</array>
<key>CFBundlePackageType</key>
<string>XFWK</string>
<key>XCFrameworkFormatVersion</key>
<string>1.0</string>
</dict>
</plist>

View File

@@ -5,13 +5,13 @@
"main": "index.js",
"license": "GPL-3.0-or-later",
"overrides": {
"react-native": "0.74.5",
"react-native": "0.77.2",
"react": "18.2.0"
},
"dependencies": {
"@ammarahmed/notifee-react-native": "7.4.7",
"@callstack/repack": "~5.0.0",
"@bam.tech/react-native-image-resizer": "3.0.5",
"dependencies": {
"@ammarahmed/notifee-react-native": "7.4.9",
"@callstack/repack": "~5.1.2",
"@bam.tech/react-native-image-resizer": "3.0.11",
"@react-native-clipboard/clipboard": "^1.9.0",
"@react-native-community/checkbox": "^0.5.8",
"@react-native-community/netinfo": "^9.3.7",
@@ -20,9 +20,9 @@
"@react-navigation/elements": "^1.3.3",
"@react-navigation/native": "^6.0.10",
"@react-navigation/native-stack": "6.6.2",
"@sayem314/react-native-keep-awake": "^1.0.4",
"@sayem314/react-native-keep-awake": "^1.3.1",
"react": "18.2.0",
"react-native": "0.74.5",
"react-native": "0.77.2",
"react-native-actions-shortcuts": "^1.0.1",
"react-native-background-actions": "^2.6.6",
"react-native-blob-util": "^0.18.3",
@@ -33,31 +33,32 @@
"react-native-document-picker": "^7.1.1",
"@ammarahmed/react-native-eventsource": "1.1.0",
"react-native-file-viewer": "^2.1.1",
"react-native-gesture-handler": "^2.18.0",
"react-native-reanimated": "3.14.0",
"react-native-safe-area-context": "^4.10.8",
"react-native-screens": "^3.33.0",
"react-native-webview": "^13.10.0",
"@shopify/flash-list": "1.7.0",
"react-native-gesture-handler": "^2.25.0",
"react-native-reanimated": "3.17.5",
"react-native-safe-area-context": "^5.4.0",
"react-native-screens": "^4.10.0",
"react-native-vector-icons": "9.2.0",
"react-native-get-random-values": "^1.7.0",
"react-native-gzip": "1.1.0",
"react-native-html-to-pdf-lite": "^0.9.1",
"react-native-iap": "12.15.1",
"react-native-iap": "12.16.2",
"react-native-in-app-review": "4.3.3",
"react-native-keychain": "4.0.5",
"react-native-modal-datetime-picker": "14.0.0",
"react-native-navigation-bar-color": "2.0.2",
"react-native-notification-sounds": "0.5.5",
"react-native-pdf": "6.6.2",
"@shopify/flash-list": "^1.8.0",
"react-native-mmkv-storage": "^0.11.2",
"react-native-quick-sqlite": "^8.2.7",
"react-native-svg": "^15.12.0",
"react-native-webview": "^13.13.5",
"react-native-pdf": "6.7.7",
"react-native-scoped-storage": "^1.9.5",
"react-native-securerandom": "^1.0.1",
"react-native-share": "^12.0.3",
"react-native-svg": "^12.3.0",
"react-native-swiper-flatlist": "3.2.2",
"react-native-tooltips": "^1.0.3",
"react-native-zip-archive": "6.0.9",
"react-native-quick-sqlite": "^8.0.6",
"react-native-theme-switch-animation": "^0.6.0",
"@ammarahmed/react-native-background-fetch": "^4.2.2",
"react-native-image-crop-picker": "^0.40.2",
@@ -65,8 +66,7 @@
"react-native-screenguard": "^1.0.0",
"@formatjs/intl-locale": "4.0.0",
"@formatjs/intl-pluralrules": "5.2.14",
"@ammarahmed/react-native-sodium": "^1.6.1",
"react-native-mmkv-storage": "^0.10.2",
"@ammarahmed/react-native-sodium": "^1.6.4",
"@react-native-community/datetimepicker": "^8.2.0",
"react-native-exit-app": "github:ammarahm-ed/react-native-exit-app",
"react-native-begin-background-task": "github:blockfirm/react-native-begin-background-task",
@@ -78,19 +78,26 @@
"react-native-orientation-locker": "^1.7.0"
},
"devDependencies": {
"@rspack/core": "^1.2.7",
"@babel/core": "^7.27.1",
"@babel/preset-env": "^7.27.2",
"@babel/runtime": "^7.27.1",
"@react-native-community/cli": "15.0.1",
"@rspack/core": "^1.3.15",
"@react-native-community/cli-platform-android": "15.0.1",
"@react-native-community/cli-platform-ios": "15.0.1",
"@react-native/babel-preset": "0.77.2",
"@react-native/eslint-config": "0.77.2",
"@react-native/metro-config": "0.77.2",
"@react-native/typescript-config": "0.77.2",
"@types/jest": "^29.5.13",
"react-test-renderer": "18.2.0",
"babel-loader": "^10.0.0",
"@babel/plugin-transform-unicode-property-regex": "^7.25.9",
"@callstack/repack-plugin-reanimated": "^5.0.0",
"@callstack/repack-plugin-reanimated": "^5.1.2",
"babel-plugin-syntax-hermes-parser": "^0.26.0",
"@swc/helpers": "^0.5.15",
"detox": "^20.27.6",
"@babel/core": "^7.20.0",
"@babel/eslint-parser": "^7.16.5",
"@babel/preset-env": "^7.20.0",
"@babel/runtime": "^7.20.0",
"@react-native/eslint-config": "0.74.86",
"@react-native/metro-config": "0.74.86",
"@tsconfig/react-native": "^3.0.2",
"@types/html-to-text": "^8.0.1",
"@types/metro-config": "^0.76.3",
@@ -98,22 +105,20 @@
"@types/react-native": "^0.69.1",
"@types/react-native-vector-icons": "^6.4.10",
"@types/react-test-renderer": "^18.0.0",
"@typescript-eslint/eslint-plugin": "^5.14.0",
"@typescript-eslint/parser": "^5.14.0",
"@typescript-eslint/eslint-plugin": "^8.32.1",
"@typescript-eslint/parser": "^8.32.1",
"babel-jest": "^29.6.3",
"eslint": "^8.19.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-react": "^7.28.0",
"eslint-plugin-react-native": "^4.0.0",
"eslint-plugin-unused-imports": "^2.0.0",
"@react-native/babel-preset": "0.74.86",
"prettier": "2.8.8",
"eslint": "^9.27.0",
"eslint-config-prettier": "^10.1.5",
"eslint-plugin-prettier": "^5.4.0",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-native": "^5.0.0",
"eslint-plugin-unused-imports": "^4.1.4",
"prettier": "3.5.3",
"react-native-actions-shortcuts": "^1.0.1",
"react-native-bundle-visualizer": "^3.1.1",
"react-native-cli-bump-version": "^1.3.0",
"react-refresh": "0.14.0",
"react-test-renderer": "18.2.0",
"metro-react-native-babel-preset": "0.77.0",
"acorn-import-attributes": "1.9.5",
"expect": "^29.7.0",
@@ -122,7 +127,6 @@
"jest-image-snapshot": "^6.4.0",
"ts-jest": "^29.2.5",
"pixelmatch": "^6.0.0",
"@types/jest": "^29.5.14",
"@messageformat/parser": "^5.1.1"
}
}

View File

@@ -228,16 +228,6 @@ module.exports = (env) => {
* from `Repack.plugins`.
*/
new Repack.RepackPlugin({
logger: {
console: false,
listener: (e => {
if (e.message[0].includes("Bundle built with warnings")) {
console.warn(` ` + e.message[0] + " time: " + e.message[1].time);
return;
}
})
},
extraChunks: [
{
type: "local",

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "@notesnook/mobile",
"version": "3.1.0",
"version": "3.2.2",
"private": true,
"license": "GPL-3.0-or-later",
"workspaces": [
@@ -34,7 +34,7 @@
"react-refresh": "0.14.0"
},
"overrides": {
"react-native": "0.74.5",
"react-native": "0.77.2",
"react": "18.2.0"
},
"dependencies": {
@@ -54,6 +54,6 @@
"@types/validator": "^13.12.2",
"diffblazer": "^1.0.1",
"react": "18.2.0",
"react-native": "0.74.5"
"react-native": "0.77.2"
}
}
}

View File

@@ -0,0 +1,14 @@
diff --git a/node_modules/@callstack/repack/android/build.gradle b/node_modules/@callstack/repack/android/build.gradle
index b968f5a..62464d8 100644
--- a/node_modules/@callstack/repack/android/build.gradle
+++ b/node_modules/@callstack/repack/android/build.gradle
@@ -106,7 +106,8 @@ android {
cmake {
cppFlags "-O2 -frtti -fexceptions -Wall -Wno-unused-variable -fstack-protector-all"
arguments "-DANDROID_STL=c++_shared",
- "-DREACT_NATIVE_DIR=${REACT_NATIVE_DIR}"
+ "-DREACT_NATIVE_DIR=${REACT_NATIVE_DIR}",
+ "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON"
abiFilters(*reactNativeArchitectures())
}
}

View File

@@ -1,8 +1,8 @@
diff --git a/node_modules/@react-native/community-cli-plugin/dist/utils/loadMetroConfig.js b/node_modules/@react-native/community-cli-plugin/dist/utils/loadMetroConfig.js
index 636c0d8..87f4ee6 100644
index c0749e1..bbcb97e 100644
--- a/node_modules/@react-native/community-cli-plugin/dist/utils/loadMetroConfig.js
+++ b/node_modules/@react-native/community-cli-plugin/dist/utils/loadMetroConfig.js
@@ -105,5 +105,6 @@ This warning will be removed in future (https://github.com/facebook/metro/issues
@@ -83,5 +83,6 @@ This warning will be removed in future (https://github.com/facebook/metro/issues
...options,
});
const overrideConfig = getOverrideConfig(ctx, config);

View File

@@ -0,0 +1,14 @@
diff --git a/node_modules/react-native-mmkv-storage/android/build.gradle b/node_modules/react-native-mmkv-storage/android/build.gradle
index abb696e..ba35baa 100644
--- a/node_modules/react-native-mmkv-storage/android/build.gradle
+++ b/node_modules/react-native-mmkv-storage/android/build.gradle
@@ -98,7 +98,8 @@ android {
cmake {
cppFlags "-O3 -frtti -fexceptions -Wall -fstack-protector-all"
arguments "-DANDROID_STL=c++_shared",
- "-DREACT_NATIVE_MINOR_VERSION=${REACT_NATIVE_MINOR_VERSION}"
+ "-DREACT_NATIVE_MINOR_VERSION=${REACT_NATIVE_MINOR_VERSION}",
+ "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON"
abiFilters (*reactNativeArchitectures())
}
}

View File

@@ -0,0 +1,38 @@
diff --git a/node_modules/react-native-pdf/android/.gradle/5.6.1/fileChanges/last-build.bin b/node_modules/react-native-pdf/android/.gradle/5.6.1/fileChanges/last-build.bin
deleted file mode 100644
index f76dd23..0000000
Binary files a/node_modules/react-native-pdf/android/.gradle/5.6.1/fileChanges/last-build.bin and /dev/null differ
diff --git a/node_modules/react-native-pdf/android/.gradle/5.6.1/fileHashes/fileHashes.lock b/node_modules/react-native-pdf/android/.gradle/5.6.1/fileHashes/fileHashes.lock
deleted file mode 100644
index 52d8866..0000000
Binary files a/node_modules/react-native-pdf/android/.gradle/5.6.1/fileHashes/fileHashes.lock and /dev/null differ
diff --git a/node_modules/react-native-pdf/android/.gradle/5.6.1/gc.properties b/node_modules/react-native-pdf/android/.gradle/5.6.1/gc.properties
deleted file mode 100644
index e69de29..0000000
diff --git a/node_modules/react-native-pdf/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/node_modules/react-native-pdf/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock
deleted file mode 100644
index 1508dc9..0000000
Binary files a/node_modules/react-native-pdf/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock and /dev/null differ
diff --git a/node_modules/react-native-pdf/android/.gradle/buildOutputCleanup/cache.properties b/node_modules/react-native-pdf/android/.gradle/buildOutputCleanup/cache.properties
deleted file mode 100644
index f4a32a7..0000000
--- a/node_modules/react-native-pdf/android/.gradle/buildOutputCleanup/cache.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-#Sat Oct 12 21:44:37 CST 2019
-gradle.version=5.6.1
diff --git a/node_modules/react-native-pdf/android/.gradle/vcs-1/gc.properties b/node_modules/react-native-pdf/android/.gradle/vcs-1/gc.properties
deleted file mode 100644
index e69de29..0000000
diff --git a/node_modules/react-native-pdf/android/build.gradle b/node_modules/react-native-pdf/android/build.gradle
index 3dfe1dc..70ef9da 100644
--- a/node_modules/react-native-pdf/android/build.gradle
+++ b/node_modules/react-native-pdf/android/build.gradle
@@ -126,6 +126,6 @@ dependencies {
// The repo from zacharee is based on PdfiumAndroidKt, a much newer fork of PdfiumAndroid, with better maintenance and updated native libraries.
implementation 'com.github.zacharee:AndroidPdfViewer:4.0.1'
// Depend on PdfiumAndroidKt directly so this can be updated independently of AndroidPdfViewer as updates are provided.
- implementation 'io.legere:pdfiumandroid:1.0.24'
+ implementation 'io.legere:pdfiumandroid:1.0.32'
implementation 'com.google.code.gson:gson:2.8.5'
}

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