Compare commits

...

280 Commits

Author SHA1 Message Date
Ammar Ahmed
28c93b26c8 mobile: update intl 2025-03-28 16:12:58 +05:00
Ammar Ahmed
a57d153e3c intl: update po files 2025-03-28 16:12:58 +05:00
Ammar Ahmed
5bced2378c mobile: focus keyboard if biometry is disabled 2025-03-28 16:11:55 +05:00
Ammar Ahmed
07d7cd65ad mobile: restore pinned notes on reboot 2025-03-28 16:11:55 +05:00
Ammar Ahmed
a8eb893f55 mobile: cleanup 2025-03-28 16:11:55 +05:00
Ammar Ahmed
7dcd06cf02 mobile: update deps 2025-03-28 16:11:32 +05:00
Ammar Ahmed
742735a7a4 mobile: update locales 2025-03-28 16:11:32 +05:00
Ammar Ahmed
68dbf729cc mobile: bump version 2025-03-28 16:11:32 +05:00
Ammar Ahmed
dc8ca1774d mobile: fix virtualization errors 2025-03-28 16:11:32 +05:00
Ammar Ahmed
ea7e47a087 mobile: run sync when necessary 2025-03-28 16:11:32 +05:00
Ammar Ahmed
1f22c1308e mobile: fix slow launch 2025-03-28 16:11:32 +05:00
Ammar Ahmed
36ded3a419 mobile: fix item counts not showing in side menu 2025-03-28 16:11:32 +05:00
Ammar Ahmed
6fdfd7b30e mobile: fix minor bugs in tablets 2025-03-28 16:11:32 +05:00
Ammar Ahmed
e4d2210722 mobile: cleanup 2025-03-28 16:11:32 +05:00
Ammar Ahmed
139c5c8a67 mobile: fix tablet rotation 2025-03-28 16:11:32 +05:00
Ammar Ahmed
181ad335d8 mobile: fix tablet bugs 2025-03-28 16:11:32 +05:00
Ammar Ahmed
fba3cc442a mobile: fix login ui on tablets 2025-03-28 16:11:32 +05:00
Ammar Ahmed
400c93cb01 mobile: add notebooks button in notebook screen to view subnotebooks 2025-03-28 16:11:32 +05:00
Ammar Ahmed
3f148de7b8 mobile: fix crash when clicking sort button in trash 2025-03-28 16:11:32 +05:00
Ammar Ahmed
c7806686f7 mobile: fix ui 2025-03-28 16:11:32 +05:00
Ammar Ahmed
d9388f9d0c mobile: fix sorting sheet in reminders 2025-03-28 16:11:32 +05:00
Ammar Ahmed
58ed4c03cd mobile: do not call scroll into view on focus 2025-03-28 16:11:32 +05:00
Ammar Ahmed
d61251961b mobile: change item positions 2025-03-28 16:11:32 +05:00
Ammar Ahmed
83d2ccddfe mobile: fix check mark color in dialog 2025-03-28 16:11:32 +05:00
Ammar Ahmed
50049eafd0 mobile: fix logout button not working in user sheet 2025-03-28 16:11:32 +05:00
Ammar Ahmed
30d55082ac mobile: minor improvements 2025-03-28 16:11:32 +05:00
Ammar Ahmed
abe727c023 mobile: add missing check when dragging to end 2025-03-28 16:11:32 +05:00
Ammar Ahmed
c5a31bc7cb mobile: fix colors 2025-03-28 16:11:32 +05:00
Ammar Ahmed
65d8ac7d51 mobile: update rspack to v1.2.7 2025-03-28 16:11:32 +05:00
Ammar Ahmed
eca7f83fac mobile: use re.pack v5 with rspack 2025-03-28 16:11:32 +05:00
Ammar Ahmed
f8ffc8827d ci: update to actions/cache@v3 2025-03-28 16:11:32 +05:00
Ammar Ahmed
74e1ebe991 ci: release app to beta track on play 2025-03-28 16:11:32 +05:00
Ammar Ahmed
c2e59f146e mobile: release beta 2 2025-03-28 16:11:32 +05:00
Ammar Ahmed
1eca51aa0f mobile: fix linking a note 2025-03-28 16:11:32 +05:00
Ammar Ahmed
6d273d0a48 mobile: fix tree filtering in move notebook 2025-03-28 16:11:32 +05:00
Ammar Ahmed
b4fda399ed mobile: fix items hides behind selection bar 2025-03-28 16:11:32 +05:00
Ammar Ahmed
294d5e69c3 mobile: cleanup 2025-03-28 16:11:32 +05:00
Ammar Ahmed
145badae97 mobile: fix breadcrumbs 2025-03-28 16:11:32 +05:00
Ammar Ahmed
0dcc1b5af7 mobile: fix properties not opening 2025-03-28 16:11:32 +05:00
Ammar Ahmed
9d46ff5b95 mobile: fix ui 2025-03-28 16:11:32 +05:00
Ammar Ahmed
210fe8c05a mobile: fix toggle switch color in settings 2025-03-28 16:11:32 +05:00
Ammar Ahmed
4efc526ecd mobile: fix input border color 2025-03-28 16:11:32 +05:00
Ammar Ahmed
d24b5e2a1b mobile: fix separator color 2025-03-28 16:11:32 +05:00
Ammar Ahmed
0f6ace54e4 mobile: fix sidemenu colors 2025-03-28 16:11:32 +05:00
Ammar Ahmed
23c976e292 mobile: fix ui 2025-03-28 16:11:32 +05:00
Ammar Ahmed
b00bb624b1 mobile: fix zindex 2025-03-28 16:11:32 +05:00
Ammar Ahmed
d1fa24ed46 mobile: fix beta release getting update dialog prompt 2025-03-28 16:11:32 +05:00
Ammar Ahmed
966e020bdd mobile: fix loading locales in release 2025-03-28 16:11:32 +05:00
Ammar Ahmed
b527f0f4b3 mobile: minor ui fixups 2025-03-28 16:11:32 +05:00
Ammar Ahmed
8c5df7219b mobile: minor ui fixes 2025-03-28 16:11:32 +05:00
Ammar Ahmed
c321e721f0 ci: add beta release workflow 2025-03-28 16:11:32 +05:00
Ammar Ahmed
e382bf5ec6 mobile: ui updates 2025-03-28 16:11:32 +05:00
Ammar Ahmed
5d5d23bbc3 mobile: fix back navigation bug 2025-03-28 16:11:32 +05:00
Ammar Ahmed
deb26dc9e7 mobile: fix editor state not restored sometimes on app launch 2025-03-28 16:11:32 +05:00
Ammar Ahmed
30a7a3db23 mobile: fix task list title rendered above status bar in editor 2025-03-28 16:11:32 +05:00
Ammar Ahmed
a79b97be29 mobile: fix selection in sidebar on app launch 2025-03-28 16:11:32 +05:00
Ammar Ahmed
20d758585e mobile: fix various bugs 2025-03-28 16:11:32 +05:00
Ammar Ahmed
3c80ae7534 mobile: refactor and fix bugs 2025-03-28 16:11:32 +05:00
Ammar Ahmed
692ebf8e8d mobile: improve app launch perf 2025-03-28 16:11:32 +05:00
Ammar Ahmed
4ca962a6b4 mobile: refactor some sheets into screens 2025-03-28 16:11:32 +05:00
Ammar Ahmed
b306014ae9 mobile: add test-id 2025-03-28 16:10:26 +05:00
Ammar Ahmed
b704e7f179 mobile: refactor 2025-03-28 16:10:26 +05:00
Ammar Ahmed
be8b6dd879 mobile: use custom cache key for persist store 2025-03-28 16:10:26 +05:00
Ammar Ahmed
dc2f1ad54b mobile: minor refactor 2025-03-28 16:10:26 +05:00
Ammar Ahmed
b1e00ec8e1 mobile: refactor 2025-03-28 16:10:26 +05:00
Ammar Ahmed
14321330e5 mobile: refactor 2025-03-28 16:10:26 +05:00
Ammar Ahmed
8914e9ef62 mobile: fix moving and updating notebooks 2025-03-28 16:10:26 +05:00
Ammar Ahmed
e374679733 mobile: small ui improvements and perf fixes 2025-03-28 16:10:26 +05:00
Ammar Ahmed
e100222b01 mobile: make skip login work properly 2025-03-28 16:10:26 +05:00
Ammar Ahmed
c080598b67 mobile: more fixes 2025-03-28 16:10:26 +05:00
Ammar Ahmed
3aa2375f1f mobile: fix selected item ui 2025-03-28 16:10:26 +05:00
Ammar Ahmed
56568d214a mobile: fix bugs 2025-03-28 16:10:26 +05:00
Ammar Ahmed
fc3a696c14 mobile: fix missing delete button in trash 2025-03-28 16:10:26 +05:00
Ammar Ahmed
5a1a498aa0 mobile: fix pro button 2025-03-28 16:10:26 +05:00
Ammar Ahmed
f34fcdc64d mobile: enable testing in debug build 2025-03-28 16:10:26 +05:00
Ammar Ahmed
7be1ac05b1 mobile: enable debug tests 2025-03-28 16:10:26 +05:00
Ammar Ahmed
06d3e52aa0 mobile: cleanup 2025-03-28 16:10:26 +05:00
Ammar Ahmed
c7f8035baa mobile: fix error set state in render 2025-03-28 16:10:26 +05:00
Ammar Ahmed
a9ef32bf74 mobile: add pro button in side-menu 2025-03-28 16:10:26 +05:00
Ammar Ahmed
9a32616d59 mobile: fix sidemenu padding top 2025-03-28 16:10:26 +05:00
Ammar Ahmed
9112851c7e mobile: fix minor bugs 2025-03-28 16:10:26 +05:00
Ammar Ahmed
9807a316c4 mobile: fix typo 2025-03-28 16:10:26 +05:00
Ammar Ahmed
f9ec881e14 mobile: make all e2e tests pass 2025-03-28 16:10:26 +05:00
Ammar Ahmed
c72fb4fb11 mobile: minor cleanup 2025-03-28 16:10:26 +05:00
Ammar Ahmed
ac9dbbe3c4 mobile: finalize sidebar and list revamp 2025-03-28 16:10:26 +05:00
Ammar Ahmed
13fd4d66eb mobile: refactor goToPage 2025-03-28 16:10:26 +05:00
Ammar Ahmed
229488eb29 mobile: fix tsc errors 2025-03-28 16:10:26 +05:00
Ammar Ahmed
b208a468c4 mobile: ui redesign 2025-03-28 16:10:25 +05:00
Abdullah Atta
8895f13c51 web: fix tests 2025-03-28 16:09:15 +05:00
Abdullah Atta
fb6f0a0c1e web: bump version to 3.1.0-beta.4 2025-03-28 16:09:15 +05:00
Abdullah Atta
8ee3249ecb web: close expanded nav pane on navigation 2025-03-28 16:09:15 +05:00
Abdullah Atta
7fdf5ca10f web: force list pane to be visible when reveal item in list is called 2025-03-28 16:09:15 +05:00
Abdullah Atta
286050b323 web: improve item flash animation when revealing item in list
this also fixes a potential memory leak due to event listener not unsubscribing
2025-03-28 16:09:15 +05:00
Abdullah Atta
fd5af6a8eb Revert "web: fix list pane not expanding (#7758)"
This reverts commit fd9db3605d.
2025-03-28 16:09:15 +05:00
Abdullah Atta
f431ccb45c web: fix active tab background 2025-03-28 16:09:15 +05:00
Abdullah Atta
fcd3728a83 web: fix Service worker did not respond. error 2025-03-28 16:09:15 +05:00
Abdullah Atta
da9eeea741 web: fix app not starting up on firefox 2025-03-28 16:09:15 +05:00
01zulfi
54edbc3f2e web: don't remove properties pane when editor is refocused (#7780)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-03-28 16:09:15 +05:00
Abdullah Atta
04986b594a intl: update strings 2025-03-28 16:09:15 +05:00
Abdullah Atta
8972296445 web: replace shared worker with service worker for sqlite 2025-03-28 16:09:15 +05:00
01zulfi
3dddf995d0 web: collapse hovered navbar when item is clicked (#7771)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-03-28 16:09:15 +05:00
Abdullah Atta
d0197bf095 web: release v3.1.0-beta.3 2025-03-28 16:09:15 +05:00
Ammar Ahmed
6a34319455 web: cleanup 2025-03-28 16:09:15 +05:00
01zulfi
b65fcedf29 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-03-28 16:09:15 +05:00
01zulfi
9addf95c76 web: restore notebook crumbs (#7765)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-03-28 16:09:15 +05:00
Ammar Ahmed
55adcc906f web: bump version to 3.1.0-beta.2 for desktop and web 2025-03-28 16:09:15 +05:00
Abdullah Atta
f1f39f17da web: make editor note properties work like toc 2025-03-28 16:09:15 +05:00
Abdullah Atta
1dcb0a363c web: slightly improve add note button ui 2025-03-28 16:09:15 +05:00
Abdullah Atta
c6c6f62319 web: bump version to 3.1.0-beta.1 2025-03-28 16:09:15 +05:00
Abdullah Atta
5faf8378a2 desktop: set publish channel to beta for beta builds 2025-03-28 16:09:15 +05:00
Abdullah Atta
bcc7a6fb05 web: minor ui fixes 2025-03-28 16:09:15 +05:00
Abdullah Atta
a44650ee1a theme: fix button hover colors 2025-03-28 16:09:15 +05:00
Abdullah Atta
e734e87c14 web: make notesnook branding a bit smaller 2025-03-28 16:09:15 +05:00
Abdullah Atta
232dfad3ac web: minor ui changes and fixes 2025-03-28 16:09:15 +05:00
Abdullah Atta
f61c868eed web: fix theme not persisting 2025-03-28 16:09:15 +05:00
Abdullah Atta
8e211d65ce web: collapse sidebar on navigate if sidebar is temporarily expanded 2025-03-28 16:09:15 +05:00
Abdullah Atta
9a0d6fbbb4 desktop: explicitly deny geolocation permission to electron process 2025-03-28 16:09:15 +05:00
Abdullah Atta
9256aec1c9 web: fix scrollbar styling in sidebar 2025-03-28 16:09:15 +05:00
Abdullah Atta
2734965bce web: reset search on navigate 2025-03-28 16:09:15 +05:00
Abdullah Atta
453ccf0a89 web: fix expand sidebar button not working 2025-03-28 16:09:15 +05:00
Abdullah Atta
564e7190e8 web: always show "X" button if there is query in search input 2025-03-28 16:08:56 +05:00
Abdullah Atta
9c32fe9c2e web: bump version to 3.1.0-beta.0 2025-03-28 16:08:56 +05:00
Abdullah Atta
5a23223a85 web: use virtualized tree for rendering toc 2025-03-28 16:08:11 +05:00
Abdullah Atta
a7c8cef69c editor: fix toc level mapping 2025-03-28 16:08:11 +05:00
Abdullah Atta
fa37d6cc25 web: add support for pre-expanding tree nodes on creation 2025-03-28 16:08:11 +05:00
Abdullah Atta
c52eb4608d web: do not collapse child nodes when collapsing parent 2025-03-28 16:08:11 +05:00
Abdullah Atta
c156defd57 web: fix all tests 2025-03-28 16:08:11 +05:00
Abdullah Atta
a0b4553344 global: update ui 2025-03-28 16:08:11 +05:00
01zulfi
c3080e9446 web: fix faulty useEffect
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-03-28 16:08:11 +05:00
01zulfi
c020b0ae7c web: refactor props for Tags component
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-03-28 16:08:11 +05:00
01zulfi
7802e4a530 web: separate component for tab items in sidebar
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-03-28 16:08:11 +05:00
01zulfi
9978532f57 web: new sidebar ui
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-03-28 16:08:11 +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
536 changed files with 25595 additions and 18388 deletions

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
@@ -129,7 +129,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 +138,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 +146,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

@@ -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-22.04
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -61,9 +69,14 @@ jobs:
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
@@ -99,7 +112,8 @@ jobs:
- 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 .
@@ -185,7 +199,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
@@ -199,9 +213,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
@@ -263,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
@@ -271,9 +285,9 @@ 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 AppImage:arm64 -p always
else
yarn electron-builder --linux AppImage:x64 AppImage:arm64 -p never
yarn electron-builder --config=electron-builder.config.js --linux AppImage:x64 AppImage:arm64 -p never
fi
working-directory: ./apps/desktop
@@ -333,8 +347,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

@@ -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
@@ -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

@@ -9,7 +9,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Setup Node
uses: ./.github/actions/setup-node-with-cache
@@ -47,7 +47,7 @@ jobs:
ccache -p
- name: Cache Pods
uses: actions/cache@v2
uses: actions/cache@v3
id: pods-cache
with:
path: apps/mobile/native/ios/Pods

View File

@@ -1,6 +1,16 @@
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:
@@ -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

@@ -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

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,203 @@
/*
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");
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/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: linuxExecutableName,
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: path.join(buildRoot, "build", "electron.js")
},
directories: {
buildResources: "assets",
output: outputDir
},
publish: [
{
provider: "github",
repo: "notesnook",
owner: "streetwriters",
channel: isBeta ? "beta" : "latest"
}
]
};

View File

@@ -1,12 +1,12 @@
{
"name": "@notesnook/desktop",
"version": "3.0.25",
"version": "3.1.0-beta.4",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@notesnook/desktop",
"version": "3.0.25",
"version": "3.1.0-beta.4",
"hasInstallScript": true,
"license": "GPL-3.0-or-later",
"dependencies": {
@@ -15,7 +15,7 @@
"@trpc/client": "10.45.2",
"@trpc/server": "10.45.2",
"better-sqlite3-multiple-ciphers": "11.5.0",
"electron-trpc": "0.6.1",
"electron-trpc": "0.7.1",
"electron-updater": "^6.3.4",
"icojs": "^0.19.4",
"sqlite-better-trigram": "0.0.2",
@@ -38,7 +38,7 @@
"slugify": "1.6.6",
"tree-kill": "^1.2.2",
"undici": "^6.19.8",
"vitest": "2.1.8"
"vitest": "^2.1.8"
},
"optionalDependencies": {
"dmg-license": "^1.0.11"
@@ -3190,9 +3190,9 @@
}
},
"node_modules/electron-trpc": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/electron-trpc/-/electron-trpc-0.6.1.tgz",
"integrity": "sha512-Yj13UrjjjOW4+TD06YunAML2tgmtSYJMiFw6E6r1D4in/0EZ2MRwMoQc7AtMPAA6In23e+Kmq71e8h0ir+c3Jg==",
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/electron-trpc/-/electron-trpc-0.7.1.tgz",
"integrity": "sha512-aWjZ5pLeVhrX9A9d8O8YgR8N+q4IXXzc76CJT1PwtDijIw+y5I+c75IAAtZ4JayYLeR3ll95PNGl5RTBu2qePw==",
"license": "MIT",
"dependencies": {
"debug": "^4.3.4"
@@ -6658,6 +6658,7 @@
"resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.8.tgz",
"integrity": "sha512-1vBKTZskHw/aosXqQUlVWWlGUxSJR8YtiyZDJAFeW2kPAeX6S3Sool0mjspO+kXLuxVWlEDDowBAeqeAQefqLQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@vitest/expect": "2.1.8",
"@vitest/mocker": "2.1.8",

View File

@@ -2,7 +2,7 @@
"name": "@notesnook/desktop",
"productName": "Notesnook",
"description": "Your private note taking space",
"version": "3.0.25",
"version": "3.1.0-beta.4",
"appAppleId": "1544027013",
"private": true,
"main": "./dist/cjs/index.js",
@@ -30,7 +30,7 @@
"@trpc/client": "10.45.2",
"@trpc/server": "10.45.2",
"better-sqlite3-multiple-ciphers": "11.5.0",
"electron-trpc": "0.6.1",
"electron-trpc": "0.7.1",
"electron-updater": "^6.3.4",
"icojs": "^0.19.4",
"sqlite-better-trigram": "0.0.2",
@@ -46,14 +46,14 @@
"electron": "^31.7.4",
"electron-builder": "^25.1.8",
"esbuild": "0.21.5",
"vitest": "2.1.8",
"node-abi": "^3.68.0",
"node-gyp-build": "^4.8.2",
"playwright": "^1.48.2",
"prebuildify": "^6.0.1",
"slugify": "1.6.6",
"tree-kill": "^1.2.2",
"undici": "^6.19.8"
"undici": "^6.19.8",
"vitest": "^2.1.8"
},
"optionalDependencies": {
"dmg-license": "^1.0.11"
@@ -63,203 +63,14 @@
"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

@@ -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(
@@ -44,21 +46,25 @@ 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 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

@@ -29,7 +29,7 @@ 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";
@@ -49,6 +49,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 }) => {

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

@@ -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

@@ -19,26 +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 { 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 RNBootSplash from "react-native-bootsplash";
import AppLocked from "./components/app-lock";
I18nManager.allowRTL(false);
I18nManager.forceRTL(false);
@@ -48,11 +52,13 @@ if (appLockEnabled || appLockMode !== "none") {
useUserStore.getState().lockApp(true);
}
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();
@@ -64,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>
);
};
@@ -141,13 +132,15 @@ export const withTheme = (Element: (props: any) => JSX.Element) => {
// 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

@@ -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,7 @@ 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";
const getUser = () => {
const user = MMKV.getString("user");
@@ -82,7 +82,7 @@ const verifyUserPassword = async (password: string) => {
}
};
const AppLockedOverlay = () => {
const AppLocked = () => {
const initialLaunchBiometricRequest = useRef(true);
const { colors } = useThemeColors();
const user = getUser();
@@ -182,7 +182,13 @@ 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 (
@@ -283,6 +289,14 @@ const AppLockedOverlay = () => {
keyboardType={
appLockHasPasswordSecurity ? keyboardType : "default"
}
onLayout={async () => {
if (
!biometricsAuthEnabled ||
!(await BiometricService.isBiometryAvailable())
) {
passwordInputRef.current?.focus();
}
}}
placeholder={
appLockHasPasswordSecurity
? keyboardType === "numeric"
@@ -315,7 +329,7 @@ const AppLockedOverlay = () => {
borderRadius: 150,
marginBottom: 10
}}
fontSize={SIZE.md}
fontSize={AppFontSize.md}
/>
</>
) : null}
@@ -336,4 +350,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,
@@ -226,14 +227,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>
@@ -241,21 +243,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}
@@ -268,7 +270,7 @@ const Actions = ({
context: "local"
});
}}
size={SIZE.xs}
size={AppFontSize.xs}
color={colors.secondary.paragraph}
>
{attachment.hash}
@@ -283,16 +285,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>
@@ -307,14 +309,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>
))}
</>
@@ -335,7 +337,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",
@@ -347,7 +349,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

@@ -36,6 +36,7 @@ import { Dialog } from "../dialog";
import BackupService from "../../services/backup";
import { sleep } from "../../utils/time";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../utils/styles";
export const ChangePassword = () => {
const passwordInputRef = useRef();
@@ -103,7 +104,7 @@ export const ChangePassword = () => {
<View
style={{
width: "100%",
padding: 12
padding: DefaultAppStyles.GAP
}}
>
<Dialog context="change-password-dialog" />
@@ -148,7 +149,7 @@ export const ChangePassword = () => {
<Button
style={{
marginTop: 10,
marginTop: DefaultAppStyles.GAP_VERTICAL,
width: "100%"
}}
loading={loading}

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,7 @@ 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";
const LoginSteps = {
emailAuth: 1,
@@ -71,8 +71,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);
@@ -96,23 +96,24 @@ export const Login = ({ changeMode }) => {
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 +144,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 +164,7 @@ export const Login = ({ changeMode }) => {
: "99.9%",
backgroundColor: colors.primary.background,
alignSelf: "center",
paddingHorizontal: 20
paddingHorizontal: DefaultAppStyles.GAP
}}
>
<Input
@@ -216,7 +217,7 @@ export const Login = ({ changeMode }) => {
title={strings.forgotPassword()}
style={{
alignSelf: "flex-end",
height: 30,
paddingVertical: DefaultAppStyles.GAP_VERTICAL_SMALL,
paddingHorizontal: 0
}}
onPress={() => {
@@ -226,7 +227,7 @@ export const Login = ({ changeMode }) => {
textStyle={{
textDecorationLine: "underline"
}}
fontSize={SIZE.xs}
fontSize={AppFontSize.xs}
type="plain"
/>
</>
@@ -244,11 +245,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 +256,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 +278,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

@@ -30,13 +30,14 @@ import {
ToastManager
} from "../../services/event-manager";
import { eCloseSheet } from "../../utils/events";
import { SIZE } from "../../utils/size";
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";
const TwoFactorVerification = ({ onMfaLogin, mfaInfo, onCancel }) => {
const { colors } = useThemeColors();
@@ -204,9 +205,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 +217,13 @@ const TwoFactorVerification = ({ onMfaLogin, mfaInfo, onCancel }) => {
}
enablesReturnKeyAutomatically
containerStyle={{
height: 60,
borderWidth: 0,
width: undefined,
minWidth: "50%"
}}
wrapperStyle={{
height: 60
}}
/>
<Button
@@ -229,9 +232,12 @@ const TwoFactorVerification = ({ onMfaLogin, mfaInfo, onCancel }) => {
width={250}
loading={loading}
onPress={onNext}
style={{
borderRadius: 100
}}
/>
<Button
title={strings.cancel()}
type="secondaryAccented"
onPress={onCancel}
width={250}
/>
<Button
@@ -242,13 +248,6 @@ const TwoFactorVerification = ({ onMfaLogin, mfaInfo, onCancel }) => {
onPress={onRequestSecondaryMethod}
height={30}
/>
<Button
title={strings.cancel()}
type="plain"
onPress={onCancel}
height={30}
/>
</>
) : (
<>
@@ -262,8 +261,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 +274,6 @@ const TwoFactorVerification = ({ onMfaLogin, mfaInfo, onCancel }) => {
<IconButton
type="secondaryAccented"
style={{
width: 40,
height: 40,
marginRight: 10
}}
size={15}
@@ -288,7 +285,7 @@ const TwoFactorVerification = ({ onMfaLogin, mfaInfo, onCancel }) => {
flexShrink: 1
}}
>
<Paragraph size={SIZE.md}>{item.title}</Paragraph>
<Paragraph size={AppFontSize.md}>{item.title}</Paragraph>
</View>
</Pressable>
))}

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,30 @@ 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";
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 +118,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 +145,27 @@ 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: 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={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 { getColorLinearShade } from "../../utils/colors";
import { AppFontSize } from "../../utils/size";
import { DefaultAppStyles } from "../../utils/styles";
import { Button } from "../ui/button";
import Paragraph from "../ui/typography/paragraph";
import { getColorLinearShade } from "../../utils/colors";
import { strings } from "@notesnook/intl";
const DialogButtons = ({
onPressPositive,
@@ -46,9 +47,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 +57,7 @@ const DialogButtons = ({
}
]}
>
{loading ? (
<ActivityIndicator color={colors.primary.accent} size={SIZE.lg} />
) : doneText ? (
{doneText ? (
<View
style={{
flexDirection: "row",
@@ -70,7 +67,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 +83,7 @@ const DialogButtons = ({
>
<Button
onPress={onPressNegative}
fontSize={SIZE.md}
fontSize={AppFontSize.sm}
testID={notesnook.ids.default.dialog.no}
type="plain"
bold
@@ -95,11 +92,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 +115,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,33 +17,35 @@ 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 { strings } from "@notesnook/intl";
import { useThemeColors } from "@notesnook/theme";
import React, { useCallback, 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 { 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 { 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 [loading, setLoading] = useState(false);
const values = useRef({
inputValue: undefined
});
@@ -72,16 +74,26 @@ export const Dialog = ({ context = "global" }) => {
const onPressPositive = async () => {
if (dialogInfo.positivePress) {
inputRef.current?.blur();
let result = await dialogInfo.positivePress(
values.current.inputValue || dialogInfo.defaultValue,
checked
);
setLoading(true);
let result;
try {
result = await dialogInfo.positivePress(
values.current.inputValue || dialogInfo.defaultValue,
checked
);
} catch (e) {
/** Empty */
}
setLoading(false);
if (result === false) {
return;
}
}
hide();
setChecked(false);
values.current.inputValue = undefined;
setVisible(false);
};
const show = useCallback(
@@ -104,14 +116,14 @@ export const Dialog = ({ context = "global" }) => {
eUnSubscribeEvent(eOpenSimpleDialog, show);
eUnSubscribeEvent(eCloseSimpleDialog, hide);
};
}, [show]);
}, [hide, show]);
const hide = () => {
const hide = React.useCallback(() => {
setChecked(false);
values.current.inputValue = undefined;
setVisible(false);
dialogInfo.onClose();
};
dialogInfo.onClose?.();
}, [dialogInfo]);
const onNegativePress = async () => {
if (dialogInfo.onClose) {
@@ -124,10 +136,11 @@ export const Dialog = ({ context = "global" }) => {
...getElevationStyle(5),
width: DDS.isTab ? 400 : "85%",
maxHeight: 450,
borderRadius: 5,
borderRadius: defaultBorderRadius,
backgroundColor: colors.primary.background,
paddingTop: 12,
...getContainerBorder(colors.primary.border, 0.5)
...getContainerBorder(colors.primary.border, 0.5),
overflow: "hidden"
};
return visible ? (
@@ -163,7 +176,7 @@ export const Dialog = ({ context = "global" }) => {
{dialogInfo.input ? (
<View
style={{
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
>
<Input
@@ -187,7 +200,7 @@ export const Dialog = ({ context = "global" }) => {
{dialogInfo?.notice ? (
<View
style={{
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
>
<Notice
@@ -208,6 +221,7 @@ export const Dialog = ({ context = "global" }) => {
? "check-circle-outline"
: "checkbox-blank-circle-outline"
}
iconColor={checked ? colors.secondary.icon : colors.primary.icon}
style={{
justifyContent: "flex-start"
}}
@@ -223,6 +237,7 @@ export const Dialog = ({ context = "global" }) => {
<DialogButtons
onPressNegative={onNegativePress}
onPressPositive={dialogInfo.positivePress && onPressPositive}
loading={loading}
positiveTitle={dialogInfo.positiveText}
negativeTitle={dialogInfo.negativeText}
positiveType={dialogInfo.positiveType}

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
}),
@@ -294,8 +302,8 @@ export const FluidTabs = forwardRef<TabsRef, TabProps>(function FluidTabs(
const gesture = Gesture.Pan()
.maxPointers(1)
.enabled(enabled && !disabled)
.activeOffsetX([-5, 5])
.failOffsetY([-15, 15])
.activeOffsetX([-10, 10])
.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,48 @@ 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",
marginTop: DefaultAppStyles.GAP_SMALL,
borderRadius: 10,
paddingVertical: DefaultAppStyles.GAP_VERTICAL_SMALL - 2,
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,126 @@ 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={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"}
/>
)
});
}}
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>
);

View File

@@ -29,24 +29,31 @@ import { EntityLevel, decode } from "entities";
import React from "react";
import { View } from "react-native";
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
import { notesnook } from "../../../../e2e/test.ids";
import { useIsCompactModeEnabled } from "../../../hooks/use-is-compact-mode-enabled";
import NotebookScreen from "../../../screens/notebook";
import { TaggedNotes } from "../../../screens/notes/tagged";
import useNavigationStore from "../../../stores/use-navigation-store";
import { useRelationStore } from "../../../stores/use-relation-store";
import { SIZE } from "../../../utils/size";
import { AppFontSize } from "../../../utils/size";
import {
getFormattedDate,
NotebooksWithDateEdited,
TagsWithDateEdited
} from "@notesnook/common";
import { strings } from "@notesnook/intl";
import { notesnook } from "../../../../e2e/test.ids";
import useIsSelected from "../../../hooks/use-selected";
import { useTabStore } from "../../../screens/editor/tiptap/use-tab-store";
import { NotebooksWithDateEdited, TagsWithDateEdited } from "@notesnook/common";
import { useSelectionStore } from "../../../stores/use-selection-store";
import { DefaultAppStyles } from "../../../utils/styles";
import { Properties } from "../../properties";
import { Button } from "../../ui/button";
import AppIcon from "../../ui/AppIcon";
import { IconButton } from "../../ui/icon-button";
import { ReminderTime } from "../../ui/reminder-time";
import { TimeSince } from "../../ui/time-since";
import Heading from "../../ui/typography/heading";
import Paragraph from "../../ui/typography/paragraph";
import { strings } from "@notesnook/intl";
import dayjs from "dayjs";
import { useRoute } from "@react-navigation/native";
type NoteItemProps = {
item: Note | BaseTrashItem<Note>;
@@ -74,9 +81,11 @@ const NoteItem = ({
locked,
noOpen = false
}: NoteItemProps) => {
const route = useRoute();
const isEditingNote = useTabStore(
(state) =>
state.tabs.find((t) => t.id === state.currentTab)?.noteId === item.id
state.tabs.find((t) => t.id === state.currentTab)?.session?.noteId ===
item.id
);
const { colors } = useThemeColors();
const compactMode = useIsCompactModeEnabled(
@@ -84,7 +93,8 @@ const NoteItem = ({
);
const _update = useRelationStore((state) => state.updater);
const primaryColors = isEditingNote ? colors.selected : colors.primary;
const selectionMode = useSelectionStore((state) => state.selectionMode);
const [selected] = useIsSelected(item);
return (
<>
<View
@@ -93,69 +103,27 @@ const NoteItem = ({
flexShrink: 1
}}
>
{!compactMode ? (
<View
{compactMode ? null : (
<Paragraph
style={{
flexDirection: "row",
alignItems: "center",
zIndex: 10,
elevation: 10,
marginBottom: 2.5,
flexWrap: "wrap"
fontSize: AppFontSize.xxxs,
color: colors.secondary.paragraph
}}
>
{notebooks?.items
?.filter(
(item) =>
item.id !== useNavigationStore.getState().focusedRouteId
)
.map((item) => (
<Button
title={
item.title.length > 25
? item.title.slice(0, 25) + "..."
: item.title
}
tooltipText={item.title}
key={item.id}
height={25}
icon="book-outline"
type="secondary"
fontSize={SIZE.xs}
iconSize={SIZE.sm}
textStyle={{
marginRight: 0
}}
style={{
borderRadius: 5,
marginRight: 5,
paddingHorizontal: 6,
marginBottom: 5
}}
onPress={() => {
NotebookScreen.navigate(item, true);
}}
/>
))}
<ReminderTime
reminder={reminder}
color={color?.colorCode}
onPress={() => {
Properties.present(reminder);
}}
style={{
height: 25
}}
/>
</View>
) : null}
{getFormattedDate(
date,
dayjs(date).isBefore(dayjs().subtract(1, "day").hour(23))
? "date"
: "time"
)}
</Paragraph>
)}
{compactMode ? (
<Paragraph
numberOfLines={1}
color={color?.colorCode || primaryColors.heading}
size={SIZE.sm}
size={AppFontSize.sm}
style={{
paddingRight: 10
}}
@@ -166,7 +134,7 @@ const NoteItem = ({
<Heading
numberOfLines={1}
color={color?.colorCode || primaryColors.heading}
size={SIZE.md}
size={AppFontSize.sm}
style={{
paddingRight: 10
}}
@@ -196,8 +164,10 @@ const NoteItem = ({
justifyContent: "flex-start",
alignItems: "center",
width: "100%",
marginTop: 5,
height: SIZE.md + 2
marginTop: DefaultAppStyles.GAP_VERTICAL_SMALL,
columnGap: 8,
rowGap: 4,
flexWrap: "wrap"
}}
>
{!isTrash ? (
@@ -205,10 +175,7 @@ const NoteItem = ({
{item.conflicted ? (
<Icon
name="alert-circle"
style={{
marginRight: 6
}}
size={SIZE.sm}
size={AppFontSize.sm}
color={colors.error.accent}
/>
) : null}
@@ -217,10 +184,7 @@ const NoteItem = ({
<Icon
testID="sync-off"
name="sync-off"
size={SIZE.sm}
style={{
marginRight: 6
}}
size={AppFontSize.sm}
color={primaryColors.icon}
/>
) : null}
@@ -229,41 +193,27 @@ const NoteItem = ({
<Icon
testID="pencil-lock"
name="pencil-lock"
size={SIZE.sm}
style={{
marginRight: 6
}}
size={AppFontSize.sm}
color={primaryColors.icon}
/>
) : null}
<TimeSince
style={{
fontSize: SIZE.xs,
color: colors.secondary.paragraph,
marginRight: 6
}}
time={date}
updateFrequency={Date.now() - date < 60000 ? 2000 : 60000}
/>
{attachmentsCount > 0 ? (
<View
style={{
flexDirection: "row",
alignItems: "center",
marginRight: 6,
gap: 2
}}
>
<Icon
name="attachment"
size={SIZE.sm}
size={AppFontSize.sm}
color={primaryColors.icon}
/>
<Paragraph
color={colors.secondary.paragraph}
size={SIZE.xs}
size={AppFontSize.xxs}
>
{attachmentsCount}
</Paragraph>
@@ -274,10 +224,7 @@ const NoteItem = ({
<Icon
testID="icon-pinned"
name="pin-outline"
size={SIZE.sm}
style={{
marginRight: 6
}}
size={AppFontSize.sm}
color={color?.colorCode || primaryColors.accent}
/>
) : null}
@@ -286,10 +233,7 @@ const NoteItem = ({
<Icon
name="lock"
testID="note-locked-icon"
size={SIZE.sm}
style={{
marginRight: 6
}}
size={AppFontSize.sm}
color={primaryColors.icon}
/>
) : null}
@@ -298,37 +242,82 @@ const NoteItem = ({
<Icon
testID="icon-star"
name="star-outline"
size={SIZE.sm}
style={{
marginRight: 6
}}
size={AppFontSize.sm}
color="orange"
/>
) : null}
{reminder ? (
<ReminderTime
reminder={reminder}
disabled
color={color?.colorCode}
textStyle={{
fontSize: AppFontSize.xxxs
}}
iconSize={AppFontSize.xxxs}
style={{
height: "auto"
}}
/>
) : null}
{notebooks?.items
?.filter(
(item) =>
route.name !== "Notebook" ||
item.id !== useNavigationStore.getState().focusedRouteId
)
.map((item) => (
<View
key={item.id}
style={{
borderRadius: 4,
backgroundColor: colors.secondary.background,
paddingHorizontal: DefaultAppStyles.GAP_SMALL / 2,
borderWidth: 0.5,
borderColor: primaryColors.border,
paddingVertical: 1,
flexDirection: "row",
alignItems: "center",
gap: DefaultAppStyles.GAP_SMALL / 2
}}
>
<AppIcon
name="book-outline"
size={AppFontSize.xxxs}
color={colors.secondary.icon}
/>
<Paragraph
size={AppFontSize.xxxs}
color={colors.secondary.paragraph}
>
{item.title}
</Paragraph>
</View>
))}
{!isTrash && !compactMode && tags
? tags.items?.map((item) =>
item.id ? (
<Button
title={"#" + item.title}
<View
key={item.id}
height={23}
type="plain"
textStyle={{
textDecorationLine: "underline",
color: colors.secondary.paragraph
}}
hitSlop={{ top: 8, bottom: 12, left: 0, right: 0 }}
fontSize={SIZE.xs}
style={{
borderRadius: 5,
paddingHorizontal: 6,
marginRight: 4,
zIndex: 10,
maxWidth: tags.items?.length > 1 ? 130 : null
borderRadius: 4,
backgroundColor: colors.secondary.background,
paddingHorizontal: DefaultAppStyles.GAP_SMALL / 2,
borderWidth: 0.5,
borderColor: primaryColors.border,
paddingVertical: 1
}}
onPress={() => TaggedNotes.navigate(item, true)}
/>
>
<Paragraph
size={AppFontSize.xxxs}
color={colors.secondary.paragraph}
>
#{item.title}
</Paragraph>
</View>
) : null
)
: null}
@@ -337,7 +326,7 @@ const NoteItem = ({
<>
<Paragraph
color={colors.secondary.paragraph}
size={SIZE.xs}
size={AppFontSize.xxs}
style={{
marginRight: 6
}}
@@ -351,7 +340,7 @@ const NoteItem = ({
<Paragraph
color={primaryColors.accent}
size={SIZE.xs}
size={AppFontSize.xxs}
style={{
marginRight: 6
}}
@@ -377,7 +366,7 @@ const NoteItem = ({
style={{
marginRight: 6
}}
size={SIZE.sm}
size={AppFontSize.sm}
color={colors.error.accent}
/>
) : null}
@@ -386,11 +375,11 @@ const NoteItem = ({
<Icon
name="lock"
testID="note-locked-icon"
size={SIZE.sm}
size={AppFontSize.sm}
style={{
marginRight: 6
}}
color={colors.secondary.background}
color={primaryColors.icon}
/>
) : null}
@@ -398,17 +387,17 @@ const NoteItem = ({
<Icon
testID="icon-star"
name="star-outline"
size={SIZE.sm}
size={AppFontSize.sm}
style={{
marginRight: 6
}}
color="orange"
color={colors.static.orange}
/>
) : null}
<TimeSince
style={{
fontSize: SIZE.xs,
fontSize: AppFontSize.xxs,
color: colors.secondary.paragraph,
marginRight: 6
}}
@@ -418,20 +407,39 @@ const NoteItem = ({
</>
) : null}
<IconButton
testID={notesnook.listitem.menu}
color={primaryColors.paragraph}
name="dots-horizontal"
size={SIZE.xl}
onPress={() => !noOpen && Properties.present(item)}
style={{
justifyContent: "center",
height: 35,
width: 35,
borderRadius: 100,
alignItems: "center"
}}
/>
{selectionMode === "note" || selectionMode === "trash" ? (
<>
<View
style={{
height: 35,
width: 35,
alignItems: "center",
justifyContent: "center"
}}
>
<AppIcon
name={selected ? "checkbox-outline" : "checkbox-blank-outline"}
color={selected ? colors.selected.icon : colors.primary.icon}
size={AppFontSize.lg}
/>
</View>
</>
) : (
<IconButton
testID={notesnook.listitem.menu}
color={colors.secondary.icon}
name="dots-horizontal"
size={AppFontSize.lg}
onPress={() => !noOpen && Properties.present(item)}
style={{
justifyContent: "center",
height: 35,
width: 35,
borderRadius: 100,
alignItems: "center"
}}
/>
)}
</View>
</>
);

View File

@@ -29,7 +29,7 @@ import {
presentSheet
} from "../../../services/event-manager";
import { eOnLoadNote, eShowMergeDialog } from "../../../utils/events";
import { tabBarRef } from "../../../utils/global-refs";
import { fluidTabsRef } from "../../../utils/global-refs";
import { NotebooksWithDateEdited, TagsWithDateEdited } from "@notesnook/common";
import NotePreview from "../../note-history/preview";
@@ -66,7 +66,7 @@ export const openNote = async (
item: note
});
if (!DDS.isTab) {
tabBarRef.current?.goToPage(1);
fluidTabsRef.current?.goToPage("editor");
}
}
};
@@ -101,6 +101,7 @@ export const NoteWrapper = React.memo<
onPress={() => openNote(item as Note, isTrash, isRenderedInActionSheet)}
isSheet={isRenderedInActionSheet}
item={item}
index={index}
color={restProps.color?.colorCode}
>
<NoteItem {...restProps} item={item} index={index} isTrash={isTrash} />

View File

@@ -19,18 +19,22 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import { getFormattedDate } from "@notesnook/common";
import { BaseTrashItem, Notebook, TrashItem } from "@notesnook/core";
import { strings } from "@notesnook/intl";
import { useThemeColors } from "@notesnook/theme";
import React from "react";
import { View } from "react-native";
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
import { notesnook } from "../../../../e2e/test.ids";
import { useIsCompactModeEnabled } from "../../../hooks/use-is-compact-mode-enabled";
import { SIZE } from "../../../utils/size";
import useIsSelected from "../../../hooks/use-selected";
import { useSelectionStore } from "../../../stores/use-selection-store";
import { AppFontSize } from "../../../utils/size";
import { Properties } from "../../properties";
import AppIcon from "../../ui/AppIcon";
import { IconButton } from "../../ui/icon-button";
import Heading from "../../ui/typography/heading";
import Paragraph from "../../ui/typography/paragraph";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../../utils/styles";
type NotebookItemProps = {
item: Notebook | BaseTrashItem<Notebook>;
@@ -50,6 +54,8 @@ export const NotebookItem = ({
const compactMode = useIsCompactModeEnabled(
(item as TrashItem).itemType || item.type
);
const selectionMode = useSelectionStore((state) => state.selectionMode);
const [selected] = useIsSelected(item);
return (
<>
@@ -61,7 +67,7 @@ export const NotebookItem = ({
>
{compactMode ? (
<Paragraph
size={SIZE.sm}
size={AppFontSize.sm}
numberOfLines={1}
style={{
flexWrap: "wrap"
@@ -71,7 +77,7 @@ export const NotebookItem = ({
</Paragraph>
) : (
<Heading
size={SIZE.md}
size={AppFontSize.md}
numberOfLines={1}
style={{
flexWrap: "wrap"
@@ -83,7 +89,7 @@ export const NotebookItem = ({
{!item.description || compactMode ? null : (
<Paragraph
size={SIZE.sm}
size={AppFontSize.sm}
numberOfLines={2}
style={{
flexWrap: "wrap"
@@ -99,15 +105,15 @@ export const NotebookItem = ({
flexDirection: "row",
justifyContent: "flex-start",
alignItems: "center",
marginTop: 5,
height: SIZE.md + 2
marginTop: DefaultAppStyles.GAP_VERTICAL_SMALL,
height: AppFontSize.md + 2
}}
>
{isTrash ? (
<>
<Paragraph
color={colors.secondary.paragraph}
size={SIZE.xs}
size={AppFontSize.xs}
style={{
textAlignVertical: "center",
marginRight: 6
@@ -121,7 +127,7 @@ export const NotebookItem = ({
</Paragraph>
<Paragraph
color={colors.primary.accent}
size={SIZE.xs}
size={AppFontSize.xs}
style={{
textAlignVertical: "center",
marginRight: 6
@@ -134,7 +140,7 @@ export const NotebookItem = ({
) : (
<Paragraph
color={colors.secondary.paragraph}
size={SIZE.xs}
size={AppFontSize.xs}
style={{
marginRight: 6
}}
@@ -144,7 +150,7 @@ export const NotebookItem = ({
)}
<Paragraph
color={colors.secondary.paragraph}
size={SIZE.xs}
size={AppFontSize.xs}
style={{
marginRight: 6
}}
@@ -155,7 +161,7 @@ export const NotebookItem = ({
{item.pinned ? (
<Icon
name="pin-outline"
size={SIZE.sm}
size={AppFontSize.sm}
style={{
marginRight: 10,
marginTop: 2
@@ -176,7 +182,7 @@ export const NotebookItem = ({
<>
<Paragraph
color={colors.primary.icon}
size={SIZE.xs}
size={AppFontSize.xs}
style={{
marginRight: 6
}}
@@ -185,21 +191,39 @@ export const NotebookItem = ({
</Paragraph>
</>
) : null}
<IconButton
color={colors.primary.heading}
name="dots-horizontal"
testID={notesnook.ids.notebook.menu}
size={SIZE.xl}
onPress={() => Properties.present(item)}
style={{
justifyContent: "center",
height: 35,
width: 35,
borderRadius: 100,
alignItems: "center"
}}
/>
{selectionMode === "notebook" || selectionMode === "trash" ? (
<>
<View
style={{
height: 35,
width: 35,
alignItems: "center",
justifyContent: "center"
}}
>
<AppIcon
name={selected ? "checkbox-outline" : "checkbox-blank-outline"}
color={selected ? colors.selected.icon : colors.primary.icon}
size={AppFontSize.lg}
/>
</View>
</>
) : (
<IconButton
color={colors.primary.heading}
name="dots-horizontal"
testID={notesnook.ids.notebook.menu}
size={AppFontSize.xl}
onPress={() => Properties.present(item)}
style={{
justifyContent: "center",
height: 35,
width: 35,
borderRadius: 100,
alignItems: "center"
}}
/>
)}
</View>
</>
);

View File

@@ -22,7 +22,7 @@ import React from "react";
import { View } from "react-native";
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
import { notesnook } from "../../../../e2e/test.ids";
import { SIZE } from "../../../utils/size";
import { defaultBorderRadius, AppFontSize } from "../../../utils/size";
import { Properties } from "../../properties";
import ReminderSheet from "../../sheets/reminder";
import { IconButton } from "../../ui/icon-button";
@@ -31,6 +31,10 @@ import Heading from "../../ui/typography/heading";
import Paragraph from "../../ui/typography/paragraph";
import SelectionWrapper, { selectItem } from "../selection-wrapper";
import { strings } from "@notesnook/intl";
import { useSelectionStore } from "../../../stores/use-selection-store";
import useIsSelected from "../../../hooks/use-selected";
import AppIcon from "../../ui/AppIcon";
import { DefaultAppStyles } from "../../../utils/styles";
const ReminderItem = React.memo(
({
@@ -48,6 +52,8 @@ const ReminderItem = React.memo(
ReminderSheet.present(item, undefined, isSheet);
};
const selectionMode = useSelectionStore((state) => state.selectionMode);
const [selected] = useIsSelected(item);
return (
<SelectionWrapper onPress={openReminder} item={item} isSheet={isSheet}>
<View
@@ -62,7 +68,7 @@ const ReminderItem = React.memo(
style={{
flexWrap: "wrap"
}}
size={SIZE.md}
size={AppFontSize.md}
>
{item.title}
</Heading>
@@ -82,18 +88,18 @@ const ReminderItem = React.memo(
style={{
flexDirection: "row",
flexWrap: "wrap",
marginTop: 5
marginTop: DefaultAppStyles.GAP_VERTICAL_SMALL
}}
>
{item.disabled ? (
<View
style={{
backgroundColor: colors.secondary.background,
borderRadius: 5,
borderRadius: defaultBorderRadius,
flexDirection: "row",
paddingHorizontal: 6,
paddingHorizontal: DefaultAppStyles.GAP_SMALL,
alignItems: "center",
marginTop: 5,
marginTop: DefaultAppStyles.GAP_VERTICAL_SMALL,
justifyContent: "flex-start",
alignSelf: "flex-start",
marginRight: 10,
@@ -102,11 +108,11 @@ const ReminderItem = React.memo(
>
<Icon
name="bell-off-outline"
size={SIZE.md}
size={AppFontSize.md}
color={colors.error.icon}
/>
<Paragraph
size={SIZE.xs}
size={AppFontSize.xs}
color={colors.secondary.paragraph}
style={{ marginLeft: 5 }}
>
@@ -118,24 +124,24 @@ const ReminderItem = React.memo(
<View
style={{
backgroundColor: colors.secondary.background,
borderRadius: 5,
borderRadius: defaultBorderRadius,
flexDirection: "row",
paddingHorizontal: 6,
paddingHorizontal: DefaultAppStyles.GAP_SMALL,
alignItems: "center",
marginTop: 5,
marginTop: DefaultAppStyles.GAP_VERTICAL_SMALL,
justifyContent: "flex-start",
alignSelf: "flex-start",
marginRight: 10,
marginRight: DefaultAppStyles.GAP_SMALL,
height: 30
}}
>
<Icon
name="reload"
size={SIZE.md}
size={AppFontSize.md}
color={colors.primary.accent}
/>
<Paragraph
size={SIZE.xs}
size={AppFontSize.xs}
color={colors.secondary.paragraph}
style={{ marginLeft: 5 }}
>
@@ -147,29 +153,49 @@ const ReminderItem = React.memo(
<ReminderTime
reminder={item}
checkIsActive={false}
fontSize={SIZE.xs}
fontSize={AppFontSize.xxs}
style={{
justifyContent: "flex-start",
height: 25,
paddingVertical: DefaultAppStyles.GAP_VERTICAL_SMALL / 2,
alignSelf: "flex-start"
}}
/>
</View>
</View>
<IconButton
testID={notesnook.listitem.menu}
color={colors.primary.paragraph}
name="dots-horizontal"
size={SIZE.xl}
onPress={() => Properties.present(item, [], isSheet)}
style={{
justifyContent: "center",
height: 35,
width: 35,
borderRadius: 100,
alignItems: "center"
}}
/>
{selectionMode === "note" || selectionMode === "trash" ? (
<>
<View
style={{
height: 35,
width: 35,
alignItems: "center",
justifyContent: "center"
}}
>
<AppIcon
name={selected ? "checkbox-outline" : "checkbox-blank-outline"}
color={selected ? colors.selected.icon : colors.primary.icon}
size={AppFontSize.lg}
/>
</View>
</>
) : (
<IconButton
testID={notesnook.listitem.menu}
color={colors.primary.paragraph}
name="dots-horizontal"
size={AppFontSize.xl}
onPress={() => Properties.present(item, isSheet)}
style={{
justifyContent: "center",
height: 35,
width: 35,
borderRadius: 100,
alignItems: "center"
}}
/>
)}
</SelectionWrapper>
);
},

View File

@@ -28,7 +28,8 @@ export const Filler = ({ item, color }: { item: Item; color?: string }) => {
const { colors } = useThemeColors();
const isEditingNote = useTabStore(
(state) =>
state.tabs.find((t) => t.id === state.currentTab)?.noteId === item.id
state.tabs.find((t) => t.id === state.currentTab)?.session?.noteId ===
item.id
);
const [selected] = useIsSelected(item);
@@ -38,16 +39,15 @@ export const Filler = ({ item, color }: { item: Item; color?: string }) => {
style={{
position: "absolute",
width: "110%",
height: "150%",
backgroundColor: colors.selected.background,
borderLeftWidth: 5,
borderLeftColor: isEditingNote
? color
? color
: colors.selected.accent
: "transparent"
height: "100%",
backgroundColor: colors.selected.accent
// borderLeftWidth: 5,
// borderLeftColor: isEditingNote
// ? color
// ? color
// : colors.selected.accent
// : "transparent"
}}
collapsable={false}
/>
) : null;
};

View File

@@ -17,14 +17,14 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { Item, TrashItem } from "@notesnook/core";
import { useThemeColors } from "@notesnook/theme";
import React, { PropsWithChildren, useRef } from "react";
import { useIsCompactModeEnabled } from "../../../hooks/use-is-compact-mode-enabled";
import { useTabStore } from "../../../screens/editor/tiptap/use-tab-store";
import { useSelectionStore } from "../../../stores/use-selection-store";
import { DefaultAppStyles } from "../../../utils/styles";
import { Pressable } from "../../ui/pressable";
import { Filler } from "./back-fill";
import { SelectionIcon } from "./selection";
import { Item, TrashItem } from "@notesnook/core";
export function selectItem(item: Item) {
if (useSelectionStore.getState().selectionMode === item.type) {
@@ -49,6 +49,7 @@ type SelectionWrapperProps = PropsWithChildren<{
testID?: string;
isSheet?: boolean;
color?: string;
index?: number;
}>;
const SelectionWrapper = ({
@@ -57,10 +58,16 @@ const SelectionWrapper = ({
testID,
isSheet,
children,
color
color,
index = 0
}: SelectionWrapperProps) => {
const itemId = useRef(item.id);
const { colors, isDark } = useThemeColors();
const isEditingNote = useTabStore(
(state) =>
state.tabs.find((t) => t.id === state.currentTab)?.session?.noteId ===
item.id
);
const compactMode = useIsCompactModeEnabled(
(item as TrashItem).itemType || item.type
);
@@ -79,7 +86,13 @@ const SelectionWrapper = ({
return (
<Pressable
customColor={isSheet ? colors.secondary.background : "transparent"}
customColor={
isEditingNote
? colors.selected.background
: isSheet
? colors.primary.hover
: "transparent"
}
testID={testID}
onLongPress={onLongPress}
onPress={onPress}
@@ -91,15 +104,14 @@ const SelectionWrapper = ({
justifyContent: "space-between",
alignItems: "center",
width: "100%",
alignSelf: "center",
overflow: "hidden",
paddingHorizontal: 12,
paddingVertical: compactMode ? 4 : 12,
paddingHorizontal: DefaultAppStyles.GAP,
paddingVertical: compactMode ? 4 : DefaultAppStyles.GAP_VERTICAL,
borderRadius: isSheet ? 10 : 0,
marginBottom: isSheet ? 12 : undefined
marginBottom: isSheet ? DefaultAppStyles.GAP_VERTICAL : undefined
}}
>
{item.type === "note" ? <Filler item={item} color={color} /> : null}
<SelectionIcon item={item} />
{children}
</Pressable>
);

View File

@@ -24,7 +24,7 @@ import Icon from "react-native-vector-icons/MaterialCommunityIcons";
import { useIsCompactModeEnabled } from "../../../hooks/use-is-compact-mode-enabled";
import useIsSelected from "../../../hooks/use-selected";
import { useSelectionStore } from "../../../stores/use-selection-store";
import { SIZE } from "../../../utils/size";
import { AppFontSize } from "../../../utils/size";
import { Item, TrashItem } from "@notesnook/core";
export const SelectionIcon = ({ item }: { item: Item }) => {
@@ -52,7 +52,7 @@ export const SelectionIcon = ({ item }: { item: Item }) => {
>
{selected ? (
<Icon
size={compactMode ? SIZE.xl - 2 : SIZE.xl}
size={compactMode ? AppFontSize.xl - 2 : AppFontSize.xl}
color={selected ? colors.selected.accent : colors.primary.icon}
name={"check"}
/>

View File

@@ -23,13 +23,14 @@ import React from "react";
import { View } from "react-native";
import { notesnook } from "../../../../e2e/test.ids";
import { TaggedNotes } from "../../../screens/notes/tagged";
import { SIZE } from "../../../utils/size";
import { AppFontSize } from "../../../utils/size";
import { Properties } from "../../properties";
import { IconButton } from "../../ui/icon-button";
import Heading from "../../ui/typography/heading";
import Paragraph from "../../ui/typography/paragraph";
import SelectionWrapper, { selectItem } from "../selection-wrapper";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../../utils/styles";
const TagItem = React.memo(
({
@@ -60,9 +61,9 @@ const TagItem = React.memo(
flexShrink: 1
}}
>
<Heading size={SIZE.md}>
<Heading size={AppFontSize.md}>
<Heading
size={SIZE.md}
size={AppFontSize.md}
style={{
color: colors.primary.accent
}}
@@ -73,9 +74,9 @@ const TagItem = React.memo(
</Heading>
<Paragraph
color={colors.secondary.paragraph}
size={SIZE.xs}
size={AppFontSize.xs}
style={{
marginTop: 5
marginTop: DefaultAppStyles.GAP_VERTICAL_SMALL
}}
>
{strings.notes(totalNotes)}
@@ -85,7 +86,7 @@ const TagItem = React.memo(
<IconButton
color={colors.primary.heading}
name="dots-horizontal"
size={SIZE.xl}
size={AppFontSize.xl}
onPress={() => {
Properties.present(item);
}}

View File

@@ -17,20 +17,28 @@ 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 { useThemeColors } from "@notesnook/theme";
import React from "react";
import { Dimensions, View } from "react-native";
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
import { useMessageStore } from "../../stores/use-message-store";
import { useThemeColors } from "@notesnook/theme";
import { getContainerBorder, hexToRGBA } from "../../utils/colors";
import { SIZE } from "../../utils/size";
import { Message, useMessageStore } from "../../stores/use-message-store";
import { AppFontSize } from "../../utils/size";
import { DefaultAppStyles } from "../../utils/styles";
import { Pressable } from "../ui/pressable";
import Paragraph from "../ui/typography/paragraph";
export const Card = ({ color }: { color?: string }) => {
export const Card = ({
color,
customMessage
}: {
color?: string;
customMessage?: Omit<Message, "data">;
}) => {
const { colors } = useThemeColors();
color = color ? color : colors.primary.accent;
const messageBoardState = useMessageStore((state) => state.message);
const messageBoardState = useMessageStore(
(state) => customMessage || state.message
);
const announcements = useMessageStore((state) => state.announcements);
const fontScale = Dimensions.get("window").fontScale;
@@ -38,18 +46,19 @@ export const Card = ({ color }: { color?: string }) => {
(announcements && announcements.length) ? null : (
<View
style={{
width: "95%"
width: "100%",
paddingHorizontal: DefaultAppStyles.GAP,
paddingVertical: DefaultAppStyles.GAP_VERTICAL
}}
>
<Pressable
onPress={messageBoardState.onPress}
type="plain"
style={{
paddingVertical: 12,
paddingVertical: DefaultAppStyles.GAP_VERTICAL,
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
paddingHorizontal: 0,
width: "100%"
}}
>
@@ -63,24 +72,14 @@ export const Card = ({ color }: { color?: string }) => {
<View
style={{
width: 40 * fontScale,
backgroundColor:
messageBoardState.type === "error"
? hexToRGBA(colors.error.accent, 0.15)
: hexToRGBA(color, 0.15),
height: 40 * fontScale,
borderRadius: 100,
alignItems: "center",
justifyContent: "center",
...getContainerBorder(
messageBoardState.type === "error"
? colors.error.accent
: color || colors.primary.accent,
0.4
)
justifyContent: "center"
}}
>
<Icon
size={SIZE.lg}
size={AppFontSize.xxxl}
color={
messageBoardState.type === "error" ? colors.error.icon : color
}
@@ -95,18 +94,19 @@ export const Card = ({ color }: { color?: string }) => {
marginRight: 10
}}
>
<Paragraph color={colors.secondary.paragraph} size={SIZE.xs}>
{messageBoardState.message}
</Paragraph>
<Paragraph
style={{
flexWrap: "nowrap",
flexShrink: 1
}}
size={AppFontSize.sm}
color={colors.primary.heading}
>
{messageBoardState.actionText}
</Paragraph>
<Paragraph color={colors.secondary.paragraph} size={AppFontSize.xs}>
{messageBoardState.message}
</Paragraph>
</View>
</View>
@@ -124,7 +124,7 @@ export const Card = ({ color }: { color?: string }) => {
color={
messageBoardState.type === "error" ? colors.error.icon : color
}
size={SIZE.lg}
size={AppFontSize.lg}
/>
</View>
)}

View File

@@ -19,12 +19,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import { useThemeColors } from "@notesnook/theme";
import React from "react";
import { ActivityIndicator, useWindowDimensions, View } from "react-native";
import { ActivityIndicator, View } from "react-native";
import { notesnook } from "../../../e2e/test.ids";
import useGlobalSafeAreaInsets from "../../hooks/use-global-safe-area-insets";
import { TTip, useTip } from "../../services/tip-manager";
import { RouteParams } from "../../stores/use-navigation-store";
import { useSettingStore } from "../../stores/use-setting-store";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import { Tip } from "../tip";
import { Button } from "../ui/button";
import Seperator from "../ui/seperator";
@@ -46,7 +46,7 @@ type EmptyListProps = {
title?: string;
color?: string;
dataType: string;
screen?: string;
screen?: keyof RouteParams;
};
export const Empty = React.memo(function Empty({
@@ -58,8 +58,6 @@ export const Empty = React.memo(function Empty({
screen
}: EmptyListProps) {
const { colors } = useThemeColors();
const insets = useGlobalSafeAreaInsets();
const { height } = useWindowDimensions();
const introCompleted = useSettingStore(
(state) => state.settings.introCompleted
);
@@ -74,7 +72,7 @@ export const Empty = React.memo(function Empty({
<View
style={[
{
height: height - (140 + insets.top),
flex: 1,
width: "80%",
justifyContent: "center",
alignSelf: "center"
@@ -98,18 +96,13 @@ export const Empty = React.memo(function Empty({
{placeholder?.button && (
<Button
testID={notesnook.buttons.add}
type="accent"
type="secondaryAccented"
title={placeholder?.button}
iconPosition="right"
icon="arrow-right"
onPress={placeholder?.action}
buttonType={{
text: "white"
}}
style={{
alignSelf: "flex-start",
borderRadius: 5,
height: 40
alignSelf: "flex-start"
}}
/>
)}
@@ -124,12 +117,12 @@ export const Empty = React.memo(function Empty({
}}
>
<Heading>{placeholder?.title}</Heading>
<Paragraph size={SIZE.sm} textBreakStrategy="balanced">
<Paragraph size={AppFontSize.sm} textBreakStrategy="balanced">
{placeholder?.loading}
</Paragraph>
<Seperator />
<ActivityIndicator
size={SIZE.lg}
size={AppFontSize.lg}
color={color || colors.primary.accent}
/>
</View>

View File

@@ -24,9 +24,9 @@ import React, { useEffect, useRef } from "react";
import {
NativeScrollEvent,
NativeSyntheticEvent,
RefreshControl
RefreshControl,
View
} from "react-native";
import Animated, { FadeInDown } from "react-native-reanimated";
import { notesnook } from "../../../e2e/test.ids";
import { useGroupOptions } from "../../hooks/use-group-options";
import { eSendEvent } from "../../services/event-manager";
@@ -34,15 +34,16 @@ import Sync from "../../services/sync";
import { RouteName } from "../../stores/use-navigation-store";
import { useSettingStore } from "../../stores/use-setting-store";
import { eScrollEvent } from "../../utils/events";
import { tabBarRef } from "../../utils/global-refs";
import { Footer } from "../list-items/footer";
import { fluidTabsRef } from "../../utils/global-refs";
import { Header } from "../list-items/headers/header";
import { Empty, PlaceholderData } from "./empty";
import { ListItemWrapper } from "./list-item.wrapper";
import { useSelectionStore } from "../../stores/use-selection-store";
type ListProps = {
data: VirtualizedGrouping<Item> | undefined;
dataType: Item["type"];
mode?: "drawer" | "sheet";
onRefresh?: () => void;
loading?: boolean;
headerTitle?: string;
@@ -145,70 +146,80 @@ export default function List(props: ListProps) {
return (
<>
<Animated.View
<View
style={{
flex: 1
}}
entering={props.renderedInRoute === "Search" ? undefined : FadeInDown}
>
<ListView
style={styles}
ref={scrollRef}
testID={notesnook.list.id}
data={props.data?.placeholders || []}
renderItem={renderItem}
onScroll={onListScroll}
nestedScrollEnabled={true}
onMomentumScrollEnd={() => {
tabBarRef.current?.unlock();
}}
getItemType={(item: number, index: number) => {
return props.data?.type(index);
}}
estimatedItemSize={isCompactModeEnabled ? 60 : 120}
directionalLockEnabled={true}
keyboardShouldPersistTaps="always"
keyboardDismissMode="interactive"
refreshControl={
props.isRenderedInActionSheet ? null : (
<RefreshControl
tintColor={colors.primary.accent}
colors={[colors.primary.accent]}
progressBackgroundColor={colors.secondary.background}
onRefresh={_onRefresh}
refreshing={false}
/>
)
}
ListEmptyComponent={
props.placeholder ? (
<Empty
loading={props.loading}
title={props.headerTitle}
dataType={props.dataType}
{props.data?.placeholders?.length === 0 ? (
<>
{props.CustomLisHeader ? (
props.CustomLisHeader
) : !props.headerTitle ? null : (
<Header
color={props.customAccentColor}
placeholder={props.placeholder}
screen={props.renderedInRoute}
/>
) : null
}
ListFooterComponent={
<Footer height={props.renderedInRoute === "Notebook" ? 300 : 150} />
}
ListHeaderComponent={
<>
{props.CustomLisHeader ? (
props.CustomLisHeader
) : !props.headerTitle ? null : (
<Header
color={props.customAccentColor}
screen={props.renderedInRoute}
)}
<Empty
loading={props.loading}
title={props.headerTitle}
dataType={props.dataType}
color={props.customAccentColor}
placeholder={props.placeholder}
screen={props.renderedInRoute}
/>
</>
) : (
<ListView
style={styles}
ref={scrollRef}
testID={notesnook.list.id}
data={props.data?.placeholders || []}
renderItem={renderItem}
onScroll={onListScroll}
nestedScrollEnabled={true}
onMomentumScrollEnd={() => {
fluidTabsRef.current?.unlock();
}}
getItemType={(item: number, index: number) => {
return props.data?.type(index);
}}
estimatedItemSize={isCompactModeEnabled ? 60 : 120}
directionalLockEnabled={true}
keyboardShouldPersistTaps="always"
keyboardDismissMode="interactive"
ListFooterComponent={
<View
style={{ height: props.data?.placeholders?.length ? 100 : 0 }}
/>
}
refreshControl={
props.isRenderedInActionSheet ? null : (
<RefreshControl
tintColor={colors.primary.accent}
colors={[colors.primary.accent]}
progressBackgroundColor={colors.secondary.background}
onRefresh={_onRefresh}
refreshing={false}
/>
)}
</>
}
/>
</Animated.View>
)
}
ListHeaderComponent={
<>
{props.CustomLisHeader ? (
props.CustomLisHeader
) : !props.headerTitle ? null : (
<Header
color={props.customAccentColor}
screen={props.renderedInRoute}
/>
)}
</>
}
/>
)}
</View>
</>
);
}

View File

@@ -26,8 +26,8 @@ import {
DraxListRenderItemContent
} from "react-native-drax";
import { tabBarRef } from "../../utils/global-refs";
import { SIZE } from "../../utils/size";
import { fluidTabsRef } from "../../utils/global-refs";
import { AppFontSize } from "../../utils/size";
import { useSideBarDraggingStore } from "../side-menu/dragging-store";
import { IconButton } from "../ui/icon-button";
@@ -61,9 +61,9 @@ function ReorderableList<T extends { id: string }>({
const listRef = useRef<FlatList | null>(null);
if (dragging) {
tabBarRef.current?.lock();
fluidTabsRef.current?.lock();
} else {
tabBarRef.current?.unlock();
fluidTabsRef.current?.unlock();
}
useEffect(() => {
@@ -79,13 +79,14 @@ function ReorderableList<T extends { id: string }>({
<View
style={{
flexDirection: "row",
paddingHorizontal: 12
width: "100%"
}}
>
<View
style={{
opacity: isHidden ? 0.4 : 1,
flexGrow: 1,
opacity: isHidden ? 0.4 : 1
flexShrink: 1
}}
>
{renderDraggableItem(info, props)}
@@ -94,13 +95,12 @@ function ReorderableList<T extends { id: string }>({
<IconButton
name={!isHidden ? "minus" : "plus"}
color={colors.primary.icon}
size={SIZE.lg}
size={AppFontSize.lg}
top={0}
bottom={0}
onPress={() => {
const _hiddenItems = hiddenItemsState.slice();
const index = _hiddenItems.indexOf(info.item.id);
if (index === -1) {
_hiddenItems.push(info.item?.id);
} else {

View File

@@ -38,7 +38,7 @@ import Navigation from "../../services/navigation";
import Sync from "../../services/sync";
import { useSettingStore } from "../../stores/use-setting-store";
import { eOnLoadNote, eShowMergeDialog } from "../../utils/events";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import BaseDialog from "../dialog/base-dialog";
import DialogButtons from "../dialog/dialog-buttons";
import DialogContainer from "../dialog/dialog-container";
@@ -49,6 +49,7 @@ import Seperator from "../ui/seperator";
import Paragraph from "../ui/typography/paragraph";
import { diff } from "diffblazer";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../utils/styles";
const MergeConflicts = () => {
const { colors } = useThemeColors();
@@ -142,7 +143,7 @@ const MergeConflicts = () => {
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
paddingLeft: 6
}}
>
@@ -164,7 +165,7 @@ const MergeConflicts = () => {
<Paragraph
style={{ flexWrap: "wrap" }}
color={colors.secondary.paragraph}
size={SIZE.xs}
size={AppFontSize.xs}
>
<Text
style={{
@@ -201,9 +202,9 @@ const MergeConflicts = () => {
height={30}
style={{
borderRadius: 100,
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
fontSize={SIZE.xs}
fontSize={AppFontSize.xs}
/>
) : null}
<View style={{ width: 10 }} />
@@ -218,9 +219,9 @@ const MergeConflicts = () => {
height={30}
style={{
borderRadius: 100,
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
fontSize={SIZE.xs}
fontSize={AppFontSize.xs}
color={colors.error.paragraph}
onPress={() => {
setDialogVisible(true);
@@ -233,12 +234,12 @@ const MergeConflicts = () => {
height={30}
style={{
borderRadius: 100,
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
minWidth: 60,
marginLeft: 10
}}
type="accent"
fontSize={SIZE.xs}
fontSize={AppFontSize.xs}
title={
keeping && !isDiscarded ? strings.undo() : strings.keep()
}

View File

@@ -30,7 +30,7 @@ import { db } from "../../common/database";
import { useDBItem } from "../../hooks/use-db-item";
import { presentSheet } from "../../services/event-manager";
import { openLinkInBrowser } from "../../utils/functions";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import DialogHeader from "../dialog/dialog-header";
import SheetProvider from "../sheet-provider";
import { Pressable } from "../ui/pressable";
@@ -38,6 +38,7 @@ import Seperator from "../ui/seperator";
import Paragraph from "../ui/typography/paragraph";
import NotePreview from "./preview";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../utils/styles";
const HistoryItem = ({
index,
@@ -88,16 +89,16 @@ const HistoryItem = ({
style={{
justifyContent: "space-between",
alignItems: "center",
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
height: 45,
marginBottom: 10,
marginBottom: DefaultAppStyles.GAP_VERTICAL,
flexDirection: "row"
}}
>
{!item ? null : (
<>
<Paragraph>{getDate(item.dateCreated, item.dateModified)}</Paragraph>
<Paragraph color={colors.secondary.paragraph} size={SIZE.xs}>
<Paragraph color={colors.secondary.paragraph} size={AppFontSize.xs}>
{getTimeAgo(item.dateModified)}
</Paragraph>
</>
@@ -148,7 +149,7 @@ export default function NoteHistory({
<View
style={{
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
height: !history?.placeholders.length
? 300
: (history.placeholders.length + 1) * 55,
@@ -170,7 +171,7 @@ export default function NoteHistory({
>
{_loading ? (
<ActivityIndicator
size={SIZE.xl}
size={AppFontSize.xl}
color={colors.primary.accent}
/>
) : (
@@ -187,7 +188,7 @@ export default function NoteHistory({
/>
</View>
<Paragraph
size={SIZE.xs}
size={AppFontSize.xs}
color={colors.secondary.paragraph}
style={{
alignSelf: "center"

View File

@@ -36,6 +36,7 @@ import { Button } from "../ui/button";
import Paragraph from "../ui/typography/paragraph";
import { diff } from "diffblazer";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../utils/styles";
/**
*
@@ -158,7 +159,7 @@ export default function NotePreview({ session, content, note }) {
<View
style={{
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
>
<Button
@@ -173,7 +174,7 @@ export default function NotePreview({ session, content, note }) {
type="error"
width="100%"
style={{
marginTop: 12
marginTop: DefaultAppStyles.GAP_VERTICAL
}}
/>
</View>

View File

@@ -20,6 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import React from "react";
import { FeatureBlock } from "./feature";
import { ScrollView } from "react-native-actions-sheet";
import { DefaultAppStyles } from "../../utils/styles";
export const CompactFeatures = ({
vertical,
@@ -84,7 +85,7 @@ export const CompactFeatures = ({
style={{
width: "100%",
maxHeight: maxHeight,
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
>
{data.map((item) => (

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 { useThemeColors } from "@notesnook/theme";
import React, { useState } from "react";
import { ActivityIndicator, Platform, ScrollView, View } from "react-native";
import { LAUNCH_ROCKET } from "../../assets/images/assets";
@@ -24,17 +25,13 @@ import { db } from "../../common/database";
import { usePricing } from "../../hooks/use-pricing";
import { DDS } from "../../services/device-detection";
import { eSendEvent, presentSheet } from "../../services/event-manager";
import { useThemeColors } from "@notesnook/theme";
import Navigation from "../../services/navigation";
import { useUserStore } from "../../stores/use-user-store";
import { getElevationStyle } from "../../utils/elevation";
import {
eClosePremiumDialog,
eCloseSheet,
eOpenLoginDialog
} from "../../utils/events";
import { SIZE } from "../../utils/size";
import { eClosePremiumDialog, eCloseSheet } from "../../utils/events";
import { AppFontSize } from "../../utils/size";
import { sleep } from "../../utils/time";
import { AuthMode } from "../auth";
import { AuthMode } from "../auth/common";
import SheetProvider from "../sheet-provider";
import { Toast } from "../toast";
import { Button } from "../ui/button";
@@ -47,6 +44,7 @@ import { Walkthrough } from "../walkthroughs";
import { features } from "./features";
import { Group } from "./group";
import { PricingPlans } from "./pricing-plans";
import { DefaultAppStyles } from "../../utils/styles";
export const Component = ({ close, promo }) => {
const { colors } = useThemeColors();
@@ -66,9 +64,9 @@ export const Component = ({ close, promo }) => {
});
} else {
close();
setTimeout(() => {
eSendEvent(eOpenLoginDialog, AuthMode.trialSignup);
}, 400);
Navigation.navigate("Auth", {
mode: AuthMode.trialSignup
});
}
};
@@ -137,14 +135,14 @@ export const Component = ({ close, promo }) => {
<Heading
key="heading"
size={SIZE.lg}
size={AppFontSize.lg}
style={{
alignSelf: "center",
paddingTop: 20
}}
>
Notesnook{" "}
<Heading size={SIZE.lg} color={colors.primary.accent}>
<Heading size={AppFontSize.lg} color={colors.primary.accent}>
Pro
</Heading>
</Heading>
@@ -154,7 +152,7 @@ export const Component = ({ close, promo }) => {
style={{
marginBottom: 20
}}
size={SIZE.md}
size={AppFontSize.md}
color={colors.primary.accent}
/>
) : (
@@ -163,7 +161,7 @@ export const Component = ({ close, promo }) => {
alignSelf: "center",
marginBottom: 20
}}
size={SIZE.md}
size={AppFontSize.md}
>
(
{Platform.OS === "android"
@@ -176,9 +174,9 @@ export const Component = ({ close, promo }) => {
<Paragraph
key="description"
size={SIZE.md}
size={AppFontSize.md}
style={{
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
textAlign: "center",
alignSelf: "center",
paddingBottom: 20,
@@ -206,7 +204,7 @@ export const Component = ({ close, promo }) => {
type="accent"
width={250}
style={{
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
marginBottom: 15,
borderRadius: 100
}}
@@ -222,7 +220,7 @@ export const Component = ({ close, promo }) => {
type={userCanRequestTrial ? "secondaryAccented" : "accent"}
width={250}
style={{
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
marginBottom: 15,
borderRadius: 100
}}
@@ -231,18 +229,18 @@ export const Component = ({ close, promo }) => {
{!user || userCanRequestTrial ? (
<Paragraph
color={colors.secondary.paragraph}
size={SIZE.xs}
size={AppFontSize.xs}
style={{
alignSelf: "center",
textAlign: "center",
marginTop: 10,
marginTop: DefaultAppStyles.GAP_VERTICAL,
maxWidth: "80%"
}}
>
{user
? 'On clicking "Try free for 14 days", your free trial will be activated.'
: "After sign up you will be asked to activate your free trial."}{" "}
<Paragraph size={SIZE.xs} style={{ fontWeight: "bold" }}>
<Paragraph size={AppFontSize.xs} style={{ fontWeight: "bold" }}>
No credit card is required.
</Paragraph>
</Paragraph>
@@ -257,7 +255,7 @@ export const Component = ({ close, promo }) => {
<View
key="plans"
style={{
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
>
<PricingPlans showTrialOption={false} promo={promo} />
@@ -272,7 +270,7 @@ export const Component = ({ close, promo }) => {
}
type="accent"
style={{
paddingHorizontal: 24,
paddingHorizontal: DefaultAppStyles.GAP * 2,
position: "absolute",
borderRadius: 100,
bottom: 30,

View File

@@ -32,7 +32,7 @@ import {
eOpenResultDialog,
eOpenTrialEndingDialog
} 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 DialogContainer from "../dialog/dialog-container";
@@ -42,6 +42,7 @@ import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import { CompactFeatures } from "./compact-features";
import { Offer } from "./offer";
import { DefaultAppStyles } from "../../utils/styles";
export const Expiring = () => {
const { colors } = useThemeColors();
@@ -94,7 +95,7 @@ export const Expiring = () => {
>
<View
style={{
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
width: "100%"
}}
>
@@ -127,7 +128,7 @@ export const Expiring = () => {
paddingTop: 0,
paddingBottom: 20
}}
size={SIZE.md + 2}
size={AppFontSize.md + 2}
>
Upgrade now to continue using all the pro features after
your trial ends
@@ -143,11 +144,11 @@ export const Expiring = () => {
await sleep(300);
eSendEvent(eOpenPremiumDialog, promo);
}}
size={SIZE.xs}
size={AppFontSize.xs}
style={{
textDecorationLine: "underline",
color: colors.secondary.paragraph,
marginTop: 10
marginTop: DefaultAppStyles.GAP_VERTICAL
}}
>
{"See what's included in Basic & Pro plans"}
@@ -176,11 +177,11 @@ export const Expiring = () => {
promo?.discount > 30 ? null : promo
);
}}
fontSize={SIZE.md + 2}
fontSize={AppFontSize.md + 2}
style={{
marginBottom: status.extend ? 0 : 10,
marginTop: 10,
paddingHorizontal: 24
marginTop: DefaultAppStyles.GAP_VERTICAL,
paddingHorizontal: DefaultAppStyles.GAP * 2
}}
/>
@@ -201,10 +202,10 @@ export const Expiring = () => {
button: "Continue"
});
}}
fontSize={SIZE.xs}
fontSize={AppFontSize.xs}
height={30}
style={{
marginBottom: 10
marginBottom: DefaultAppStyles.GAP_VERTICAL
}}
/>
)}

View File

@@ -21,9 +21,10 @@ import React from "react";
import { Text, View } from "react-native";
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
import { useThemeColors } from "@notesnook/theme";
import { SIZE } from "../../utils/size";
import { defaultBorderRadius, AppFontSize } from "../../utils/size";
import Paragraph from "../ui/typography/paragraph";
import { ProTag } from "./pro-tag";
import { DefaultAppStyles } from "../../utils/styles";
export const FeatureBlock = ({
vertical,
@@ -40,11 +41,11 @@ export const FeatureBlock = ({
style={{
flexDirection: "row",
alignItems: "center",
paddingHorizontal: 12,
marginBottom: 10,
paddingHorizontal: DefaultAppStyles.GAP,
marginBottom: DefaultAppStyles.GAP_VERTICAL,
backgroundColor: colors.secondary.background,
borderRadius: 10,
paddingVertical: 12
paddingVertical: DefaultAppStyles.GAP_VERTICAL
}}
>
<Paragraph
@@ -53,7 +54,7 @@ export const FeatureBlock = ({
marginLeft: 5,
flexShrink: 1
}}
size={SIZE.sm}
size={AppFontSize.sm}
>
{content}
</Paragraph>
@@ -63,14 +64,14 @@ export const FeatureBlock = ({
style={{
height: 100,
justifyContent: "center",
padding: 10,
padding: DefaultAppStyles.GAP_SMALL,
marginRight: 10,
borderRadius: 5,
borderRadius: defaultBorderRadius,
minWidth: 100
}}
>
<Icon color={colors.primary.icon} name={icon} size={SIZE.xl} />
<Paragraph size={SIZE.md}>
<Icon color={colors.primary.icon} name={icon} size={AppFontSize.xl} />
<Paragraph size={AppFontSize.md}>
<Text style={{ color: colors.primary.accent }}>{highlight}</Text>
{content ? "\n" + content : null}
</Paragraph>
@@ -78,14 +79,14 @@ export const FeatureBlock = ({
{pro ? (
<>
<View style={{ height: 5 }} />
<ProTag width={50} size={SIZE.xs} background={proTagBg} />
<ProTag width={50} size={AppFontSize.xs} background={proTagBg} />
</>
) : (
<View
style={{
width: 30,
height: 3,
marginTop: 10,
marginTop: DefaultAppStyles.GAP_VERTICAL,
borderRadius: 100,
backgroundColor: colors.primary.accent
}}

View File

@@ -20,11 +20,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import React from "react";
import { ScrollView, View } from "react-native";
import { useThemeColors } from "@notesnook/theme";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import { FeatureBlock } from "./feature";
import { ProTag } from "./pro-tag";
import { DefaultAppStyles } from "../../utils/styles";
export const Group = ({ item, index }) => {
const { colors } = useThemeColors();
@@ -32,24 +33,31 @@ export const Group = ({ item, index }) => {
return (
<View
style={{
paddingHorizontal: 12,
backgroundColor: index % 2 !== 0 ? colors.primary.background : colors.secondary.background,
paddingHorizontal: DefaultAppStyles.GAP,
backgroundColor:
index % 2 !== 0
? colors.primary.background
: colors.secondary.background,
paddingVertical: 40
}}
>
{item?.pro ? (
<ProTag
size={SIZE.sm}
background={index % 2 === 0 ? colors.primary.background : colors.secondary.background}
size={AppFontSize.sm}
background={
index % 2 === 0
? colors.primary.background
: colors.secondary.background
}
/>
) : null}
<Heading>{item.title}</Heading>
<Paragraph size={SIZE.md}>{item.detail}</Paragraph>
<Paragraph size={AppFontSize.md}>{item.detail}</Paragraph>
{item.features && (
<ScrollView
style={{
marginTop: 20
marginTop: DefaultAppStyles.GAP
}}
horizontal
showsHorizontalScrollIndicator={false}
@@ -60,7 +68,11 @@ export const Group = ({ item, index }) => {
{...item}
detail={item.detail}
pro={item.pro}
proTagBg={index % 2 === 0 ? colors.primary.background : colors.secondary.background}
proTagBg={
index % 2 === 0
? colors.primary.background
: colors.secondary.background
}
/>
))}
</ScrollView>
@@ -68,9 +80,9 @@ export const Group = ({ item, index }) => {
{item.info ? (
<Paragraph
style={{
marginTop: 10
marginTop: DefaultAppStyles.GAP_VERTICAL
}}
size={SIZE.xs}
size={AppFontSize.xs}
color={colors.secondary.paragraph}
>
{item.info}

View File

@@ -20,7 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import React from "react";
import { Text } from "react-native";
import { useThemeColors } from "@notesnook/theme";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import Paragraph from "../ui/typography/paragraph";
export const Offer = ({
@@ -36,7 +36,7 @@ export const Offer = ({
textAlign: "center",
paddingVertical: padding
}}
size={SIZE.xxxl}
size={AppFontSize.xxxl}
>
GET {off}
<Text style={{ color: colors.primary.accent }}>%</Text> OFF!{"\n"}

View File

@@ -35,11 +35,12 @@ import {
eOpenPremiumDialog,
eShowGetPremium
} from "../../utils/events";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import { sleep } from "../../utils/time";
import { Button } from "../ui/button";
import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import { DefaultAppStyles } from "../../utils/styles";
export const PremiumToast = ({ context = "global", offset = 0 }) => {
const { colors } = useThemeColors();
@@ -95,7 +96,7 @@ export const PremiumToast = ({ context = "global", offset = 0 }) => {
backgroundColor: colors.secondary.background,
zIndex: 999,
...getElevationStyle(20),
padding: 12,
padding: DefaultAppStyles.GAP,
borderRadius: 10,
flexDirection: "row",
alignSelf: "center",
@@ -120,7 +121,7 @@ export const PremiumToast = ({ context = "global", offset = 0 }) => {
flexWrap: "wrap"
}}
color={colors.primary.accent}
size={SIZE.md}
size={AppFontSize.md}
>
{msg.title}
</Heading>
@@ -129,7 +130,7 @@ export const PremiumToast = ({ context = "global", offset = 0 }) => {
style={{
flexWrap: "wrap"
}}
size={SIZE.sm}
size={AppFontSize.sm}
color={colors.primary.paragraph}
>
{msg.desc}

View File

@@ -19,11 +19,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import React from "react";
import { Platform, View } from "react-native";
import { SIZE } from "../../utils/size";
import { AppFontSize } from "../../utils/size";
import { Pressable } from "../ui/pressable";
import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import RNIap from "react-native-iap";
import { DefaultAppStyles } from "../../utils/styles";
export const PricingItem = ({
product,
@@ -49,7 +50,7 @@ export const PricingItem = ({
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
paddingVertical: compact ? 15 : 10,
width: compact ? null : "100%",
minWidth: 150,
@@ -59,13 +60,13 @@ export const PricingItem = ({
>
{!compact && (
<View>
<Heading size={SIZE.lg - 2}>
<Heading size={AppFontSize.lg - 2}>
{product?.type === "yearly" || product?.offerType === "yearly"
? "Yearly"
: "Monthly"}
</Heading>
{product?.info && (
<Paragraph size={SIZE.xs}>{product.info}</Paragraph>
<Paragraph size={AppFontSize.xs}>{product.info}</Paragraph>
)}
</View>
)}
@@ -75,13 +76,13 @@ export const PricingItem = ({
style={{
textDecorationLine: strikethrough ? "line-through" : undefined
}}
size={SIZE.sm}
size={AppFontSize.sm}
>
<Heading
style={{
textDecorationLine: strikethrough ? "line-through" : undefined
}}
size={SIZE.lg - 2}
size={AppFontSize.lg - 2}
>
{Platform.OS === "android"
? (product.data as RNIap.SubscriptionAndroid | undefined)

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