Compare commits

...

671 Commits

Author SHA1 Message Date
Ammar Ahmed
10b495cdbe mobile: convert sheets with input to screens or simple modals 2025-06-25 13:45:01 +05:00
Ammar Ahmed
d456132dd6 mobile: release v3.2.2 2025-06-21 13:24:24 +05:00
Abdullah Atta
4ac7941b6c web: bump version to v3.2.2 2025-06-21 13:03:04 +05:00
Abdullah Atta
e7f5463917 web: make trash actions multi selectable 2025-06-21 13:00:46 +05:00
Abdullah Atta
6e41ce459d common: bulk resolve notebooks & tags 2025-06-21 13:00:46 +05:00
Abdullah Atta
f5095fa643 core: fix hang when resolving recursive nested notebooks 2025-06-21 13:00:46 +05:00
Abdullah Atta
e6a5b85011 web: register fts5 extensions after db decryption 2025-06-21 13:00:46 +05:00
Abdullah Atta
409c5a2517 web: update sqlite to v3.49.2 2025-06-21 13:00:46 +05:00
Abdullah Atta
35cd6b101d desktop: update better-sqlite3-multiple-ciphers to v11.10.0 2025-06-21 13:00:46 +05:00
Ammar Ahmed
2440e28168 mobile: fix android toolbar hidden behind keyboard on android 15 2025-06-20 14:49:15 +05:00
Ammar Ahmed
0078d509c5 mobile: release v3.2.1 2025-06-18 11:25:33 +05:00
Ammar Ahmed
0c2d57716d mobile: fix app crash on android 15 & 16 2025-06-18 11:16:07 +05:00
Abdullah Atta
678aeb98c3 ci: release snap to stable track (instead of release track) 2025-06-18 10:35:56 +05:00
Abdullah Atta
5f422f4eb7 web: bump version to v3.2.1 2025-06-18 10:27:50 +05:00
Abdullah Atta
2b26524fcd web: bump version to v3.2.1-beta.0 2025-06-18 10:27:13 +05:00
Abdullah Atta
7326533cc1 ci: publish snap beta 2025-06-18 10:27:13 +05:00
Abdullah Atta
c8aae5be61 desktop: change snap base to core22 2025-06-18 10:27:13 +05:00
Abdullah Atta
be1a8bf849 docs: remove mention of importer.notesnook.com (#8218) 2025-06-17 13:59:38 +05:00
Ammar Ahmed
2ffc2a27a5 mobile: fix android build 2025-06-17 12:49:38 +05:00
Ammar Ahmed
b0a9f3320b mobile: fix ios workflow
Signed-off-by: Ammar Ahmed <40239442+ammarahm-ed@users.noreply.github.com>
2025-06-17 12:17:36 +05:00
Ammar Ahmed
0ef844f08c mobile: update pods 2025-06-17 11:58:48 +05:00
Abdullah Atta
bbe00b0f9a ci: disable snap on arm64 2025-06-17 11:56:42 +05:00
Ammar Ahmed
4dcaf70346 mobile: release v3.2.0 2025-06-17 11:45:39 +05:00
Abdullah Atta
76e5e3758a desktop: fix `'environment/DISABLE_WAYLAND' property does not match the
required schema`
2025-06-17 11:42:58 +05:00
Abdullah Atta
f460772d75 web: bump version to v3.2.0 2025-06-17 11:01:02 +05:00
Abdullah Atta
1cf1605564 core: fix small tokens ignored from query 2025-06-17 10:49:42 +05:00
01zulfi
0abbd41ff2 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:26:15 +05:00
Abdullah Atta
f16818ea93 web: fix tag navigation from editor 2025-06-17 10:26:15 +05:00
Abdullah Atta
719ab6dff3 web: fix ui glitch in note linking dialog 2025-06-17 10:26:15 +05:00
01zulfi
ed50d8041e editor: fix failing snapshot tests (#8215)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-17 10:26:15 +05:00
01zulfi
9a0de8dff8 web: fix navigating to notebooks & tags from note item (#8211)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-17 10:26:15 +05:00
01zulfi
caba714798 core: fix notebooks parentId() tests (#8213)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-17 10:26:15 +05:00
01zulfi
154cf897b3 web: fix move notebook dialog (#8214)
* also use db.notebooks.parentId()

Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-17 10:26:15 +05:00
Abdullah Atta
323e53a1ef global: regenerate package-lock files to fix CI (#8212) 2025-06-17 09:44:35 +05:00
Ammar Ahmed
9b097cf233 mobile: update deps 2025-06-16 14:52:06 +05:00
Ammar Ahmed
75cb2fe194 mobile: fix pin and unpin from notifications 2025-06-16 14:09:45 +05:00
Ammar Ahmed
7aa975457c mobile: support android 16 2025-06-16 14:09:45 +05:00
Abdullah Atta
1932d27f1c core: fix group header for search results hidden 2025-06-16 14:09:45 +05:00
01zulfi
f226bdbff1 docs: add monograph size limit (#8206)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-16 14:09:45 +05:00
Abdullah Atta
7843943130 web: bump version to v3.2.0-beta.9 2025-06-16 14:09:45 +05:00
Abdullah Atta
a92afab3fc core: remove search results count
it was inaccurate and confused users
2025-06-16 14:09:45 +05:00
Abdullah Atta
1354ee683f web: reduce trial2pro discount to 30% 2025-06-16 14:09:45 +05:00
Abdullah Atta
891e311374 desktop: do not use native menu for tag suggestions on macos 2025-06-16 14:09:45 +05:00
Ammar Ahmed
881099c2c9 mobile: release beta 4 2025-06-16 14:09:45 +05:00
Ammar Ahmed
2dde6b6150 mobile: make adding notebook a dialog
* make manage tags sheet a screen
2025-06-16 14:09:45 +05:00
Abdullah Atta
a1f75dfed3 editor: fix search popup removed on link hover 2025-06-16 14:09:45 +05:00
Abdullah Atta
493ee81c42 core: fix search results sorting not working 2025-06-16 14:09:45 +05:00
Abdullah Atta
7109a36006 web: bump version to v3.2.0-beta.8 2025-06-16 14:09:45 +05:00
Abdullah Atta
6fccac9aea core: take into account boolean parameters in query 2025-06-16 14:09:45 +05:00
Ammar Ahmed
fa43f97bb4 mobile: default tag 2025-06-16 14:09:45 +05:00
01zulfi
e3a973d61e web: fix navigation commands in command palette (#8070)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-16 14:09:45 +05:00
01zulfi
542a628435 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-16 14:09:45 +05:00
Ammar Ahmed
fdd25a11e7 mobile: fix ci build 2025-06-16 14:09:45 +05:00
Abdullah Atta
449ae78700 web: bump version to v3.2.0-beta.7 2025-06-16 14:09:45 +05:00
Ammar Ahmed
6bda4a9a73 mobile: fix mmkv patch 2025-06-16 14:09:27 +05:00
Ammar Ahmed
2d316ed1ec mobile: beta release 2025-06-16 14:09:27 +05:00
Abdullah Atta
570ae00453 core: fix false positives appearing in search 2025-06-16 14:09:27 +05:00
Ammar Ahmed
c845f7c1e1 mobile: update deps 2025-06-16 14:09:27 +05:00
Abdullah Atta
659e963b39 core: remove porter tokenizer for stemming
it didn't work very well. It was stemming things like "one" into "on"
2025-06-16 14:09:27 +05:00
Ammar Ahmed
63b8f7ef91 mobile: fix key missing warning in search-result item 2025-06-16 14:09:27 +05:00
Abdullah Atta
841e229866 core: fix lookup tests 2025-06-16 14:09:27 +05:00
Abdullah Atta
4098a27df0 core: update htmlparser2 2025-06-16 14:09:27 +05:00
Ammar Ahmed
918824f26b core: skip decodine entities when parsing html 2025-06-16 14:09:27 +05:00
Ammar Ahmed
83735705d2 mobile: update lockfiles 2025-06-16 14:09:27 +05:00
Ammar Ahmed
8ac6ccb701 mobile: fix android build 2025-06-16 14:09:27 +05:00
Ammar Ahmed
9ae00db676 mobile: fix ios build on rn 77 2025-06-16 14:09:27 +05:00
Ammar Ahmed
c389a1ce4d mobile: update fts5-html patch 2025-06-16 14:09:27 +05:00
Ammar Ahmed
817a58611e mobile: remove patch 2025-06-16 14:09:27 +05:00
Ammar Ahmed
bfa0f09fa0 mobile: update patches 2025-06-16 14:09:27 +05:00
Ammar Ahmed
0e461c19ed mobile: upgrade to RN 0.77.2 2025-06-16 14:09:27 +05:00
Abdullah Atta
7b289f8e58 core: sort content matches 2025-06-16 14:09:27 +05:00
Abdullah Atta
071052ce37 core: only expand matching callout & outline list items 2025-06-16 14:09:27 +05:00
Abdullah Atta
ec6ad79586 ci: fix prerelease not setting correctly on gh release 2025-06-16 14:09:27 +05:00
Abdullah Atta
96205fd5b7 web: bump version to 3.2.0-beta.6 2025-06-16 14:09:27 +05:00
01zulfi
4028a29bdb web: add support for setting a tag as default (#8060)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-16 14:09:27 +05:00
01zulfi
d812024c25 editor: remove styling for sibling elements of double spaced paragraphs (#8144)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-16 14:09:27 +05:00
Ammar Ahmed
92f4e33ac7 mobile: release new beta 2025-06-16 14:09:27 +05:00
Ammar Ahmed
ad056e0e3b mobile: skip rendering if query changed during search 2025-06-16 14:09:27 +05:00
Abdullah Atta
dc40601fb5 web: discard results if query changed during search 2025-06-16 14:09:27 +05:00
Abdullah Atta
65f3338df4 core: auto expand outline & callout in search result 2025-06-16 14:09:27 +05:00
Abdullah Atta
4f9a5cb074 core: fix phrase queries not getting highlighted 2025-06-16 14:09:27 +05:00
Abdullah Atta
eb550e95dc web: fix click on match no opening note at desired location 2025-06-16 14:09:27 +05:00
Ammar Ahmed
84dbab5bdf mobile: enable regexp in sqlite 2025-06-16 14:09:27 +05:00
Ammar Ahmed
c2aff26dfc mobile: fix tab gets focused in loop 2025-06-16 14:09:27 +05:00
Abdullah Atta
5dd9ce9f25 desktop: add SQLITE_ENABLE_REGEXP define to better-sqlite3 2025-06-16 14:09:27 +05:00
Abdullah Atta
e5998f51e9 desktop: do not gitignore *.patch 2025-06-16 14:09:27 +05:00
Abdullah Atta
538f1f1910 web: bump version to 3.2.0-beta.5 2025-06-16 14:09:27 +05:00
Abdullah Atta
9c2fa4eb30 core: use intl for showing search results count 2025-06-16 14:09:26 +05:00
Abdullah Atta
ab04b13582 core: install @notesnook/intl 2025-06-16 14:09:26 +05:00
Abdullah Atta
a6ef69905e web: use plain list instead of tree for showing search results 2025-06-16 14:09:26 +05:00
Abdullah Atta
565a2396f1 web: enable regexp in sqlite 2025-06-16 14:09:26 +05:00
Abdullah Atta
5a395aca3c desktop: enable regexp in sqlite 2025-06-16 14:09:26 +05:00
Abdullah Atta
f99ee88499 core: speed up search 2025-06-16 14:09:26 +05:00
Ammar Ahmed
dc7e5dfa50 core: fix stop-words import 2025-06-16 14:09:26 +05:00
Abdullah Atta
4f1bb994f2 core: filter out stop words in search query 2025-06-16 14:09:26 +05:00
Abdullah Atta
6357a8f3a1 web: bump version to v3.2.0-beta.4 2025-06-16 14:09:26 +05:00
Abdullah Atta
6c083bd76d 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-06-16 14:09:26 +05:00
Abdullah Atta
c53fbb7441 web: fix editor not jumping to search result 2025-06-16 14:09:26 +05:00
Abdullah Atta
6c28075070 web: fix various type errors causing crashes 2025-06-16 14:09:26 +05:00
Abdullah Atta
bb027c6f25 core: bring back limit in lookup 2025-06-16 14:09:12 +05:00
Ammar Ahmed
7dc5daffe8 mobile: release v3.2.0-beta.1 2025-06-16 14:09:12 +05:00
Ammar Ahmed
3e4862d768 mobile: fix note search 2025-06-16 14:09:12 +05:00
Abdullah Atta
29b0c2eeda web: use notesWithHighlighting for full notes search 2025-06-16 14:09:12 +05:00
Abdullah Atta
08e5f889f8 core: bring back old notes search 2025-06-16 14:09:12 +05:00
Ammar Ahmed
bc198b4cd7 mobile: release v3.2.0-beta.0 2025-06-16 14:09:12 +05:00
Abdullah Atta
5c71b77b98 web: bump version to 3.2.0-beta.3 2025-06-16 14:09:12 +05:00
Ammar Ahmed
5660178760 mobile: search and sorting 2025-06-16 14:08:56 +05:00
Abdullah Atta
8dac907ead web: localize search results count 2025-06-16 14:08:56 +05:00
Abdullah Atta
5b7c8eaa70 web: hide search results on editor focus & search cancel 2025-06-16 14:08:55 +05:00
Abdullah Atta
7ab4a2210a editor: make search results style toggleable 2025-06-16 14:08:55 +05:00
Abdullah Atta
c861b11c5f web: fix note not scrolling to selected match 2025-06-16 14:08:55 +05:00
Abdullah Atta
4f540dfdcb web: fix note not opening from search results if its already opened 2025-06-16 14:08:55 +05:00
Abdullah Atta
0e0add2f71 web: use same search ux for notes everywhere 2025-06-16 14:08:55 +05:00
Abdullah Atta
29edb3a3c3 web: improve search results ui 2025-06-16 14:08:55 +05:00
Abdullah Atta
ff723e5c78 core: improve prefix/suffix generation for matches 2025-06-16 14:08:55 +05:00
Abdullah Atta
ea76929c80 web: add full support for highlighting results in notes search 2025-06-16 14:08:55 +05:00
Abdullah Atta
5d4d84bded editor: add support for nn-search-result node 2025-06-16 14:08:55 +05:00
Abdullah Atta
0faf267735 core: add raw html content with highlighting in results 2025-06-16 14:08:55 +05:00
Abdullah Atta
197e95e66f web: add support for highlighting in search results 2025-06-16 14:08:55 +05:00
Abdullah Atta
9d4ae71bfe core: add console.time tracing for notes search 2025-06-16 14:08:55 +05:00
Abdullah Atta
422869c3d2 core: improve search results highlighting 2025-06-16 14:08:55 +05:00
Abdullah Atta
b7d478088b core: fix title matches not merged when query contains short tokens 2025-06-16 14:08:55 +05:00
Abdullah Atta
1827cbeb93 core: bring back search result sorting for notes 2025-06-16 14:08:55 +05:00
Abdullah Atta
66041a45f6 core: add support for highlighting search results 2025-06-16 14:08:55 +05:00
Ammar Ahmed
ccb0c858a2 mobile: fix archive count not shown 2025-06-16 14:08:55 +05:00
Ammar Ahmed
659b937852 mobile: update fts5-html lib 2025-06-16 14:08:55 +05:00
Ammar Ahmed
de48cea9eb mobile: support sorting search results 2025-06-16 14:08:55 +05:00
Abdullah Atta
404e3147b0 core: add a new migration to reindex fts5 2025-06-16 14:08:55 +05:00
Abdullah Atta
c0d64ff674 web: update sqlite3-fts5-html to v0.0.3 2025-06-16 14:08:55 +05:00
Abdullah Atta
bbcce64549 web: show date created on search results if sort by is set to date created 2025-06-16 14:08:55 +05:00
Abdullah Atta
1ca30b8a5b web: add support for sorting in search 2025-06-16 14:08:55 +05:00
Abdullah Atta
22b037ea1d core: add support for sortable search 2025-06-16 14:08:55 +05:00
01zulfi
2d74e3d4c0 editor: support ctrl/cmd+click to open internal links in new tab (#8131)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-16 14:08:55 +05:00
01zulfi
1be0e4790e web: add 'move to top' for sub-notebooks (#8066)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-16 14:08:55 +05:00
Ammar Ahmed
3770091b58 mobile: handle crash in background on device boot 2025-06-16 14:08:55 +05:00
Ammar Ahmed
0c86f11e21 mobile: fix new reminder title/headline is not autofill 2025-06-16 14:08:55 +05:00
Ammar Ahmed
73bf283fd7 mobile: add line break when appending to note 2025-06-16 14:08:55 +05:00
Ammar Ahmed
208bd13cdd mobile: fix crash in settings -> user subscription 2025-06-16 14:08:55 +05:00
01zulfi
42887a1dd5 web: persist double spaced lines config on logout (#8097)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-16 14:08:55 +05:00
01zulfi
0ec2f07be0 web: fix readonly note not locking when vault is locked (#8092)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-16 14:08:55 +05:00
01zulfi
82b70d2951 web: add support for drag/dropping notes on tab strip (#8090)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-16 14:08:55 +05:00
Abdullah Atta
8da961f300 web: bump version to 3.2.0-beta.2 2025-06-16 14:08:55 +05:00
Abdullah Atta
4fba380f2d core: fix `expected previously executed migration 2 to be at index 1 but
10 was found in its place.`
2025-06-16 14:08:54 +05:00
01zulfi
e1b046ec0c core: fix db.settings.getTrashCleanupInterval return type (#8076)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-16 14:08:54 +05:00
01zulfi
5d01159e20 web: add support for removing recents in command palette using delete key (#8069)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-16 14:08:54 +05:00
01zulfi
aeef53df55 web: press shift+enter to create note in quick open (#8068)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-16 14:08:54 +05:00
Ammar Ahmed
29433c4149 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-06-16 14:08:54 +05:00
Abdullah Atta
0edac2ee9d desktop: update patched better-sqlite3-multiple-ciphers to 11.6.1 2025-06-16 14:08:54 +05:00
Abdullah Atta
4607dc3084 global: regenerate package-lock.json for theme & ui packages 2025-06-16 14:08:54 +05:00
Ammar Ahmed
41babda9b7 mobile: fix error in build 2025-06-16 14:08:54 +05:00
Ammar Ahmed
0fec38610c mobile: add option to disable auto update check 2025-06-16 14:08:54 +05:00
Abdullah Atta
3ecc43d976 misc: include @notesnook/theme package when generating flatpak sources 2025-06-16 14:08:54 +05:00
Abdullah Atta
9730560fb7 desktop: downgrade playwright 2025-06-16 14:08:54 +05:00
Abdullah Atta
6c0e51dc9d desktop: fix flatpak sources generation 2025-06-16 14:08:54 +05:00
Abdullah Atta
2a313a0026 desktop: regenerate package-lock.json 2025-06-16 14:08:54 +05:00
Abdullah Atta
5d4e60b829 web: update package-lock.json 2025-06-16 14:08:54 +05:00
Abdullah Atta
c0666d8547 global: fix dependencies version differences 2025-06-16 14:08:24 +05:00
Abdullah Atta
a5fa261e3b global: update package-lock.json 2025-06-16 14:08:24 +05:00
Ammar Ahmed
fa8aa4d88f mobile: archive notes 2025-06-16 14:08:24 +05:00
Abdullah Atta
b63be2de15 web: bump version to 3.2.0-beta.1 2025-06-16 14:08:24 +05:00
Abdullah Atta
173caf41d0 core: fix query-transformer tests 2025-06-16 14:08:24 +05:00
Ammar Ahmed
30e4f55218 mobile: add sqlite3-fts5-html module 2025-06-16 14:08:24 +05:00
Abdullah Atta
f3895f534e desktop: install sqlite3-fts5-html 2025-06-16 14:08:24 +05:00
Abdullah Atta
ea14db77de web: update wa-sqlite to use sqlite3-fts5-html for stripping html 2025-06-16 14:08:24 +05:00
Abdullah Atta
9bb48f4896 core: fix short queries search 2025-06-16 14:08:24 +05:00
Abdullah Atta
62b5cc853b core: remove @orama/stopwords 2025-06-16 14:08:24 +05:00
Abdullah Atta
90900628a2 core: strip html when searching notes
this commit also properly fixes search queries containing
words less than 3 characters in length
2025-06-16 14:08:24 +05:00
Abdullah Atta
ebf98bc652 core: fix warnings in tests 2025-06-16 14:08:24 +05:00
Ammar Ahmed
ddd3fe6ac5 mobile: update better trigram 2025-06-16 14:08:24 +05:00
Abdullah Atta
2964e7a8f0 core: fix db migration 2025-06-16 14:08:24 +05:00
Abdullah Atta
f6d1f5890a core: wrap query with invalid symbols in quotes 2025-06-16 14:08:24 +05:00
Abdullah Atta
1cc0cf19c8 core: update sqlite-better-trigram to v0.0.3 2025-06-16 14:08:24 +05:00
01zulfi
efc4f3566a core: fix trash cleanup interval setting retrieval (#8045)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-16 14:08:06 +05:00
01zulfi
85b7760e1e web: add more archive test cases (#8040)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-16 14:08:06 +05:00
Abdullah Atta
40ee0ecf47 desktop: no need to externalize @resvg/resvg-js 2025-06-16 14:08:06 +05:00
Abdullah Atta
513c9ee8a7 desktop: remove icon from native menu 2025-06-16 14:08:06 +05:00
Abdullah Atta
2aacadc24d desktop: only show native menus on macos 2025-06-16 14:08:06 +05:00
Abdullah Atta
716bb67b96 desktop: show native menus where possible 2025-06-16 14:08:06 +05:00
01zulfi
916b6a17aa web: assign accent color to links (#8041)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-16 14:08:06 +05:00
Abdullah Atta
813401ea91 desktop: update packages 2025-06-16 14:08:06 +05:00
01zulfi
70e5efbcea desktop: upgrade electron to v34.0.0 (#8038)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-16 14:07:44 +05:00
01zulfi
6c8dc223f2 web: fix automatic backup reminder setting reverting to never (#8037)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-16 14:07:44 +05:00
01zulfi
5b09528e7e web: fix focus last active tab method (#8034)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-16 14:07:44 +05:00
01zulfi
5de5ffe068 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-06-16 14:07:44 +05:00
Abdullah Atta
1b511c8ddd web: bump version to 3.2.0-beta.0 2025-06-16 14:07:44 +05:00
Abdullah Atta
68d1a3f50e web: update @notesnook-imoporter/core to 2.2.2 2025-06-16 14:06:37 +05:00
01zulfi
74edd466d4 web: fix notestore is not defined error (#8012)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-16 14:05:54 +05:00
Abdullah Atta
34aa21790c web: update @notesnook-importer/core to 2.2.1 2025-06-16 14:05:54 +05:00
01zulfi
e7ec9e2aa3 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-06-16 14:05:54 +05:00
tarynlucia
20bbb6dd5b ui: correct grammar in vault creation message (issue #7497) (#8188)
Signed-off-by: Taryn Eng <taryn.eng@gmail.com>
2025-06-10 11:18:11 +05:00
Abdullah Atta
f937b164e9 web: update lockfile 2025-06-06 11:16:34 +05:00
Abdullah Atta
5b4e888ddd web: fix infinite rerenders on checkout screen 2025-06-06 11:01:14 +05:00
Abdullah Atta
410d983842 web: chore bump version to v3.1.1 2025-05-22 11:27:10 +05:00
Abdullah Atta
16cd92f03a web: fix flicker when programatically updating title 2025-05-22 11:20:58 +05:00
Abdullah Atta
c6ee1e6303 core: do not allow empty titles 2025-05-22 11:20:44 +05:00
SB
0f00d0e508 docs: add missing '-' in build-steps for MacOS and Linux (AppImage) 2025-05-16 10:12:24 +05:00
01zulfi
21fdc39db7 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-04-29 12:51:19 +05:00
01zulfi
bb5d5a5731 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-04-29 09:27:35 +05:00
Ammar Ahmed
bf5e68a82e ci: fix build ios
Signed-off-by: Ammar Ahmed <40239442+ammarahm-ed@users.noreply.github.com>
2025-04-28 14:03:48 +05:00
Ammar Ahmed
cc7f479627 ci: fix build ios
Signed-off-by: Ammar Ahmed <40239442+ammarahm-ed@users.noreply.github.com>
2025-04-28 13:53:21 +05:00
Ammar Ahmed
9eb183f6b5 ci: fix build ios
Signed-off-by: Ammar Ahmed <40239442+ammarahm-ed@users.noreply.github.com>
2025-04-28 13:42:39 +05:00
Ammar Ahmed
cb29d71619 mobile: fix crash when going from trash -> search 2025-04-28 12:30:50 +05:00
Ammar Ahmed
a6120ed90f mobile: release v3.1.1 2025-04-28 12:26:46 +05:00
Ammar Ahmed
48040c955d mobile: fix crash on delete item 2025-04-28 12:26:12 +05:00
Ammar Ahmed
18b43882e1 mobile: fix crash in list 2025-04-28 11:36:48 +05:00
Ammar Ahmed
37dc409b60 mobile: fix cursor bug on ios 2025-04-28 11:36:37 +05:00
Ammar Ahmed
8ab05c5a98 mobile: fix typing in editor title input 2025-04-28 11:36:27 +05:00
Abdullah Atta
38509c66c5 web: update @notesnook-importer/core to 2.2.0 2025-04-25 14:33:32 +05:00
Abdullah Atta
fc40a05254 web: open settings with importer page instead of importer.notesnook.com 2025-04-25 14:33:32 +05:00
Ammar Ahmed
8078c3ed3c mobile: fix default font setting not followed 2025-04-25 11:51:28 +05:00
01zulfi
57280f3ebb 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-25 11:21:16 +05:00
Ammar Ahmed
dc54644b4f mobile: remove READ_MEDIA_IMAGES permission 2025-04-24 15:29:58 +05:00
Abdullah Atta
ce31b0495d web: refresh app after import 2025-04-24 14:39:15 +05:00
Abdullah Atta
a62d4b5d4b web: move importer into web/desktop app (#7472)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-04-24 13:20:06 +05:00
Abdullah Atta
6f585c5e17 web: validate release track on app launch 2025-04-24 12:39:51 +05:00
Abdullah Atta
ffe7d944a6 web: use separate service worker cache for each app version 2025-04-24 12:39:51 +05:00
Abdullah Atta
bf0d6857d3 web: improve update installation 2025-04-24 12:39:51 +05:00
Ammar Ahmed
69f117bab7 mobile: fix swipe active offsets 2025-04-24 11:45:08 +05:00
Ammar Ahmed
cac945501d ci: fix release workflow
Signed-off-by: Ammar Ahmed <40239442+ammarahm-ed@users.noreply.github.com>
2025-04-22 16:34:21 +05:00
Abdullah Atta
85a0762ccf web: update test snapshots 2025-04-22 12:37:08 +05:00
Abdullah Atta
0ce51bf481 web: fix tests 2025-04-22 12:25:39 +05:00
Abdullah Atta
6adc5065fb Merge v3.1.0 from streetwriters/beta 2025-04-22 12:06:04 +05:00
Ammar Ahmed
3b90a6d90e mobile: release v3.1.0 2025-04-22 12:00:24 +05:00
Abdullah Atta
aa5e6e7199 web: remove duplicate item in changelog 2025-04-22 11:47:16 +05:00
Abdullah Atta
ca53ec38d1 web: add more items in changelog 2025-04-22 11:46:39 +05:00
Abdullah Atta
80a3cc2fc1 web: conform notebook header with mobile ui 2025-04-22 11:42:43 +05:00
Ammar Ahmed
32c4e987dc mobile: fix crash in reminder notify sheet 2025-04-22 11:16:35 +05:00
Ammar Ahmed
ce0ef0a1cf mobile: hide keyboard when app is locked 2025-04-22 11:16:35 +05:00
Abdullah Atta
95fc9bd3d0 web: bump version to 3.1.0 2025-04-22 11:10:04 +05:00
Ammar Ahmed
fb21fef82f mobile: fix invalid tags linked to note from share menu 2025-04-21 12:34:48 +05:00
Ammar Ahmed
7760f5e898 mobile: fix sorting trash 2025-04-21 12:34:48 +05:00
Ammar Ahmed
fcc9915b04 mobile: fix focused route id incorrect 2025-04-21 12:34:48 +05:00
Abdullah Atta
8347dd5db7 common: remove limit on resolve tags & notebook in note 2025-04-21 12:26:10 +05:00
01zulfi
c2d3ba087a web: reduce snapSize of nav & list panes (#7951)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-04-21 11:39:30 +05:00
Abdullah Atta
e5883f179c web: fix search tests 2025-04-21 11:26:35 +05:00
Abdullah Atta
f7f1d3b3f0 web: fix crash on entering focus mode 2025-04-21 11:26:21 +05:00
Abdullah Atta
df3674f570 web: check if user is premium in behavior settings 2025-04-21 10:54:20 +05:00
01zulfi
a62beab172 web: show reset search button only when query text present (#7950)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-04-21 10:54:04 +05:00
01zulfi
528810155f web: fix toc bugs (#7775)
* fix duplicate headings showing in toc view
* fix negative level for some headings

Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-04-21 10:12:53 +05:00
01zulfi
5c80b5300e web: fix notebooks tree (#7941)
* web: fix notebooks tree
* fix flicker when creating a new notebook/subnotebook
* fix crash when creating subnotebook
* fix notebook not expanding when subnotebook is created against it

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

* web: fix duplicate notebooks in notebook search
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>

* web: consider node's children when expanding in refreshItem
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>

* web: get childNodes to check expansion in refreshItem
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>

---------

Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-04-21 10:09:15 +05:00
Abdullah Atta
36c33160f4 web: make remove shortcut icon same size as shortcut link icon 2025-04-21 09:41:32 +05:00
Abdullah Atta
5cca28daa1 global: minor refactors 2025-04-21 09:39:18 +05:00
Abdullah Atta
5298ccd638 web: fix list pane not showing on navigate 2025-04-21 09:39:18 +05:00
Abdullah Atta
a5db1797e3 web: fix search not working in notebook 2025-04-21 09:39:18 +05:00
Ammar Ahmed
b1d034cf3f mobile: reload note on tab focus 2025-04-21 09:39:01 +05:00
Ammar Ahmed
4620ed0c1c mobile: fix color of tags border when note is colored 2025-04-18 13:10:36 +05:00
Ammar Ahmed
5c87b6f3b0 mobile: make sure fluid tabs panel loads 2025-04-18 13:00:56 +05:00
01zulfi
29ad783b3f intl: fix notes string (#7942)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-04-18 12:57:12 +05:00
01zulfi
3eae13e237 web: wrap notice text (#7938)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-04-18 12:55:58 +05:00
Ammar Ahmed
ee222b6302 mobile: move blue bar to left 2025-04-18 12:02:54 +05:00
Abdullah Atta
ae795a837d web: move the opened note indicator to the left of note item 2025-04-17 13:28:49 +05:00
Abdullah Atta
0396264842 web: show provider subtitle if pro plan is canceled 2025-04-17 13:17:17 +05:00
Abdullah Atta
e9fcd16fb5 web: hide subscription provider description on basic plan 2025-04-17 13:03:17 +05:00
01zulfi
944fcf0567 web: improve diff viewing (#7936)
* add close button to quit diff viewer
* allow property pane to open with only note history list

Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-04-17 12:57:40 +05:00
01zulfi
251cc08a7d web: don't close tab on trash if note is in tab history (#7933)
* don't close tab if note was present in tab history

Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-04-17 09:56:33 +05:00
Abdullah Atta
d2719123eb web: fix editor overflow on small screens 2025-04-16 13:27:31 +05:00
Abdullah Atta
88c0e2a2ce web: fix minor layout issue in note list when in compact mode 2025-04-16 12:24:45 +05:00
Abdullah Atta
b4366058dd web: fix flicker when typing in multiline title 2025-04-16 12:24:24 +05:00
01zulfi
b103cc09f2 core: fix notes search results having mismatched references (#7930)
* ids and items had different orders

Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-04-15 10:37:47 +05:00
Abdullah Atta
d35c0be116 vericrypt: update instructions according to latest notesnook version 2025-04-14 14:00:49 +05:00
Ammar Ahmed
c9cf15e519 mobile: fix $headline$ format title not updating in realtime 2025-04-11 11:31:07 +05:00
Ammar Ahmed
408ae26b76 mobile: fix color scope 2025-04-11 10:51:04 +05:00
Abdullah Atta
3159d8fcc5 web: add accented bottom border on opened note 2025-04-11 10:49:31 +05:00
Ammar Ahmed
b976788f07 mobile: release v3.1.0-beta.4 2025-04-11 10:10:40 +05:00
Ammar Ahmed
a0311c1516 mobile: add bottom line to show note being edited 2025-04-11 09:20:10 +05:00
01zulfi
e17351f702 editor: disable spellcheck for links (#7911)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-04-11 09:12:43 +05:00
Ammar Ahmed
ffafae9970 mobile: fix color of section header 2025-04-10 14:38:22 +05:00
Ammar Ahmed
fa3d993ffd mobile: load new note always 2025-04-10 11:52:51 +05:00
01zulfi
2b7b8d526e web: don't close pinned tab on ctrl+w (#7805)
* web: don't close pinned tab on ctrl+w
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>

* web: focus previously activated tab if ctrl+w on pinned tab
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-04-10 10:51:40 +05:00
Ammar Ahmed
270394dc36 mobile: add missing break; 2025-04-10 10:29:27 +05:00
Ammar Ahmed
552e8f50b7 mobile: add support for changin sidebar + default home page 2025-04-10 10:29:27 +05:00
Abdullah Atta
b6d0d124fd web: replace switch with array.find to be more reliable 2025-04-10 10:29:27 +05:00
Abdullah Atta
7e3abc5819 web: add support for setting default sidebar tab 2025-04-10 10:29:27 +05:00
Abdullah Atta
6b3065617d ui: leave space for icon in menu button even if no icon 2025-04-10 10:29:26 +05:00
Abdullah Atta
9752ccf7cb intl: add strings for homepage 2025-04-10 10:29:26 +05:00
Abdullah Atta
ad1921a938 web: allow setting any thing in the sidebar as homepage 2025-04-10 10:29:26 +05:00
Ammar Ahmed
ed2201d525 mobile: catch error when moving file fails after download 2025-04-10 10:29:26 +05:00
Abdullah Atta
09b9719a3f web: bump version to 3.1.0-beta.6 2025-04-10 10:29:26 +05:00
Abdullah Atta
673ea6da86 editor: remove fixed line height 2025-04-10 10:29:26 +05:00
Ammar Ahmed
77d81ecc12 mobile: fix auto theme switching 2025-04-10 10:29:26 +05:00
Ammar Ahmed
00c38b6bcc mobile: fix last heading not shown in toc 2025-04-10 10:29:26 +05:00
Ammar Ahmed
24d9568c5d editor: add missing node types in editor 2025-04-10 10:29:26 +05:00
01zulfi
3b89b0c436 web: fix command palette not scrolling (#7881)
* Remove overflow: hidden styling from GroupedVirtuoso

Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-04-10 10:29:26 +05:00
Abdullah Atta
940a3de130 web: fix note counts not updating in tags list 2025-04-10 10:29:26 +05:00
Abdullah Atta
81b291ae37 web: fix note counts not updating in notebooks list 2025-04-10 10:29:26 +05:00
01zulfi
f5ad31f0a3 web: fix search result note item not updating (#7878)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-04-10 10:29:26 +05:00
Abdullah Atta
59d4b92839 web: fix item counts not updating in sidebar 2025-04-10 10:29:26 +05:00
Abdullah Atta
530c864d10 web: fix filter input removed when no notebooks in list 2025-04-10 10:29:26 +05:00
Ammar Ahmed
fae6bf8f43 mobile: bug fixes 2025-04-10 10:29:26 +05:00
Ammar Ahmed
c395bc829f mobile: fix orientation check 2025-04-10 10:29:26 +05:00
Ammar Ahmed
19ee33ec3a mobile: fix input padding in side menu on ios 2025-04-10 10:29:26 +05:00
Ammar Ahmed
64ab6a3436 mobile: release v3.1.0-beta.3 2025-04-10 10:29:26 +05:00
Abdullah Atta
b758cd28e5 web: bump version to 3.1.0-beta.5 2025-04-10 10:29:26 +05:00
Abdullah Atta
db8e21f83b web: remove SharedWorker requirement for multi tab sqlite driver 2025-04-10 10:29:26 +05:00
Abdullah Atta
c23f31f284 web: use service worker for cross-tab communication only as a fallback
This commit basically reverts 1b63b2dccf.
Using service worker for this by default is a bad idea because:

1. It takes some time for the service worker to be installed and ready
which slows down first launch significantly
2. Service worker is not as reliable when updating from version to
version

We can, however, use it as a fallback i.e for devices that don't yet
support shared worker.
2025-04-10 10:29:26 +05:00
Ammar Ahmed
84d5420b51 mobile: update intl 2025-04-10 10:29:26 +05:00
Ammar Ahmed
02bdc61543 intl: update po files 2025-04-10 10:29:26 +05:00
Ammar Ahmed
71811ebf0d mobile: focus keyboard if biometry is disabled 2025-04-10 10:29:00 +05:00
Ammar Ahmed
b07d7e4f3f mobile: restore pinned notes on reboot 2025-04-10 10:29:00 +05:00
Ammar Ahmed
b141907066 mobile: cleanup 2025-04-10 10:28:59 +05:00
Ammar Ahmed
a0b46d49d6 mobile: update deps 2025-04-10 10:28:59 +05:00
Ammar Ahmed
85386c945f mobile: update locales 2025-04-10 10:28:59 +05:00
Ammar Ahmed
9de1373bdd mobile: bump version 2025-04-10 10:28:59 +05:00
Ammar Ahmed
6f4c35672d mobile: fix virtualization errors 2025-04-10 10:28:59 +05:00
Ammar Ahmed
ed32552155 mobile: run sync when necessary 2025-04-10 10:28:59 +05:00
Ammar Ahmed
88858308fb mobile: fix slow launch 2025-04-10 10:28:59 +05:00
Ammar Ahmed
78f875ab0f mobile: fix item counts not showing in side menu 2025-04-10 10:28:59 +05:00
Ammar Ahmed
9104c64170 mobile: fix minor bugs in tablets 2025-04-10 10:28:59 +05:00
Ammar Ahmed
aabb33a435 mobile: cleanup 2025-04-10 10:28:59 +05:00
Ammar Ahmed
ad43591f2c mobile: fix tablet rotation 2025-04-10 10:28:59 +05:00
Ammar Ahmed
8bc779d882 mobile: fix tablet bugs 2025-04-10 10:28:59 +05:00
Ammar Ahmed
193bddbe9e mobile: fix login ui on tablets 2025-04-10 10:28:59 +05:00
Ammar Ahmed
e03d394555 mobile: add notebooks button in notebook screen to view subnotebooks 2025-04-10 10:28:59 +05:00
Ammar Ahmed
72e4116773 mobile: fix crash when clicking sort button in trash 2025-04-10 10:28:59 +05:00
Ammar Ahmed
9b682163db mobile: fix ui 2025-04-10 10:28:59 +05:00
Ammar Ahmed
076312da7a mobile: fix sorting sheet in reminders 2025-04-10 10:28:59 +05:00
Ammar Ahmed
856a9b16e9 mobile: do not call scroll into view on focus 2025-04-10 10:28:59 +05:00
Ammar Ahmed
9de4e3eba6 mobile: change item positions 2025-04-10 10:28:59 +05:00
Ammar Ahmed
d90d263b04 mobile: fix check mark color in dialog 2025-04-10 10:28:59 +05:00
Ammar Ahmed
0170e51843 mobile: fix logout button not working in user sheet 2025-04-10 10:28:59 +05:00
Ammar Ahmed
b7f5a5dc66 mobile: minor improvements 2025-04-10 10:28:59 +05:00
Ammar Ahmed
20866ab2f5 mobile: add missing check when dragging to end 2025-04-10 10:28:59 +05:00
Ammar Ahmed
4efc13a602 mobile: fix colors 2025-04-10 10:28:59 +05:00
Ammar Ahmed
96303f5d0f mobile: update rspack to v1.2.7 2025-04-10 10:28:59 +05:00
Ammar Ahmed
020c9b254e mobile: use re.pack v5 with rspack 2025-04-10 10:28:59 +05:00
Ammar Ahmed
24c0f2f409 ci: update to actions/cache@v3 2025-04-10 10:28:59 +05:00
Ammar Ahmed
1b608f01ac ci: release app to beta track on play 2025-04-10 10:28:59 +05:00
Ammar Ahmed
fd98ab0a64 mobile: release beta 2 2025-04-10 10:28:59 +05:00
Ammar Ahmed
3d1dc879e0 mobile: fix linking a note 2025-04-10 10:28:59 +05:00
Ammar Ahmed
16253b8bf7 mobile: fix tree filtering in move notebook 2025-04-10 10:28:59 +05:00
Ammar Ahmed
3dba3079f7 mobile: fix items hides behind selection bar 2025-04-10 10:28:59 +05:00
Ammar Ahmed
1fe4ae199f mobile: cleanup 2025-04-10 10:28:59 +05:00
Ammar Ahmed
55842f1265 mobile: fix breadcrumbs 2025-04-10 10:28:59 +05:00
Ammar Ahmed
6644940115 mobile: fix properties not opening 2025-04-10 10:28:59 +05:00
Ammar Ahmed
dfd0dc72b8 mobile: fix ui 2025-04-10 10:28:59 +05:00
Ammar Ahmed
d7c4b9c776 mobile: fix toggle switch color in settings 2025-04-10 10:28:59 +05:00
Ammar Ahmed
728553115c mobile: fix input border color 2025-04-10 10:28:59 +05:00
Ammar Ahmed
6ee0d28a8b mobile: fix separator color 2025-04-10 10:28:59 +05:00
Ammar Ahmed
ead23c36c6 mobile: fix sidemenu colors 2025-04-10 10:28:59 +05:00
Ammar Ahmed
e62891b9c0 mobile: fix ui 2025-04-10 10:28:59 +05:00
Ammar Ahmed
9483c63cdc mobile: fix zindex 2025-04-10 10:28:59 +05:00
Ammar Ahmed
3eab773fd1 mobile: fix beta release getting update dialog prompt 2025-04-10 10:28:59 +05:00
Ammar Ahmed
30dd0e8657 mobile: fix loading locales in release 2025-04-10 10:28:59 +05:00
Ammar Ahmed
5d05df7f83 mobile: minor ui fixups 2025-04-10 10:28:59 +05:00
Ammar Ahmed
ebf80aacc5 mobile: minor ui fixes 2025-04-10 10:28:59 +05:00
Ammar Ahmed
55c6be4622 ci: add beta release workflow 2025-04-10 10:28:59 +05:00
Ammar Ahmed
8f1545916f mobile: ui updates 2025-04-10 10:28:59 +05:00
Ammar Ahmed
7f05043e03 mobile: fix back navigation bug 2025-04-10 10:28:59 +05:00
Ammar Ahmed
e663655924 mobile: fix editor state not restored sometimes on app launch 2025-04-10 10:28:59 +05:00
Ammar Ahmed
2fab9dc6f1 mobile: fix task list title rendered above status bar in editor 2025-04-10 10:28:59 +05:00
Ammar Ahmed
aba79c11d3 mobile: fix selection in sidebar on app launch 2025-04-10 10:28:59 +05:00
Ammar Ahmed
4e897dde47 mobile: fix various bugs 2025-04-10 10:28:59 +05:00
Ammar Ahmed
3375439e35 mobile: refactor and fix bugs 2025-04-10 10:28:59 +05:00
Ammar Ahmed
89dce0b655 mobile: improve app launch perf 2025-04-10 10:28:59 +05:00
Ammar Ahmed
ff53ea322d mobile: refactor some sheets into screens 2025-04-10 10:28:59 +05:00
Ammar Ahmed
d6f6bc2c5b mobile: add test-id 2025-04-10 10:28:59 +05:00
Ammar Ahmed
905080e743 mobile: refactor 2025-04-10 10:28:59 +05:00
Ammar Ahmed
d33f3c4769 mobile: use custom cache key for persist store 2025-04-10 10:28:59 +05:00
Ammar Ahmed
b6a1c9b73b mobile: minor refactor 2025-04-10 10:28:59 +05:00
Ammar Ahmed
20823f103c mobile: refactor 2025-04-10 10:28:59 +05:00
Ammar Ahmed
25a5d3277b mobile: refactor 2025-04-10 10:28:59 +05:00
Ammar Ahmed
72a80c8f57 mobile: fix moving and updating notebooks 2025-04-10 10:28:59 +05:00
Ammar Ahmed
a082c7d33a mobile: small ui improvements and perf fixes 2025-04-10 10:28:59 +05:00
Ammar Ahmed
99cac4b041 mobile: make skip login work properly 2025-04-10 10:28:59 +05:00
Ammar Ahmed
f804d7848f mobile: more fixes 2025-04-10 10:28:59 +05:00
Ammar Ahmed
446841e0f5 mobile: fix selected item ui 2025-04-10 10:28:59 +05:00
Ammar Ahmed
1d347fe26c mobile: fix bugs 2025-04-10 10:28:58 +05:00
Ammar Ahmed
abfa5d719a mobile: fix missing delete button in trash 2025-04-10 10:28:58 +05:00
Ammar Ahmed
32bc6ed328 mobile: fix pro button 2025-04-10 10:28:58 +05:00
Ammar Ahmed
ea2bc359cb mobile: enable testing in debug build 2025-04-10 10:28:58 +05:00
Ammar Ahmed
c540cb0fe4 mobile: enable debug tests 2025-04-10 10:28:58 +05:00
Ammar Ahmed
1642495754 mobile: cleanup 2025-04-10 10:28:58 +05:00
Ammar Ahmed
b034a59422 mobile: fix error set state in render 2025-04-10 10:28:58 +05:00
Ammar Ahmed
2486c055e4 mobile: add pro button in side-menu 2025-04-10 10:28:58 +05:00
Ammar Ahmed
79b43b1058 mobile: fix sidemenu padding top 2025-04-10 10:28:58 +05:00
Ammar Ahmed
b30fa436bd mobile: fix minor bugs 2025-04-10 10:28:58 +05:00
Ammar Ahmed
9e79a311cf mobile: fix typo 2025-04-10 10:28:58 +05:00
Ammar Ahmed
2f695d0b34 mobile: make all e2e tests pass 2025-04-10 10:28:58 +05:00
Ammar Ahmed
952a484994 mobile: minor cleanup 2025-04-10 10:28:58 +05:00
Ammar Ahmed
74b5e42492 mobile: finalize sidebar and list revamp 2025-04-10 10:28:58 +05:00
Ammar Ahmed
7f8dc88c5a mobile: refactor goToPage 2025-04-10 10:28:58 +05:00
Ammar Ahmed
c9a9b8dffb mobile: fix tsc errors 2025-04-10 10:28:58 +05:00
Ammar Ahmed
b315a834c2 mobile: ui redesign 2025-04-10 10:28:58 +05:00
Abdullah Atta
8f84c85c23 web: fix tests 2025-04-10 10:28:58 +05:00
Abdullah Atta
707ff935fe web: bump version to 3.1.0-beta.4 2025-04-10 10:28:58 +05:00
Abdullah Atta
39af23b349 web: close expanded nav pane on navigation 2025-04-10 10:28:58 +05:00
Abdullah Atta
318b95beec web: force list pane to be visible when reveal item in list is called 2025-04-10 10:28:58 +05:00
Abdullah Atta
174bb9a935 web: improve item flash animation when revealing item in list
this also fixes a potential memory leak due to event listener not unsubscribing
2025-04-10 10:28:58 +05:00
Abdullah Atta
f0fd20051e Revert "web: fix list pane not expanding (#7758)"
This reverts commit fd9db3605d.
2025-04-10 10:28:58 +05:00
Abdullah Atta
e3d72bd271 web: fix active tab background 2025-04-10 10:28:58 +05:00
Abdullah Atta
4dcd0cd356 web: fix Service worker did not respond. error 2025-04-10 10:28:58 +05:00
Abdullah Atta
e3793e67aa web: fix app not starting up on firefox 2025-04-10 10:28:58 +05:00
01zulfi
3f344c7249 web: don't remove properties pane when editor is refocused (#7780)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-04-10 10:28:58 +05:00
Abdullah Atta
8a1af7d01f intl: update strings 2025-04-10 10:28:58 +05:00
Abdullah Atta
117fc44f00 web: replace shared worker with service worker for sqlite 2025-04-10 10:28:58 +05:00
01zulfi
703456b808 web: collapse hovered navbar when item is clicked (#7771)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-04-10 10:28:58 +05:00
Abdullah Atta
b90cc90ea8 web: release v3.1.0-beta.3 2025-04-10 10:28:57 +05:00
Ammar Ahmed
45730e2a07 web: cleanup 2025-04-10 10:28:57 +05:00
01zulfi
c0272b9755 web: fix list pane not expanding (#7758)
* web: fix list pane not expanding
* when a nav item was clicked, list pane was removed entirely which made it difficult to re-open it, now when nav item is clicked we manually collapse, expand, or reset the list pane
* open list pane if 'reveal in list' is called
* open list pane if navigated to a different nav item

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

* web: clicking on nav item should not collapse list pane
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>

* web: collapse hovered nav pane when notebook/tag item clicked
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>

---------

Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-04-10 10:28:57 +05:00
01zulfi
a27a8804c4 web: restore notebook crumbs (#7765)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-04-10 10:28:57 +05:00
Ammar Ahmed
073d23aed3 web: bump version to 3.1.0-beta.2 for desktop and web 2025-04-10 10:28:57 +05:00
Abdullah Atta
7d9a795a1c web: make editor note properties work like toc 2025-04-10 10:28:57 +05:00
Abdullah Atta
8359fb8919 web: slightly improve add note button ui 2025-04-10 10:28:57 +05:00
Abdullah Atta
7c0ffff93f web: bump version to 3.1.0-beta.1 2025-04-10 10:28:57 +05:00
Abdullah Atta
46d2ea508c desktop: set publish channel to beta for beta builds 2025-04-10 10:28:57 +05:00
Abdullah Atta
fb48faa3af web: minor ui fixes 2025-04-10 10:28:57 +05:00
Abdullah Atta
048bb36165 theme: fix button hover colors 2025-04-10 10:28:57 +05:00
Abdullah Atta
0f01a03587 web: make notesnook branding a bit smaller 2025-04-10 10:28:57 +05:00
Abdullah Atta
fe17a6e9da web: minor ui changes and fixes 2025-04-10 10:28:57 +05:00
Abdullah Atta
a17414dd89 web: fix theme not persisting 2025-04-10 10:28:57 +05:00
Abdullah Atta
5d3f2182f0 web: collapse sidebar on navigate if sidebar is temporarily expanded 2025-04-10 10:28:57 +05:00
Abdullah Atta
03cd320665 desktop: explicitly deny geolocation permission to electron process 2025-04-10 10:28:57 +05:00
Abdullah Atta
2415ede4fa web: fix scrollbar styling in sidebar 2025-04-10 10:28:57 +05:00
Abdullah Atta
844efd5958 web: reset search on navigate 2025-04-10 10:28:57 +05:00
Abdullah Atta
4ba88b6f03 web: fix expand sidebar button not working 2025-04-10 10:28:57 +05:00
Abdullah Atta
d17d0c190b web: always show "X" button if there is query in search input 2025-04-10 10:28:57 +05:00
Abdullah Atta
beec9fab22 web: bump version to 3.1.0-beta.0 2025-04-10 10:28:57 +05:00
Abdullah Atta
710b3c412f web: use virtualized tree for rendering toc 2025-04-10 10:28:57 +05:00
Abdullah Atta
6bf31bf0ea editor: fix toc level mapping 2025-04-10 10:28:57 +05:00
Abdullah Atta
2f8bef5f3e web: add support for pre-expanding tree nodes on creation 2025-04-10 10:28:57 +05:00
Abdullah Atta
2dcf886322 web: do not collapse child nodes when collapsing parent 2025-04-10 10:28:57 +05:00
Abdullah Atta
0a362e9ce7 web: fix all tests 2025-04-10 10:28:57 +05:00
Abdullah Atta
e186615163 global: update ui 2025-04-10 10:28:57 +05:00
01zulfi
7abf19071d web: fix faulty useEffect
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-04-10 10:28:57 +05:00
01zulfi
30838749e1 web: refactor props for Tags component
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-04-10 10:28:57 +05:00
01zulfi
06df49d5d7 web: separate component for tab items in sidebar
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-04-10 10:28:57 +05:00
01zulfi
2c5e1f611b web: new sidebar ui
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-04-10 10:28:56 +05:00
01zulfi
0cc33f7a81 core: fix title generation when title format is set to $headline$ (#7739)
* core: generate headline title until user edit && update headline extraction
* when title format is set to $, keep generating headline title until user manually edits the title
* extract headline from first html tag with content rather than first paragraph

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

* core: extract headline up to 150 chars regardless of html tag
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>

* core: improve note headline title code quality
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>

* core: remove HEADLINE_CHARACTER_LIMIT constant
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>

* web: only update title input if note title changes

---------

Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
Co-authored-by: Abdullah Atta <abdullahatta@streetwriters.co>
2025-04-10 10:17:45 +05:00
01zulfi
8a431fb79b web: add publish:update item in note menu options (#7664)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-04-07 11:21:12 +05:00
01zulfi
12cfc0dafd web: clear query when search is closed (#7700)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-04-07 11:19:49 +05:00
Ammar Ahmed
93c8a1827c editor: increase drop-cursor width 2025-03-28 14:25:59 +05:00
Ammar Ahmed
ca60eda7f2 editor: fix checklist item size 2025-03-28 14:25:59 +05:00
Ammar Ahmed
c22c51791e editor: fix task-list item alignment 2025-03-28 14:25:59 +05:00
01zulfi
d5a719c9f6 editor: font ligatures for common symbols (#7800)
* editor: font ligatures for common symbols
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>

* Update packages/editor/src/extensions/font-ligature/font-ligature.ts

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-03-28 14:13:02 +05:00
Abdullah Atta
904c452cfe web: bump version to v3.0.32 2025-03-28 12:45:32 +05:00
Ammar Ahmed
2078ef9081 editor: do not use look behind regex (#7809) 2025-03-28 12:34:26 +05:00
Ammar Ahmed
fc9ee5bee1 mobile: release v3.0.34 2025-03-28 12:32:42 +05:00
01zulfi
d27595cfd9 web: pinned tab fixes (#7692)
* web: pinned tab fixes
* fix pinned tab not working after page reload
* fix note opening in new tab even if its tab is present when active note is pinned

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

* web: fix focusing pinned tab after reloading app

---------

Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
Co-authored-by: Abdullah Atta <abdullahatta@streetwriters.co>
2025-03-27 16:00:50 +05:00
Abdullah Atta
b618386e6b web: clear caches on switching release track 2025-03-26 15:30:12 +05:00
Abdullah Atta
2e79b2c7a2 core: run trash cleanup after sync completion 2025-03-26 13:44:16 +05:00
01zulfi
4e4990bd98 web: add toggle focus mode command (#7736)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-03-25 12:09:19 +05:00
Abdullah Atta
4c8a44353a web: bump version to 3.0.31 2025-03-24 14:32:27 +05:00
Abdullah Atta
7dd8b13bc8 web: fix tests 2025-03-24 14:32:27 +05:00
01zulfi
e1aa3b59be web: add reset zoom button (#7750)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-03-24 12:36:01 +05:00
01zulfi
d79888793a web: mask email in session expired page description (#7783)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-03-24 12:34:57 +05:00
Abdullah Atta
b56e381022 web: fix editor cursor jumping to start on creating a new note 2025-03-24 12:28:30 +05:00
Ammar Ahmed
15b32b312d ci: use actions/cache v3
Signed-off-by: Ammar Ahmed <40239442+ammarahm-ed@users.noreply.github.com>
2025-03-17 16:39:44 +05:00
Ammar Ahmed
6a0a00f126 ci: use actions/checkout v3
Signed-off-by: Ammar Ahmed <40239442+ammarahm-ed@users.noreply.github.com>
2025-03-17 16:38:25 +05:00
Ammar Ahmed
9876c2ef6d mobile: bump version 2025-03-17 16:34:07 +05:00
Ammar Ahmed
fba29e3c80 mobile: fix sharing image from ios share sheet 2025-03-17 16:25:08 +05:00
Ammar Ahmed
b8275f5a3f Fix creating backups ios (#7777)
* mobile: fix copying file from app group during backup

* mobile: catch and show error if copying file fails during backup
2025-03-17 16:24:04 +05:00
01zulfi
b7e8365117 web: increase reminder dialog width (#7767)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-03-14 12:24:21 +05:00
Ammar Ahmed
8df7b5c56b web: fix editor rerendering on session type change from new to default (#7759)
* web: fix editor rerendering on session type change from new to default

* web: fix multiple notes created on typing new note
2025-03-14 11:57:16 +05:00
01zulfi
04519d1db7 editor: fix scroll into view when used by toc (#7764)
* add scroll-margin-top: 35px

Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-03-14 11:55:55 +05:00
Ammar Ahmed
7b808bea0b web: fix ui flicker in editor when creating new note (#7761) 2025-03-12 13:16:13 +05:00
Ammar Ahmed
2878f1d9cf editor: ensure consistent gap between heading and first element in callout (#7757) 2025-03-12 13:11:14 +05:00
Ammar Ahmed
651f6011b8 desktop: release v3.0.30 2025-03-06 15:56:02 +05:00
Ammar Ahmed
f17cbb5aa3 web: release v3.0.30 2025-03-06 15:55:51 +05:00
Ammar Ahmed
a2a4a165a5 editor: fix item margins in editor (#7744) 2025-03-06 15:49:51 +05:00
Ammar Ahmed
9c7ff38f99 editor: fix image padding in readonly mode (#7743)
* editor: fix image padding in readonly mode

* editor: fix class name
2025-03-06 15:46:03 +05:00
01zulfi
76f27adbea web: command palette fixes (#7669)
* web: command palette fixes
* core: add getIdentifier in fuzzy; this allows the caller to provide a custom indentifier instead of relying on id field in the items list
* fix crashing when hitting enter when no results found
* fix commands list not refreshing when removing recent command
* fix recent command not showing up in the commands list
* fix searched commands showing up under wrong group label

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

* web: improve getCommandById && improve remove from recents logic
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>

---------

Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-03-04 13:11:26 +05:00
01zulfi
85a5f38590 web: adding notes in tag/color should also add it to default notebook (#7732)
* when default notebook is set, adding notes in tag and color context should also add that note to default notebook
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-03-04 13:00:43 +05:00
01zulfi
dcdd876a4c web: align note title with rest of ui (#7731)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-03-04 09:54:57 +05:00
Abdullah Atta
d055908809 ci: build in beta mode when release track is beta 2025-03-01 15:31:28 +05:00
Abdullah Atta
89806148b2 ci: run apt-get update before installing flatpak etc 2025-03-01 14:55:39 +05:00
Abdullah Atta
433be12b2b desktop: hide release track selector for flatpak/snap builds 2025-03-01 14:49:38 +05:00
Abdullah Atta
9ff235e767 ci: change working-directory to ./apps/web before deployment 2025-03-01 13:19:18 +05:00
Abdullah Atta
9b6f7ff225 web: fix release track switching 2025-03-01 13:13:25 +05:00
Abdullah Atta
99f97ac565 web: fix release-track cookie not getting set 2025-03-01 11:41:37 +05:00
Abdullah Atta
7e598098fe ci: add support for publishing web app beta 2025-03-01 11:15:03 +05:00
Abdullah Atta
02afbf6c90 web: only redirect to beta if env.BETA_BASE_URL is present 2025-03-01 11:07:40 +05:00
Abdullah Atta
b464fafc18 web: bump version to 3.0.29 2025-03-01 11:05:26 +05:00
Abdullah Atta
e06320108b web: fix gap between title and editor on entering focus mode 2025-03-01 10:50:38 +05:00
Abdullah Atta
a377b13e2b editor: fix single & double spaced paragraph margins 2025-03-01 10:40:27 +05:00
Abdullah Atta
4728212531 core: fix tags & notebooks search 2025-03-01 10:23:58 +05:00
01zulfi
71fc2a3cac web: add keyboard shortcut for opening settings (#7701)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-03-01 09:31:23 +05:00
01zulfi
303282624e editor: hide hover popup if right click occurs before popup is shown (#7687)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-03-01 09:23:26 +05:00
01zulfi
2ca02937df editor: open internal links in new tab for middle mouse click (#7688)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-03-01 09:22:47 +05:00
Abdullah Atta
00b62df2e8 desktop: fix tests on windows 2025-02-28 18:03:05 +05:00
Abdullah Atta
6d377ded9a desktop: set APPIMAGE to true when testing linux to allow auto updater to work 2025-02-28 18:03:05 +05:00
Abdullah Atta
087c404225 desktop: fix tests on linux 2025-02-28 18:03:05 +05:00
Abdullah Atta
4932763468 desktop: extend test timeout to 2 minutes 2025-02-28 18:03:05 +05:00
Abdullah Atta
abcc19d5da desktop: skip tsc build during tests 2025-02-28 18:03:05 +05:00
Abdullah Atta
f1ce1e9b60 desktop: enable staging mode during tests to disable code signing 2025-02-28 18:03:05 +05:00
Abdullah Atta
5a6f99a41b desktop: double test timeout on CI 2025-02-28 18:03:05 +05:00
Abdullah Atta
1862802052 desktop: pass --config arg to electron-builder everywhere 2025-02-28 18:03:05 +05:00
Abdullah Atta
1adddbdb4c desktop: add more tests for auto updater 2025-02-28 18:03:05 +05:00
Abdullah Atta
15f4f2accb desktop: add support for switching release tracks
this also includes relevant tests for the auto updater
2025-02-28 18:03:05 +05:00
Abdullah Atta
725f3c3522 web: add support for switching release tracks
we make use of Cloudflare Pages Functions to redirect to the beta site
if a certain cookie is present. This ensures seamless switching between
release tracks.
2025-02-28 18:03:05 +05:00
01zulfi
efa73a1c32 web: update toast position (#7665)
* current position would overlap slightly with the status bar, this commit moves the toast a little higher so it doesn't overlap
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-02-25 13:21:57 +05:00
Abdullah Atta
00250c6669 web: bump version to v3.0.28 2025-02-25 11:41:46 +05:00
01zulfi
d11afda1a8 web: fix attachment table height for few items (#7662)
* assign min-height to container
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-02-25 11:39:44 +05:00
Abdullah Atta
1350784c33 editor: allow other permissions to iframe embeds 2025-02-25 11:00:52 +05:00
Abdullah Atta
1852a216a2 editor: fix Applying mismatched transaction errors on editor load
fixes #7656
2025-02-25 11:00:31 +05:00
Abdullah Atta
422c2492c4 web: fix react error on feature dialog 2025-02-25 10:10:06 +05:00
Abdullah Atta
c9c72741b3 desktop: fix app icon size on macos 2025-02-24 12:58:44 +05:00
Abdullah Atta
99dbcaff7d web: make tabs tests more resilient 2025-02-24 12:19:21 +05:00
Abdullah Atta
8d83f5474d web: fix editor tests 2025-02-24 11:53:51 +05:00
Abdullah Atta
a912a1a22e web: fix invalid usage of sessionId as noteId 2025-02-24 11:53:41 +05:00
Abdullah Atta
ea7afbe93e web: fix invalid usage of closeSessions 2025-02-24 11:53:18 +05:00
Abdullah Atta
7b2a8c3e20 web: fix executing recent command does nothing
fixes #7650
2025-02-24 11:16:38 +05:00
Abdullah Atta
911adfc151 web: fix reloading app loses the expanded size of a collapsed pane 2025-02-24 11:11:03 +05:00
Abdullah Atta
23f710856e web: fix collapsed pane cannot be resized 2025-02-24 11:10:37 +05:00
Abdullah Atta
7f6274821c web: fix title auto resizing on firefox 2025-02-24 10:48:11 +05:00
Abdullah Atta
4700843517 web: fix note content loading in editor
this broke when we migrated to the new tabs logic and was fixed by
using `editor.updateContent` which is significantly slower than
creating a new editor/editor view. This commit fixes that by
depending on the `getContent` function which changes whenever the
content is changed in a session handling all kinds of different
cases.
2025-02-24 10:38:37 +05:00
Abdullah Atta
8823054227 editor: disable suspiciousAttributes check in prosemirror
this check causes a significant slowdown when loading notes with huge
amount of nodes as it recursively scans the attributes of all the
nodes. Disabling this speeds up loading significantly but might
cause issues in some special cases. Fortunately, this error has never
been triggered by anyone in Notesnook. I wouldn't recommend anyone to
disable this without first testing it properly as it might expose you
to cross site scripting attacks.
2025-02-24 10:36:18 +05:00
Abdullah Atta
7c63a3e004 editor: optimize @tiptap/core
this optimizes the following functions in @tiptap/core:

- `mergeAttributes`
- `getRenderedAttributes`
- `injectExtensionAttributesToParseRule`

These functions stood out the most in the profiler.
2025-02-24 10:33:13 +05:00
Abdullah Atta
2a59154268 editor: improve note loading performance
this commit gets rid of the custom logic when loading a new note in
the same editor. Instead, we just create a new view in the same
editor which seems to be much faster then just replacing the state
of the old view.
2025-02-24 10:31:35 +05:00
Abdullah Atta
ed15d53484 editor: fix block-id extension slowing down pasting
we were using `tr.setNodeMarkup` which created a new step for each
node. If there were a lot of nodes, it'd cause an exponential slow
down. As an alternative, we are directly updating the node's blockId
attribute which is against the spec but it works and it's fast.
2025-02-22 09:42:33 +05:00
Abdullah Atta
fc8a4bb55d ci: run desktop build in ubuntu-24.04 2025-02-21 15:07:53 +05:00
Abdullah Atta
dd1c1bb11d ci: use apt-get with --quiet 2025-02-21 15:03:10 +05:00
Abdullah Atta
3ffbad5727 theme-builder: make theme builder compile again 2025-02-21 14:52:38 +05:00
Abdullah Atta
207ae39d13 ci: run web tests on 5 shards (instead of 4) 2025-02-21 14:34:02 +05:00
Abdullah Atta
ae141ac9c5 web: fix control + alt + right/left arrow tests 2025-02-21 14:26:50 +05:00
Abdullah Atta
40f058b14b web: bump version to v3.0.27 2025-02-21 13:13:53 +05:00
Abdullah Atta
865c9f3e32 web: remove check that compares note title with session title 2025-02-21 13:10:27 +05:00
Abdullah Atta
26df9bfdd8 web: fix editing a note and switching immediately to another note and editing the title shouldn't overlap both notes test 2025-02-21 13:04:53 +05:00
Abdullah Atta
1e52e01fb8 web: fix debug strings showing in production builds 2025-02-21 12:39:44 +05:00
01zulfi
5fece5faaa web: fix note title sync if note is opened in multiple tabs (#7636)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-02-21 12:36:07 +05:00
01zulfi
d7fdaf6c46 ui: fix submenu positioning (#7632)
position.top wasn't calculated correctly for the out of screen height case for non-mouse target

Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-02-21 12:34:10 +05:00
Abdullah Atta
8e1faf9f60 web: command palette improvements
This includes:

- Full refactoring of the command palette
- Remove command transformation logic for dynamic
commands
- Replace note, notebook & tag specific commands
with a simple menu item -> command conversion logic
- Cached filtering (with notes, notebooks etc.
refetching on sync)
- Add support for fuzzy searching on command group
- Modernize UI to look more like a command palette and less like a dialog
2025-02-21 12:29:25 +05:00
Abdullah Atta
9dce39b32d core: reuse fuzzy search logic 2025-02-21 12:29:25 +05:00
Abdullah Atta
80a0b75887 core: remove matchOnly logic from fuzzy searcher
Search should always filter out the results, not return everything.
2025-02-21 12:29:25 +05:00
Abdullah Atta
c9704e1031 core: remove titleOnly lookup tests 2025-02-21 12:29:25 +05:00
Abdullah Atta
31e32cd154 core: fix query transformer tests 2025-02-21 12:29:25 +05:00
Abdullah Atta
61c296fc37 core: improve fuzzy filter lookup api to be more robust
- add ability to wrap matching text in prefix/suffix
- return match score for further sorting etc.
- fetch everything eagerly (instead of iterating on matches) for perf
- add support for ignoring fields (i.e. ignore id field)
2025-02-21 12:29:25 +05:00
Abdullah Atta
c8d38235b2 web: close command palette if already open on Ctrl/Cmd+K/P 2025-02-21 12:29:25 +05:00
Abdullah Atta
b717a64607 web: add support for closing dialogs imperatively 2025-02-21 12:29:25 +05:00
01zulfi
0f2b1d3e14 web: fix tags not adding/removing in note header bar (#7623)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-02-20 13:02:49 +05:00
Ammar Ahmed
4abefe63db core: fix error can't resolve './fuzzy' 2025-02-20 10:49:03 +05:00
Abdullah Atta
fc31b2a8d7 web: pressing escape key shouldn't exit fullscreen mode in firefox 2025-02-19 16:04:21 +05:00
01zulfi
2708bac4fb web: wrap & remove auto-resize of note title (#7290)
* web: wrap & remove auto-resize of note title
* wrap note title if it overflows
* remove auto-resizing of note title based on its length
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>

* web: remove newlines in title textarea

---------

Co-authored-by: Abdullah Atta <abdullahatta@streetwriters.co>
2025-02-19 15:56:36 +05:00
01zulfi
a47967dd53 web: add command palette (#7314)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-02-19 15:48:44 +05:00
01zulfi
53ba5562d3 intl: fix account casing (#7624)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-02-19 14:13:49 +05:00
three-b0dy
347df32943 monograph: fix docker build for aarch64 (#7622)
--platform=$BUILDPLATFORM will overwrite buildx settings

Signed-off-by: three-b0dy <120573565+three-b0dy@users.noreply.github.com>
2025-02-19 14:03:52 +05:00
01zulfi
ac8c63526b editor: add scroll margin & threshold props (#7292)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-02-18 12:27:55 +05:00
01zulfi
a48bd360ca editor: improve hr & p styling (#7489)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-02-17 12:10:10 +05:00
Ammar Ahmed
f476969e9e mobile: pinned tab changes 2025-02-17 11:58:26 +05:00
Abdullah Atta
c45539dea6 web: add tests for pinned tabs 2025-02-17 11:58:26 +05:00
Abdullah Atta
d8f5815b84 web: disable opening new note in pinned tab 2025-02-17 11:58:26 +05:00
Abdullah Atta
2eaf07118a web: open note history in new tab if active tab is pinned 2025-02-17 11:58:26 +05:00
Abdullah Atta
b636b09a96 web: disable all kinds of navigation in pinned tabs 2025-02-17 11:58:26 +05:00
Abdullah Atta
c16bbcaad5 editor: add support for pasting as markdown 2025-02-17 11:57:24 +05:00
Abdullah Atta
49ffcbea03 editor: fix youtube embeds 2025-02-17 10:30:12 +05:00
Waqar Ahmed
f772cf0f14 editor: fix search in complex elements like tables (#7605)
The current search algorithm while accumulating text assumes that the
text nodes are always followed by a paragraph node with endPos ==
textNode.endPos + 1. This is not true for complex text elements like
tables where the endPos can be higher. Thus the start,end offsets of
TextNodesWithPosition start getting off and results in incorrectly
highlighted search results.

To fix this, simplify the TextNodesWithPosition to only hold start
position and offset since startPos is always correct. We can calculate
the end position on the fly by simply adding text length to startPos.

Issue #7431

Signed-off-by: Waqar Ahmed <waqar.17a@gmail.com>
2025-02-17 10:16:55 +05:00
Abdullah Atta
3f1406a05b monograph: bump version to v1.2.4 2025-02-15 23:39:37 +05:00
Abdullah Atta
21760b2b74 monograph: add a strict csp 2025-02-15 23:38:52 +05:00
Ammar Ahmed
d8011f0239 mobile: release v3.0.31 2025-02-14 15:07:12 +05:00
Ammar Ahmed
b9a8b054e2 Fix sharing screenshot on iOS does not work (#7589) 2025-02-14 15:05:18 +05:00
Abdullah Atta
2ab321869e web: bump version to v3.0.26 2025-02-14 10:08:43 +05:00
Abdullah Atta
fcb45a24d6 monograph: use latest version of bun in prod 2025-02-14 09:57:07 +05:00
Abdullah Atta
7cdb13def6 Merge pull request #7588 from streetwriters/fix/tighten-iframe-security
This fixes a potential security vulnerability where pasting unknown content into the editor could create an RCE risk.

This PR fixes two issues:

1. Potential RCE when pasting/inserting an `iframe` containing a `javascript` link.
2. Potential RCE when pasting/inserting an `svg` containing JavaScript (why do SVGs allow JS in the first place?).

Mitigations include disallowing all execution of JS inside an SVG by rendering it in a sandboxed `iframe`. While we cannot disallow JS execution in embeds (that would break all embeds like YouTube videos), we have disallowed access to the parent window to all `iframe`s, again, by using a sandboxed `iframe` and by disallowing embedding of `javascript:` links.

To be clear, both of these issues can only be triggered when pasting/importing untrusted content (which you shouldn't be doing anyway).

**These cannot be used to steal or access your notes or any other data. They could be used to access what's shown in the window or do automated clicks etc. but since everything is stored and access from an encrypted SQLite database, your data would be 100% safe and isolated from such an attack.**
2025-02-14 09:50:43 +05:00
Abdullah Atta
2ab58f9203 editor: use sandboxed iframe to render SVGs 2025-02-14 09:31:06 +05:00
Abdullah Atta
df74448e17 editor: disallow embedding javascript code in iframes 2025-02-13 20:27:21 +05:00
01zulfi
ada98fca93 web: hide undo & redo buttons for readonly notes (#7541)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-02-13 10:13:44 +05:00
Yash Kumar
1d3650659f editor: select language by pressing enter (#7484)
Signed-off-by: Yash Kumar <kyash03@student.ubc.ca>
2025-02-13 10:12:37 +05:00
Ammar Ahmed
9b43af475b mobile: release v3.0.31 2025-02-11 14:01:11 +05:00
Ammar Ahmed
d9c592c7fb common: always remove the last session from history (#7555) 2025-02-11 13:31:39 +05:00
Ammar Ahmed
f10ac9fbb5 Merge pull request #7556 from streetwriters/fix-tabs-mobile
Fix tabs on mobile
2025-02-11 13:12:12 +05:00
Ammar Ahmed
b7334c09d4 Merge branch 'master' into fix-tabs-mobile
Signed-off-by: Ammar Ahmed <40239442+ammarahm-ed@users.noreply.github.com>
2025-02-11 13:11:55 +05:00
Ammar Ahmed
0cd3bd5739 mobile: fix dialog calling onClose after pressing positive button 2025-02-11 13:11:13 +05:00
Ammar Ahmed
33d69480eb mobile: fix ts errors 2025-02-11 13:11:02 +05:00
Ammar Ahmed
5cae4eb0d9 mobile: add null checks before setting items on storage 2025-02-11 12:18:28 +05:00
Ammar Ahmed
840c7fda5e mobile: fix loading placeholder 2025-02-11 12:17:45 +05:00
Ammar Ahmed
4ce24ac8fd mobile: do not show sheet in uncaught errors in editor 2025-02-11 12:17:11 +05:00
Ammar Ahmed
ae9e80e12e mobile: fix stuck at loading in editor 2025-02-11 12:16:51 +05:00
luis-411
43356e5b6a core: escape special characters in SQL search query (#7418)
Signed-off-by: Luis Kriner <luis@kriner.info>
2025-02-11 11:00:51 +05:00
xa4hf8
7b13f35424 desktop: replace corrupt Mac icons bundle (#7542)
There is a long-standing bug in Electron builder that generates corrupt Macintosh icon bundles. The issue is visible in Finder "list" view.  This file is correct and was created on Mac with https://github.com/alptugan/icns-creator/

Signed-off-by: xa4hf8 <174972649+xa4hf8@users.noreply.github.com>
2025-02-11 10:54:50 +05:00
luis-411
0517c6ce41 web: fix status-bar not visible on medium sized screens (#7493)
Signed-off-by: Luis Kriner <luis@kriner.info>
2025-02-08 19:31:37 +05:00
01zulfi
54d06328c1 web: add tab keyboard shortcuts (#7322)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-02-08 19:30:20 +05:00
Ammar Ahmed
c74677acd4 mobile: restore settings on logout (#7423) 2025-02-05 09:30:00 +05:00
01zulfi
7689e1a7c5 web: keep some configs in local storage on logout (#7436)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-02-05 09:29:36 +05:00
luzpaz
5ffae2a08b global: fix various typos (#7463)
Found via `codespell -q 3 -D ../dictionary.txt -S "*.patch,*.po" -L actualy,childs,modifer,ontext,ontop,ony,recieved,reciever,se,seperator,te`

Signed-off-by: Luz Paz <luzpaz@pm.me>
2025-02-05 09:28:06 +05:00
Ammar Ahmed
5fa80abdc8 mobile: update changelog 2025-02-04 19:25:16 +05:00
Ammar Ahmed
a30598fedf mobile: release v3.0.30 2025-02-04 19:23:49 +05:00
Ammar Ahmed
48ffecfb5f mobile: fix e2e tests 2025-02-04 19:23:11 +05:00
Ammar Ahmed
89fe712104 mobile: fix file size is 0 errors when downloading attachments 2025-02-04 17:36:46 +05:00
Ammar Ahmed
5dd298ee86 mobile: fix unlocking note with biometrics 2025-02-04 17:36:32 +05:00
Ammar Ahmed
275b285a8b mobile: release v3.0.29 2025-02-04 12:39:04 +05:00
Ammar Ahmed
96310a46e9 mobile: fix configure note activity not showing biometric unlock prompt 2025-02-04 12:33:05 +05:00
Ammar Ahmed
42f9bf1593 mobile: fix opening widget note on app launch 2025-02-04 12:33:05 +05:00
Ammar Ahmed
25aab6913a mobile: show progress when taking backup and allow to hide backup dialog 2025-02-04 12:32:51 +05:00
Ammar Ahmed
3bd7da68be mobile: fix crash on app launch with new tabs 2025-02-04 12:32:30 +05:00
Abdullah Atta
a218738eff web: improve unfocused window ui 2025-02-04 11:11:51 +05:00
Abdullah Atta
8bf283b3bc config: add *.patch files to .gitignore 2025-02-04 10:14:59 +05:00
luis-411
cb09430ff4 web: fix subnotebook title not updating on navigate (#7286)
Signed-off-by: Luis Kriner <luis@kriner.info>
2025-02-04 10:06:59 +05:00
luis-411
66d75492bb editor: fix task list stats 0/0 on app reload (#7327)
Signed-off-by: Luis Kriner <luis@kriner.info>
2025-02-04 10:04:16 +05:00
Abdullah Atta
d772d38dc7 web: fix collapsed pane expanding on app reload 2025-02-04 09:35:04 +05:00
Ammar Ahmed
46a74f9512 mobile: release v3.0.28 2025-02-03 15:45:54 +05:00
Ammar Ahmed
7df1037e3f mobile: fix realtime sync editor updates in tabs 2025-02-03 15:38:32 +05:00
Abdullah Atta
5c3136d07d ci: run actions on ubuntu-22.04 2025-02-03 14:57:30 +05:00
Abdullah Atta
6a9ddb770e web: bump version to 3.0.25 2025-02-03 14:39:44 +05:00
Abdullah Atta
f4c54fd27f web: fix crash on setting a reminder 2025-02-03 14:22:58 +05:00
Ammar Ahmed
05b12df7d7 mobile: cache password when restoring backup 2025-02-03 14:16:46 +05:00
Ammar Ahmed
dcf053eede mobile: call onClose when closing dialog 2025-02-03 14:16:46 +05:00
Abdullah Atta
5430966b02 web: fix tabs are not clickable everywhere 2025-02-03 13:25:17 +05:00
Ammar Ahmed
7271140627 mobile: fix release notes rendering 2025-02-03 13:02:06 +05:00
01zulfi
eb5ae0773b editor: fix hover styling in toolbar color buttons
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-02-03 12:36:06 +05:00
Ammar Ahmed
9661dd0c5e mobile: fix android widget bugs 2025-02-03 12:19:53 +05:00
Ammar Ahmed
8e70860918 mobile: fix attaching a file in new note editor 2025-02-03 12:19:34 +05:00
Ammar Ahmed
3540ecf4ab mobile: close sheet on backup completed 2025-02-03 12:19:17 +05:00
Ammar Ahmed
f1dba9ffc2 mobile: cleanup 2025-02-03 12:17:57 +05:00
Abdullah Atta
3f1761a540 core: fix empty note cannot be exported 2025-02-03 12:17:57 +05:00
Abdullah Atta
a25d21038a core: fix Object is not iterable error on some platforms
This happened due to [Symbol.asyncIterable] not getting
transformed when it was a method of a class. Moving it inside
another method fixes the issue.
2025-02-03 12:17:57 +05:00
Abdullah Atta
d55a6a6fc0 web: fix pinned tab not moving to the beginning 2025-02-03 10:46:24 +05:00
Abdullah Atta
e5cf902780 web: fix unnecessary rerenders of the tab strip 2025-02-03 10:01:52 +05:00
Abdullah Atta
a99996fcf6 web: fix tab drag/drop 2025-02-03 09:52:00 +05:00
Abdullah Atta
0cc9c31bc3 editor: fix Failed to execute 'collapse' on 'Selection' 2025-02-01 15:14:34 +05:00
Abdullah Atta
62da8484ad web: ignore notes in other tabs when navigating back 2025-02-01 14:26:12 +05:00
Ammar Ahmed
821b8eebaa mobile: fix tab issues 2025-02-01 13:47:27 +05:00
Ammar Ahmed
269941c297 mobile: keep all datatype classes 2025-02-01 13:47:27 +05:00
Abdullah Atta
e37ff88f1f web: fix flicker when opening a note in new tab 2025-02-01 13:38:48 +05:00
Abdullah Atta
1a1b4bc43c web: fix note already opened in another tab is not focused 2025-02-01 13:18:31 +05:00
Abdullah Atta
2c59df9fb7 web: remove unused code from action-bar 2025-02-01 12:58:53 +05:00
Abdullah Atta
4fc30cc224 web: move focus mode and editor margins to status bar 2025-02-01 12:57:55 +05:00
Abdullah Atta
9bd7d392af web: fix zoom buttons ui 2025-02-01 12:27:51 +05:00
Abdullah Atta
3bcd288bc7 web: more compact and unified action bar 2025-02-01 12:18:47 +05:00
Ammar Ahmed
3b86e51c49 mobile: fix commands 2025-01-31 15:17:45 +05:00
Abdullah Atta
c286b1d595 web: use new storage key for storing editor sessions 2025-01-31 15:15:48 +05:00
Abdullah Atta
2f6b1e6bcc web: fix rapidly clicking on back/forward buttons opened new tab 2025-01-31 15:15:48 +05:00
Abdullah Atta
abb918e179 web: fix tests 2025-01-31 15:15:48 +05:00
Abdullah Atta
dd0dc09977 web: fix note version can't be restored 2025-01-31 15:15:48 +05:00
Abdullah Atta
211ab47165 web: save selection state before switching note 2025-01-31 15:15:48 +05:00
Abdullah Atta
bc44e28e1e web: remove more usages of session.id where noteId was expected 2025-01-31 15:15:48 +05:00
Abdullah Atta
ade60e4272 web: move tab navigation keyboard shortcuts to key-map.ts 2025-01-31 15:15:48 +05:00
Abdullah Atta
3f5bfcb499 web: focus tab if note is already opened in one & reuse sessions for note 2025-01-31 15:15:48 +05:00
Abdullah Atta
782a979397 web: handle case where a new note session is in the tab history 2025-01-31 15:15:48 +05:00
Abdullah Atta
e7f1e2d533 web: add support for opening a session without focusing the tab 2025-01-31 15:15:48 +05:00
Abdullah Atta
12e5f2acc1 web: fix focus next/prev tab not working 2025-01-31 15:15:48 +05:00
Abdullah Atta
dccc79ace3 web: remove usage of session.id in places where note id is expected 2025-01-31 15:15:48 +05:00
Abdullah Atta
a9a5ba09ff web: activate a new note session on tab rehydration 2025-01-31 15:15:48 +05:00
Abdullah Atta
a6c8bbbf0a web: reactivate same session if user tries to create consecutive new notes 2025-01-31 15:15:48 +05:00
Abdullah Atta
e19e9eb96f web: get fresh note context when saving a new note 2025-01-31 15:15:48 +05:00
Ammar Ahmed
9208140b97 mobile: improve tab button 2025-01-31 15:15:48 +05:00
Ammar Ahmed
8241bb8ae5 mobile: fix opening tab for the first time 2025-01-31 15:15:48 +05:00
Ammar Ahmed
329c2e220f mobile: fix tabs 2025-01-31 15:15:48 +05:00
Abdullah Atta
140e343289 common: allow using custom session id in tab session history 2025-01-31 15:15:48 +05:00
Abdullah Atta
0d99367a93 web: fix title not updating in real time sync 2025-01-31 15:15:48 +05:00
Abdullah Atta
b802b3e165 web: fix diff session not opening in editor 2025-01-31 15:15:48 +05:00
Ammar Ahmed
46583e12d9 mobile: update tabs 2025-01-31 15:15:48 +05:00
Abdullah Atta
c9a3f31e8f web: add more tests 2025-01-31 15:15:48 +05:00
Abdullah Atta
53f68aaf81 web: add tests for new tab button 2025-01-31 15:15:48 +05:00
Abdullah Atta
f31df9a6cc web: add tests for new tabs 2025-01-31 15:15:48 +05:00
Abdullah Atta
c812581bb9 web: add support for new tab navigation 2025-01-31 15:15:48 +05:00
Abdullah Atta
1e6e940f17 common: string tab ids, get rid of currentTab taking tab id as a parameter 2025-01-31 15:15:48 +05:00
Ammar Ahmed
9ab670d933 mobile: fix deps 2025-01-31 15:15:48 +05:00
Ammar Ahmed
c46e57418b mobile: remove unused properties 2025-01-31 15:15:48 +05:00
Ammar Ahmed
83557401f5 mobile: update tabs 2025-01-31 15:15:48 +05:00
Ammar Ahmed
2277644e89 mobile: cleanup 2025-01-31 15:15:48 +05:00
Ammar Ahmed
5eb09a1d3e mobile: cleanup 2025-01-31 15:15:48 +05:00
Ammar Ahmed
d957be7a7b mobile: fix editor header ui 2025-01-31 15:15:48 +05:00
Ammar Ahmed
44ddb49d0e editor: fix imports 2025-01-31 15:15:48 +05:00
Ammar Ahmed
24fcd5cd0c common: fix missing exports 2025-01-31 15:15:48 +05:00
Ammar Ahmed
2a34225d49 global: update deps 2025-01-31 15:15:48 +05:00
Ammar Ahmed
e81c825fc7 mobile: multi-tab support 2025-01-31 15:15:48 +05:00
Ammar Ahmed
c80286b587 mobile: tab history 2025-01-31 15:15:48 +05:00
luis-411
e85f8b60b0 editor: add field labels to add a link popup (#7097)
Signed-off-by: Luis Kriner <luis@kriner.info>
2025-01-31 10:11:59 +05:00
luis-411
5daa99d969 web: fix nav menu collapse (#7377)
Signed-off-by: Luis Kriner <luis@kriner.info>
2025-01-30 09:09:28 +05:00
01zulfi
073bb576b5 editor: fix search not resetting when closed (#7415)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-01-29 11:23:26 +05:00
Abdullah Atta
eaeac130df Revert "intl: update lockfile"
This reverts commit 95a20b3740.
2025-01-29 10:22:18 +05:00
Abdullah Atta
b21519c24e ci: include bundled electron app in desktop build 2025-01-29 10:22:18 +05:00
Abdullah Atta
4f9fe9b1e0 Revert "intl: update lockfile"
This reverts commit f657380ec7.
2025-01-28 14:49:12 +05:00
Abdullah Atta
f657380ec7 intl: update lockfile 2025-01-28 14:20:41 +05:00
Abdullah Atta
05b2e559d8 setup: downgrade tsup version 2025-01-28 13:33:29 +05:00
Abdullah Atta
ab21f02c2d ci: include intl, theme-builder & monograph in npm cache 2025-01-28 13:07:50 +05:00
Abdullah Atta
12b51ed72a intl: update lockfiles 2025-01-28 13:04:19 +05:00
Abdullah Atta
b672fd540c setup: generate sources for intl package 2025-01-28 12:50:42 +05:00
Abdullah Atta
95a20b3740 intl: update lockfile 2025-01-28 11:25:38 +05:00
Abdullah Atta
6f5a7a4923 global: use same version for @lingui deps everywhere 2025-01-28 10:45:04 +05:00
Ammar Ahmed
1b4d98ac0e mobile: fix strings not rendering correctly in editor 2025-01-22 15:23:56 +05:00
Ammar Ahmed
ef2ed2bba0 mobile: show toast when changing some settings 2025-01-22 14:03:52 +05:00
748 changed files with 71009 additions and 43909 deletions

View File

@@ -14,6 +14,8 @@ runs:
apps/mobile/package-lock.json
apps/desktop/package-lock.json
apps/web/package-lock.json
apps/monograph/package-lock.json
apps/theme-builder/package-lock.json
extensions/web-clipper/package-lock.json
packages/core/package-lock.json
packages/crypto/package-lock.json
@@ -24,3 +26,4 @@ runs:
packages/logger/package-lock.json
packages/streamable-fs/package-lock.json
packages/theme/package-lock.json
packages/intl/package-lock.json

View File

@@ -4,7 +4,7 @@ on: workflow_dispatch
jobs:
build:
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
timeout-minutes: 40
env:
CMAKE_C_COMPILER_LAUNCHER: ccache
@@ -22,7 +22,7 @@ jobs:
- name: Use specific Java version for the builds
uses: joschi/setup-jdk@v2
with:
java-version: "11"
java-version: "17"
architecture: "x64"
- name: Install node modules
@@ -58,7 +58,7 @@ jobs:
ccache -p
- name: Cache gradle
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: |
~/.gradle/caches
@@ -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
@@ -129,7 +127,7 @@ jobs:
serviceAccountJsonPlainText: ${{ secrets.SERVICE_ACCOUNT_JSON }}
packageName: com.streetwriters.notesnook
releaseFiles: ${{steps.sign_app.outputs.signedReleaseFile}}
track: alpha
track: beta
status: completed
whatsNewDirectory: apps/mobile/native/android/releasenotes/
@@ -138,7 +136,7 @@ jobs:
with:
draft: true
tag_name: ${{ steps.package-version.outputs.current-version}}-beta-android
name: Notesnook Android v${{ steps.package-version.outputs.current-version}} Beta
name: Notesnook Android v${{ steps.package-version.outputs.current-version}}
repository: streetwriters/notesnook
token: ${{ secrets.GITHUB_TOKEN }}
files: |
@@ -146,6 +144,7 @@ jobs:
apps/mobile/native/android/app/build/outputs/apk/release/notesnook-armeabi-v7a.apk
apps/mobile/native/android/app/build/outputs/apk/release/notesnook-x86.apk
apps/mobile/native/android/app/build/outputs/apk/release/notesnook-x86_64.apk
${{steps.sign_app.outputs.signedReleaseFile}}
- name: Upload sourcemaps
uses: actions/upload-artifact@v4

View File

@@ -58,7 +58,7 @@ jobs:
ccache -p
- name: Cache gradle
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: |
~/.gradle/caches
@@ -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

@@ -18,7 +18,7 @@ on:
jobs:
test:
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4

View File

@@ -33,11 +33,19 @@ on:
required: true
default: true
description: "Build for macOS?"
release-track:
type: choice
required: true
default: stable
description: "Select the release track"
options:
- stable
- beta
jobs:
build:
name: Build
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -49,14 +57,30 @@ jobs:
run: |
npm ci --ignore-scripts --prefer-offline --no-audit
npm run bootstrap -- --scope=web
npm run bootstrap -- --scope=desktop
- 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
- name: Setup environment
run: |
echo "NX_CLOUD_ACCESS_TOKEN=${{ secrets.NX_CLOUD_ACCESS_TOKEN }}" >> $GITHUB_ENV
- name: Generate desktop build
- name: Generate desktop build (stable)
if: ${{ inputs.release-track == 'stable' }}
run: npx nx build:desktop @notesnook/web
- name: Generate desktop build (beta)
if: ${{ inputs.release-track == 'beta' }}
run: BETA=true npx nx build:desktop @notesnook/web
- name: Build desktop bundle
working-directory: ./apps/desktop
run: npm run bundle
- name: Archive build artifact
uses: actions/upload-artifact@v4
with:
@@ -71,7 +95,8 @@ jobs:
- name: Package desktop build
run: |
zip -r ./notesnook_build_v${{ steps.app_metadata.outputs.app_version }}.zip ./apps/web/build/
cp -r ./apps/web/build ./apps/desktop/
zip -r ./notesnook_build_v${{ steps.app_metadata.outputs.app_version }}.zip ./apps/desktop/build/
echo "Build folder archived to ./notesnook_build_v${{ steps.app_metadata.outputs.app_version }}.zip"
- name: Upload desktop build
@@ -82,12 +107,14 @@ 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
run: |
sudo apt-get install -y flatpak flatpak-builder pipx
sudo apt-get update
sudo apt-get install -y --quiet flatpak flatpak-builder pipx
git clone https://github.com/flatpak/flatpak-builder-tools.git /tmp/flatpak-builder-tools
cd /tmp/flatpak-builder-tools/node
pipx install .
@@ -173,7 +200,7 @@ jobs:
CSC_KEY_PASSWORD: ${{ secrets.mac_certs_password }}
run: |
npx nx run release --project @notesnook/desktop -- --variant=mas
yarn electron-builder --mac mas --universal -p never
yarn electron-builder --config=electron-builder.config.js --mac mas --universal -p never
working-directory: ./apps/desktop
- name: Build zip and dmg
@@ -187,9 +214,9 @@ jobs:
run: |
npx nx run release --project @notesnook/desktop
if [ ${{ inputs.publish-github }} == true ]; then
yarn electron-builder --mac zip dmg --arm64 --x64 -p always
yarn electron-builder --config=electron-builder.config.js --mac zip dmg --arm64 --x64 -p always
else
yarn electron-builder --mac zip dmg --arm64 --x64 -p never
yarn electron-builder --config=electron-builder.config.js --mac zip dmg --arm64 --x64 -p never
fi
working-directory: ./apps/desktop
@@ -206,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
@@ -224,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
@@ -240,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
@@ -251,7 +277,7 @@ jobs:
- name: Build snap
if: inputs.publish-snap
run: |
yarn electron-builder --linux snap:x64 -p never
yarn electron-builder --config=electron-builder.config.js --linux snap:x64 -p never
working-directory: ./apps/desktop
- name: Build AppImage
@@ -259,18 +285,86 @@ jobs:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
if [ ${{ inputs.publish-github }} == true ]; then
yarn electron-builder --linux AppImage:x64 AppImage:arm64 -p always
yarn electron-builder --config=electron-builder.config.js --linux AppImage:x64 -p always
else
yarn electron-builder --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
@@ -321,8 +415,8 @@ jobs:
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
run: |
if ($${{ inputs.publish-github }} -eq $true) {
yarn electron-builder --win --publish always
yarn electron-builder --config=electron-builder.config.js --win --publish always
} else {
yarn electron-builder --win --publish never
yarn electron-builder --config=electron-builder.config.js --win --publish never
}
working-directory: ./apps/desktop

View File

@@ -14,7 +14,7 @@ on:
jobs:
build:
name: Build
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -69,12 +69,11 @@ jobs:
- name: Build app
run: |
yarn electron-builder --mac --dir --x64
yarn electron-builder --config=electron-builder.config.js --mac --dir --x64
working-directory: ./apps/desktop
- name: Run tests x64
run: |
EXECUTABLE_PATH=output/mac/Notesnook.app/Contents/MacOS/Notesnook npm run test
run: npm run test
working-directory: ./apps/desktop
- name: Upload test results
@@ -114,12 +113,11 @@ jobs:
- name: Build app
run: |
yarn electron-builder --mac --dir --arm64
yarn electron-builder --config=electron-builder.config.js --mac --dir --arm64
working-directory: ./apps/desktop
- name: Run tests arm64
run: |
EXECUTABLE_PATH=output/mac-arm64/Notesnook.app/Contents/MacOS/Notesnook npm run test
run: npm run test
working-directory: ./apps/desktop
- name: Upload test results
@@ -133,7 +131,7 @@ jobs:
test-linux:
name: Test for Linux
needs: build
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- name: Check out Git repository
@@ -165,12 +163,11 @@ jobs:
- name: Build app
run: |
yarn electron-builder --linux --dir --arm64 --x64
yarn electron-builder --config=electron-builder.config.js --linux --dir --arm64 --x64
working-directory: ./apps/desktop
- name: Run tests
run: |
EXECUTABLE_PATH=output/linux-unpacked/notesnook xvfb-run --auto-servernum --server-args="-screen 0 1920x1080x24" -- npm run test
run: xvfb-run --auto-servernum --server-args="-screen 0 1920x1080x24" -- npm run test
working-directory: ./apps/desktop
- name: Upload test results
@@ -216,12 +213,11 @@ jobs:
- name: Build app
run: |
npx cross-env NOTESNOOK_STAGING=true yarn electron-builder --win --dir --arm64 --x64
npx cross-env NOTESNOOK_STAGING=true yarn electron-builder --config=electron-builder.config.js --win --dir --arm64 --x64
working-directory: ./apps/desktop
- name: Run tests
run: |
npx cross-env EXECUTABLE_PATH=output/win-unpacked/Notesnook.exe npm run test
run: npm run test
working-directory: ./apps/desktop
- name: Upload test results

View File

@@ -19,7 +19,7 @@ on:
jobs:
build:
name: Build
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4

View File

@@ -11,7 +11,7 @@ on:
jobs:
build:
name: Build
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4

View File

@@ -4,16 +4,21 @@ on: workflow_dispatch
jobs:
build:
runs-on: macos-latest
runs-on: macos-14
timeout-minutes: 60
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v3
- 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
@@ -47,14 +52,17 @@ jobs:
ccache -p
- name: Cache Pods
uses: actions/cache@v2
uses: actions/cache@v3
id: pods-cache
with:
path: apps/mobile/native/ios/Pods
key: ${{ runner.os }}-pods-${{ hashFiles('apps/mobile/native/ios/Podfile.lock') }}
- name: Install Pods
run: npm run prepare:ios
run: |
cd apps/mobile/native/ios
bundle install
RCT_NEW_ARCH_ENABLED=0 bundle exec pod install
- name: CCache Stats Before Build
run: ccache -sv

View File

@@ -14,7 +14,7 @@ on: workflow_dispatch
jobs:
push_to_registry:
name: Push Docker image to Docker Hub
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
permissions:
packages: write
contents: read

View File

@@ -5,7 +5,7 @@ on: workflow_dispatch
jobs:
build:
name: Build
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4

View File

@@ -5,7 +5,7 @@ on: workflow_dispatch
jobs:
build:
name: Build
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4

View File

@@ -14,7 +14,7 @@ on:
jobs:
bench:
name: Bench
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4

View File

@@ -1,11 +1,21 @@
name: Publish @notesnook/web
on: workflow_dispatch
on:
workflow_dispatch:
inputs:
release-track:
type: choice
required: true
default: stable
description: "Select the release track"
options:
- stable
- beta
jobs:
build:
name: Build
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -24,8 +34,20 @@ jobs:
echo "CLOUDFLARE_ACCOUNT_ID=${{ secrets.CLOUDFLARE_ACCOUNT_ID }}" >> $GITHUB_ENV
echo "CLOUDFLARE_API_TOKEN=${{ secrets.CLOUDFLARE_API_TOKEN }}" >> $GITHUB_ENV
- name: Generate build
- name: Generate build (stable)
if: ${{ inputs.release-track == 'stable' }}
run: npm run build:web
- name: Publish to Cloudflare Pages
run: npx --yes wrangler pages deploy --project-name=notesnook-app ./apps/web/build/
- name: Publish to Cloudflare Pages (stable)
if: ${{ inputs.release-track == 'stable' }}
working-directory: ./apps/web
run: npx --yes wrangler pages deploy --project-name=notesnook-app ./build/
- name: Generate build (beta)
if: ${{ inputs.release-track == 'beta' }}
run: npm run build:beta:web
- name: Publish to Cloudflare Pages (beta)
if: ${{ inputs.release-track == 'beta' }}
working-directory: ./apps/web
run: npx --yes wrangler pages deploy --branch=beta --project-name=notesnook-app-beta ./build/

View File

@@ -19,7 +19,7 @@ on:
jobs:
build:
name: Build
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -49,7 +49,7 @@ jobs:
name: 🧪 Test (${{ matrix.shard }}/${{ strategy.job-total }})
strategy:
matrix:
shard: [1, 2, 3, 4]
shard: [1, 2, 3, 4, 5]
runs-on: ubuntu-latest
steps:
- name: Checkout

1
.gitignore vendored
View File

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

View File

@@ -66,7 +66,7 @@ We take all queries, issues and bug reports that you might have. Feel free to as
## Additional Resources
- [Migrating & Importing your data from other apps — Importer](https://importer.notesnook.com/)
- [Migrating & Importing your data from other apps — Importer](https://help.notesnook.com/importing-notes)
- [Privacy policy](https://notesnook.com/privacy) & [Terms of service](https://notesnook.com/terms)
- [Verify Notesnook encryption claims yourself — Vericrypt](https://vericrypt.notesnook.com/)
- [Why Notesnook requires an email address?](https://blog.notesnook.com/why-notesnook-requires-an-email-address/)

View File

@@ -2,4 +2,6 @@ node_modules
build
output
dist
_catalog
_catalog
test-results
test-artifacts

View File

@@ -58,13 +58,13 @@ 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 --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 --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 --win --publish never
npx electron-builder --config=electron-builder.config.js --win --publish never
```
Feel free to play around with the `electron-builder` command to get the packages you need. `npx electron-builder --help` is a great resource to learn different commands & platforms supported by `electron-builder`.

View File

@@ -0,0 +1,246 @@
/*
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 { test } from "vitest";
import { harness } from "./utils.js";
import { writeFile } from "fs/promises";
import { Page } from "playwright";
import { gt, lt } from "semver";
test("update starts downloading if version is outdated", async (t) => {
await harness(
t,
async ({ page }) => {
await page.waitForSelector("#authForm");
t.expect(
await page.getByRole("button", { name: "Create account" }).isVisible()
).toBe(true);
await page
.getByRole("button", { name: "Skip & go directly to the app" })
.click();
await skipDialog(page);
await page.waitForSelector(".ProseMirror");
await page
.locator(".theme-scope-statusBar")
.getByRole("button", { name: /updating/i })
.waitFor({ state: "attached" });
},
{ version: "3.0.0" }
);
});
test("update is only shown if version is outdated and auto updates are disabled", async (t) => {
await harness(
t,
async (ctx) => {
await ctx.app.close();
await writeFile(
ctx.configPath,
JSON.stringify({
automaticUpdates: false
})
);
await ctx.relaunch();
const { page } = ctx;
await page.waitForSelector("#authForm");
t.expect(
await page.getByRole("button", { name: "Create account" }).isVisible()
).toBe(true);
await page
.getByRole("button", { name: "Skip & go directly to the app" })
.click();
await skipDialog(page);
await page.waitForSelector(".ProseMirror");
await page
.locator(".theme-scope-statusBar")
.getByRole("button", { name: /available/i })
.waitFor({ state: "attached" });
},
{ version: "3.0.0" }
);
});
test("update to stable if it is newer", async (t) => {
await harness(
t,
async (ctx) => {
await ctx.app.close();
await writeFile(
ctx.configPath,
JSON.stringify({
automaticUpdates: false,
releaseTrack: "beta"
})
);
await ctx.relaunch();
const { page } = ctx;
await page.waitForSelector("#authForm");
t.expect(
await page.getByRole("button", { name: "Create account" }).isVisible()
).toBe(true);
await page
.getByRole("button", { name: "Skip & go directly to the app" })
.click();
await skipDialog(page);
await page.waitForSelector(".ProseMirror");
const updateButton = page
.locator(".theme-scope-statusBar")
.getByRole("button", { name: /available/i });
await updateButton.waitFor({ state: "visible" });
const content = await updateButton.textContent();
const version = content?.split(" ")?.[0] || "";
t.expect(gt(version, "3.0.0-beta.0")).toBe(true);
},
{ version: "3.0.0-beta.0" }
);
});
test("update is not available if it latest stable version is older", async (t) => {
await harness(
t,
async (ctx) => {
await ctx.app.close();
await writeFile(
ctx.configPath,
JSON.stringify({
automaticUpdates: false,
releaseTrack: "beta"
})
);
await ctx.relaunch();
const { page } = ctx;
await page.waitForSelector("#authForm");
t.expect(
await page.getByRole("button", { name: "Create account" }).isVisible()
).toBe(true);
await page
.getByRole("button", { name: "Skip & go directly to the app" })
.click();
await skipDialog(page);
await page.waitForSelector(".ProseMirror");
await page
.locator(".theme-scope-statusBar")
.getByRole("button", { name: /checking for updates/i })
.waitFor({ state: "hidden" });
t.expect(
await page
.locator(".theme-scope-statusBar")
.getByRole("button", { name: /available/i })
.isHidden()
).toBe(true);
},
{ version: "99.0.0-beta.0" }
);
});
test("downgrade to stable on switching to stable release track", async (t) => {
await harness(
t,
async (ctx) => {
await ctx.app.close();
await writeFile(
ctx.configPath,
JSON.stringify({
automaticUpdates: false,
releaseTrack: "stable"
})
);
await ctx.relaunch();
const { page } = ctx;
await page.waitForSelector("#authForm");
t.expect(
await page.getByRole("button", { name: "Create account" }).isVisible()
).toBe(true);
await page
.getByRole("button", { name: "Skip & go directly to the app" })
.click();
await skipDialog(page);
await page.waitForSelector(".ProseMirror");
await page
.locator(".theme-scope-statusBar")
.getByRole("button", { name: /checking for updates/i })
.waitFor({ state: "hidden" });
const updateButton = page
.locator(".theme-scope-statusBar")
.getByRole("button", { name: /available/i });
await updateButton.waitFor({ state: "visible" });
const content = await updateButton.textContent();
const version = content?.split(" ")?.[0] || "";
t.expect(lt(version, "99.0.0-beta.0")).toBe(true);
},
{ version: "99.0.0-beta.0" }
);
});
async function skipDialog(page: Page) {
await page
.waitForSelector(".ReactModal__Content", {
timeout: 1000
})
.catch(() => {})
.then(async () => {
const positiveButton = page.locator(
"button[data-role='positive-button']"
);
const negativeButton = page.locator(
"button[data-role='negative-button']"
);
if (await positiveButton.isVisible()) await positiveButton.click();
else if (await negativeButton.isVisible()) await negativeButton.click();
});
}

View File

@@ -17,16 +17,12 @@ 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 test from "node:test";
import { launchApp } from "./utils.mjs";
import { test } from "vitest";
import { harness } from "./utils.js";
import assert from "assert";
import slugify from "slugify";
import path from "path";
import { mkdir } from "fs/promises";
test("make sure app loads", async (t) => {
const { app, page } = await launchApp();
try {
await harness(t, async ({ page }) => {
await page.waitForSelector("#authForm");
assert.ok(
@@ -38,16 +34,5 @@ test("make sure app loads", async (t) => {
.click();
await page.waitForSelector(".ProseMirror");
} catch (e) {
await mkdir("test-results", { recursive: true });
await page.screenshot({
path: path.join(
"test-results",
`${slugify(t.name)}-${process.platform}-${process.arch}-error.png`
)
});
throw e;
} finally {
await app.close();
}
});
});

View File

@@ -0,0 +1,172 @@
/*
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 { execSync } from "child_process";
import { mkdir } from "fs/promises";
import { fileURLToPath } from "node:url";
import path from "path";
import { _electron as electron } from "playwright";
import slugify from "slugify";
import { TaskContext } from "vitest";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const IS_DEBUG = process.env.NN_DEBUG === "true" || process.env.CI === "true";
interface AppContext {
app: import("playwright").ElectronApplication;
page: import("playwright").Page;
configPath: string;
relaunch: () => Promise<void>;
}
interface TestOptions {
version: string;
}
export async function harness(
t: TaskContext,
cb: (ctx: AppContext) => Promise<void>,
options?: TestOptions
) {
const ctx = await buildAndLaunchApp(options);
t.onTestFinished(async (result) => {
if (result.state === "fail") {
await mkdir("test-results", { recursive: true });
await ctx.page.screenshot({
path: path.join(
"test-results",
`${slugify(t.task.name)}-${process.platform}-${
process.arch
}-error.png`
)
});
}
await ctx.app.close();
});
await cb(ctx);
}
async function buildAndLaunchApp(options?: TestOptions): Promise<AppContext> {
const productName = makeid(10);
const executablePath = await buildApp({ ...options, productName });
const { app, page, configPath } = await launchApp(executablePath);
const ctx: AppContext = {
app,
page,
configPath,
relaunch: async () => {
const { app, page, configPath } = await launchApp(executablePath);
ctx.app = app;
ctx.page = page;
ctx.configPath = configPath;
}
};
return ctx;
}
async function launchApp(executablePath: string) {
const app = await electron.launch({
executablePath,
args: IS_DEBUG ? [] : ["--hidden"],
env:
process.platform === "linux"
? {
...(process.env as Record<string, string>),
APPIMAGE: "true"
}
: (process.env as Record<string, string>)
});
const page = await app.firstWindow();
const userDataDirectory = await app.evaluate((a) => {
return a.app.getPath("userData");
});
const configPath = path.join(userDataDirectory, "config.json");
return {
app,
page,
configPath
};
}
async function buildApp({
version,
productName
}: {
version?: string;
productName: string;
}) {
const buildRoot = path.join("test-artifacts", `${productName}-build`);
const output = path.join("test-artifacts", `${productName}-output`);
execSync(`npm run release -- --root ${buildRoot} --skip-tsc-build`, {
stdio: IS_DEBUG ? "inherit" : "ignore"
});
const args = [
`--config electron-builder.config.js`,
`--c.extraMetadata.productName=${productName}`,
"--publish=never"
];
if (version) args.push(`--c.extraMetadata.version=${version}`);
execSync(`npx electron-builder --dir --${process.arch} ${args.join(" ")}`, {
stdio: IS_DEBUG ? "inherit" : "ignore",
env: {
...process.env,
NOTESNOOK_STAGING: "true",
NN_BUILD_ROOT: buildRoot,
NN_PRODUCT_NAME: productName,
NN_APP_ID: `com.notesnook.test.${productName}`,
NN_OUTPUT_DIR: output
}
});
return path.join(
__dirname,
"..",
output,
process.platform === "linux"
? process.arch === "arm64"
? "linux-arm64-unpacked"
: "linux-unpacked"
: process.platform === "darwin"
? process.arch === "arm64"
? `mac-arm64/${productName}.app/Contents/MacOS/`
: `mac/${productName}.app/Contents/MacOS/`
: "win-unpacked",
process.platform === "win32" ? `${productName}.exe` : productName
);
}
function makeid(length: number) {
let result = "";
const characters =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
const charactersLength = characters.length;
let counter = 0;
while (counter < length) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
counter += 1;
}
return result.toLowerCase();
}

Binary file not shown.

View File

@@ -0,0 +1,219 @@
/*
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/>.
*/
const path = require("path");
const pkg = require("./package.json");
const buildRoot = process.env.NN_BUILD_ROOT || ".";
const buildFiles = [
`${buildRoot}/build/`,
`!${buildRoot}/build/screenshots\${/*}`,
`!${buildRoot}/build/banner.jpg`,
`!${buildRoot}/build/*.ico`,
`!${buildRoot}/build/*.png`
];
const productName = process.env.NN_PRODUCT_NAME || "Notesnook";
const appId = process.env.NN_APP_ID || "org.streetwriters.notesnook";
const outputDir = process.env.NN_OUTPUT_DIR || "output";
const linuxExecutableName = process.env.NN_PRODUCT_NAME
? process.env.NN_PRODUCT_NAME.toLowerCase().replace(/\s+/g, "-")
: "notesnook";
const year = new Date().getFullYear();
const isBeta = pkg.version.includes("-beta");
/**
* @type {import("app-builder-lib").Configuration}
*/
module.exports = {
appId: appId,
productName: productName,
copyright: `Copyright © ${year} Streetwriters (Private) Limited`,
artifactName: "notesnook_${os}_${arch}.${ext}",
generateUpdatesFilesForAllChannels: true,
asar: false,
files: [
"!*.chunk.js.map",
"!*.chunk.js.LICENSE.txt",
...buildFiles,
"!node_modules${/*}",
"node_modules/better-sqlite3-multiple-ciphers/build/Release/better_sqlite3.node",
"node_modules/better-sqlite3-multiple-ciphers/lib",
"node_modules/better-sqlite3-multiple-ciphers/package.json",
"node_modules/file-uri-to-path",
"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}",
to: "node_modules/sqlite-better-trigram-linux-${arch}"
},
{
from: "node_modules/sqlite-better-trigram-darwin-${arch}",
to: "node_modules/sqlite-better-trigram-darwin-${arch}"
},
{
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"
],
afterPack: "./scripts/removeLocales.js",
mac: {
bundleVersion: "240",
minimumSystemVersion: "10.12.0",
target: [
{
target: "dmg",
arch: ["arm64", "x64"]
},
{
target: "zip",
arch: ["arm64", "x64"]
}
],
category: "public.app-category.productivity",
darkModeSupport: true,
type: "distribution",
hardenedRuntime: true,
entitlements: "assets/entitlements.mac.plist",
entitlementsInherit: "assets/entitlements.mac.plist",
gatekeeperAssess: false,
icon: "assets/icons/app.icns",
notarize: true
},
dmg: {
contents: [
{
x: 130,
y: 220
},
{
x: 410,
y: 220,
type: "link",
path: "/Applications"
}
],
icon: "assets/icons/app.icns",
title: "Install Notesnook"
},
mas: {
entitlements: "assets/entitlements.mas.plist",
entitlementsInherit: "assets/entitlements.mas.inherit.plist",
entitlementsLoginHelper: "assets/entitlements.mas.loginhelper.plist",
hardenedRuntime: true
},
win: {
target: [
{
target: "nsis",
arch: ["x64", "arm64"]
},
{
target: "portable",
arch: ["x64", "arm64"]
}
],
signtoolOptions: {
signingHashAlgorithms: ["sha256"],
sign: "./scripts/sign.js"
},
icon: "assets/icons/app.ico"
},
portable: {
artifactName: "notesnook_${os}_${arch}_portable.${ext}"
},
nsis: {
oneClick: true,
createDesktopShortcut: "always",
deleteAppDataOnUninstall: true
},
linux: {
target: [
{
target: "AppImage",
arch: ["x64", "arm64"]
},
{
target: "snap",
arch: ["x64", "arm64"]
}
],
category: "Office",
icon: "assets/icons/app.icns",
description: "Your private note taking space",
executableName: linuxExecutableName,
desktop: {
desktopActions: {
"new-note": {
Name: "New note",
Exec: `${linuxExecutableName} new note`
},
"new-notebook": {
Name: "New notebook",
Exec: `${linuxExecutableName} new notebook`
},
"new-reminder": {
Name: "New reminder",
Exec: `${linuxExecutableName} new reminder`
}
}
}
},
snap: {
autoStart: false,
confinement: "strict",
allowNativeWayland: true,
base: "core22"
},
extraResources: ["app-update.yml", "./assets/**"],
extraMetadata: {
main: path.join(buildRoot, "build", "electron.js")
},
directories: {
buildResources: "assets",
output: outputDir
},
publish: [
{
provider: "github",
repo: "notesnook",
owner: "streetwriters",
channel: isBeta ? "beta" : "latest"
}
]
};

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.0.24",
"version": "3.2.2",
"appAppleId": "1544027013",
"private": true,
"main": "./dist/cjs/index.js",
@@ -25,241 +25,57 @@
"repository": "https://github.com/streetwriters/notesnook",
"license": "GPL-3.0-or-later",
"dependencies": {
"@lingui/core": "4.11.4",
"@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",
"electron-trpc": "0.6.1",
"electron-updater": "^6.3.4",
"icojs": "^0.19.4",
"sqlite-better-trigram": "0.0.2",
"better-sqlite3-multiple-ciphers": "^11.10.0",
"electron-trpc": "0.7.1",
"electron-updater": "^6.6.2",
"icojs": "^0.19.5",
"sqlite-better-trigram": "0.0.3",
"sqlite3-fts5-html": "^0.0.3",
"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",
"vitest": "2.1.8",
"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"
"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",
"release": "node scripts/build.mjs",
"build": "node ../../scripts/build.mjs",
"bundle": "esbuild electron=./src/main.ts ./src/preload.ts --external:electron --external:fsevents --external:better-sqlite3-multiple-ciphers --external:sodium-native --minify --bundle --outdir=./build --platform=node --tsconfig=tsconfig.json --define:MAC_APP_STORE=false --define:RELEASE=true",
"bundle": "esbuild electron=./src/main.ts ./src/preload.ts --external:electron --external:fsevents --external:better-sqlite3-multiple-ciphers --external:sodium-native --bundle --outdir=./build --platform=node --tsconfig=tsconfig.json --define:MAC_APP_STORE=false --define:RELEASE=true",
"bundle:mas": "esbuild electron=./src/main.ts ./src/preload.ts --minify --external:electron --external:fsevents --bundle --outdir=./build --platform=node --tsconfig=tsconfig.json --define:MAC_APP_STORE=true --define:RELEASE=true",
"postinstall": "patch-package",
"test": "node --test --test-timeout 30000 --test-force-exit"
"test": "vitest run"
},
"author": {
"name": "Streetwriters (Private) Limited",
"email": "support@streetwriters.co",
"url": "https://streetwriters.co"
},
"build": {
"appId": "org.streetwriters.notesnook",
"productName": "Notesnook",
"copyright": "Copyright © 2023 Streetwriters (Private) Limited",
"artifactName": "notesnook_${os}_${arch}.${ext}",
"generateUpdatesFilesForAllChannels": true,
"asar": false,
"files": [
"!*.chunk.js.map",
"!*.chunk.js.LICENSE.txt",
"build/",
"!build/screenshots${/*}",
"!build/banner.jpg",
"!build/*.ico",
"!build/*.png",
"!node_modules${/*}",
"node_modules/better-sqlite3-multiple-ciphers/build/Release/better_sqlite3.node",
"node_modules/better-sqlite3-multiple-ciphers/lib",
"node_modules/better-sqlite3-multiple-ciphers/package.json",
"node_modules/file-uri-to-path",
"node_modules/bindings",
"node_modules/node-gyp-build",
"node_modules/sqlite-better-trigram",
"node_modules/sodium-native/prebuilds/${platform}-${arch}",
{
"from": "node_modules/sqlite-better-trigram-linux-${arch}",
"to": "node_modules/sqlite-better-trigram-linux-${arch}"
},
{
"from": "node_modules/sqlite-better-trigram-darwin-${arch}",
"to": "node_modules/sqlite-better-trigram-darwin-${arch}"
},
{
"from": "node_modules/sqlite-better-trigram-windows-${arch}",
"to": "node_modules/sqlite-better-trigram-windows-${arch}"
},
"node_modules/sodium-native/index.js",
"node_modules/sodium-native/package.json"
],
"afterPack": "./scripts/removeLocales.js",
"mac": {
"bundleVersion": "240",
"minimumSystemVersion": "10.12.0",
"target": [
{
"target": "dmg",
"arch": [
"arm64",
"x64"
]
},
{
"target": "zip",
"arch": [
"arm64",
"x64"
]
}
],
"category": "public.app-category.productivity",
"darkModeSupport": true,
"type": "distribution",
"hardenedRuntime": true,
"entitlements": "assets/entitlements.mac.plist",
"entitlementsInherit": "assets/entitlements.mac.plist",
"gatekeeperAssess": false,
"icon": "assets/icons/app.icns",
"notarize": true
},
"dmg": {
"contents": [
{
"x": 130,
"y": 220
},
{
"x": 410,
"y": 220,
"type": "link",
"path": "/Applications"
}
],
"icon": "assets/icons/app.icns",
"title": "Install Notesnook"
},
"mas": {
"entitlements": "assets/entitlements.mas.plist",
"entitlementsInherit": "assets/entitlements.mas.inherit.plist",
"entitlementsLoginHelper": "assets/entitlements.mas.loginhelper.plist",
"hardenedRuntime": true
},
"win": {
"target": [
{
"target": "nsis",
"arch": [
"x64",
"arm64"
]
},
{
"target": "portable",
"arch": [
"x64",
"arm64"
]
}
],
"signtoolOptions": {
"signingHashAlgorithms": [
"sha256"
],
"sign": "./scripts/sign.js"
},
"icon": "assets/icons/app.ico"
},
"portable": {
"artifactName": "notesnook_${os}_${arch}_portable.${ext}"
},
"nsis": {
"oneClick": true,
"createDesktopShortcut": "always",
"deleteAppDataOnUninstall": true
},
"linux": {
"target": [
{
"target": "AppImage",
"arch": [
"x64",
"arm64"
]
},
{
"target": "snap",
"arch": [
"x64",
"arm64"
]
}
],
"category": "Office",
"icon": "assets/icons/app.icns",
"description": "Your private note taking space",
"executableName": "notesnook",
"desktop": {
"actions": [
{
"id": "new-note",
"name": "New note",
"args": "new note"
},
{
"id": "new-notebook",
"name": "New notebook",
"args": "new notebook"
},
{
"id": "new-reminder",
"name": "New reminder",
"args": "new reminder"
}
]
}
},
"snap": {
"autoStart": false,
"confinement": "strict",
"allowNativeWayland": true
},
"extraResources": [
"app-update.yml",
"./assets/**"
],
"extraMetadata": {
"main": "./build/electron.js"
},
"directories": {
"buildResources": "assets",
"output": "./output/"
},
"publish": [
{
"provider": "github",
"repo": "notesnook",
"owner": "streetwriters"
}
]
}
}
}

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

@@ -29,10 +29,12 @@ import { patchBetterSQLite3 } from "./patch-better-sqlite3.mjs";
const args = yargs(process.argv);
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const root = args.root || path.join(__dirname, "..");
const skipTscBuild = args.skipTscBuild || false;
const webAppPath = path.resolve(path.join(__dirname, "..", "..", "web"));
await fs.rm("./build/", { force: true, recursive: true });
await fs.rm(path.join(root, "build"), { force: true, recursive: true });
if (args.rebuild || !existsSync(path.join(webAppPath, "build"))) {
await exec(
@@ -41,24 +43,27 @@ 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"), "build", {
await fs.cp(path.join(webAppPath, "build"), path.join(root, "build"), {
recursive: true,
force: true
});
if (args.variant === "mas") {
await exec(`yarn run bundle:mas`);
await exec(`yarn run bundle:mas --outdir=${path.join(root, "build")}`);
} else {
await exec(`yarn run bundle`);
await exec(`yarn run bundle --outdir=${path.join(root, "build")}`);
}
await exec(`yarn run build`);
if (!skipTscBuild) {
await exec(`yarn run build`);
}
if (args.run) {
await exec(`yarn electron-builder --dir --${process.arch}`);
await exec(
`yarn electron-builder --dir --${process.arch} --config=electron-builder.config.js`
);
if (process.platform === "win32") {
await exec(`.\\output\\win-unpacked\\Notesnook.exe`);
} else if (process.platform === "darwin") {

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";
@@ -29,10 +38,11 @@ import { dirname } from "path";
import { resolvePath } from "../utils/resolve-path";
import { observable } from "@trpc/server/observable";
import { AssetManager } from "../utils/asset-manager";
import { isFlatpak } from "../utils";
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();
@@ -49,6 +59,7 @@ const NotificationOptions = z.object({
export const osIntegrationRouter = t.router({
isFlatpak: t.procedure.query(() => isFlatpak()),
isSnap: t.procedure.query(() => isSnap()),
zoomFactor: t.procedure.query(() => config.zoomFactor),
setZoomFactor: t.procedure.input(z.number()).mutation(({ input: factor }) => {
@@ -224,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

@@ -23,6 +23,7 @@ import { CancellationToken, autoUpdater } from "electron-updater";
import type { AppUpdaterEvents } from "electron-updater/out/AppUpdater";
import { z } from "zod";
import { config } from "../utils/config";
import { app } from "electron";
type UpdateInfo = { version: string };
type Progress = { percent: number };
@@ -33,6 +34,7 @@ let downloadTimeout: NodeJS.Timeout | undefined = undefined;
export const updaterRouter = t.router({
autoUpdates: t.procedure.query(() => config.automaticUpdates),
releaseTrack: t.procedure.query(() => config.releaseTrack),
install: t.procedure.query(() => autoUpdater.quitAndInstall()),
download: t.procedure.query(async () => {
if (cancellationToken) return;
@@ -67,7 +69,13 @@ export const updaterRouter = t.router({
.mutation(({ input: { enabled } }) => {
config.automaticUpdates = enabled;
}),
changeReleaseTrack: t.procedure
.input(z.object({ track: z.string() }))
.mutation(({ input: { track } }) => {
config.releaseTrack = track;
app.relaunch();
app.exit();
}),
onChecking: createSubscription("checking-for-update"),
onDownloaded: createSubscription<"update-downloaded", UpdateInfo>(
"update-downloaded"

View File

@@ -85,6 +85,8 @@ async function createWindow() {
const mainWindowState = new WindowState({});
const mainWindow = new BrowserWindow({
show: !cliOptions.hidden,
paintWhenInitiallyHidden: cliOptions.hidden,
skipTaskbar: cliOptions.hidden,
x: mainWindowState.x,
y: mainWindowState.y,
width: mainWindowState.width,
@@ -101,7 +103,10 @@ async function createWindow() {
...(config.desktopSettings.nativeTitlebar
? {}
: {
titleBarStyle: process.platform === "win32" || process.platform === "darwin" ? "hidden" : "default",
titleBarStyle:
process.platform === "win32" || process.platform === "darwin"
? "hidden"
: "default",
frame: process.platform === "win32" || process.platform === "darwin",
titleBarOverlay: {
height: 37,
@@ -142,6 +147,11 @@ async function createWindow() {
await AssetManager.loadIcons();
setupDesktopIntegration(config.desktopSettings);
mainWindow.webContents.session.setPermissionRequestHandler(
(webContents, permission, callback) => {
callback(permission === "geolocation" ? false : true);
}
);
mainWindow.webContents.session.setSpellCheckerDictionaryDownloadURL(
"http://dictionaries.notesnook.com/"
);

View File

@@ -20,19 +20,22 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import { autoUpdater } from "electron-updater";
import { config } from "./config";
const CHANNEL = autoUpdater.currentVersion.raw.endsWith("-beta")
? "beta"
: "latest";
async function configureAutoUpdater() {
const releaseTrack =
config.releaseTrack === "stable" ? "latest" : config.releaseTrack;
autoUpdater.setFeedURL({
provider: "generic",
url: `https://notesnook.com/api/v1/releases/${process.platform}/${CHANNEL}`,
url: `https://notesnook.com/api/v1/releases/${process.platform}/${releaseTrack}`,
useMultipleRangeRequest: false,
channel: CHANNEL
channel: releaseTrack
});
autoUpdater.autoDownload = config.automaticUpdates;
autoUpdater.allowDowngrade = false;
autoUpdater.allowDowngrade =
// only allow downgrade if the current version is a prerelease
// and the user has changed the release track to stable
config.releaseTrack === "stable" &&
autoUpdater.currentVersion.prerelease.length > 0;
autoUpdater.allowPrerelease = false;
autoUpdater.autoInstallOnAppQuit = true;
autoUpdater.disableWebInstaller = true;

View File

@@ -20,6 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import { nativeTheme } from "electron";
import { JSONStorage } from "./json-storage";
import { z } from "zod";
import { autoUpdater } from "electron-updater";
export const DesktopIntegration = z.object({
autoStart: z.boolean().optional(),
@@ -46,6 +47,9 @@ export const config = {
automaticUpdates: true,
proxyRules: "",
customDns: true,
releaseTrack: autoUpdater.currentVersion.raw.includes("-beta")
? "beta"
: "stable",
backgroundColor: nativeTheme.themeSource === "dark" ? "#0f0f0f" : "#ffffff",
windowControlsIconColor:

View File

@@ -29,3 +29,7 @@ export function isDevelopment() {
export function isFlatpak() {
return existsSync("/.flatpak-info");
}
export function isSnap() {
return process.env.SNAP !== undefined;
}

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

@@ -0,0 +1,40 @@
/*
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 { defineConfig } from "vitest/config";
export default defineConfig({
test: {
testTimeout: process.env.CI ? 120 * 1000 : 120 * 1000,
sequence: {
concurrent: true,
shuffle: true
},
dir: "./__tests__/",
exclude: [
"**/node_modules/**",
"**/dist/**",
"**/cypress/**",
"**/.{idea,git,cache,output,temp}/**",
"**/{karma,rollup,webpack,vite,vitest,jest,ava,babel,nyc,cypress,tsup,build,eslint,prettier}.config.*",
"**/test-results/**",
"**/test-artifacts/**"
]
}
});

View File

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

View File

@@ -19,27 +19,30 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import { i18n } from "@lingui/core";
import { I18nProvider } from "@lingui/react";
import {
ScopedThemeProvider,
THEME_COMPATIBILITY_VERSION,
useThemeEngineStore
} from "@notesnook/theme";
import React, { useEffect } from "react";
import { I18nManager, View } from "react-native";
import { Appearance, I18nManager, StatusBar } from "react-native";
import "react-native-gesture-handler";
import { GestureHandlerRootView } from "react-native-gesture-handler";
import { SafeAreaProvider } from "react-native-safe-area-context";
import AppLockedOverlay from "./components/app-lock-overlay";
import DialogProvider from "./components/dialog-provider";
import { withErrorBoundry } from "./components/exception-handler";
import GlobalSafeAreaProvider from "./components/globalsafearea";
import { Toast } from "./components/toast";
import { useAppEvents } from "./hooks/use-app-events";
import { ApplicationHolder } from "./navigation";
import { NotePreviewConfigure } from "./screens/note-preview-configure";
import { RootNavigation } from "./navigation/navigation-stack";
import { themeTrpcClient } from "./screens/settings/theme-selector";
import Notifications from "./services/notifications";
import SettingsService from "./services/settings";
import { TipManager } from "./services/tip-manager";
import { useThemeStore } from "./stores/use-theme-store";
import { changeSystemBarColors, useThemeStore } from "./stores/use-theme-store";
import { useUserStore } from "./stores/use-user-store";
import { IntentService } from "./services/intent";
import RNBootSplash from "react-native-bootsplash";
import AppLocked from "./components/app-lock";
I18nManager.allowRTL(false);
I18nManager.forceRTL(false);
@@ -49,12 +52,13 @@ if (appLockEnabled || appLockMode !== "none") {
useUserStore.getState().lockApp(true);
}
IntentService.onLaunch();
RNBootSplash.hide();
const App = (props: { configureMode: "note-preview" }) => {
useAppEvents();
//@ts-ignore
globalThis["IS_MAIN_APP_RUNNING"] = true;
useEffect(() => {
changeSystemBarColors();
SettingsService.onFirstLaunch();
setTimeout(async () => {
await Notifications.get();
@@ -66,42 +70,27 @@ const App = (props: { configureMode: "note-preview" }) => {
}, []);
return (
<View
style={{
height: "100%",
width: "100%",
justifyContent: "center",
alignItems: "center"
}}
>
<View
style={{
position: "absolute",
width: "100%",
height: "100%",
zIndex: -1
}}
pointerEvents="none"
>
<SafeAreaProvider>
<GlobalSafeAreaProvider />
</SafeAreaProvider>
</View>
<SafeAreaProvider>
<StatusBar translucent={true} backgroundColor="transparent" />
<GestureHandlerRootView
style={{
height: "100%",
width: "100%"
}}
>
<GlobalSafeAreaProvider />
{props.configureMode === "note-preview" ? (
<NotePreviewConfigure />
) : (
<ApplicationHolder />
<RootNavigation />
)}
<ScopedThemeProvider value="dialog">
<Toast />
</ScopedThemeProvider>
<DialogProvider />
<AppLocked />
</GestureHandlerRootView>
<AppLockedOverlay />
</View>
</SafeAreaProvider>
);
};
@@ -140,16 +129,27 @@ export const withTheme = (Element: (props: any) => JSX.Element) => {
/* empty */
});
}, 1000);
const listener = Appearance.addChangeListener(({ colorScheme }) => {
if (colorScheme && SettingsService.getProperty("useSystemTheme")) {
useThemeStore.getState().setColorScheme(colorScheme);
}
});
return () => {
listener.remove();
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const nextTheme = colorScheme === "dark" ? darkTheme : lightTheme;
if (JSON.stringify(nextTheme) !== JSON.stringify(currTheme)) {
useThemeEngineStore
.getState()
.setTheme(colorScheme === "dark" ? darkTheme : lightTheme);
currTheme = nextTheme;
}
useEffect(() => {
const nextTheme = colorScheme === "dark" ? darkTheme : lightTheme;
if (JSON.stringify(nextTheme) !== JSON.stringify(currTheme)) {
useThemeEngineStore
.getState()
.setTheme(colorScheme === "dark" ? darkTheme : lightTheme);
currTheme = nextTheme;
}
}, [colorScheme, darkTheme, lightTheme]);
return (
<I18nProvider i18n={i18n}>

File diff suppressed because one or more lines are too long

View File

@@ -149,7 +149,9 @@ export async function downloadFile(
});
}
await RNFetchBlob.fs.mv(tempFilePath, originalFilePath);
await RNFetchBlob.fs.mv(tempFilePath, originalFilePath).catch(() => {
/* empty */
});
if (!(await exists(filename))) {
throw new Error("File size mismatch");

View File

@@ -231,6 +231,26 @@ export async function deleteDCacheFiles() {
}
}
export async function getCachePathForFile(filename: string) {
const path = `${cacheDir}/${filename}`;
const iosAppGroup =
Platform.OS === "ios"
? await (RNFetchBlob.fs as any).pathForAppGroup(IOS_APPGROUPID)
: null;
const appGroupPath = `${iosAppGroup}/${filename}`;
const exists = await RNFetchBlob.fs.exists(path);
// Check if file is present in app group path.
let existsInAppGroup = false;
if (!exists && Platform.OS === "ios") {
existsInAppGroup = await RNFetchBlob.fs.exists(appGroupPath);
}
return existsInAppGroup ? appGroupPath : path;
}
export async function exists(filename: string) {
const path = `${cacheDir}/${filename}`;

View File

@@ -115,7 +115,7 @@ export const FileSizeResult = {
Error: -1
};
export async function getUploadedFileSize(hash: string) {
export async function getUploadedFileSize(hash: string, retry = 0) {
try {
const url = `${hosts.API_HOST}/s3?name=${hash}`;
const token = await db.tokenManager.getAccessToken();
@@ -123,8 +123,24 @@ export async function getUploadedFileSize(hash: string) {
method: "HEAD",
headers: { Authorization: `Bearer ${token}` }
});
if (
!attachmentInfo.ok ||
attachmentInfo.headers?.get("content-length") === null
) {
if (retry < 3) {
DatabaseLogger.log(`Retrying file size check: ${hash}, ${retry}`);
return getUploadedFileSize(hash, retry + 1);
}
throw new Error(
`File size check failed: ${hash}, ${
attachmentInfo.status
}, ${attachmentInfo.headers?.get("content-length")}`
);
}
const contentLength = parseInt(
attachmentInfo.headers?.get("content-length") || "0"
attachmentInfo.headers?.get("content-length") as string
);
return isNaN(contentLength) ? FileSizeResult.Empty : contentLength;
} catch (e) {

View File

@@ -24,6 +24,7 @@ import { useMessageStore } from "../../stores/use-message-store";
import { useSelectionStore } from "../../stores/use-selection-store";
import { allowedOnPlatform, renderItem } from "./functions";
import { getContainerBorder } from "../../utils/colors";
import { DefaultAppStyles } from "../../utils/styles";
export const Announcement = ({ color }) => {
const { colors } = useThemeColors();
@@ -36,9 +37,8 @@ export const Announcement = ({ color }) => {
style={{
backgroundColor: colors.primary.background,
width: "100%",
paddingHorizontal: 12,
paddingTop: 12,
paddingBottom: 12
paddingHorizontal: DefaultAppStyles.GAP,
paddingVertical: DefaultAppStyles.GAP_VERTICAL
}}
>
<View
@@ -54,7 +54,7 @@ export const Announcement = ({ color }) => {
<View
style={{
width: "100%",
marginTop: 12
marginTop: DefaultAppStyles.GAP_VERTICAL
}}
>
{announcement?.body

View File

@@ -20,12 +20,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import React from "react";
import Paragraph from "../ui/typography/paragraph";
import { getStyle } from "./functions";
import { DefaultAppStyles } from "../../utils/styles";
export const Body = ({ text, style = {} }) => {
return (
<Paragraph
style={{
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
...getStyle(style)
}}
>

View File

@@ -23,12 +23,13 @@ import { Linking, View } from "react-native";
import { useThemeColors } from "@notesnook/theme";
import { eSendEvent, presentSheet } from "../../services/event-manager";
import { eCloseAnnouncementDialog } from "../../utils/events";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import { sleep } from "../../utils/time";
import { PricingPlans } from "../premium/pricing-plans";
import SheetProvider from "../sheet-provider";
import { Button } from "../ui/button";
import { allowedOnPlatform, getStyle } from "./functions";
import { DefaultAppStyles } from "../../utils/styles";
export const Cta = ({ actions, style = {}, color, inline }) => {
const { colors } = useThemeColors();
@@ -61,7 +62,7 @@ export const Cta = ({ actions, style = {}, color, inline }) => {
return (
<View
style={{
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
...getStyle(style),
flexDirection: inline ? "row" : "column"
}}
@@ -75,7 +76,7 @@ export const Cta = ({ actions, style = {}, color, inline }) => {
<Button
key={item.title}
title={item.title}
fontSize={SIZE.sm}
fontSize={AppFontSize.sm}
type="transparent"
textStyle={{
textDecorationLine: "underline"
@@ -83,7 +84,7 @@ export const Cta = ({ actions, style = {}, color, inline }) => {
onPress={() => onPress(item)}
bold
style={{
height: 30,
paddingVertical: DefaultAppStyles.GAP_VERTICAL_SMALL,
alignSelf: "flex-start",
paddingHorizontal: 0
}}
@@ -95,7 +96,7 @@ export const Cta = ({ actions, style = {}, color, inline }) => {
<Button
key={item.title}
title={item.title}
fontSize={SIZE.sm}
fontSize={AppFontSize.sm}
type="plain"
onPress={() => onPress(item)}
width={null}
@@ -118,7 +119,7 @@ export const Cta = ({ actions, style = {}, color, inline }) => {
<Button
key={item.title}
title={item.title}
fontSize={SIZE.md}
fontSize={AppFontSize.md}
buttonType={{
color: color ? color : colors.primary.accent,
text: color
@@ -130,7 +131,7 @@ export const Cta = ({ actions, style = {}, color, inline }) => {
onPress={() => onPress(item)}
width={250}
style={{
marginBottom: 5,
marginBottom: DefaultAppStyles.GAP_VERTICAL,
borderRadius: 100
}}
/>
@@ -141,14 +142,14 @@ export const Cta = ({ actions, style = {}, color, inline }) => {
<Button
key={item.title}
title={item.title}
fontSize={SIZE.xs}
fontSize={AppFontSize.xs}
type="plain"
onPress={() => onPress(item)}
width={null}
height={30}
style={{
minWidth: "50%",
marginTop: 5
marginTop: DefaultAppStyles.GAP_VERTICAL_SMALL
}}
textStyle={{
textDecorationLine: "underline"

View File

@@ -18,7 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import React from "react";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import Paragraph from "../ui/typography/paragraph";
import { getStyle } from "./functions";
@@ -30,7 +30,7 @@ export const Description = ({ text, style = {}, inline }) => {
...getStyle(style),
textAlign: inline ? "left" : style?.textAlign
}}
size={inline ? SIZE.sm : SIZE.md}
size={inline ? AppFontSize.sm : AppFontSize.md}
>
{text}
</Paragraph>

View File

@@ -28,6 +28,7 @@ import { List } from "./list";
import { Photo } from "./photo";
import { SubHeading } from "./subheading";
import { Title } from "./title";
import { DefaultAppStyles } from "../../utils/styles";
export function allowedOnPlatform(platforms) {
if (!platforms) return true;
@@ -53,7 +54,7 @@ const Features = () => {
return (
<View
style={{
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
alignItems: "center",
width: "100%"
}}

View File

@@ -22,12 +22,13 @@ import { View } from "react-native";
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
import Paragraph from "../ui/typography/paragraph";
import { getStyle } from "./functions";
import { DefaultAppStyles } from "../../utils/styles";
export const List = ({ items, listType, style = {} }) => {
return (
<View
style={{
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
paddingLeft: listType === "ordered" ? 25 : 25,
...getStyle(style)
}}
@@ -36,7 +37,7 @@ export const List = ({ items, listType, style = {} }) => {
<View
key={item.text}
style={{
paddingVertical: 6,
paddingVertical: DefaultAppStyles.GAP_VERTICAL,
flexDirection: "row"
}}
>

View File

@@ -18,17 +18,18 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import React from "react";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import Heading from "../ui/typography/heading";
import { getStyle } from "./functions";
import { DefaultAppStyles } from "../../utils/styles";
export const SubHeading = ({ text, style = {} }) => {
return (
<Heading
size={SIZE.md + 2}
size={AppFontSize.md + 2}
style={{
marginHorizontal: 12,
marginTop: 12,
marginHorizontal: DefaultAppStyles.GAP,
marginTop: DefaultAppStyles.GAP_VERTICAL,
...getStyle(style)
}}
>

View File

@@ -20,10 +20,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import React from "react";
import { View } from "react-native";
import { useMessageStore } from "../../stores/use-message-store";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import { Button } from "../ui/button";
import Heading from "../ui/typography/heading";
import { getStyle } from "./functions";
import { DefaultAppStyles } from "../../utils/styles";
export const Title = ({ text, style = {}, inline }) => {
const announcements = useMessageStore((state) => state.announcements);
@@ -36,19 +37,19 @@ export const Title = ({ text, style = {}, inline }) => {
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
marginBottom: inline ? 5 : 0
marginBottom: inline ? DefaultAppStyles.GAP_VERTICAL_SMALL : 0
}}
>
<Heading
style={{
marginHorizontal: 12,
marginTop: 12,
marginHorizontal: DefaultAppStyles.GAP,
marginTop: DefaultAppStyles.GAP_VERTICAL,
...getStyle(style),
textAlign: inline ? "left" : style?.textAlign,
flexShrink: 1
}}
numberOfLines={1}
size={inline ? SIZE.md : SIZE.xl}
size={inline ? AppFontSize.md : AppFontSize.xl}
>
{inline ? text?.toUpperCase() : text}
</Heading>
@@ -67,7 +68,7 @@ export const Title = ({ text, style = {}, inline }) => {
right: 0
}}
iconSize={24}
fontSize={SIZE.xs}
fontSize={AppFontSize.xs}
style={{
borderRadius: 100,
paddingVertical: 0,
@@ -80,9 +81,9 @@ export const Title = ({ text, style = {}, inline }) => {
) : (
<Heading
style={{
marginHorizontal: 12,
marginHorizontal: DefaultAppStyles.GAP,
...getStyle(style),
marginTop: style?.marginTop || 12
marginTop: style?.marginTop || DefaultAppStyles.GAP_VERTICAL
}}
>
{text}

View File

@@ -44,7 +44,6 @@ import SettingsService from "../../services/settings";
import { useSettingStore } from "../../stores/use-setting-store";
import { useUserStore } from "../../stores/use-user-store";
import { NotesnookModule } from "../../utils/notesnook-module";
import { SIZE } from "../../utils/size";
import { Toast } from "../toast";
import { Button } from "../ui/button";
import { IconButton } from "../ui/icon-button";
@@ -54,6 +53,9 @@ import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import { KeyboardAwareScrollView } from "react-native-keyboard-aware-scroll-view";
import { strings } from "@notesnook/intl";
import { AppFontSize } from "../../utils/size";
import { editorController } from "../../screens/editor/tiptap/utils";
import { useTabStore } from "../../screens/editor/tiptap/use-tab-store";
const getUser = () => {
const user = MMKV.getString("user");
@@ -82,7 +84,7 @@ const verifyUserPassword = async (password: string) => {
}
};
const AppLockedOverlay = () => {
const AppLocked = () => {
const initialLaunchBiometricRequest = useRef(true);
const { colors } = useThemeColors();
const user = getUser();
@@ -109,17 +111,25 @@ const AppLockedOverlay = () => {
);
const onUnlockAppRequested = useCallback(async () => {
editorController.current?.commands.blur(useTabStore.getState().currentTab);
editorController.current?.commands.blurPassInput();
if (
!biometricsAuthEnabled ||
!(await BiometricService.isBiometryAvailable())
)
) {
return;
}
biometricUnlockAwaitingUserInput.current = true;
if (Platform.OS === "android") {
const activityName = await NotesnookModule.getActivityName();
if (activityName !== "MainActivity") return;
if (
activityName !== "MainActivity" &&
activityName !== "NotePreviewConfigureActivity"
)
return;
}
useSettingStore.getState().setRequestBiometrics(true);
@@ -177,10 +187,15 @@ const AppLockedOverlay = () => {
(prevState === "background" || initialLaunchBiometricRequest.current)
) {
if (SettingsService.shouldLockAppOnEnterForeground()) {
if (useSettingStore.getState().appDidEnterBackgroundForAction) {
useSettingStore.getState().setAppDidEnterBackgroundForAction(false);
return;
}
DatabaseLogger.info("Locking app on entering foreground");
useUserStore.getState().lockApp(true);
}
if (
!(
biometricUnlockAwaitingUserInput.current ||
@@ -279,6 +294,16 @@ const AppLockedOverlay = () => {
keyboardType={
appLockHasPasswordSecurity ? keyboardType : "default"
}
onLayout={async () => {
if (
!biometricsAuthEnabled ||
!(await BiometricService.isBiometryAvailable())
) {
setTimeout(() => {
passwordInputRef.current?.focus();
}, 32);
}
}}
placeholder={
appLockHasPasswordSecurity
? keyboardType === "numeric"
@@ -311,7 +336,7 @@ const AppLockedOverlay = () => {
borderRadius: 150,
marginBottom: 10
}}
fontSize={SIZE.md}
fontSize={AppFontSize.md}
/>
</>
) : null}
@@ -332,4 +357,4 @@ const AppLockedOverlay = () => {
) : null;
};
export default AppLockedOverlay;
export default AppLocked;

View File

@@ -45,7 +45,7 @@ import {
eDBItemUpdate,
eOnLoadNote
} from "../../utils/events";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import { sleep } from "../../utils/time";
import { Dialog } from "../dialog";
import { presentDialog } from "../dialog/functions";
@@ -58,6 +58,7 @@ import { Pressable } from "../ui/pressable";
import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../utils/styles";
const Actions = ({
attachment,
@@ -166,6 +167,7 @@ const Actions = ({
setAttachments();
eSendEvent(eDBItemUpdate, attachment.id);
}
return true;
},
positiveText: strings.rename()
});
@@ -182,18 +184,17 @@ const Actions = ({
relations
.map((relation) => relation.fromId)
.forEach(async (id) => {
const tab = useTabStore.getState().getTabForNote(id);
if (tab !== undefined) {
const isFocused = useTabStore.getState().currentTab === tab;
useTabStore.getState().forEachNoteTab(id, async (tab) => {
const isFocused = useTabStore.getState().currentTab === tab.id;
if (isFocused) {
eSendEvent(eOnLoadNote, {
item: await db.notes.note(id),
forced: true
});
} else {
editorController.current.commands.setLoading(true, tab);
editorController.current.commands.setLoading(true, tab.id);
}
}
});
});
close?.();
},
@@ -227,14 +228,15 @@ const Actions = ({
style={{
borderBottomWidth: 1,
borderBottomColor: colors.primary.border,
marginBottom: notes && notes.length > 0 ? 0 : 12
marginBottom:
notes && notes.length > 0 ? 0 : DefaultAppStyles.GAP_VERTICAL
}}
>
<Heading
style={{
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
size={SIZE.lg}
size={AppFontSize.lg}
>
{filename}
</Heading>
@@ -242,21 +244,21 @@ const Actions = ({
<View
style={{
flexDirection: "row",
marginBottom: 10,
paddingHorizontal: 12,
marginTop: 6,
marginBottom: DefaultAppStyles.GAP_VERTICAL,
paddingHorizontal: DefaultAppStyles.GAP,
marginTop: DefaultAppStyles.GAP_VERTICAL_SMALL,
gap: 10
}}
>
<Paragraph size={SIZE.xs} color={colors.secondary.paragraph}>
<Paragraph size={AppFontSize.xs} color={colors.secondary.paragraph}>
{attachment.mimeType}
</Paragraph>
<Paragraph size={SIZE.xs} color={colors.secondary.paragraph}>
<Paragraph size={AppFontSize.xs} color={colors.secondary.paragraph}>
{formatBytes(attachment.size)}
</Paragraph>
{notes.length ? (
<Paragraph size={SIZE.xs} color={colors.secondary.paragraph}>
<Paragraph size={AppFontSize.xs} color={colors.secondary.paragraph}>
{strings.notes(notes.length)}
</Paragraph>
) : null}
@@ -269,7 +271,7 @@ const Actions = ({
context: "local"
});
}}
size={SIZE.xs}
size={AppFontSize.xs}
color={colors.secondary.paragraph}
>
{attachment.hash}
@@ -284,16 +286,16 @@ const Actions = ({
style={{
borderBottomWidth: 1,
borderBottomColor: colors.primary.border,
marginBottom: 12,
paddingVertical: 12
marginBottom: DefaultAppStyles.GAP_VERTICAL,
paddingVertical: DefaultAppStyles.GAP_VERTICAL
}}
>
<>
<Heading
style={{
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
size={SIZE.sm}
size={AppFontSize.sm}
>
{strings.listOf()} {strings.dataTypesPlural.note()}:
</Heading>
@@ -308,14 +310,14 @@ const Actions = ({
openNote(item, (item as any).type === "trash");
}}
style={{
paddingVertical: 12,
paddingVertical: DefaultAppStyles.GAP_VERTICAL,
alignItems: "flex-start",
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
key={item.id}
>
<Paragraph size={SIZE.xs}>{item.title}</Paragraph>
<Paragraph size={AppFontSize.xs}>{item.title}</Paragraph>
</Pressable>
))}
</>
@@ -336,7 +338,7 @@ const Actions = ({
icon={item.icon}
loading={loading?.name === item.name}
type="plain"
fontSize={SIZE.sm}
fontSize={AppFontSize.sm}
style={{
borderRadius: 0,
justifyContent: "flex-start",
@@ -348,7 +350,7 @@ const Actions = ({
<View
style={{
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
>
{failed ? (

View File

@@ -25,13 +25,14 @@ import { TouchableOpacity, View } from "react-native";
import { db } from "../../common/database";
import { useAttachmentProgress } from "../../hooks/use-attachment-progress";
import { useDBItem } from "../../hooks/use-db-item";
import { SIZE } from "../../utils/size";
import { defaultBorderRadius, AppFontSize } from "../../utils/size";
import { IconButton } from "../ui/icon-button";
import { ProgressCircleComponent } from "../ui/svg/lazy";
import Paragraph from "../ui/typography/paragraph";
import Actions from "./actions";
import { strings } from "@notesnook/intl";
import { Pressable } from "../ui/pressable";
import { DefaultAppStyles } from "../../utils/styles";
function getFileExtension(filename: string) {
const ext = /^.+\.([^.]+)$/.exec(filename);
@@ -76,8 +77,8 @@ export const AttachmentItem = ({
flexDirection: "row",
marginVertical: 5,
justifyContent: "space-between",
padding: 12,
paddingVertical: 6,
padding: DefaultAppStyles.GAP,
paddingVertical: DefaultAppStyles.GAP_VERTICAL,
minHeight: 45
}}
>
@@ -101,7 +102,7 @@ export const AttachmentItem = ({
paddingHorizontal: 2,
width: 30,
height: 30,
borderRadius: 5
borderRadius: defaultBorderRadius
}}
>
<Paragraph
@@ -124,7 +125,7 @@ export const AttachmentItem = ({
}}
>
<Paragraph
size={SIZE.sm}
size={AppFontSize.sm}
style={{
flexWrap: "wrap"
}}
@@ -136,7 +137,10 @@ export const AttachmentItem = ({
</Paragraph>
{!hideWhenNotDownloading ? (
<Paragraph color={colors.secondary.paragraph} size={SIZE.xxs}>
<Paragraph
color={colors.secondary.paragraph}
size={AppFontSize.xxs}
>
{strings.fileSize()}: {formatBytes(attachment.size)}
</Paragraph>
) : null}
@@ -159,7 +163,7 @@ export const AttachmentItem = ({
}}
>
<ProgressCircleComponent
size={SIZE.xxl}
size={AppFontSize.xxl}
progress={
currentProgress?.value ? currentProgress?.value / 100 : 0
}

View File

@@ -38,7 +38,7 @@ import { downloadAttachments } from "../../common/filesystem/download-attachment
import { AttachmentGroupProgress } from "../../screens/settings/attachment-group-progress";
import { presentSheet, ToastManager } from "../../services/event-manager";
import { useAttachmentStore } from "../../stores/use-attachment-store";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import { Dialog } from "../dialog";
import { presentDialog } from "../dialog/functions";
import { Header } from "../header";
@@ -50,6 +50,7 @@ import Seperator from "../ui/seperator";
import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import { AttachmentItem } from "./attachment-item";
import { DefaultAppStyles } from "../../utils/styles";
const DEFAULT_SORTING: SortOptions = {
sortBy: "dateEdited",
@@ -325,30 +326,31 @@ export const AttachmentDialog = ({
title={strings.manageAttachments()}
renderedInRoute="SettingsGroup"
canGoBack
headerRightButtons={[
{
onPress() {
onCheck();
},
title: strings.recheckAll()
},
{
onPress() {
if (!attachments) return;
presentDialog({
title: strings.doActions.download.attachment(
attachments.placeholders.length
),
positiveText: strings.network.download(),
positivePress: async () => {
downloadAttachments(await attachments.ids());
},
negativeText: strings.cancel()
});
},
title: strings.downloadAllAttachments()
}
]}
// TODO: Add headerRightButtons
// headerRightButtons={[
// {
// onPress() {
// onCheck();
// },
// title: strings.recheckAll()
// },
// {
// onPress() {
// if (!attachments) return;
// presentDialog({
// title: strings.doActions.download.attachment(
// attachments.placeholders.length
// ),
// positiveText: strings.network.download(),
// positivePress: async () => {
// downloadAttachments(await attachments.ids());
// },
// negativeText: strings.cancel()
// });
// },
// title: strings.downloadAllAttachments()
// }
// ]}
/>
) : (
<View
@@ -356,7 +358,7 @@ export const AttachmentDialog = ({
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
>
<Heading>{strings.dataTypesPluralCamelCase.attachment()}</Heading>
@@ -369,21 +371,15 @@ export const AttachmentDialog = ({
<IconButton
name="check-all"
style={{
height: 40,
width: 40,
marginRight: 10
}}
color={colors.primary.paragraph}
size={SIZE.lg}
size={AppFontSize.lg}
onPress={onCheck}
/>
<IconButton
name="download"
style={{
height: 40,
width: 40
}}
color={colors.primary.paragraph}
onPress={() => {
if (!attachments) return;
@@ -398,7 +394,7 @@ export const AttachmentDialog = ({
negativeText: strings.cancel()
});
}}
size={SIZE.lg}
size={AppFontSize.lg}
/>
</View>
</View>
@@ -408,7 +404,7 @@ export const AttachmentDialog = ({
style={{
width: "100%",
alignSelf: "center",
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
height: "100%"
}}
>
@@ -428,7 +424,7 @@ export const AttachmentDialog = ({
alignItems: "center",
width: "100%",
borderRadius: 10,
padding: 10,
padding: DefaultAppStyles.GAP_SMALL,
borderWidth: 1,
borderColor: colors.primary.border,
gap: 12,
@@ -473,7 +469,7 @@ export const AttachmentDialog = ({
<IconButton
type={rechecker.isWorking ? "errorShade" : "plain"}
name={rechecker.isWorking ? "close" : "check"}
size={SIZE.lg}
size={AppFontSize.lg}
color={
rechecker.isWorking ? colors.error.icon : colors.primary.accent
}
@@ -494,7 +490,7 @@ export const AttachmentDialog = ({
backgroundColor: colors.primary.background,
flexWrap: "wrap",
flexDirection: "row",
paddingVertical: 12
paddingVertical: DefaultAppStyles.GAP_VERTICAL
}}
contentContainerStyle={{
alignItems: "center"
@@ -511,10 +507,10 @@ export const AttachmentDialog = ({
}
key={item.title}
title={item.title}
fontSize={SIZE.sm}
fontSize={AppFontSize.sm}
style={{
borderRadius: 100,
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
height: 40,
minWidth: 80
}}

View File

@@ -37,6 +37,7 @@ import { hideAuth, initialAuthMode } from "./common";
import { Login } from "./login";
import { Signup } from "./signup";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../utils/styles";
export const AuthMode = {
login: 0,
@@ -133,7 +134,7 @@ const AuthModal = () => {
style={{
flexDirection: "row",
alignItems: "center",
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
width: "100%",
height: 50,
justifyContent:
@@ -167,7 +168,7 @@ const AuthModal = () => {
marginTop: 2
}}
style={{
paddingHorizontal: 6
paddingHorizontal: DefaultAppStyles.GAP_SMALL
}}
/>
)}

View File

@@ -17,25 +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";
export const ChangePassword = () => {
const passwordInputRef = useRef();
@@ -84,8 +79,7 @@ export const ChangePassword = () => {
context: "global"
});
setLoading(false);
eSendEvent(eCloseSheet);
await sleep(300);
Navigation.goBack();
eSendEvent(eOpenRecoveryKeyDialog);
} catch (e) {
setLoading(false);
@@ -103,13 +97,10 @@ export const ChangePassword = () => {
<View
style={{
width: "100%",
padding: 12
padding: DefaultAppStyles.GAP
}}
>
<Dialog context="change-password-dialog" />
<DialogHeader title={strings.changePassword()} />
<Seperator />
<Input
fwdRef={oldPasswordInputRef}
onChangeText={(value) => {
@@ -148,7 +139,7 @@ export const ChangePassword = () => {
<Button
style={{
marginTop: 10,
marginTop: DefaultAppStyles.GAP_VERTICAL,
width: "100%"
}}
loading={loading}
@@ -159,9 +150,3 @@ export const ChangePassword = () => {
</View>
);
};
ChangePassword.present = () => {
presentSheet({
component: <ChangePassword />
});
};

View File

@@ -20,23 +20,20 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import { createRef } from "react";
import { eSendEvent } from "../../services/event-manager";
import { eCloseLoginDialog } from "../../utils/events";
import Navigation from "../../services/navigation";
export const AuthMode = {
login: 0,
signup: 1,
welcomeSignup: 2,
trialSignup: 3
};
export const initialAuthMode = createRef(0);
export function hideAuth() {
eSendEvent(eCloseLoginDialog);
// if (initialAuthMode.current === 2) {
// Navigation.replace(
// {
// name: 'Notes'
// },
// {
// menu: true
// }
// );
// } else {
// Navigation.goBack();
// }
// tabBarRef.current?.unlock();
if (initialAuthMode.current === AuthMode.welcomeSignup) {
Navigation.replace("FluidPanelsView");
} else {
Navigation.goBack();
}
}

View File

@@ -33,6 +33,7 @@ import Seperator from "../ui/seperator";
import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../utils/styles";
export const ForgotPassword = () => {
const { colors } = useThemeColors("sheet");
@@ -107,7 +108,7 @@ export const ForgotPassword = () => {
{sent ? (
<View
style={{
padding: 12,
padding: DefaultAppStyles.GAP,
justifyContent: "center",
alignItems: "center",
paddingBottom: 50
@@ -138,7 +139,7 @@ export const ForgotPassword = () => {
backgroundColor: colors.primary.background,
zIndex: 10,
width: "100%",
padding: 12
padding: DefaultAppStyles.GAP
}}
>
<DialogHeader title={strings.accountRecovery()} />
@@ -164,7 +165,7 @@ export const ForgotPassword = () => {
<Button
style={{
marginTop: 10,
marginTop: DefaultAppStyles.GAP_VERTICAL,
width: "100%"
}}
loading={loading}

View File

@@ -17,35 +17,98 @@ 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 { useThemeColors } from "@notesnook/theme";
import React, { useState } from "react";
import { View } from "react-native";
import { useNavigationFocus } from "../../hooks/use-navigation-focus";
import useGlobalSafeAreaInsets from "../../hooks/use-global-safe-area-insets";
import Navigation from "../../services/navigation";
import { Toast } from "../toast";
import { initialAuthMode } from "./common";
import { Button } from "../ui/button";
import { IconButton } from "../ui/icon-button";
import { AuthMode, initialAuthMode } from "./common";
import { Login } from "./login";
import { Signup } from "./signup";
export const AuthMode = {
login: 0,
signup: 1,
welcomeSignup: 2,
trialSignup: 3
};
import { useNavigationFocus } from "../../hooks/use-navigation-focus";
import { DefaultAppStyles } from "../../utils/styles";
import { useSettingStore } from "../../stores/use-setting-store";
const Auth = ({ navigation, route }) => {
const [currentAuthMode, setCurrentAuthMode] = useState(
route?.params?.mode || AuthMode.login
);
const deviceMode = useSettingStore((state) => state.deviceMode);
const { colors } = useThemeColors();
const insets = useGlobalSafeAreaInsets();
initialAuthMode.current = route?.params.mode || AuthMode.login;
useNavigationFocus(navigation, {
onFocus: () => {
//tabBarRef?.current.lock();
initialAuthMode.current = route?.params.mode || AuthMode.login;
}
});
useNavigationFocus(navigation, {});
return (
<View style={{ flex: 1 }}>
<View
style={{
position: "absolute",
paddingTop: insets.top,
top: 0,
zIndex: 999,
backgroundColor:
deviceMode === "mobile" ? colors.secondary.background : null,
width: "100%"
}}
>
<View
style={{
flexDirection: "row",
alignItems: "center",
paddingHorizontal: DefaultAppStyles.GAP,
width: "100%",
height: 50,
justifyContent:
initialAuthMode.current !== AuthMode.welcomeSignup
? "space-between"
: "flex-end"
}}
>
{initialAuthMode.current === AuthMode.welcomeSignup ? null : (
<IconButton
name="arrow-left"
onPress={() => {
if (initialAuthMode.current === 2) {
Navigation.replace("FluidPanelsView");
} else {
Navigation.goBack();
}
}}
color={colors.primary.paragraph}
/>
)}
{initialAuthMode.current !== AuthMode.welcomeSignup ? null : (
<Button
title={strings.skip()}
onPress={() => {
if (initialAuthMode.current === 2) {
Navigation.replace("FluidPanelsView");
} else {
Navigation.goBack();
}
}}
iconSize={16}
type="plain"
iconPosition="right"
icon="chevron-right"
height={25}
iconStyle={{
marginTop: 2
}}
style={{
paddingHorizontal: DefaultAppStyles.GAP_SMALL
}}
/>
)}
</View>
</View>
{currentAuthMode !== AuthMode.login ? (
<Signup
changeMode={(mode) => setCurrentAuthMode(mode)}

View File

@@ -17,6 +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 { strings } from "@notesnook/intl";
import { useThemeColors } from "@notesnook/theme";
import React, { useEffect, useState } from "react";
import { TouchableOpacity, View, useWindowDimensions } from "react-native";
@@ -24,10 +25,9 @@ import { SheetManager } from "react-native-actions-sheet";
import { DDS } from "../../services/device-detection";
import { eSendEvent } from "../../services/event-manager";
import Sync from "../../services/sync";
import { useSettingStore } from "../../stores/use-setting-store";
import { useUserStore } from "../../stores/use-user-store";
import { eUserLoggedIn } from "../../utils/events";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import { sleep } from "../../utils/time";
import SheetProvider from "../sheet-provider";
import { Progress } from "../sheets/progress";
@@ -38,7 +38,8 @@ import Paragraph from "../ui/typography/paragraph";
import { hideAuth } from "./common";
import { ForgotPassword } from "./forgot-password";
import { useLogin } from "./use-login";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../utils/styles";
import { Dialog } from "../dialog";
const LoginSteps = {
emailAuth: 1,
@@ -71,8 +72,8 @@ export const Login = ({ changeMode }) => {
}
}, 5000);
});
const deviceMode = useSettingStore((state) => state.deviceMode);
const { width, height } = useWindowDimensions();
const isTablet = width > 600;
useEffect(() => {
async () => {
setStep(LoginSteps.emailAuth);
@@ -89,30 +90,31 @@ export const Login = ({ changeMode }) => {
return (
<>
<ForgotPassword />
<SheetProvider context="two_factor_verify" />
<Dialog context="two_factor_verify" />
<View
style={{
borderRadius: DDS.isTab ? 5 : 0,
backgroundColor: colors.primary.background,
zIndex: 10,
width: "100%",
height: "100%",
alignSelf: "center"
}}
>
<View
style={{
justifyContent: "flex-end",
paddingHorizontal: 20,
paddingHorizontal: DefaultAppStyles.GAP,
backgroundColor: colors.secondary.background,
borderBottomWidth: 0.8,
marginBottom: 12,
marginBottom: DefaultAppStyles.GAP_VERTICAL,
borderBottomColor: colors.primary.border,
alignSelf: deviceMode !== "mobile" ? "center" : undefined,
borderWidth: deviceMode !== "mobile" ? 1 : null,
borderColor: deviceMode !== "mobile" ? colors.primary.border : null,
borderRadius: deviceMode !== "mobile" ? 20 : null,
marginTop: deviceMode !== "mobile" ? 50 : null,
width: deviceMode === "mobile" ? null : "50%",
alignSelf: isTablet ? "center" : undefined,
borderWidth: isTablet ? 1 : null,
borderColor: isTablet ? colors.primary.border : null,
borderRadius: isTablet ? 20 : null,
marginTop: isTablet ? 50 : null,
width: !isTablet ? null : "70%",
minHeight: height * 0.4
}}
>
@@ -143,10 +145,10 @@ export const Login = ({ changeMode }) => {
<Heading
style={{
marginBottom: 25,
marginTop: 10
marginTop: DefaultAppStyles.GAP_VERTICAL
}}
extraBold
size={SIZE.xxl}
size={AppFontSize.xxl}
>
{strings.loginToYourAccount()}
</Heading>
@@ -163,7 +165,7 @@ export const Login = ({ changeMode }) => {
: "99.9%",
backgroundColor: colors.primary.background,
alignSelf: "center",
paddingHorizontal: 20
paddingHorizontal: DefaultAppStyles.GAP
}}
>
<Input
@@ -216,7 +218,7 @@ export const Login = ({ changeMode }) => {
title={strings.forgotPassword()}
style={{
alignSelf: "flex-end",
height: 30,
paddingVertical: DefaultAppStyles.GAP_VERTICAL_SMALL,
paddingHorizontal: 0
}}
onPress={() => {
@@ -226,7 +228,7 @@ export const Login = ({ changeMode }) => {
textStyle={{
textDecorationLine: "underline"
}}
fontSize={SIZE.xs}
fontSize={AppFontSize.xs}
type="plain"
/>
</>
@@ -244,11 +246,8 @@ export const Login = ({ changeMode }) => {
login();
}}
style={{
width: 250,
borderRadius: 100
width: 250
}}
height={50}
fontSize={SIZE.md}
type="accent"
title={!loading ? strings.continue() : null}
/>
@@ -258,19 +257,16 @@ export const Login = ({ changeMode }) => {
title={strings.cancelLogin()}
style={{
alignSelf: "center",
height: 30,
marginTop: 10
marginTop: DefaultAppStyles.GAP_VERTICAL,
width: 250
}}
onPress={() => {
if (loading) return;
setStep(LoginSteps.emailAuth);
setLoading(false);
}}
textStyle={{
textDecorationLine: "underline"
}}
fontSize={SIZE.xs}
type="errorShade"
fontSize={AppFontSize.xs}
type="secondaryAccented"
/>
)}
@@ -283,17 +279,17 @@ export const Login = ({ changeMode }) => {
activeOpacity={0.8}
style={{
alignSelf: "center",
marginTop: 12,
paddingVertical: 12
marginTop: DefaultAppStyles.GAP_VERTICAL,
paddingVertical: DefaultAppStyles.GAP_VERTICAL
}}
>
<Paragraph
size={SIZE.xs + 1}
size={AppFontSize.xs}
color={colors.secondary.paragraph}
>
{strings.dontHaveAccount()}{" "}
<Paragraph
size={SIZE.xs + 1}
size={AppFontSize.xs}
style={{ color: colors.primary.accent }}
>
{strings.signUp()}

View File

@@ -34,7 +34,7 @@ import Sync from "../../services/sync";
import { clearAllStores } from "../../stores";
import { useUserStore } from "../../stores/use-user-store";
import { eLoginSessionExpired, eUserLoggedIn } from "../../utils/events";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import { sleep } from "../../utils/time";
import { Dialog } from "../dialog";
import BaseDialog from "../dialog/base-dialog";
@@ -48,18 +48,8 @@ import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import { LoginSteps, useLogin } from "./use-login";
import { strings } from "@notesnook/intl";
function getObfuscatedEmail(email) {
if (!email) return "";
const [username, provider] = email.split("@");
if (username.length === 1) return `****@${provider}`;
return email.replace(/(.{1})(.*)(?=@)/, function (gp1, gp2, gp3) {
for (let i = 0; i < gp3.length; i++) {
gp2 += "*";
}
return gp2;
});
}
import { getObfuscatedEmail } from "../../utils/functions";
import { DefaultAppStyles } from "../../utils/styles";
export const SessionExpired = () => {
const { colors } = useThemeColors();
@@ -168,7 +158,7 @@ export const SessionExpired = () => {
<View
style={{
width: focused ? "100%" : "99.9%",
padding: 12,
padding: DefaultAppStyles.GAP,
justifyContent: "center",
flex: 1,
backgroundColor: colors.primary.background
@@ -193,7 +183,7 @@ export const SessionExpired = () => {
color={colors.error.icon}
size={50}
/>
<Heading size={SIZE.xxxl} color={colors.primary.heading}>
<Heading size={AppFontSize.xxxl} color={colors.primary.heading}>
{strings.sessionExpired()}
</Heading>
<Paragraph
@@ -224,7 +214,7 @@ export const SessionExpired = () => {
<Button
style={{
marginTop: 10,
marginTop: DefaultAppStyles.GAP_VERTICAL,
width: 250,
borderRadius: 100
}}
@@ -236,7 +226,7 @@ export const SessionExpired = () => {
<Button
style={{
marginTop: 10,
marginTop: DefaultAppStyles.GAP_VERTICAL,
width: "100%"
}}
onPress={() => {

View File

@@ -17,6 +17,8 @@ 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 { useThemeColors } from "@notesnook/theme";
import React, { useRef, useState } from "react";
import { TouchableOpacity, View, useWindowDimensions } from "react-native";
import { db } from "../../common/database";
@@ -24,19 +26,17 @@ import { DDS } from "../../services/device-detection";
import { ToastManager } from "../../services/event-manager";
import { clearMessage, setEmailVerifyMessage } from "../../services/message";
import PremiumService from "../../services/premium";
import { useThemeColors } from "@notesnook/theme";
import SettingsService from "../../services/settings";
import { useUserStore } from "../../stores/use-user-store";
import { openLinkInBrowser } from "../../utils/functions";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import { sleep } from "../../utils/time";
import { Button } from "../ui/button";
import Input from "../ui/input";
import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import { hideAuth } from "./common";
import { useSettingStore } from "../../stores/use-setting-store";
import SettingsService from "../../services/settings";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../utils/styles";
export const Signup = ({ changeMode, trial }) => {
const { colors } = useThemeColors();
@@ -50,8 +50,8 @@ export const Signup = ({ changeMode, trial }) => {
const [loading, setLoading] = useState(false);
const setUser = useUserStore((state) => state.setUser);
const setLastSynced = useUserStore((state) => state.setLastSynced);
const deviceMode = useSettingStore((state) => state.deviceMode);
const { width, height } = useWindowDimensions();
const isTablet = width > 600;
const validateInfo = () => {
if (!password.current || !email.current || !confirmPassword.current) {
ToastManager.show({
@@ -105,23 +105,24 @@ export const Signup = ({ changeMode, trial }) => {
backgroundColor: colors.primary.background,
zIndex: 10,
width: "100%",
height: "100%",
alignSelf: "center"
}}
>
<View
style={{
justifyContent: "flex-end",
paddingHorizontal: 20,
paddingHorizontal: DefaultAppStyles.GAP,
backgroundColor: colors.secondary.background,
marginBottom: 20,
borderBottomWidth: 0.8,
marginBottom: DefaultAppStyles.GAP_VERTICAL,
borderBottomColor: colors.primary.border,
alignSelf: deviceMode !== "mobile" ? "center" : undefined,
borderWidth: deviceMode !== "mobile" ? 1 : null,
borderColor: deviceMode !== "mobile" ? colors.primary.border : null,
borderRadius: deviceMode !== "mobile" ? 20 : null,
marginTop: deviceMode !== "mobile" ? 50 : null,
width: deviceMode === "mobile" ? null : "50%",
alignSelf: isTablet ? "center" : undefined,
borderWidth: isTablet ? 1 : null,
borderColor: isTablet ? colors.primary.border : null,
borderRadius: isTablet ? 20 : null,
marginTop: isTablet ? 50 : null,
width: !isTablet ? null : "70%",
minHeight: height * 0.4
}}
>
@@ -153,9 +154,9 @@ export const Signup = ({ changeMode, trial }) => {
extraBold
style={{
marginBottom: 25,
marginTop: 10
marginTop: DefaultAppStyles.GAP_VERTICAL
}}
size={SIZE.xxl}
size={AppFontSize.xxl}
>
{strings.createYourAccount()}
</Heading>
@@ -164,7 +165,7 @@ export const Signup = ({ changeMode, trial }) => {
<View
style={{
width: DDS.isTab ? "50%" : "100%",
paddingHorizontal: 20,
paddingHorizontal: DefaultAppStyles.GAP,
backgroundColor: colors.primary.background,
alignSelf: "center"
}}
@@ -233,12 +234,12 @@ export const Signup = ({ changeMode, trial }) => {
style={{
marginBottom: 25
}}
size={SIZE.xs}
size={AppFontSize.xxs}
color={colors.secondary.paragraph}
>
{strings.signupAgreement[0]()}
<Paragraph
size={SIZE.xs}
size={AppFontSize.xxs}
onPress={() => {
openLinkInBrowser("https://notesnook.com/tos", colors);
}}
@@ -247,11 +248,12 @@ export const Signup = ({ changeMode, trial }) => {
}}
color={colors.primary.accent}
>
{" "}
{strings.signupAgreement[1]()}
</Paragraph>
</Paragraph>{" "}
{strings.signupAgreement[2]()}
<Paragraph
size={SIZE.xs}
size={AppFontSize.xxs}
onPress={() => {
openLinkInBrowser("https://notesnook.com/privacy", colors);
}}
@@ -260,8 +262,9 @@ export const Signup = ({ changeMode, trial }) => {
}}
color={colors.primary.accent}
>
{" "}
{strings.signupAgreement[3]()}
</Paragraph>
</Paragraph>{" "}
{strings.signupAgreement[4]()}
</Paragraph>
@@ -270,11 +273,8 @@ export const Signup = ({ changeMode, trial }) => {
type="accent"
loading={loading}
onPress={signup}
fontSize={SIZE.md}
style={{
marginRight: 12,
width: 250,
borderRadius: 100
width: 250
}}
/>
@@ -286,14 +286,14 @@ export const Signup = ({ changeMode, trial }) => {
activeOpacity={0.8}
style={{
alignSelf: "center",
marginTop: 12,
paddingVertical: 12
marginTop: DefaultAppStyles.GAP_VERTICAL,
paddingVertical: DefaultAppStyles.GAP_VERTICAL
}}
>
<Paragraph size={SIZE.xs + 1} color={colors.secondary.paragraph}>
<Paragraph size={AppFontSize.xs} color={colors.secondary.paragraph}>
{strings.alreadyHaveAccount()}{" "}
<Paragraph
size={SIZE.xs + 1}
size={AppFontSize.xs}
style={{ color: colors.primary.accent }}
>
{strings.login()}

View File

@@ -24,19 +24,17 @@ 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 { SIZE } from "../../utils/size";
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";
import Input from "../ui/input";
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();
@@ -45,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);
@@ -61,7 +59,7 @@ const TwoFactorVerification = ({ onMfaLogin, mfaInfo, onCancel }) => {
},
(result) => {
if (result) {
eSendEvent(eCloseSheet, "two_factor_verify");
eSendEvent(eCloseSimpleDialog, "two_factor_verify");
}
setLoading(false);
}
@@ -132,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={{
@@ -204,9 +208,9 @@ const TwoFactorVerification = ({ onMfaLogin, mfaInfo, onCancel }) => {
}}
onSubmitEditing={onNext}
caretHidden
height={60}
inputStyle={{
fontSize: SIZE.lg,
height: 60,
fontSize: AppFontSize.lg,
textAlign: "center",
letterSpacing: 10,
width: 250
@@ -216,11 +220,13 @@ const TwoFactorVerification = ({ onMfaLogin, mfaInfo, onCancel }) => {
}
enablesReturnKeyAutomatically
containerStyle={{
height: 60,
borderWidth: 0,
width: undefined,
minWidth: "50%"
}}
wrapperStyle={{
height: 60
}}
/>
<Button
@@ -229,9 +235,15 @@ const TwoFactorVerification = ({ onMfaLogin, mfaInfo, onCancel }) => {
width={250}
loading={loading}
onPress={onNext}
style={{
borderRadius: 100
/>
<Button
title={strings.cancel()}
type="secondaryAccented"
onPress={() => {
reset();
onCancel();
}}
width={250}
/>
<Button
@@ -242,13 +254,6 @@ const TwoFactorVerification = ({ onMfaLogin, mfaInfo, onCancel }) => {
onPress={onRequestSecondaryMethod}
height={30}
/>
<Button
title={strings.cancel()}
type="plain"
onPress={onCancel}
height={30}
/>
</>
) : (
<>
@@ -262,8 +267,8 @@ const TwoFactorVerification = ({ onMfaLogin, mfaInfo, onCancel }) => {
});
}}
style={{
paddingHorizontal: 12,
paddingVertical: 12,
paddingHorizontal: DefaultAppStyles.GAP,
paddingVertical: DefaultAppStyles.GAP_VERTICAL,
marginTop: 0,
flexDirection: "row",
borderRadius: 0,
@@ -275,8 +280,6 @@ const TwoFactorVerification = ({ onMfaLogin, mfaInfo, onCancel }) => {
<IconButton
type="secondaryAccented"
style={{
width: 40,
height: 40,
marginRight: 10
}}
size={15}
@@ -288,7 +291,7 @@ const TwoFactorVerification = ({ onMfaLogin, mfaInfo, onCancel }) => {
flexShrink: 1
}}
>
<Paragraph size={SIZE.md}>{item.title}</Paragraph>
<Paragraph size={AppFontSize.md}>{item.title}</Paragraph>
</View>
</Pressable>
))}
@@ -300,7 +303,7 @@ const TwoFactorVerification = ({ onMfaLogin, mfaInfo, onCancel }) => {
};
TwoFactorVerification.present = (onMfaLogin, data, onCancel, context) => {
presentSheet({
presentDialog({
component: () => (
<TwoFactorVerification
onMfaLogin={onMfaLogin}
@@ -309,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

@@ -20,7 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import { useThemeColors } from "@notesnook/theme";
import { useRoute } from "@react-navigation/native";
import React, { useCallback, useEffect } from "react";
import { Keyboard, View } from "react-native";
import { Keyboard, TouchableOpacity, View, ViewStyle } from "react-native";
import Animated, {
Easing,
useAnimatedStyle,
@@ -33,20 +33,31 @@ import { editorState } from "../../screens/editor/tiptap/utils";
import { useSelectionStore } from "../../stores/use-selection-store";
import { useSettingStore } from "../../stores/use-setting-store";
import { getElevationStyle } from "../../utils/elevation";
import { SIZE, normalize } from "../../utils/size";
import { Pressable } from "../ui/pressable";
import { AppFontSize, normalize } from "../../utils/size";
import { DefaultAppStyles } from "../../utils/styles";
import { hexToRGBA, RGB_Linear_Shade } from "../../utils/colors";
interface FloatingButtonProps {
onPress: () => void;
color?: string;
shouldShow?: boolean;
alwaysVisible?: boolean;
icon?: string;
testID?: string;
position?: "left" | "right";
size?: "small" | "large";
style?: ViewStyle;
}
const FloatingButton = ({
onPress,
color,
alwaysVisible = false
alwaysVisible = false,
icon,
testID,
position = "right",
size = "large",
style
}: FloatingButtonProps) => {
const { colors } = useThemeColors();
const deviceMode = useSettingStore((state) => state.deviceMode);
@@ -108,20 +119,26 @@ const FloatingButton = ({
style={[
{
position: "absolute",
right: 12,
right: position === "right" ? DefaultAppStyles.GAP : undefined,
left: position === "left" ? DefaultAppStyles.GAP : undefined,
bottom: 20,
zIndex: 10
zIndex: 10,
...style
},
animatedStyle
]}
>
<Pressable
testID={notesnook.buttons.add}
type="accent"
accentColor={color}
<TouchableOpacity
testID={testID || notesnook.buttons.add}
activeOpacity={0.95}
style={{
...getElevationStyle(5),
borderRadius: 100
borderRadius: size === "small" ? 15 : 20,
borderTopWidth: 0,
borderBottomWidth: 0,
borderLeftWidth: 0,
borderRightWidth: 0,
backgroundColor: colors.primary.background
}}
onPress={onPress}
>
@@ -129,23 +146,29 @@ const FloatingButton = ({
style={{
alignItems: "center",
justifyContent: "center",
height: normalize(60),
width: normalize(60)
height: normalize(size === "small" ? 40 : 60),
width: normalize(size === "small" ? 40 : 60),
backgroundColor: color
? RGB_Linear_Shade(0.87, hexToRGBA(color))
: colors.primary.shade,
borderRadius: size === "small" ? 15 : 20
}}
>
<Icon
name={
route.name === "Notebooks"
icon
? icon
: route.name === "Notebooks"
? "notebook-plus"
: route.name === "Trash"
? "delete"
: "plus"
}
color={colors.primary.accentForeground}
size={SIZE.xxl}
color={color || colors.primary.accent}
size={size === "small" ? AppFontSize.xl : AppFontSize.xxxl}
/>
</View>
</Pressable>
</TouchableOpacity>
</Animated.View>
);
};

View File

@@ -23,6 +23,8 @@ import { useMessageStore } from "../../stores/use-message-store";
import { useThemeColors } from "@notesnook/theme";
import { ColorValues } from "../../utils/colors";
import { hexToRGBA } from "../../utils/colors";
import { defaultBorderRadius } from "../../utils/size";
import { DefaultAppStyles } from "../../utils/styles";
export const DefaultPlaceholder = ({ color }: { color: string }) => {
const { colors } = useThemeColors();
@@ -40,7 +42,7 @@ export const DefaultPlaceholder = ({ color }: { color: string }) => {
<View
style={{
width: "100%",
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
>
{hasAnnoucements ? (
@@ -51,7 +53,7 @@ export const DefaultPlaceholder = ({ color }: { color: string }) => {
borderRadius: 10,
marginBottom: 20,
backgroundColor: colors.secondary.background,
padding: 12
padding: DefaultAppStyles.GAP
}}
>
<View
@@ -59,7 +61,7 @@ export const DefaultPlaceholder = ({ color }: { color: string }) => {
width: 150,
height: 20,
backgroundColor: colors.primary.hover,
borderRadius: 5,
borderRadius: defaultBorderRadius,
marginBottom: 10
}}
/>
@@ -68,7 +70,7 @@ export const DefaultPlaceholder = ({ color }: { color: string }) => {
width: 250,
height: 14,
backgroundColor: colors.primary.hover,
borderRadius: 5
borderRadius: defaultBorderRadius
}}
/>
@@ -78,7 +80,7 @@ export const DefaultPlaceholder = ({ color }: { color: string }) => {
height: 15,
backgroundColor: shadeColor,
borderRadius: 3,
marginTop: 10
marginTop: DefaultAppStyles.GAP_VERTICAL
}}
/>
</View>
@@ -93,7 +95,7 @@ export const DefaultPlaceholder = ({ color }: { color: string }) => {
marginBottom: 20,
flexDirection: "row",
alignItems: "center",
paddingHorizontal: 20
paddingHorizontal: DefaultAppStyles.GAP
}}
>
<View
@@ -111,7 +113,7 @@ export const DefaultPlaceholder = ({ color }: { color: string }) => {
width: 150,
height: 12,
backgroundColor: colors.secondary.background,
borderRadius: 5,
borderRadius: defaultBorderRadius,
marginBottom: 10
}}
/>
@@ -120,7 +122,7 @@ export const DefaultPlaceholder = ({ color }: { color: string }) => {
width: 250,
height: 16,
backgroundColor: colors.secondary.background,
borderRadius: 5
borderRadius: defaultBorderRadius
}}
/>
</View>
@@ -134,7 +136,7 @@ export const DefaultPlaceholder = ({ color }: { color: string }) => {
backgroundColor: colors.secondary.background,
borderRadius: 10,
marginBottom: 20,
padding: 5,
padding: DefaultAppStyles.GAP_SMALL,
justifyContent: "space-between",
flexDirection: "row",
alignItems: "center"
@@ -179,7 +181,7 @@ export const DefaultPlaceholder = ({ color }: { color: string }) => {
width: 200,
height: 16,
backgroundColor: colors.secondary.background,
borderRadius: 5
borderRadius: defaultBorderRadius
}}
/>
<View
@@ -187,15 +189,15 @@ export const DefaultPlaceholder = ({ color }: { color: string }) => {
width: "85%",
height: 13,
backgroundColor: colors.secondary.background,
borderRadius: 5,
marginTop: 10
borderRadius: defaultBorderRadius,
marginTop: DefaultAppStyles.GAP_VERTICAL
}}
/>
<View
style={{
flexDirection: "row",
marginTop: 10
marginTop: DefaultAppStyles.GAP_VERTICAL
}}
>
<View
@@ -203,7 +205,7 @@ export const DefaultPlaceholder = ({ color }: { color: string }) => {
width: 50,
height: 10,
backgroundColor: colors.secondary.background,
borderRadius: 5
borderRadius: defaultBorderRadius
}}
/>
<View
@@ -211,7 +213,7 @@ export const DefaultPlaceholder = ({ color }: { color: string }) => {
width: 60,
height: 10,
backgroundColor: colors.secondary.background,
borderRadius: 5,
borderRadius: defaultBorderRadius,
marginLeft: 10
}}
/>

View File

@@ -17,11 +17,10 @@ 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 { ViewProps } from "react-native";
import Animated, { FadeOutUp } from "react-native-reanimated";
import { useDelayLayout } from "../../hooks/use-delay-layout";
import { useThemeColors } from "@notesnook/theme";
import React from "react";
import { View, ViewProps } from "react-native";
import { useDelayLayout } from "../../hooks/use-delay-layout";
import { DefaultPlaceholder } from "./default-placeholder";
import { SettingsPlaceholder } from "./settings-placeholder";
@@ -49,8 +48,7 @@ export default function DelayLayout({
const Placeholder = placeholder[props.type || "default"];
return loading || props.wait ? (
<Animated.View
exiting={animated ? FadeOutUp : undefined}
<View
style={{
backgroundColor: colors.primary.background,
flex: 1,
@@ -58,7 +56,7 @@ export default function DelayLayout({
}}
>
<Placeholder color={props.color || colors.primary.accent} />
</Animated.View>
</View>
) : (
<>{props.children}</>
);

View File

@@ -20,6 +20,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import React from "react";
import { View } from "react-native";
import { useThemeColors } from "@notesnook/theme";
import { defaultBorderRadius } from "../../utils/size";
import { DefaultAppStyles } from "../../utils/styles";
export const SettingsPlaceholder = () => {
const { colors } = useThemeColors();
@@ -31,7 +33,7 @@ export const SettingsPlaceholder = () => {
width: 100,
height: 12,
backgroundColor: colors.primary.shade,
borderRadius: 5,
borderRadius: defaultBorderRadius,
marginLeft: 12,
marginBottom: 12
}}
@@ -44,7 +46,7 @@ export const SettingsPlaceholder = () => {
marginBottom: 20,
flexDirection: "row",
alignItems: "center",
paddingHorizontal: 16
paddingHorizontal: DefaultAppStyles.GAP
}}
>
<View
@@ -62,7 +64,7 @@ export const SettingsPlaceholder = () => {
width: 150,
height: 12,
backgroundColor: colors.secondary.background,
borderRadius: 5,
borderRadius: defaultBorderRadius,
marginBottom: 10
}}
/>
@@ -71,7 +73,7 @@ export const SettingsPlaceholder = () => {
width: 250,
height: 16,
backgroundColor: colors.secondary.background,
borderRadius: 5
borderRadius: defaultBorderRadius
}}
/>
</View>
@@ -85,7 +87,7 @@ export const SettingsPlaceholder = () => {
marginBottom: 20,
flexDirection: "row",
alignItems: "center",
paddingHorizontal: 16,
paddingHorizontal: DefaultAppStyles.GAP,
justifyContent: "space-between"
}}
>
@@ -104,7 +106,7 @@ export const SettingsPlaceholder = () => {
width: 150,
height: 12,
backgroundColor: colors.secondary.background,
borderRadius: 5,
borderRadius: defaultBorderRadius,
marginBottom: 10
}}
/>
@@ -113,7 +115,7 @@ export const SettingsPlaceholder = () => {
width: 250,
height: 16,
backgroundColor: colors.secondary.background,
borderRadius: 5
borderRadius: defaultBorderRadius
}}
/>
</View>

View File

@@ -17,6 +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 { ScopedThemeProvider } from "@notesnook/theme";
import React, { PropsWithChildren, useEffect, useRef, useState } from "react";
import {
ColorValue,
@@ -30,11 +31,8 @@ import {
} from "react-native";
import useIsFloatingKeyboard from "../../hooks/use-is-floating-keyboard";
import { useSettingStore } from "../../stores/use-setting-store";
import { BouncingView } from "../ui/transitions/bouncing-view";
import { ScopedThemeProvider } from "@notesnook/theme";
import SettingsService from "../../services/settings";
import { useUserStore } from "../../stores/use-user-store";
import { useAppState } from "../../hooks/use-app-state";
import { BouncingView } from "../ui/transitions/bouncing-view";
export interface BaseDialogProps extends PropsWithChildren {
animation?: "fade" | "none" | "slide" | undefined;

View File

@@ -17,16 +17,17 @@ 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 { useThemeColors } from "@notesnook/theme";
import React from "react";
import { ActivityIndicator, StyleSheet, View } from "react-native";
import { StyleSheet, View } from "react-native";
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
import { notesnook } from "../../../e2e/test.ids";
import { useThemeColors } from "@notesnook/theme";
import { SIZE } from "../../utils/size";
import { Button } from "../ui/button";
import Paragraph from "../ui/typography/paragraph";
import { getColorLinearShade } from "../../utils/colors";
import { strings } from "@notesnook/intl";
import { AppFontSize } from "../../utils/size";
import { DefaultAppStyles } from "../../utils/styles";
import { Button, ButtonProps } from "../ui/button";
import Paragraph from "../ui/typography/paragraph";
const DialogButtons = ({
onPressPositive,
@@ -36,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();
@@ -46,9 +55,7 @@ const DialogButtons = ({
{
backgroundColor: colors.secondary.background,
height: 60,
borderBottomRightRadius: 5,
borderBottomLeftRadius: 5,
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
borderTopWidth: 0.7,
borderTopColor: getColorLinearShade(
colors.secondary.background,
@@ -58,9 +65,7 @@ const DialogButtons = ({
}
]}
>
{loading ? (
<ActivityIndicator color={colors.primary.accent} size={SIZE.lg} />
) : doneText ? (
{doneText ? (
<View
style={{
flexDirection: "row",
@@ -70,7 +75,7 @@ const DialogButtons = ({
<Icon
color={colors.primary.accent}
name="check-circle-outline"
size={SIZE.md}
size={AppFontSize.md}
/>
<Paragraph color={colors.primary.accent}>{" " + doneText}</Paragraph>
</View>
@@ -86,7 +91,7 @@ const DialogButtons = ({
>
<Button
onPress={onPressNegative}
fontSize={SIZE.md}
fontSize={AppFontSize.sm}
testID={notesnook.ids.default.dialog.no}
type="plain"
bold
@@ -95,11 +100,12 @@ const DialogButtons = ({
{onPressPositive ? (
<Button
onPress={onPressPositive}
fontSize={SIZE.md}
fontSize={AppFontSize.sm}
testID={notesnook.ids.default.dialog.yes}
style={{
marginLeft: 10
}}
loading={loading}
bold
type={positiveType || "transparent"}
title={positiveTitle}
@@ -117,6 +123,6 @@ const styles = StyleSheet.create({
justifyContent: "space-between",
alignItems: "center",
flexDirection: "row",
marginTop: 10
marginTop: DefaultAppStyles.GAP_VERTICAL
}
});

View File

@@ -20,11 +20,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import React from "react";
import { Text, View, ViewStyle } from "react-native";
import { useThemeColors } from "@notesnook/theme";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import { Button } from "../ui/button";
import { PressableProps } from "../ui/pressable";
import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import { DefaultAppStyles } from "../../utils/styles";
type DialogHeaderProps = {
icon?: string;
@@ -82,7 +83,7 @@ const DialogHeader = ({
>
<Heading
style={{ textAlign: centered ? "center" : "left" }}
size={SIZE.lg}
size={AppFontSize.lg}
>
{title}{" "}
{titlePart ? (
@@ -97,7 +98,7 @@ const DialogHeader = ({
onPress={button.onPress}
style={{
borderRadius: 100,
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
loading={button.loading}
fontSize={13}

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

@@ -1,233 +0,0 @@
/*
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, { useEffect, useRef, useState } from "react";
import { View } from "react-native";
import { DDS } from "../../services/device-detection";
import {
eSubscribeEvent,
eUnSubscribeEvent
} from "../../services/event-manager";
import { useThemeColors } from "@notesnook/theme";
import { getElevationStyle } from "../../utils/elevation";
import { eCloseSimpleDialog, eOpenSimpleDialog } from "../../utils/events";
import { sleep } from "../../utils/time";
import { Toast } from "../toast";
import Input from "../ui/input";
import Seperator from "../ui/seperator";
import BaseDialog from "./base-dialog";
import DialogButtons from "./dialog-buttons";
import DialogHeader from "./dialog-header";
import { useCallback } from "react";
import { Button } from "../ui/button";
import { getContainerBorder } from "../../utils/colors";
import { Notice } from "../ui/notice";
import { strings } from "@notesnook/intl";
export const Dialog = ({ context = "global" }) => {
const { colors } = useThemeColors();
const [visible, setVisible] = useState(false);
const [checked, setChecked] = useState(false);
const values = useRef({
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 onPressPositive = async () => {
if (dialogInfo.positivePress) {
inputRef.current?.blur();
let result = await dialogInfo.positivePress(
values.current.inputValue || dialogInfo.defaultValue,
checked
);
if (result === false) {
return;
}
}
hide();
};
const show = useCallback(
(data) => {
if (!data.context) data.context = "global";
if (data.context !== context) return;
setDialogInfo(data);
setChecked(data.check?.defaultValue);
values.current.inputValue = data.defaultValue;
setVisible(true);
},
[context]
);
useEffect(() => {
eSubscribeEvent(eOpenSimpleDialog, show);
eSubscribeEvent(eCloseSimpleDialog, hide);
return () => {
eUnSubscribeEvent(eOpenSimpleDialog, show);
eUnSubscribeEvent(eCloseSimpleDialog, hide);
};
}, [show]);
const hide = () => {
setChecked(false);
values.current.inputValue = undefined;
setVisible(false);
};
const onNegativePress = async () => {
if (dialogInfo.onClose) {
await dialogInfo.onClose();
}
hide();
};
const style = {
...getElevationStyle(5),
width: DDS.isTab ? 400 : "85%",
maxHeight: 450,
borderRadius: 5,
backgroundColor: colors.primary.background,
paddingTop: 12,
...getContainerBorder(colors.primary.border, 0.5)
};
return visible ? (
<BaseDialog
statusBarTranslucent={false}
bounce={!dialogInfo.input}
closeOnTouch={!dialogInfo.disableBackdropClosing}
onShow={async () => {
if (dialogInfo.input) {
inputRef.current?.setNativeProps({
text: dialogInfo.defaultValue
});
await sleep(300);
inputRef.current?.focus();
}
}}
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 />
{dialogInfo.input ? (
<View
style={{
paddingHorizontal: 12
}}
>
<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}
{dialogInfo?.notice ? (
<View
style={{
paddingHorizontal: 12
}}
>
<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"
}
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}
positiveTitle={dialogInfo.positiveText}
negativeTitle={dialogInfo.negativeText}
positiveType={dialogInfo.positiveType}
/>
</View>
<Toast context="local" />
</BaseDialog>
) : null;
};

View File

@@ -0,0 +1,252 @@
/*
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 { strings } from "@notesnook/intl";
import { useThemeColors } from "@notesnook/theme";
import React, { useCallback, useEffect, useRef, useState } from "react";
import { TextInput, View, ViewStyle } from "react-native";
import { DDS } from "../../services/device-detection";
import {
eSubscribeEvent,
eUnSubscribeEvent
} from "../../services/event-manager";
import { getContainerBorder } from "../../utils/colors";
import { getElevationStyle } from "../../utils/elevation";
import { eCloseSimpleDialog, eOpenSimpleDialog } from "../../utils/events";
import { defaultBorderRadius } from "../../utils/size";
import { DefaultAppStyles } from "../../utils/styles";
import { sleep } from "../../utils/time";
import { Toast } from "../toast";
import { Button } from "../ui/button";
import Input from "../ui/input";
import { Notice } from "../ui/notice";
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" }: { context?: string }) => {
const { colors } = useThemeColors();
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<TextInput>(null);
const [dialogInfo, setDialogInfo] = useState<DialogInfo>();
const onPressPositive = async () => {
if (dialogInfo?.positivePress) {
inputRef.current?.blur();
setLoading(true);
let result = false;
try {
result = await dialogInfo.positivePress(
values.current.inputValue || dialogInfo.defaultValue,
checked
);
} catch (e) {
/** Empty */
}
setLoading(false);
if (result === false) {
return;
}
}
setChecked(false);
values.current.inputValue = undefined;
setVisible(false);
};
const show = useCallback(
(data: DialogInfo) => {
if (!data.context) data.context = "global";
if (data.context !== context) return;
setDialogInfo(data);
setChecked(data.check?.defaultValue);
values.current.inputValue = data.defaultValue;
setVisible(true);
},
[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);
return () => {
eUnSubscribeEvent(eOpenSimpleDialog, show);
eUnSubscribeEvent(eCloseSimpleDialog, hide);
};
}, [hide, show]);
const onNegativePress = async () => {
if (dialogInfo?.onClose) {
await dialogInfo.onClose();
}
hide();
};
const style: ViewStyle = {
...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"
};
return visible && dialogInfo ? (
<BaseDialog
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({
text: dialogInfo.defaultValue
});
await sleep(300);
inputRef.current?.focus();
}
}}
visible={true}
onRequestClose={hide}
>
{typeof dialogInfo.component === "function"
? dialogInfo.component(() => hide())
: dialogInfo.component}
{dialogInfo.component ? null : (
<View style={style}>
<DialogHeader
title={dialogInfo.title}
icon={dialogInfo.icon}
paragraph={dialogInfo.paragraph}
paragraphColor={dialogInfo.paragraphColor}
padding={12}
style={{
minHeight: 0
}}
/>
<Seperator half />
{dialogInfo.input ? (
<View
style={{
paddingHorizontal: DefaultAppStyles.GAP
}}
>
<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}
{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

@@ -39,7 +39,7 @@ import {
eCloseAppLocKPasswordDailog,
eOpenAppLockPasswordDialog
} from "../../../utils/events";
import { SIZE } from "../../../utils/size";
import { AppFontSize } from "../../../utils/size";
import { sleep } from "../../../utils/time";
import BaseDialog from "../../dialog/base-dialog";
import DialogButtons from "../../dialog/dialog-buttons";
@@ -50,6 +50,7 @@ import { IconButton } from "../../ui/icon-button";
import Input from "../../ui/input";
import Seperator from "../../ui/seperator";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../../utils/styles";
export const AppLockPassword = () => {
const { colors } = useThemeColors();
@@ -128,7 +129,7 @@ export const AppLockPassword = () => {
<View
style={{
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
>
{mode === "change" ? (
@@ -192,7 +193,7 @@ export const AppLockPassword = () => {
height: 25,
marginRight: 5
}}
size={SIZE.lg}
size={AppFontSize.lg}
/>
)
}
@@ -248,7 +249,7 @@ export const AppLockPassword = () => {
setSecureTextEntry(true);
});
}}
iconSize={SIZE.lg}
iconSize={AppFontSize.lg}
type="plain"
iconColor={
accountPass ? colors.primary.accent : colors.primary.icon
@@ -259,7 +260,7 @@ export const AppLockPassword = () => {
alignSelf: "flex-start",
justifyContent: "flex-start",
paddingHorizontal: 0,
height: 30
paddingVertical: DefaultAppStyles.GAP_VERTICAL_SMALL
}}
/>
</>

View File

@@ -27,12 +27,13 @@ import {
import { Image as ImageType } from "react-native-image-crop-picker";
import { useThemeColors } from "@notesnook/theme";
import { presentSheet } from "../../../services/event-manager";
import { SIZE } from "../../../utils/size";
import { defaultBorderRadius, AppFontSize } from "../../../utils/size";
import { Button } from "../../ui/button";
import { IconButton } from "../../ui/icon-button";
import { Notice } from "../../ui/notice";
import Paragraph from "../../ui/typography/paragraph";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../../utils/styles";
export default function AttachImage({
response,
@@ -50,21 +51,26 @@ export default function AttachImage({
<View
style={{
alignItems: "center",
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
>
<View
style={{
backgroundColor: colors.secondary.background,
marginBottom: 12,
marginBottom: DefaultAppStyles.GAP_VERTICAL,
height: 140,
width: "100%",
borderRadius: 10,
padding: 5,
paddingHorizontal: 12
padding: DefaultAppStyles.GAP_SMALL,
paddingHorizontal: DefaultAppStyles.GAP_SMALL
}}
>
<Paragraph style={{ color: colors.primary.paragraph, marginBottom: 6 }}>
<Paragraph
style={{
color: colors.primary.paragraph,
marginBottom: DefaultAppStyles.GAP_VERTICAL_SMALL
}}
>
{strings.attachImageHeading(response?.length || 1)}
</Paragraph>
<ScrollView horizontal>
@@ -80,7 +86,7 @@ export default function AttachImage({
style={{
width: 100,
height: 100,
borderRadius: 5,
borderRadius: defaultBorderRadius,
backgroundColor: "black",
marginRight: 6
}}
@@ -96,7 +102,7 @@ export default function AttachImage({
style={{
flexDirection: "row",
alignSelf: "center",
marginBottom: 12,
marginBottom: DefaultAppStyles.GAP_VERTICAL,
alignItems: "center",
width: "100%"
}}
@@ -105,7 +111,7 @@ export default function AttachImage({
}}
>
<IconButton
size={SIZE.lg}
size={AppFontSize.lg}
name={compress ? "checkbox-marked" : "checkbox-blank-outline"}
color={compress ? colors.primary.accent : colors.primary.icon}
style={{
@@ -122,7 +128,7 @@ export default function AttachImage({
flexShrink: 1,
marginLeft: 3
}}
size={SIZE.sm}
size={AppFontSize.sm}
>
{strings.compress()} ({strings.recommended().toLowerCase()})
</Paragraph>
@@ -135,7 +141,7 @@ export default function AttachImage({
size="small"
style={{
width: "100%",
marginBottom: 12
marginBottom: DefaultAppStyles.GAP_VERTICAL
}}
/>
) : (
@@ -145,7 +151,7 @@ export default function AttachImage({
size="small"
style={{
width: "100%",
marginBottom: 12
marginBottom: DefaultAppStyles.GAP_VERTICAL
}}
/>
)}

View File

@@ -34,6 +34,7 @@ import { Button } from "../../ui/button";
import Input from "../../ui/input";
import { Pressable } from "../../ui/pressable";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../../utils/styles";
const HEX_COLOR_REGEX_ALPHA =
/^#(?:(?:[\da-fA-F]{3}){1,2}|(?:[\da-fA-F]{4}){1,2})$/;
@@ -105,16 +106,16 @@ const ColorPicker = ({
<View
style={{
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
>
<View
style={{
flexDirection: "row",
alignItems: "center",
paddingTop: 10,
columnGap: 10,
marginBottom: 10
paddingTop: DefaultAppStyles.GAP_VERTICAL,
columnGap: DefaultAppStyles.GAP_VERTICAL,
marginBottom: DefaultAppStyles.GAP_VERTICAL
}}
>
<Input
@@ -155,7 +156,7 @@ const ColorPicker = ({
<Button
title={strings.addColor()}
style={{
marginBottom: 10
marginBottom: DefaultAppStyles.GAP_VERTICAL
}}
onPress={async () => {
if (!selectedColor)

View File

@@ -39,10 +39,11 @@ import {
eOpenJumpToDialog,
eScrollEvent
} from "../../../utils/events";
import { SIZE } from "../../../utils/size";
import { AppFontSize } from "../../../utils/size";
import BaseDialog from "../../dialog/base-dialog";
import { Pressable } from "../../ui/pressable";
import Paragraph from "../../ui/typography/paragraph";
import { DefaultAppStyles } from "../../../utils/styles";
const JumpToSectionDialog = () => {
const scrollRef = useRef<RefObject<FlatList>>();
@@ -152,13 +153,13 @@ const JumpToSectionDialog = () => {
maxHeight: "65%",
borderRadius: 10,
alignSelf: "center",
padding: 10,
padding: DefaultAppStyles.GAP_SMALL,
paddingTop: 30
}}
>
{loading ? (
<ActivityIndicator
size={SIZE.lg}
size={AppFontSize.lg}
color={colors.primary.accent}
style={{
marginBottom: 20
@@ -188,15 +189,15 @@ const JumpToSectionDialog = () => {
style={{
minWidth: "20%",
width: null,
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
margin: 5,
borderRadius: 100,
height: 30,
paddingVertical: DefaultAppStyles.GAP_VERTICAL_SMALL,
marginVertical: 10
}}
>
<Paragraph
size={SIZE.sm}
size={AppFontSize.sm}
color={
currentIndex === index
? colors.static.white

View File

@@ -28,6 +28,7 @@ import {
} from "../../../services/event-manager";
import { useState } from "react";
import { eCloseLoading, eOpenLoading } from "../../../utils/events";
import { DefaultAppStyles } from "../../../utils/styles";
export const LoadingDialog = () => {
const { colors } = useThemeColors();
@@ -67,7 +68,7 @@ export const LoadingDialog = () => {
style={{
flexDirection: "row",
width: 100,
marginTop: 15
marginTop: DefaultAppStyles.GAP
}}
>
<ProgressBarComponent

View File

@@ -19,10 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import React, { useCallback, useEffect, useRef, useState } from "react";
import { Dimensions, TextInput, View } from "react-native";
import {
addOrientationListener,
removeOrientationListener
} from "react-native-orientation";
import Orientation from "react-native-orientation-locker";
import Pdf from "react-native-pdf";
import Animated, { FadeIn, FadeOut } from "react-native-reanimated";
import downloadAttachment from "../../../common/filesystem/download-attachment";
@@ -34,7 +31,7 @@ import {
eUnSubscribeEvent
} from "../../../services/event-manager";
import { useThemeColors } from "@notesnook/theme";
import { SIZE } from "../../../utils/size";
import { AppFontSize } from "../../../utils/size";
import { Dialog } from "../../dialog";
import BaseDialog from "../../dialog/base-dialog";
import { presentDialog } from "../../dialog/functions";
@@ -46,6 +43,7 @@ import { sleep } from "../../../utils/time";
import { MMKV } from "../../../common/database/mmkv";
import { deleteCacheFileByPath } from "../../../common/filesystem/io";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../../utils/styles";
const WIN_WIDTH = Dimensions.get("window").width;
const WIN_HEIGHT = Dimensions.get("window").height;
@@ -98,9 +96,9 @@ const PDFPreview = () => {
};
useEffect(() => {
addOrientationListener(onOrientationChange);
Orientation.addDeviceOrientationListener(onOrientationChange);
return () => {
removeOrientationListener(onOrientationChange);
Orientation.removeDeviceOrientationListener(onOrientationChange);
};
}, []);
@@ -184,7 +182,7 @@ const PDFPreview = () => {
/>
<Paragraph
style={{
marginTop: 10
marginTop: DefaultAppStyles.GAP_VERTICAL
}}
color={colors.static.white}
>
@@ -200,7 +198,7 @@ const PDFPreview = () => {
marginTop: insets.top,
flexDirection: "row",
justifyContent: "space-between",
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
paddingLeft: 6
}}
>
@@ -216,7 +214,7 @@ const PDFPreview = () => {
style={{
marginRight: 12
}}
size={SIZE.xxl}
size={AppFontSize.xxl}
/>
</View>

View File

@@ -21,7 +21,7 @@ import { useThemeColors } from "@notesnook/theme";
import React, { useEffect } from "react";
import { View } from "react-native";
import { eSendEvent, eSubscribeEvent } from "../../../services/event-manager";
import { SIZE } from "../../../utils/size";
import { AppFontSize } from "../../../utils/size";
import { Dialog } from "../../dialog";
import BaseDialog from "../../dialog/base-dialog";
import DialogContainer from "../../dialog/dialog-container";
@@ -29,6 +29,7 @@ import { Button } from "../../ui/button";
import { ProgressBarComponent } from "../../ui/svg/lazy";
import Heading from "../../ui/typography/heading";
import Paragraph from "../../ui/typography/paragraph";
import { DefaultAppStyles } from "../../../utils/styles";
export type ProgressOptions = {
progress?: string;
@@ -111,7 +112,7 @@ export default function Progress() {
>
<DialogContainer
style={{
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
paddingBottom: 10
}}
noBorder={data?.fillBackground ? true : false}
@@ -121,7 +122,7 @@ export default function Progress() {
style={{
justifyContent: "center",
alignItems: "center",
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
gap: 10,
paddingBottom: 20
}}
@@ -131,7 +132,7 @@ export default function Progress() {
textAlign: "center"
}}
color={colors.primary.paragraph}
size={SIZE.lg}
size={AppFontSize.lg}
>
{data?.title}
</Heading>
@@ -148,7 +149,7 @@ export default function Progress() {
style={{
flexDirection: "row",
width: 100,
paddingVertical: 12
paddingVertical: DefaultAppStyles.GAP_VERTICAL
}}
>
<ProgressBarComponent

View File

@@ -27,13 +27,14 @@ import {
import { useThemeColors } from "@notesnook/theme";
import { getElevationStyle } from "../../../utils/elevation";
import { eCloseResultDialog, eOpenResultDialog } from "../../../utils/events";
import { SIZE } from "../../../utils/size";
import { AppFontSize } from "../../../utils/size";
import BaseDialog from "../../dialog/base-dialog";
import { Button } from "../../ui/button";
import Seperator from "../../ui/seperator";
import Heading from "../../ui/typography/heading";
import Paragraph from "../../ui/typography/paragraph";
import { ProFeatures } from "./pro-features";
import { DefaultAppStyles } from "../../../utils/styles";
const ResultDialog = () => {
const { colors } = useThemeColors();
@@ -78,15 +79,15 @@ const ResultDialog = () => {
}}
>
<Heading
size={SIZE.lg}
size={AppFontSize.lg}
textBreakStrategy="balanced"
style={{
alignSelf: "center",
textAlign: "center",
marginTop: 10,
marginTop: DefaultAppStyles.GAP_VERTICAL,
maxWidth: "100%",
marginBottom: 10,
paddingHorizontal: 12
marginBottom: DefaultAppStyles.GAP_VERTICAL,
paddingHorizontal: DefaultAppStyles.GAP
}}
>
{dialogData.title}
@@ -94,12 +95,12 @@ const ResultDialog = () => {
<Paragraph
color={colors.secondary.paragraph}
size={SIZE.md}
size={AppFontSize.md}
style={{
alignSelf: "center",
textAlign: "center",
maxWidth: "80%",
lineHeight: SIZE.sm + 5
lineHeight: AppFontSize.sm + 5
}}
>
{dialogData.paragraph}
@@ -109,7 +110,7 @@ const ResultDialog = () => {
<View
style={{
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
alignItems: "center",
width: "100%"
}}
@@ -124,17 +125,17 @@ const ResultDialog = () => {
width: "100%",
borderBottomRightRadius: 10,
borderBottomLeftRadius: 10,
paddingVertical: 10
paddingVertical: DefaultAppStyles.GAP_VERTICAL
}}
>
<Button
title={dialogData.button}
width={null}
style={{
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
onPress={close}
fontSize={SIZE.md + 2}
fontSize={AppFontSize.md + 2}
/>
</View>
</View>

View File

@@ -27,9 +27,10 @@ import {
eCloseResultDialog,
eOpenPremiumDialog
} from "../../../utils/events";
import { SIZE } from "../../../utils/size";
import { defaultBorderRadius, AppFontSize } from "../../../utils/size";
import { sleep } from "../../../utils/time";
import Paragraph from "../../ui/typography/paragraph";
import { DefaultAppStyles } from "../../../utils/styles";
export const ProFeatures = ({ count = 6 }) => {
const { colors } = useThemeColors();
@@ -67,13 +68,17 @@ export const ProFeatures = ({ count = 6 }) => {
width: "100%",
height: 40,
paddingHorizontal: 0,
marginBottom: 10,
marginBottom: DefaultAppStyles.GAP_VERTICAL,
alignItems: "center",
borderRadius: 5,
borderRadius: defaultBorderRadius,
justifyContent: "flex-start"
}}
>
<Icon size={SIZE.lg} color={colors.primary.accent} name="check" />
<Icon
size={AppFontSize.lg}
color={colors.primary.accent}
name="check"
/>
<Paragraph style={{ marginLeft: 5, flexShrink: 1 }}>
{item.content}
</Paragraph>
@@ -86,7 +91,7 @@ export const ProFeatures = ({ count = 6 }) => {
await sleep(300);
eSendEvent(eOpenPremiumDialog);
}}
size={SIZE.xs}
size={AppFontSize.xs}
style={{
textDecorationLine: "underline",
color: colors.secondary.paragraph

View File

@@ -41,7 +41,7 @@ import {
eUpdateNoteInEditor
} from "../../../utils/events";
import { deleteItems } from "../../../utils/functions";
import { tabBarRef } from "../../../utils/global-refs";
import { fluidTabsRef } from "../../../utils/global-refs";
import { convertNoteToText } from "../../../utils/note-to-text";
import { sleep } from "../../../utils/time";
import BaseDialog from "../../dialog/base-dialog";
@@ -53,6 +53,7 @@ import Input from "../../ui/input";
import Seperator from "../../ui/seperator";
import Paragraph from "../../ui/typography/paragraph";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../../utils/styles";
export class VaultDialog extends Component {
constructor(props) {
@@ -553,7 +554,7 @@ export class VaultDialog extends Component {
item: note
});
if (!DDS.isTab) {
tabBarRef.current?.goToPage(1);
fluidTabsRef.current?.goToPage("editor");
}
});
}
@@ -677,7 +678,7 @@ export class VaultDialog extends Component {
<View
style={{
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
>
{(novault ||
@@ -750,7 +751,7 @@ export class VaultDialog extends Component {
: "checkbox-blank-circle-outline"
}
style={{
marginTop: 10
marginTop: DefaultAppStyles.GAP_VERTICAL
}}
width="100%"
title={strings.deleteAllNotes()}
@@ -847,7 +848,7 @@ export class VaultDialog extends Component {
});
}}
style={{
marginTop: 10
marginTop: DefaultAppStyles.GAP_VERTICAL
}}
icon="fingerprint"
width="100%"

View File

@@ -37,12 +37,13 @@ import Animated, {
WithSpringConfig,
withTiming
} from "react-native-reanimated";
import { useTabStore } from "../../screens/editor/tiptap/use-tab-store";
import { getAppState } from "../../screens/editor/tiptap/utils";
import { eSendEvent } from "../../services/event-manager";
import { useSettingStore } from "../../stores/use-setting-store";
import { eClearEditor } from "../../utils/events";
import { useSideBarDraggingStore } from "../side-menu/dragging-store";
import { useTabStore } from "../../screens/editor/tiptap/use-tab-store";
import { rootNavigatorRef } from "../../utils/global-refs";
interface TabProps extends ViewProps {
dimensions: { width: number; height: number };
@@ -53,20 +54,22 @@ interface TabProps extends ViewProps {
onDrawerStateChange: (state: boolean) => void;
}
type FluidTabPage = "home" | "editor";
export interface TabsRef {
goToPage: (page: number, animated?: boolean) => void;
goToPage: (page: FluidTabPage, animated?: boolean) => void;
goToIndex: (index: number, animated?: boolean) => 0 | undefined;
unlock: () => boolean;
lock: () => boolean;
openDrawer: (animated?: boolean) => void;
closeDrawer: (animated?: boolean) => void;
page: () => number;
page: () => FluidTabPage;
setScrollEnabled: () => true;
isDrawerOpen: () => boolean;
node: RefObject<Animated.View>;
}
export const FluidTabs = forwardRef<TabsRef, TabProps>(function FluidTabs(
export const FluidPanels = forwardRef<TabsRef, TabProps>(function FluidTabs(
{
children,
dimensions,
@@ -81,9 +84,6 @@ export const FluidTabs = forwardRef<TabsRef, TabProps>(function FluidTabs(
const appState = useMemo(() => getAppState(), []);
const deviceMode = useSettingStore((state) => state.deviceMode);
const fullscreen = useSettingStore((state) => state.fullscreen);
const introCompleted = useSettingStore(
(state) => state.settings.introCompleted
);
const translateX = useSharedValue(
widths
? appState &&
@@ -118,26 +118,40 @@ export const FluidTabs = forwardRef<TabsRef, TabProps>(function FluidTabs(
const isIPhone = Platform.OS === "ios";
useEffect(() => {
if (introCompleted) {
if (deviceMode === "tablet" || fullscreen) {
translateX.value = 0;
} else {
if (prevWidths.current?.sidebar !== widths.sidebar) {
translateX.value =
appState && appState?.movedAway === false
? editorPosition
: widths.sidebar;
if (translateX.value === editorPosition) {
onChangeTab?.({ i: 2, from: 1 });
}
if (deviceMode === "tablet" || fullscreen) {
translateX.value = 0;
} else {
if (prevWidths.current?.sidebar !== widths.sidebar) {
translateX.value =
appState && appState?.movedAway === false
? editorPosition
: widths.sidebar;
if (translateX.value === editorPosition) {
onChangeTab?.({ i: 2, from: 1 });
}
}
isLoaded.current = true;
prevWidths.current = widths;
}
isLoaded.current = true;
prevWidths.current = widths;
}, [
deviceMode,
widths,
fullscreen,
translateX,
editorPosition,
appState,
onChangeTab
]);
useEffect(() => {
const sub = BackHandler.addEventListener("hardwareBackPress", () => {
if (isDrawerOpen.value) {
if (isDrawerOpen.value && !forcedLock.value) {
const routeNames = rootNavigatorRef.current?.getState().routes;
if (routeNames) {
const currentRoute = routeNames[routeNames.length - 1].name;
if (currentRoute !== "FluidPanelsView") return false;
}
translateX.value = withTiming(homePosition);
onDrawerStateChange(false);
isDrawerOpen.value = false;
@@ -149,34 +163,28 @@ export const FluidTabs = forwardRef<TabsRef, TabProps>(function FluidTabs(
sub && sub.remove();
};
}, [
introCompleted,
deviceMode,
widths,
fullscreen,
translateX,
isDrawerOpen,
forcedLock.value,
homePosition,
isDrawerOpen,
onDrawerStateChange,
editorPosition,
appState
translateX
]);
useImperativeHandle(
ref,
(): TabsRef => ({
goToPage: (page: number, animated = true) => {
goToPage: (page: FluidTabPage, animated = true) => {
if (deviceMode === "tablet") {
translateX.value = animated ? withTiming(0) : 0;
return;
}
page = page + 1;
if (page === 1) {
if (page === "home") {
onDrawerStateChange(false);
translateX.value = !animated
? homePosition
: withTiming(homePosition);
currentTab.value = 1;
} else if (page === 2) {
} else if (page === "editor") {
onDrawerStateChange(false);
translateX.value = !animated
? editorPosition
@@ -242,7 +250,7 @@ export const FluidTabs = forwardRef<TabsRef, TabProps>(function FluidTabs(
onDrawerStateChange(false);
isDrawerOpen.value = false;
},
page: () => currentTab.value,
page: () => (currentTab.value === 1 ? "home" : "editor"),
setScrollEnabled: () => true,
node: node
}),
@@ -295,7 +303,7 @@ export const FluidTabs = forwardRef<TabsRef, TabProps>(function FluidTabs(
.maxPointers(1)
.enabled(enabled && !disabled)
.activeOffsetX([-5, 5])
.failOffsetY([-15, 15])
.failOffsetY([-10, 10])
.onBegin((event) => {
locked.value = false;
gestureStartValue.value = {

View File

@@ -17,60 +17,52 @@ 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 { useThemeColors } from "@notesnook/theme";
import React, { useCallback, useEffect, useState } from "react";
import { Platform, StyleSheet, View } from "react-native";
import useGlobalSafeAreaInsets from "../../hooks/use-global-safe-area-insets";
import { View } from "react-native";
import {
eSubscribeEvent,
eUnSubscribeEvent
} from "../../services/event-manager";
import useNavigationStore, {
RouteName
} from "../../stores/use-navigation-store";
import { RouteName } from "../../stores/use-navigation-store";
import { useSelectionStore } from "../../stores/use-selection-store";
import { eScrollEvent } from "../../utils/events";
import { AppFontSize } from "../../utils/size";
import { DefaultAppStyles } from "../../utils/styles";
import { IconButtonProps } from "../ui/icon-button";
import { Pressable } from "../ui/pressable";
import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import { LeftMenus } from "./left-menus";
import { RightMenus } from "./right-menus";
import { Title } from "./title";
type HeaderRightButton = {
title: string;
onPress: () => void;
};
export const Header = ({
renderedInRoute,
onLeftMenuButtonPress,
title,
titleHiddenOnRender,
headerRightButtons,
id,
accentColor,
isBeta,
canGoBack,
onPressDefaultRightButton,
hasSearch,
onSearch
onSearch,
rightButton
}: {
onLeftMenuButtonPress?: () => void;
renderedInRoute?: RouteName;
id?: string;
title: string;
headerRightButtons?: HeaderRightButton[];
titleHiddenOnRender?: boolean;
accentColor?: string;
isBeta?: boolean;
canGoBack?: boolean;
onPressDefaultRightButton?: () => void;
hasSearch?: boolean;
onSearch?: () => void;
rightButton?: IconButtonProps;
}) => {
const { colors } = useThemeColors();
const insets = useGlobalSafeAreaInsets();
const [borderHidden, setBorderHidden] = useState(true);
const selectionMode = useSelectionStore((state) => state.selectionMode);
const isFocused = useNavigationStore((state) => state.focusedRouteId === id);
const [selectedItemsList, selectionMode] = useSelectionStore((state) => [
state.selectedItemsList,
state.selectionMode
]);
const onScroll = useCallback(
(data: { x: number; y: number; id?: string; route: string }) => {
@@ -93,88 +85,47 @@ export const Header = ({
};
}, [borderHidden, onScroll]);
return selectionMode && isFocused ? null : (
<>
<View
style={[
styles.container,
{
marginTop: Platform.OS === "android" ? insets.top : null,
backgroundColor: colors.primary.background,
overflow: "hidden",
borderBottomWidth: 1,
borderBottomColor: borderHidden
? "transparent"
: colors.secondary.background,
justifyContent: "space-between"
}
]}
>
<>
<View style={styles.leftBtnContainer}>
<LeftMenus
canGoBack={canGoBack}
onLeftButtonPress={onLeftMenuButtonPress}
/>
const HeaderWrapper = hasSearch ? Pressable : View;
<Title
isHiddenOnRender={titleHiddenOnRender}
renderedInRoute={renderedInRoute}
id={id}
accentColor={accentColor}
title={title}
isBeta={isBeta}
/>
</View>
<RightMenus
renderedInRoute={renderedInRoute}
id={id}
headerRightButtons={headerRightButtons}
onPressDefaultRightButton={onPressDefaultRightButton}
search={hasSearch}
onSearch={onSearch}
/>
</>
</View>
</>
return (
<View
style={{
paddingHorizontal: DefaultAppStyles.GAP
}}
>
<HeaderWrapper
style={{
flexDirection: "row",
justifyContent: "space-between",
borderRadius: 10,
paddingVertical: 3,
borderWidth: hasSearch ? 1 : 0,
borderColor: colors.primary.border,
paddingHorizontal: !hasSearch ? 0 : DefaultAppStyles.GAP_SMALL,
alignItems: "center"
}}
testID="search-header"
onPress={() => {
onSearch?.();
}}
>
<LeftMenus
canGoBack={canGoBack}
onLeftButtonPress={onLeftMenuButtonPress}
/>
{hasSearch ? (
<Paragraph>
{selectionMode
? `${selectedItemsList.length} selected`
: strings.searchInRoute(title)}
</Paragraph>
) : (
<Heading size={AppFontSize.lg}>{title}</Heading>
)}
<RightMenus rightButton={rightButton} />
</HeaderWrapper>
</View>
);
};
const styles = StyleSheet.create({
container: {
flexDirection: "row",
zIndex: 11,
height: 50,
maxHeight: 50,
justifyContent: "center",
alignItems: "center",
paddingHorizontal: 12,
width: "100%"
},
leftBtnContainer: {
flexDirection: "row",
justifyContent: "flex-start",
alignItems: "center",
flexShrink: 1
},
leftBtn: {
justifyContent: "center",
alignItems: "center",
height: 40,
width: 40,
borderRadius: 100,
marginLeft: -5,
marginRight: 25
},
rightBtnContainer: {
flexDirection: "row",
alignItems: "center"
},
rightBtn: {
justifyContent: "center",
alignItems: "flex-end",
height: 40,
width: 40,
paddingRight: 0
}
});

View File

@@ -20,10 +20,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import { useThemeColors } from "@notesnook/theme";
import React from "react";
import { notesnook } from "../../../e2e/test.ids";
import { DDS } from "../../services/device-detection";
import Navigation from "../../services/navigation";
import { useSettingStore } from "../../stores/use-setting-store";
import { tabBarRef } from "../../utils/global-refs";
import { fluidTabsRef } from "../../utils/global-refs";
import { IconButton } from "../ui/icon-button";
export const LeftMenus = ({
@@ -41,7 +40,7 @@ export const LeftMenus = ({
if (onLeftButtonPress) return onLeftButtonPress();
if (!canGoBack) {
if (tabBarRef.current?.isDrawerOpen()) {
if (fluidTabsRef.current?.isDrawerOpen()) {
Navigation.closeDrawer();
} else {
Navigation.openDrawer();
@@ -54,23 +53,14 @@ export const LeftMenus = ({
return isTablet && !canGoBack ? null : (
<IconButton
testID={notesnook.ids.default.header.buttons.left}
style={{
justifyContent: "center",
alignItems: "center",
height: 40,
width: 40,
borderRadius: 100,
marginRight: DDS.isLargeTablet() ? 10 : 7
}}
left={40}
top={40}
right={DDS.isLargeTablet() ? 10 : 10}
onPress={_onLeftButtonPress}
onLongPress={() => {
Navigation.popToTop();
}}
name={canGoBack ? "arrow-left" : "menu"}
color={colors.primary.paragraph}
color={colors.primary.icon}
/>
);
};

View File

@@ -17,127 +17,30 @@ 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, { useRef } from "react";
import { Platform, StyleSheet, View } from "react-native";
import { useThemeColors } from "@notesnook/theme";
import { Menu } from "react-native-material-menu";
import { notesnook } from "../../../e2e/test.ids";
import {
HeaderRightButton,
RouteName
} from "../../stores/use-navigation-store";
import { useSettingStore } from "../../stores/use-setting-store";
import { SIZE } from "../../utils/size";
import { sleep } from "../../utils/time";
import { Button } from "../ui/button";
import { IconButton } from "../ui/icon-button";
import React from "react";
import { StyleSheet, View } from "react-native";
import { IconButton, IconButtonProps } from "../ui/icon-button";
export const RightMenus = ({
headerRightButtons,
renderedInRoute,
id,
onPressDefaultRightButton,
search,
onSearch
rightButton
}: {
headerRightButtons?: HeaderRightButton[];
renderedInRoute?: RouteName;
id?: string;
onPressDefaultRightButton?: () => void;
search?: boolean;
onSearch?: () => void;
rightButton?: IconButtonProps;
}) => {
const { colors } = useThemeColors();
const { colors: contextMenuColors } = useThemeColors("contextMenu");
const deviceMode = useSettingStore((state) => state.deviceMode);
const menuRef = useRef<Menu>(null);
return (
<View style={styles.rightBtnContainer}>
{search ? (
<IconButton
onPress={onSearch}
testID="icon-search"
name="magnify"
color={colors.primary.paragraph}
style={styles.rightBtn}
/>
) : null}
{deviceMode !== "mobile" ? (
<Button
onPress={onPressDefaultRightButton}
testID={notesnook.ids.default.addBtn}
icon={renderedInRoute === "Trash" ? "delete" : "plus"}
iconSize={SIZE.xl}
type="accent"
hitSlop={{
top: 10,
right: 10,
bottom: 10,
left: 0
}}
{rightButton ? (
<IconButton {...rightButton} color={colors.primary.icon} />
) : (
<View
style={{
marginLeft: 10,
width: 32,
height: 32,
borderRadius: 100,
paddingHorizontal: 0,
borderWidth: 1,
borderColor: colors.primary.accent
width: 40,
height: 40
}}
/>
) : null}
{headerRightButtons && headerRightButtons.length > 0 ? (
<Menu
ref={menuRef}
animationDuration={200}
style={{
borderRadius: 5,
backgroundColor: contextMenuColors.primary.background,
marginTop: 35
}}
onRequestClose={() => {
//@ts-ignore
menuRef.current?.hide();
}}
anchor={
<IconButton
onPress={() => {
//@ts-ignore
menuRef.current?.show();
}}
name="dots-vertical"
color={colors.primary.paragraph}
style={styles.rightBtn}
/>
}
>
{headerRightButtons.map((item) => (
<Button
style={{
justifyContent: "flex-start",
borderRadius: 0,
alignSelf: "flex-start",
width: "100%"
}}
type="plain"
buttonType={{
text: contextMenuColors.primary.paragraph
}}
key={item.title}
title={item.title}
onPress={async () => {
//@ts-ignore
menuRef.current?.hide();
if (Platform.OS === "ios") await sleep(300);
item.onPress();
}}
/>
))}
</Menu>
) : null}
)}
</View>
);
};
@@ -149,10 +52,6 @@ const styles = StyleSheet.create({
},
rightBtn: {
justifyContent: "center",
alignItems: "center",
height: 40,
width: 40,
marginLeft: 10,
paddingRight: 0
alignItems: "center"
}
});

View File

@@ -25,7 +25,7 @@ import {
eUnSubscribeEvent
} from "../../services/event-manager";
import { eScrollEvent } from "../../utils/events";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import Tag from "../ui/tag";
import Heading from "../ui/typography/heading";
@@ -75,7 +75,7 @@ export const Title = ({
{!visible ? (
<Heading
numberOfLines={1}
size={SIZE.lg}
size={AppFontSize.lg}
style={{
flexWrap: "wrap",
marginTop: Platform.OS === "ios" ? -1 : 0
@@ -83,7 +83,7 @@ export const Title = ({
color={accentColor || colors.primary.heading}
>
{isTag ? (
<Heading size={SIZE.xl} color={colors.primary.accent}>
<Heading size={AppFontSize.xl} color={colors.primary.accent}>
#
</Heading>
) : null}

View File

@@ -38,6 +38,7 @@ import RNFetchBlob from "react-native-blob-util";
import Share from "react-native-share";
import useGlobalSafeAreaInsets from "../../hooks/use-global-safe-area-insets";
import { useSettingStore } from "../../stores/use-setting-store";
import { DefaultAppStyles } from "../../utils/styles";
const ImagePreview = () => {
const { colors } = useThemeColors("dialog");
@@ -124,7 +125,7 @@ const ImagePreview = () => {
justifyContent: "flex-end",
alignItems: "center",
height: 50,
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
gap: 10
}}
>

View File

@@ -23,31 +23,28 @@ import React from "react";
import { Linking, ScrollView, useWindowDimensions, View } from "react-native";
import { SwiperFlatList } from "react-native-swiper-flatlist";
import useGlobalSafeAreaInsets from "../../hooks/use-global-safe-area-insets";
import { eSendEvent } from "../../services/event-manager";
import Navigation from "../../services/navigation";
import SettingsService from "../../services/settings";
import { useSettingStore } from "../../stores/use-setting-store";
import { getElevationStyle } from "../../utils/elevation";
import { eOpenLoginDialog } from "../../utils/events";
import { SIZE } from "../../utils/size";
import { AuthMode } from "../auth";
import { AppFontSize } from "../../utils/size";
import { Button } from "../ui/button";
import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import SettingsService from "../../services/settings";
import { AuthMode } from "../auth/common";
import { DefaultAppStyles } from "../../utils/styles";
const Intro = ({ navigation }) => {
const Intro = () => {
const { colors } = useThemeColors();
const { width, height } = useWindowDimensions();
const deviceMode = useSettingStore((state) => state.deviceMode);
const insets = useGlobalSafeAreaInsets();
const isTablet = width > 600;
const renderItem = React.useCallback(
({ item }) => (
({ item }: { item: (typeof strings.introData)[0] }) => (
<View
style={{
justifyContent: "center",
width: deviceMode !== "mobile" ? width / 2 : width,
paddingHorizontal:
deviceMode !== "mobile" ? (width / 2) * 0.05 : width * 0.05
width: isTablet ? width / 2 : width,
paddingHorizontal: isTablet ? (width / 2) * 0.05 : width * 0.05
}}
>
<View
@@ -76,7 +73,7 @@ const Intro = ({ navigation }) => {
</View>
<View
style={{
marginTop: 10,
marginTop: DefaultAppStyles.GAP_VERTICAL,
maxWidth: "90%",
width: "100%"
}}
@@ -88,21 +85,21 @@ const Intro = ({ navigation }) => {
marginBottom: 5
}}
extraBold
size={SIZE.xxl}
size={AppFontSize.xxl}
>
{heading()}
</Heading>
))}
{item.body ? (
<Paragraph size={SIZE.sm}>{item.body()}</Paragraph>
<Paragraph size={AppFontSize.sm}>{item.body()}</Paragraph>
) : null}
{item.tesimonial ? (
<Paragraph
style={{
fontStyle: "italic",
fontSize: SIZE.lg
fontSize: AppFontSize.lg
}}
onPress={() => {
Linking.openURL(item.link);
@@ -114,31 +111,37 @@ const Intro = ({ navigation }) => {
</View>
</View>
),
[colors.primary.accent, colors.secondary.background, deviceMode, width]
[colors.primary.accent, colors.secondary.background, isTablet, width]
);
return (
<ScrollView
testID="notesnook.splashscreen"
style={{
width: "100%"
width: "100%",
backgroundColor: colors.primary.background
}}
>
<View
style={{
width: deviceMode !== "mobile" ? width / 2 : "100%",
backgroundColor: colors.secondary.background,
borderBottomWidth: 1,
borderBottomColor: colors.primary.border,
alignSelf: deviceMode !== "mobile" ? "center" : undefined,
borderWidth: deviceMode !== "mobile" ? 1 : null,
borderColor: deviceMode !== "mobile" ? colors.primary.border : null,
borderRadius: deviceMode !== "mobile" ? 20 : null,
marginTop: deviceMode !== "mobile" ? 50 : null,
paddingTop: insets.top + 10,
paddingBottom: insets.top + 10,
minHeight: height * 0.7 - (insets.top + insets.bottom)
}}
style={[
{
width: "100%",
backgroundColor: colors.secondary.background,
borderBottomWidth: 1,
borderBottomColor: colors.primary.border,
paddingTop: insets.top + 10,
paddingBottom: insets.top + 10,
minHeight: height * 0.7 - (insets.top + insets.bottom)
},
isTablet && {
width: width / 2,
alignSelf: "center",
borderWidth: 1,
borderColor: colors.primary.border,
borderRadius: 20,
marginTop: 50
}
]}
>
<SwiperFlatList
autoplay
@@ -170,23 +173,12 @@ const Intro = ({ navigation }) => {
<Button
width={250}
onPress={async () => {
eSendEvent(eOpenLoginDialog, AuthMode.welcomeSignup);
setTimeout(() => {
SettingsService.set({
introCompleted: true
});
Navigation.replace("Notes", {
canGoBack: false
});
}, 1000);
SettingsService.set({ introCompleted: true });
Navigation.push("Auth", {
mode: AuthMode.welcomeSignup
});
}}
style={{
paddingHorizontal: 24,
alignSelf: "center",
...getElevationStyle(5),
borderRadius: 100
}}
fontSize={SIZE.md}
fontSize={AppFontSize.md}
type="accent"
title={strings.getStarted()}
/>

File diff suppressed because one or more lines are too long

View File

@@ -24,12 +24,13 @@ import { useMessageStore } from "../../../stores/use-message-store";
import { useSelectionStore } from "../../../stores/use-selection-store";
import { Announcement } from "../../announcements/announcement";
import { Card } from "../../list/card";
import { RouteParams } from "../../../stores/use-navigation-store";
export type ListHeaderProps = {
noAnnouncement?: boolean;
color?: string;
messageCard?: boolean;
screen?: string;
screen?: keyof RouteParams;
shouldShow?: boolean;
};
@@ -50,19 +51,11 @@ export const Header = React.memo(
{announcements.length !== 0 && !noAnnouncement ? (
<Announcement color={color || colors.primary.accent} />
) : (screen as any) === "Search" ? null : !shouldShow ? (
<View
style={{
marginBottom: 5,
padding: 0,
width: "100%",
justifyContent: "center",
alignItems: "center"
}}
>
<>
{messageCard ? (
<Card color={color || colors.primary.accent} />
) : null}
</View>
</>
) : null}
</>
);

View File

@@ -17,140 +17,115 @@ 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 { getFormattedDate } from "@notesnook/common";
import { Notebook } from "@notesnook/core";
import { strings } from "@notesnook/intl";
import { useThemeColors } from "@notesnook/theme";
import React, { useState } from "react";
import React from "react";
import { View } from "react-native";
import { db } from "../../../common/database";
import { ToastManager } from "../../../services/event-manager";
import { useMenuStore } from "../../../stores/use-menu-store";
import { SIZE } from "../../../utils/size";
import { IconButton } from "../../ui/icon-button";
import { AppFontSize } from "../../../utils/size";
import { DefaultAppStyles } from "../../../utils/styles";
import AppIcon from "../../ui/AppIcon";
import Heading from "../../ui/typography/heading";
import Paragraph from "../../ui/typography/paragraph";
import { getFormattedDate } from "@notesnook/common";
import { strings } from "@notesnook/intl";
import { IconButton } from "../../ui/icon-button";
import { Pressable } from "../../ui/pressable";
import NotebookScreen from "../../../screens/notebook";
import { db } from "../../../common/database";
export const NotebookHeader = ({
notebook,
onEditNotebook,
totalNotes = 0
totalNotes = 0,
breadcrumbs
}: {
notebook: Notebook;
onEditNotebook: () => void;
totalNotes: number;
breadcrumbs: { id: string; title: string }[];
}) => {
const { colors } = useThemeColors();
const [isPinnedToMenu, setIsPinnedToMenu] = useState(
db.shortcuts.exists(notebook.id)
);
const setMenuPins = useMenuStore((state) => state.setMenuPins);
const onPinNotebook = async () => {
try {
if (isPinnedToMenu) {
await db.shortcuts.remove(notebook.id);
} else {
await db.shortcuts.add({
item: {
id: notebook.id,
type: "notebook"
}
});
ToastManager.show({
heading: strings.shortcutCreated(),
type: "success"
});
}
setIsPinnedToMenu(db.shortcuts.exists(notebook.id));
setMenuPins();
} catch (e) {
console.error(e);
}
};
return (
<View
style={{
marginBottom: 5,
padding: 0,
width: "100%",
paddingVertical: 15,
paddingHorizontal: 12,
alignSelf: "center",
borderRadius: 10,
paddingTop: 25
paddingHorizontal: DefaultAppStyles.GAP,
marginTop: DefaultAppStyles.GAP,
backgroundColor: colors.secondary.background
}}
>
<Paragraph color={colors.secondary.paragraph} size={SIZE.xs}>
{getFormattedDate(notebook.dateModified, "date-time")}
</Paragraph>
<View
style={{
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center"
width: "100%",
gap: DefaultAppStyles.GAP_VERTICAL,
paddingVertical: DefaultAppStyles.GAP
}}
>
<Heading
style={{
flexShrink: 1
}}
size={SIZE.lg}
>
{notebook.title}
</Heading>
{breadcrumbs && breadcrumbs.length > 0 ? (
<View
style={{
width: "100%",
flexDirection: "row",
alignItems: "center",
flexWrap: "wrap",
paddingBottom: DefaultAppStyles.GAP_VERTICAL_SMALL
}}
>
{breadcrumbs.map((item, index) => (
<Pressable
onPress={async () => {
const notebook = await db.notebooks.notebook(item.id);
if (!notebook) return;
NotebookScreen.navigate(notebook, true);
}}
key={item.id}
style={{
width: undefined,
flexDirection: "row",
paddingHorizontal: 0,
alignItems: "center"
}}
>
{index === 0 ? null : (
<IconButton
name="chevron-right"
size={16}
top={0}
left={0}
right={0}
bottom={0}
style={{ width: 20, height: 25 }}
/>
)}
<Paragraph size={AppFontSize.xs}>{item.title}</Paragraph>
</Pressable>
))}
</View>
) : null}
<AppIcon name="notebook" size={AppFontSize.xxl} />
<View>
<Heading size={AppFontSize.lg}>{notebook.title}</Heading>
{notebook.description ? (
<Paragraph size={AppFontSize.sm} color={colors.primary.paragraph}>
{notebook.description}
</Paragraph>
) : null}
</View>
<View
style={{
flexDirection: "row"
flexDirection: "row",
gap: DefaultAppStyles.GAP_SMALL
}}
>
<IconButton
name={isPinnedToMenu ? "link-variant-off" : "link-variant"}
onPress={onPinNotebook}
tooltipText={"Create shortcut in side menu"}
style={{
marginRight: 15,
width: 40,
height: 40
}}
type="transparent"
color={isPinnedToMenu ? colors.primary.accent : colors.primary.icon}
size={SIZE.lg}
/>
<IconButton
size={SIZE.lg}
onPress={onEditNotebook}
tooltipText="Edit this notebook"
name="pencil"
type="transparent"
color={colors.primary.icon}
style={{
width: 40,
height: 40
}}
/>
<Paragraph size={AppFontSize.xxs} color={colors.secondary.paragraph}>
{strings.notes(totalNotes || 0)}
</Paragraph>
<Paragraph color={colors.secondary.paragraph} size={AppFontSize.xxs}>
{getFormattedDate(notebook.dateModified, "date-time")}
</Paragraph>
</View>
</View>
{notebook.description ? (
<Paragraph size={SIZE.sm} color={colors.primary.paragraph}>
{notebook.description}
</Paragraph>
) : null}
<Paragraph
style={{
marginTop: 10,
fontStyle: "italic",
fontFamily: undefined
}}
size={SIZE.xs}
color={colors.secondary.paragraph}
>
{strings.notes(totalNotes || 0)}
</Paragraph>
</View>
);
};

View File

@@ -21,16 +21,16 @@ import { GroupHeader, GroupOptions, ItemType } from "@notesnook/core";
import { strings } from "@notesnook/intl";
import { useThemeColors } from "@notesnook/theme";
import React from "react";
import { TouchableOpacity, View, useWindowDimensions } from "react-native";
import { View } from "react-native";
import { useIsCompactModeEnabled } from "../../../hooks/use-is-compact-mode-enabled";
import { presentSheet } from "../../../services/event-manager";
import SettingsService from "../../../services/settings";
import { RouteName } from "../../../stores/use-navigation-store";
import { getContainerBorder } from "../../../utils/colors";
import { SIZE } from "../../../utils/size";
import { AppFontSize } from "../../../utils/size";
import { DefaultAppStyles } from "../../../utils/styles";
import Sort from "../../sheets/sort";
import { Button } from "../../ui/button";
import { IconButton } from "../../ui/icon-button";
import { Pressable } from "../../ui/pressable";
import Heading from "../../ui/typography/heading";
type SectionHeaderProps = {
@@ -56,8 +56,6 @@ export const SectionHeader = React.memo<
onOpenJumpToDialog
}: SectionHeaderProps) {
const { colors } = useThemeColors();
const { fontScale } = useWindowDimensions();
const groupBy = strings.groupByStrings[groupOptions.groupBy]();
const isCompactModeEnabled = useIsCompactModeEnabled(
dataType as "note" | "notebook"
);
@@ -65,104 +63,128 @@ export const SectionHeader = React.memo<
return (
<View
style={{
flexDirection: "row",
alignItems: "center",
width: "95%",
justifyContent: "space-between",
paddingHorizontal: 12,
height: 35 * fontScale,
backgroundColor: colors.secondary.background,
alignSelf: "center",
borderRadius: 5,
marginVertical: 5,
...getContainerBorder(colors.secondary.background, 0.8)
width: "100%",
paddingHorizontal: DefaultAppStyles.GAP,
marginBottom: DefaultAppStyles.GAP_VERTICAL
}}
>
<TouchableOpacity
onPress={() => {
onOpenJumpToDialog();
}}
activeOpacity={0.9}
hitSlop={{ top: 10, left: 10, right: 30, bottom: 15 }}
style={{
height: "100%",
justifyContent: "center"
}}
>
<Heading
color={color || colors.primary.accent}
size={SIZE.sm}
style={{
alignSelf: "center",
textAlignVertical: "center"
}}
>
{!item.title || item.title === "" ? strings.pinned() : item.title}
</Heading>
</TouchableOpacity>
<View
style={{
flexDirection: "row",
alignItems: "center"
alignItems: "center",
width: "100%",
alignSelf: "center",
justifyContent: "space-between",
borderBottomWidth: 1,
borderColor: colors.primary.border,
paddingBottom: 1,
paddingTop:
index === 0
? DefaultAppStyles.GAP_VERTICAL
: DefaultAppStyles.GAP_VERTICAL_SMALL
}}
>
{index === 0 ? (
<>
<Button
onPress={() => {
presentSheet({
component: <Sort screen={screen} type={dataType} />
});
}}
title={groupBy}
icon={
groupOptions.sortDirection === "asc"
? "sort-ascending"
: "sort-descending"
}
height={25}
style={{
borderRadius: 100,
paddingHorizontal: 0,
backgroundColor: "transparent",
marginRight:
dataType === "note" ||
screen === "Notes" ||
dataType === "notebook"
? 10
: 0
}}
type="plain"
iconPosition="right"
/>
<Pressable
onPress={() => {
onOpenJumpToDialog();
}}
hitSlop={{ top: 10, left: 10, right: 30, bottom: 15 }}
style={{
justifyContent: "flex-start",
flexDirection: "row",
width: "auto"
}}
>
<Heading
size={AppFontSize.xxs}
style={{
alignSelf: "center",
textAlignVertical: "center"
}}
color={color || colors.primary.accent}
>
{!item.title || item.title === ""
? strings.pinned().toUpperCase()
: item.title.toUpperCase()}
</Heading>
</Pressable>
<IconButton
style={{
width: 25,
height: 25
}}
hidden={
dataType !== "note" &&
dataType !== "notebook" &&
screen !== "Notes"
}
testID="icon-compact-mode"
color={colors.secondary.icon}
name={isCompactModeEnabled ? "view-list" : "view-list-outline"}
onPress={() => {
SettingsService.set({
[dataType !== "notebook"
? "notesListMode"
: "notebooksListMode"]: !isCompactModeEnabled
? "compact"
: "normal"
});
}}
size={SIZE.lg - 2}
/>
</>
) : null}
<View
style={{
flexDirection: "row",
alignItems: "center",
gap: DefaultAppStyles.GAP_SMALL
}}
>
{index === 0 ? (
<>
<IconButton
name={
groupOptions.sortDirection === "asc"
? "sort-ascending"
: "sort-descending"
}
color={colors.secondary.icon}
testID="icon-sort"
onPress={() => {
if (!screen) return;
presentSheet({
component: (
<Sort
screen={screen}
type={dataType}
hideGroupOptions={
screen === "Reminders" || screen === "Search"
}
/>
)
});
}}
style={{
width: 25,
height: 25
}}
size={AppFontSize.lg - 2}
/>
<IconButton
hidden={
dataType !== "note" &&
dataType !== "notebook" &&
screen !== "Notes"
}
style={{
width: 25,
height: 25
}}
testID="icon-compact-mode"
color={colors.secondary.icon}
name={
isCompactModeEnabled ? "view-list" : "view-list-outline"
}
onPress={() => {
SettingsService.set({
[dataType !== "notebook"
? "notesListMode"
: "notebooksListMode"]: !isCompactModeEnabled
? "compact"
: "normal"
});
}}
size={AppFontSize.lg - 2}
/>
</>
) : null}
{/* <IconButton
style={{
width: 25,
height: 25
}}
color={colors.secondary.icon}
name={"chevron-down"}
size={SIZE.lg - 2}
/> */}
</View>
</View>
</View>
);

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