Compare commits

...

1634 Commits

Author SHA1 Message Date
01zulfi
26b76f12dc editor: add comment functionality
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-11-20 16:18:36 +05:00
Abdullah Atta
97d21c818e Merge pull request #8858 from 01zulfi/editor/disable-collapsible-headings-in-table
editor: disable collapsible headings inside tables
2025-11-12 11:30:38 +05:00
Abdullah Atta
3beb60d8b6 Merge pull request #8918 from streetwriters/core/fix-keys-reencryption-on-update-password
core: fix user keys re-encryption when updating password
2025-11-12 11:29:03 +05:00
Ammar Ahmed
6343212d7e Merge pull request #8923 from streetwriters/mobile-release-3.3.9
mobile: release v3.3.9
2025-11-12 09:47:26 +05:00
01zulfi
f728ad8826 editor: disable collapsible headings inside tables
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-11-11 11:39:41 +05:00
Abdullah Atta
b96af6c4cf mobile: release v3.3.9 2025-11-05 23:35:27 +05:00
Abdullah Atta
6069a41fa4 Merge pull request #8909 from streetwriters/mobile-release-3.3.8
Mobile release 3.3.8
2025-11-05 23:28:48 +05:00
01zulfi
7190207e5c core: fix user keys re-encryption when updating password
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-11-05 14:02:48 +05:00
01zulfi
015453a40b Merge pull request #8914 from streetwriters/release/v3.3.5
web: bump version to 3.3.5
2025-11-05 13:07:01 +05:00
01zulfi
dad92a186c web: bump version to 3.3.5
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-11-05 12:08:04 +05:00
Abdullah Atta
7e5e19e72c Merge pull request #8913 from streetwriters/editor/fix-checklist-bulletlist
editor: fix checklist parsing as bulletlist
2025-11-05 12:03:55 +05:00
01zulfi
8e1484a029 editor: fix checklist parsing as bulletlist
* reduce list-item's parseHTML priority lower than check-list-item's parseHTML priority

Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-11-05 11:01:52 +05:00
Ammar Ahmed
4a3b3a14ec mobile: release v3.3.8 2025-11-04 10:35:34 +05:00
Ammar Ahmed
758157cf78 mobile: update documentation link 2025-11-04 10:34:43 +05:00
Ammar Ahmed
a1a171d648 mobile: fix restore backup keeps loading 2025-11-04 10:24:22 +05:00
01zulfi
92ba4d7624 Merge pull request #8907 from streetwriters/release/v3.3.4
web: bump version to 3.3.4
2025-11-03 17:13:35 +05:00
01zulfi
d44ee5ca05 web: bump version to 3.3.4
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-11-03 16:18:57 +05:00
Abdullah Atta
d7dde74675 Merge pull request #8905 from streetwriters/editor/fix-images-in-lists
editor: fix old inline images in bullet,numbered,task&check lists
2025-11-03 16:13:02 +05:00
01zulfi
5fde1c0f07 editor: fix old inline images in bullet,numbered,task&check lists
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-11-03 16:10:26 +05:00
Abdullah Atta
ffddbe2d7a Merge pull request #8857 from 01zulfi/core/escape-paranthesis-in-search
core: escape paranthesis in notes search query
2025-11-03 12:37:39 +05:00
01zulfi
eb3998d72d core: remove unnecessary only in tests
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-11-03 12:21:11 +05:00
01zulfi
fca61afd7c core: escape paranthesis in notes search query
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-11-03 11:02:02 +05:00
Abdullah Atta
33559250d8 Merge pull request #8904 from streetwriters/editor/fix-heading-plugin
editor: fix crash in heading plugin when pasting markdown content
2025-11-03 10:27:53 +05:00
01zulfi
38daca0099 editor: fix crash in heading plugin when pasting markdown content
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-11-03 09:01:09 +05:00
Abdullah Atta
36c8b8cc25 Merge pull request #8896 from streetwriters/webclipper/release/0.4.0
Update Web Clipper to 0.4.0
2025-11-01 19:43:00 +05:00
Abdullah Atta
dd4ca817c7 clipper(web): bump version to 0.4.0 2025-11-01 19:41:01 +05:00
Ammar Ahmed
594ceb1f52 Merge pull request #8894 from streetwriters/mobile-release-3.3.7
Mobile release 3.3.7
2025-11-01 09:43:14 +05:00
Ammar Ahmed
fbc74ec359 mobile: update pods 2025-10-31 21:55:22 +05:00
Ammar Ahmed
0dfc1dfa52 mobile: release v3.3.7 2025-10-31 20:02:43 +05:00
Ammar Ahmed
b9c14ef9aa Merge pull request #8888 from streetwriters/fix-clipper-mobile
mobile: fix share extension not able to clip webpage
2025-10-31 18:38:59 +05:00
Ammar Ahmed
3fec2b397f Merge pull request #8883 from streetwriters/fix-16kb-alignment-x64
mobile: fix 16kb alignment on x86_64 platform
2025-10-31 18:38:34 +05:00
Ammar Ahmed
ec841caef7 Merge pull request #8866 from streetwriters/feat-add-clear-button-search
Feat add clear button search
2025-10-31 18:38:16 +05:00
Ammar Ahmed
c163fc3be4 Merge pull request #8865 from streetwriters/mobile-fix-crash-sub-status
mobile: fix crash in subscription-status settings item
2025-10-31 18:37:59 +05:00
Ammar Ahmed
1e04315596 Merge pull request #8853 from streetwriters/fix-export-notes-free-users
mobile: allow free users to export note in all formats
2025-10-31 18:37:18 +05:00
Ammar Ahmed
9aef28b03d Merge pull request #8856 from streetwriters/fix-table-cell-selection-mobile
Fix table cell selection mobile
2025-10-31 18:36:56 +05:00
01zulfi
88628c650f Merge pull request #8890 from streetwriters/release/v3.3.3
web: bump version to 3.3.3
2025-10-31 16:37:09 +05:00
01zulfi
9523fd52d8 web: bump version to 3.3.3
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-10-31 14:40:34 +05:00
Abdullah Atta
8cc6df92f4 Merge pull request #8889 from 01zulfi/editor/fix-heading-level-change
editor: fix changing level of collapsed heading
2025-10-31 14:05:09 +05:00
01zulfi
042656856a editor: fix changing level of collapsed heading
* preserve collasped state
* reset visibility of hidden nodes under changed heading

Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-10-31 13:14:06 +05:00
Ammar Ahmed
5921c61e98 mobile: fix share extension not able to clip webpage 2025-10-31 10:01:59 +05:00
Abdullah Atta
c5cd214d97 Merge pull request #8882 from 01zulfi/editor/fix-collapsible-hidden-under
editor: fix disappearing nodes under collapsed headings if heading is edited
2025-10-30 13:29:05 +05:00
Abdullah Atta
b30c35e59d Merge pull request #8877 from 01zulfi/editor/fix-outline-images
editor: fix images from older version not rendering in outline list
2025-10-30 13:28:00 +05:00
01zulfi
ce4fa13758 editor: fix disappearing nodes under collapsed headings if heading is edited
* design flaw in using the hiddenUnder attribute on hidden nodes, a hidden attribute should be sufficient

Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-10-30 12:59:50 +05:00
01zulfi
1f47df0f45 editor: add test case to assert migration of old inline images in outline list item
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-10-30 12:53:21 +05:00
Ammar Ahmed
91109278b6 mobile: fix 16kb alignment on x86_64 platform 2025-10-30 11:16:23 +05:00
01zulfi
78e4672871 editor: fix images from older version not rendering in outline list
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-10-29 13:12:39 +05:00
Abdullah Atta
dbecd6a466 Merge pull request #8743 from 01zulfi/editor/restrict-attachment-for-notloggedin-users
editor: restrict attachment upload for not logged-in users
2025-10-29 12:35:53 +05:00
Ammar Ahmed
e690973107 mobile: restrict attachment upload by logged out users 2025-10-29 12:33:20 +05:00
Abdullah Atta
17b14e0ac6 Merge pull request #8875 from streetwriters/fix-remove-line-through-checklist
Fix remove line through checklist
2025-10-29 11:53:58 +05:00
Abdullah Atta
0f8da747f9 Merge pull request #8867 from streetwriters/fix/warn-arm64-translation
Warn users if app is running under arm64 translation
2025-10-29 11:53:19 +05:00
Ammar Ahmed
df7d91e4f3 mobile: fix resize input delay too long 2025-10-29 11:38:51 +05:00
Ammar Ahmed
7eefecd961 editor: do not strikethrough on checked item in checklist 2025-10-29 11:38:32 +05:00
Abdullah Atta
2ec764d862 clipper: update lockfile 2025-10-28 14:36:48 +05:00
Abdullah Atta
5a9b9da47e Merge pull request #8869 from 01zulfi/editor/fix-outline-list-collapse
editor: fix outline list item collapsing the parent item
2025-10-28 13:53:33 +05:00
01zulfi
c5a82bd779 editor: fix outline list item collapsing the parent item
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-10-28 13:37:44 +05:00
Abdullah Atta
9c2a807025 desktop: show warning after app is ready 2025-10-28 13:29:57 +05:00
Abdullah Atta
4fa1ea4380 desktop: warn users if app is running under arm64 translation 2025-10-28 12:41:34 +05:00
01zulfi
351d412fdf editor: restrict attachment upload for not logged-in users
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-10-28 12:40:25 +05:00
Ammar Ahmed
38600bf2a5 mobile: add tests 2025-10-28 12:00:38 +05:00
Ammar Ahmed
4720456d63 mobile: add clear button to search on mobile 2025-10-28 11:50:25 +05:00
Ammar Ahmed
5a2221c5d3 mobile: fix crash in subscription-status settings item 2025-10-28 10:52:11 +05:00
Abdullah Atta
91ef98df4f Merge pull request #8814 from streetwriters/feature/direct-navigation-to-setting-sections
Add support for direct navigation (via url) to setting sections
2025-10-27 15:34:34 +05:00
Abdullah Atta
68b921887b Merge pull request #7294 from 01zulfi/webclipper/bookmark
webclipper: add bookmark option
2025-10-27 15:19:07 +05:00
Abdullah Atta
dea91c48a2 web: add hr after bookmark link 2025-10-27 15:18:16 +05:00
Abdullah Atta
f2e91d4a5c webclipper: fix bookmark not working in web clipper 2025-10-27 15:18:00 +05:00
01zulfi
47be00355d webclipper: add bookmark option
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-10-27 13:58:06 +05:00
Abdullah Atta
05c4051cc9 Merge pull request #8254 from 01zulfi/webclipper/start-clip-button
webclipper: improve clipping ux
2025-10-27 13:48:44 +05:00
01zulfi
71fe6bbebc webclipper: improve clipping ux
* start clip when button is clicked, not on load or selection click
* add discard button

Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-10-27 13:43:53 +05:00
Abdullah Atta
74ed529f16 Merge pull request #8195 from 01zulfi/clipper/improve-clip-with-styles
clipper: improve clip with styles
2025-10-27 13:31:53 +05:00
Abdullah Atta
24a6d8c3f9 editor: fix really large images not loading 2025-10-27 13:16:38 +05:00
Ammar Ahmed
14c1567c07 editor: fix scrollLeft value on mobile when using scroll container 2025-10-27 12:50:16 +05:00
Ammar Ahmed
fb778f56ed editor: use default scroll container on mobile to fix selection bugs 2025-10-27 12:47:41 +05:00
Abdullah Atta
1eb0ef0cbe editor: fix web clipped screenshot not visible in editor 2025-10-27 12:23:19 +05:00
Abdullah Atta
a81c8d0064 clipper: fix error on inlining css background images 2025-10-27 11:29:52 +05:00
Abdullah Atta
36099c6b4d clipper: update lockfile 2025-10-25 15:28:31 +05:00
01zulfi
8f7a15e692 clipper: remove unnecessary packages
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-10-25 15:12:44 +05:00
Abdullah Atta
de4a660eb2 clipper: add svg screenshots for debugging 2025-10-25 15:12:31 +05:00
Abdullah Atta
c53fab603f clipper: ignore noscript elements 2025-10-25 15:12:31 +05:00
01zulfi
a3e11b62e0 clipper: append head for node selection clips
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-10-25 15:12:30 +05:00
01zulfi
5d1775151d clipper: remove invalid element attributes for screenshot clips
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-10-25 15:12:30 +05:00
Abdullah Atta
a0f5880e2c clipper: serialize styles using xml serializer 2025-10-25 15:12:30 +05:00
Abdullah Atta
3dc7e70890 clipper: fix svg -> canvas -> image logic 2025-10-25 15:12:30 +05:00
01zulfi
2fa1fc8662 clipper: fix screenshot clip
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-10-25 15:12:27 +05:00
01zulfi
879a65a41c clipper: skip style inlining if property not present
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-10-25 15:12:08 +05:00
Abdullah Atta
d5b68bf0da clipper: fix tests 2025-10-25 15:12:08 +05:00
Abdullah Atta
fd460d3e90 clipper: bg images in css not clipped 2025-10-25 15:12:08 +05:00
01zulfi
a74bd4972c clipper: move inlining stylesheeet & css import resolution logic to addStylesToHead
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-10-25 15:12:08 +05:00
01zulfi
0ed8839ea9 clipper: fix build error
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-10-25 15:12:08 +05:00
Abdullah Atta
d7b0f2684a clipper: minor perf improvements 2025-10-25 15:12:08 +05:00
Abdullah Atta
b5be9b3abf clipper: fix image inlining in stylesheets 2025-10-25 15:12:08 +05:00
01zulfi
911105c409 clipper: inline background-images style for stylesheets appended to head
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-10-25 15:12:08 +05:00
01zulfi
200c842671 clipper: ignore print stylesheets when adding to head
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-10-25 15:12:08 +05:00
01zulfi
5e5930e9e8 clipper: inline styles if cssRules.length > 0
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-10-25 15:12:08 +05:00
Abdullah Atta
fd64c1cf2d clipper: set downloaded stylesheet as html instead of text 2025-10-25 15:12:08 +05:00
01zulfi
48e2916874 clipper: update filtering in cloned node
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-10-25 15:12:08 +05:00
01zulfi
a4b0e5bfef clipper: bring back node processing
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-10-25 15:12:08 +05:00
01zulfi
0b56121a26 clipper: preserve root element attributes
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-10-25 15:12:08 +05:00
01zulfi
f3f61d0e19 clipper: remove unneeded code & packages
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-10-25 15:10:21 +05:00
01zulfi
faaf1eeadf clipper: remove images from clip if images false
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-10-25 15:07:42 +05:00
01zulfi
4fbaecc24e clipper: remove clone related functions
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-10-25 15:07:42 +05:00
01zulfi
4fb056095c clipper: create & use addStylesToHead()
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-10-25 15:07:42 +05:00
01zulfi
2d6142381b clipper: remove valid attributes check
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-10-25 15:07:41 +05:00
01zulfi
d97d14e830 clipper: improve clip with styles
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-10-25 15:07:41 +05:00
01zulfi
f2f3f7e393 clipper: (wip) improve clip with styles
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-10-25 15:07:41 +05:00
Ammar Ahmed
50176d2b3a mobile: allow free users to export note in all formats 2025-10-24 13:47:02 +05:00
Ammar Ahmed
ece7b29005 Merge pull request #8839 from streetwriters/mobile-release-3.3.6
Mobile release 3.3.6
2025-10-24 09:01:33 +05:00
Ammar Ahmed
8cd8e93487 mobile: fix styles in editor 2025-10-23 21:58:27 +05:00
Ammar Ahmed
8900a6b080 mobile: release v3.3.6 2025-10-23 21:39:20 +05:00
Ammar Ahmed
19d90fa221 mobile: allow users to open redeem code url from app 2025-10-23 21:38:55 +05:00
Ammar Ahmed
2e5ff859eb Merge pull request #8835 from streetwriters/fix-reminder-widget
mobile: fix reminders widget on android
2025-10-23 13:48:28 +05:00
Ammar Ahmed
06747575ee Merge pull request #8834 from streetwriters/fix-signup-navigation
mobile: fix navigation after signup complete broken
2025-10-23 13:48:07 +05:00
Ammar Ahmed
98bb8ca186 Merge pull request #8833 from streetwriters/fix-app-lock-free-user
mobile: fix app-lock disabled dialog does not show to free users
2025-10-23 13:47:46 +05:00
Ammar Ahmed
d5f68602b6 Merge pull request #8832 from streetwriters/fix-vault-biometrics-unlock
mobile: fix vault biometrics state incorrect on app launch
2025-10-23 13:47:09 +05:00
Ammar Ahmed
312999aa5b Merge pull request #8827 from streetwriters/fix-delete-note-locked-bulk
mobile: ask user for vault password before deleting locked notes in bulk
2025-10-23 13:46:09 +05:00
Ammar Ahmed
607a4d26f4 Merge pull request #8826 from streetwriters/fix-restore-button-mobile
mobile: fix restore button is hidden in history preview item
2025-10-23 13:44:09 +05:00
Ammar Ahmed
a88b6615e4 Merge pull request #8825 from streetwriters/fix-gesture-navigation
mobile: fix gesture navigation not working
2025-10-23 13:43:50 +05:00
Ammar Ahmed
f900098201 mobile: fix app-lock disabled dialog does not show to free users 2025-10-23 12:17:01 +05:00
Ammar Ahmed
d51aaa8eb1 mobile: fix vault biometrics state incorrect on app launch 2025-10-23 12:05:50 +05:00
Ammar Ahmed
e9a48ae028 mobile: fix reminders widget on android 2025-10-23 11:01:28 +05:00
Ammar Ahmed
90a0f619ec mobile: ask user for vault password before deleting locked notes in bulk 2025-10-22 19:27:43 +05:00
Ammar Ahmed
ed3662a636 mobile: fix restore button is hidden in history preview item 2025-10-22 14:54:47 +05:00
Ammar Ahmed
26eda3b105 mobile: fix gesture navigation not working 2025-10-22 14:40:56 +05:00
Ammar Ahmed
8f43882e29 mobile: fix navigation after signup complete broken 2025-10-22 14:27:26 +05:00
Ammar Ahmed
e239597eb1 Merge pull request #8821 from streetwriters/fix--disable-post-install-script
Fix fdroid build failing due to postinstall script using bun
2025-10-22 09:11:41 +05:00
Ammar Ahmed
bf1ef07d3a mobile: fix fdroid build failing due to postinstall script using bun 2025-10-22 09:09:32 +05:00
Abdullah Atta
7d2e1dab4c web: add support for direct navigation (via url) to setting sections 2025-10-21 14:42:37 +05:00
Ammar Ahmed
80392d394a Merge pull request #8812 from streetwriters/add-fdroid-changelog
mobile: add fdroid changelog
2025-10-21 09:19:55 +05:00
Ammar Ahmed
9ffa4d38c3 mobile: add fdroid changelog 2025-10-21 09:18:57 +05:00
Abdullah Atta
efec2dc898 Merge pull request #8803 from streetwriters/release/3.3.2
Release v3.3.2
2025-10-20 16:05:15 +05:00
Ammar Ahmed
5bd032e480 mobile: release v3.3.5 2025-10-20 13:53:14 +05:00
Abdullah Atta
c1bd4cfb01 web: bump version to 3.3.2 2025-10-20 13:01:57 +05:00
Abdullah Atta
0b943d8ecd editor: fix bullet list created as sub list of outline list 2025-10-20 12:52:57 +05:00
Ammar Ahmed
75e22a591e Merge pull request #8802 from streetwriters/fix-reset-root-state
Fix reset root state
2025-10-20 12:44:13 +05:00
Ammar Ahmed
66498e12ce mobile: fix multiple timers set on reset root state causing jank 2025-10-20 12:40:20 +05:00
Ammar Ahmed
d5fefd2f10 Merge pull request #8801 from streetwriters/fix-collapsible-headings
Fix collapsible headings on mobile
2025-10-20 12:12:20 +05:00
Ammar Ahmed
e2556d3228 mobile: fix collapsible heading 2025-10-20 12:09:22 +05:00
Abdullah Atta
2eb38d236e web: allow discounts in overlay checkout 2025-10-20 11:00:26 +05:00
Abdullah Atta
d9c57162f1 Merge pull request #8800 from streetwriters/fix/allow-discounts-in-overlay-checkout
Allow discounts in overlay checkout
2025-10-20 10:59:11 +05:00
Abdullah Atta
9f8f0e8413 web: allow discounts in overlay checkout 2025-10-20 10:57:51 +05:00
Abdullah Atta
ea52893be1 Merge branch 'master' into beta 2025-10-20 10:43:07 +05:00
Abdullah Atta
eef63d2028 Merge pull request #8799 from streetwriters/fix/entities-in-markdown-import
Fix html entities in markdown import
2025-10-20 10:37:32 +05:00
Abdullah Atta
14e0112e17 Merge pull request #8798 from streetwriters/fix/handle-attachment-errors-during-export
Handle attachment errors on export
2025-10-20 10:26:56 +05:00
Abdullah Atta
8ec9034fb2 Merge pull request #8797 from streetwriters/fix/disable-in-app-notices
Disable in-app noticies (temporarily)
2025-10-20 10:26:35 +05:00
Abdullah Atta
dc5973d75d editor: update package-lock file 2025-10-20 10:24:23 +05:00
Abdullah Atta
12126b2f9f web: fix html entities in markdown import 2025-10-20 10:17:59 +05:00
Abdullah Atta
9fa256be0e web: handle attachment errors on export 2025-10-20 08:58:22 +05:00
Abdullah Atta
c103328098 web: disable in-app noticies (temporarily) 2025-10-20 08:52:22 +05:00
Ammar Ahmed
ea2022bbe4 Merge branch 'mobile-release-v3.3.4' into beta 2025-10-20 08:39:56 +05:00
Ammar Ahmed
d7ced57319 Merge pull request #8796 from streetwriters/mobile-release-v3.3.4
Mobile release v3.3.4
2025-10-20 08:38:33 +05:00
Ammar Ahmed
2cc200dc2b mobile: fix paths for fonts 2025-10-18 13:35:23 +05:00
Ammar Ahmed
baa74d0353 mobile: fix build error due to tsgo usage 2025-10-18 12:56:40 +05:00
Ammar Ahmed
72b906da14 mobile: use currency symbol when possible 2025-10-18 12:15:30 +05:00
Ammar Ahmed
6db8c2fac2 mobile: release v3.3.4 2025-10-18 12:02:00 +05:00
Ammar Ahmed
09d5c0a65e mobile: fix sharing files from other apps to Notesnook 2025-10-18 12:01:19 +05:00
Ammar Ahmed
0b6b6a02cc editor: fix crash when adding new row in column 2025-10-18 09:04:06 +05:00
Abdullah Atta
f49c673e8e editor: fix crash when adding new row in table 2025-10-18 09:00:36 +05:00
Ammar Ahmed
64a8e9a075 mobile: set github release=false 2025-10-18 09:00:12 +05:00
Ammar Ahmed
e998b07ca5 mobile: fix strings 2025-10-18 08:57:54 +05:00
Ammar Ahmed
c189279030 mobile: fix sheet insets on android 16+ 2025-10-18 08:57:54 +05:00
Ammar Ahmed
12ddd6f958 mobile: add release type in github issue template 2025-10-18 08:57:54 +05:00
Ammar Ahmed
da06afda8a mobile: fix pricing on github release 2025-10-18 08:57:54 +05:00
Ammar Ahmed
bf808b7a2e mobile: fix editor toolbar height 2025-10-18 08:57:54 +05:00
Ammar Ahmed
13476a3f50 editor: fix checklist style 2025-10-18 08:56:04 +05:00
Ammar Ahmed
cfdf77a7b5 Merge branch 'fix-plans-showing-price' into beta 2025-10-17 09:59:38 +05:00
Ammar Ahmed
070c90362a Merge pull request #8782 from streetwriters/fix-plans-showing-price
Fix prices on github release and open checkout link in browser
2025-10-17 09:58:29 +05:00
Ammar Ahmed
c8d9858a0c Merge branch 'mobile-release-3.3.3' into beta 2025-10-17 09:11:28 +05:00
Ammar Ahmed
2685f60409 Merge pull request #8781 from streetwriters/mobile-release-3.3.3
mobile: release v3.3.3
2025-10-17 09:10:51 +05:00
Abdullah Atta
8d3bb5185c Merge branch 'master' into beta 2025-10-17 08:51:19 +05:00
Abdullah Atta
1f748a4026 global: introducing Notesnook Circle (#8779)
* core: add api for getting Notesnook Circle partners

* web: introduce notesnook circle

* core: export CirclePartner type

* mobile: add notesnook-circle

* web: use strings from intl for notesnook circle

* common: add notesnook circle to features

* web: fix local ips set for hosts

* mobile: fix db hosts

---------

Co-authored-by: Ammar Ahmed <ammarahmed6506@gmail.com>
2025-10-17 08:49:32 +05:00
Sudlon
b27f064ad4 editor: Add keybindings for highlighting the currently selected text (#8577)
* editor: Add keybindings for highlighting the currently selected text

Signed-off-by: Sudlon <sudlondon@outlook.com>

* editor: Change keybinding command to TipTap "syntax"

Signed-off-by: Sudlon <sudlondon@outlook.com>

* editor: Remove SHIFT-keybinding (leaving ALT-keybinding) for highlighting currently selected text

Signed-off-by: Sudlon sudlondon@outlook.com

* editor: Remove left-over references to the double keybinding for highlighting currently selected text

Signed-off-by: Sudlon sudlondon@outlook.com

---------

Signed-off-by: Sudlon <sudlondon@outlook.com>
Signed-off-by: Sudlon sudlondon@outlook.com
Co-authored-by: sudlon <sudlondon@outlook.com>
2025-10-16 16:59:37 +05:00
01zulfi
27f781cc63 editor: improve codeblock scrollbar styling (#8548)
* editor: improve codeblock scrollbar styling
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>

* editor: fix overflowed codeblock's bg color
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-10-16 16:50:35 +05:00
Abdullah Atta
1427958eca Merge pull request #8457 from 01zulfi/editor/tasklist-checklist-styling
editor: improve checklist styling
2025-10-16 15:01:24 +05:00
Abdullah Atta
436e09c255 editor: fix text direction not working in check lists 2025-10-16 14:50:13 +05:00
Abdullah Atta
cc9b2dd5b0 editor: add back line through for checked items 2025-10-16 14:45:40 +05:00
Abdullah Atta
0ba25419f3 editor: use single li element for simple checklists 2025-10-16 14:43:51 +05:00
Abdullah Atta
9238de4cb4 Merge pull request #8772 from 01zulfi/editor/fix-images-in-outline-lists
editor: fix inserting images in outline lists
2025-10-16 11:48:34 +05:00
01zulfi
2d5fe1058c editor: add test for code block in outline list
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-10-16 10:46:31 +05:00
01zulfi
b01d1fc87e editor: improve checklist styling
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-10-16 09:28:02 +05:00
Abdullah Atta
9f4c0a4c9a editor: move outline list item indicator to li from first child 2025-10-16 09:23:19 +05:00
Abdullah Atta
9eebda86c2 editor: fix enter/tab not working in block nodes inside outline list item 2025-10-16 09:22:49 +05:00
Abdullah Atta
d43e856fea editor: add support for all block types in outline list item 2025-10-16 09:22:15 +05:00
Abdullah Atta
7af1596038 editor: remove custom inline image -> block image migration 2025-10-16 09:21:45 +05:00
01zulfi
652f6eab0b editor: fix inserting images in outline lists
* inserting images in outline list was splitting the outline list into two, this commit fixes it

Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-10-15 11:14:24 +05:00
Abdullah Atta
fdaddfdb92 Merge pull request #8767 from streetwriters/chore/update-electron-to-37 2025-10-13 14:12:34 +05:00
Abdullah Atta
9a1adf2065 Merge pull request #8767 from streetwriters/chore/update-electron-to-37
Update electron to v37
2025-10-13 14:12:01 +05:00
Abdullah Atta
f10b258f58 desktop: update electron to v37 2025-10-13 14:10:52 +05:00
01zulfi
7f558cbd41 core: handle inbox item sync & decryption (#8733)
* core: handle inbox item sync & decryption
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>

* core: minor refactors in handling inbox item sync
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>

* core: use inbox item salt
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>

* core: check inbox item version
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-10-13 14:02:32 +05:00
Ammar Ahmed
641eb28ce7 mobile: open web purchase in browser. 2025-10-13 11:33:48 +05:00
Ammar Ahmed
2c59a5f6f9 mobile: fix plan price not showing properly on gh release 2025-10-13 09:30:48 +05:00
Abdullah Atta
712f02e61e Merge branch 'master' into beta 2025-10-10 18:13:46 +05:00
Abdullah Atta
e5ad405a23 Merge pull request #8754 from streetwriters/release/3.3.1
Release v3.3.1
2025-10-10 18:12:40 +05:00
Abdullah Atta
cd1b78d8df ci: fix desktop builds 2025-10-10 17:53:41 +05:00
Abdullah Atta
3b1ca46945 web: fix desktop tests 2025-10-10 16:23:11 +05:00
Abdullah Atta
96c1636f88 web: bump version to 3.3.1 2025-10-10 15:54:29 +05:00
Abdullah Atta
a10f949856 Merge branch 'master' into beta 2025-10-10 15:53:32 +05:00
Abdullah Atta
9ff4757ed6 Merge pull request #8753 from streetwriters/fix/make-table-with-adjustable
Make table width adjustable
2025-10-10 15:52:26 +05:00
Abdullah Atta
17c1e77f54 editor: make table width adjustable 2025-10-10 15:47:05 +05:00
Abdullah Atta
187a2a7262 Merge pull request #8735 from 01zulfi/editor/restrict-pasting-premium-features
editor: restrict pasting premium features
2025-10-10 15:38:11 +05:00
Abdullah Atta
4621230549 Merge pull request #8751 from streetwriters/fix/discount-price-on-checkout
Fix discounted price in checkout
2025-10-10 15:33:42 +05:00
Abdullah Atta
d7cb3317a2 web: fix discounted price in checkout 2025-10-10 15:09:41 +05:00
01zulfi
6d81f26864 editor: restrict pasting premium features
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-10-08 13:31:24 +05:00
01zulfi
5219814b5a Merge pull request #8557 from 01zulfi/editor/refactor-collapsible-headings
editor: make headings collapsible
2025-10-08 13:26:37 +05:00
Abdullah Atta
bef9fd0fd0 Merge branch 'master' into beta 2025-10-08 13:25:42 +05:00
Abdullah Atta
2341293d92 Merge pull request #8734 from 01zulfi/common/fix-paragraph-keybinding
common: fix insert paragraph keybinding
2025-10-08 13:20:32 +05:00
Abdullah Atta
215387f8a9 Merge pull request #8731 from streetwriters/chore/get-rid-of-nx
Get rid of nx
2025-10-08 13:20:00 +05:00
01zulfi
534b8c5ad0 common: fix insert paragraph keybinding
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-10-08 11:57:42 +05:00
Abdullah Atta
b7b2ead9eb setup(tx): minor refactor 2025-10-08 10:57:58 +05:00
Abdullah Atta
b3e34d68e1 setup(tx): add support for passing flags down to commands 2025-10-08 10:55:52 +05:00
Abdullah Atta
39079612aa docs: remove mention of Nx from README 2025-10-08 10:29:18 +05:00
Abdullah Atta
be1af3111f setup: add support for passing args down to command 2025-10-08 10:28:02 +05:00
Abdullah Atta
8dcff49797 core: fix flaky note history tests 2025-10-08 10:27:43 +05:00
Abdullah Atta
687fb4e105 setup: remove editor-mobile from build all exclusion filter 2025-10-08 09:57:40 +05:00
Abdullah Atta
25ae780ad8 ci: get rid of NX_CLOUD_ACCESS_TOKEN 2025-10-08 09:49:05 +05:00
Abdullah Atta
b695367e6c global: add dotenv package 2025-10-08 09:34:59 +05:00
Abdullah Atta
bb274a84fe ci: use node v22 2025-10-08 08:56:20 +05:00
Abdullah Atta
364dccbf7a global: get rid of nx 2025-10-08 08:42:00 +05:00
Ammar Ahmed
105fb0fc69 mobile: release v3.3.3 2025-10-06 13:13:42 +05:00
Ammar Ahmed
89c408981c Merge branch 'master' into beta 2025-10-06 12:42:59 +05:00
Ammar Ahmed
110534edec Merge pull request #8714 from streetwriters/fix-mobile-client-selfhosted
Fix mobile client selfhosted
2025-10-06 12:40:26 +05:00
Ammar Ahmed
00e2190b2d Merge pull request #8713 from streetwriters/mobile-fix-legacy-pro-users
mobile: add support for LEGACY_PRO subscription plan name
2025-10-06 12:40:10 +05:00
Ammar Ahmed
e5c3fc667e Merge pull request #8712 from streetwriters/mobile-refactor-e2e-tests
mobile: refactor e2e tests
2025-10-06 12:39:57 +05:00
Ammar Ahmed
9aef8194f9 mobile: refactor e2e tests
Uses a builder pattern for writing tests to reduce code and simplify writing tests
2025-10-06 12:11:02 +05:00
Abdullah Atta
f76e0b7931 Merge pull request #8711 from 01zulfi/web/ignore-autobackup-notice-when-ignored
web: don't show auto-backup notice again after dismissal
2025-10-06 11:39:35 +05:00
Ammar Ahmed
0457e4417f mobile: minor cleanup 2025-10-06 11:10:19 +05:00
Ammar Ahmed
dae8b5c542 mobile: hide pricing flows on self hosted clients 2025-10-06 10:58:39 +05:00
01zulfi
60107dd77f web: don't show auto-backup notice again after dismissal
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-10-06 10:24:46 +05:00
Ammar Ahmed
4f3e19aaa2 mobile: add support for LEGACY_PRO subscription plan name 2025-10-06 09:55:28 +05:00
Ammar Ahmed
8c621f9f47 mobile: add null checks 2025-10-06 09:51:16 +05:00
Ammar Ahmed
74544efd62 mobile: update version to v3.3.2 2025-10-06 09:51:16 +05:00
Ammar Ahmed
c30ccbb68d mobile: fix crash on entering settings 2025-10-06 09:51:16 +05:00
Ammar Ahmed
c77050eccc Merge pull request #8710 from streetwriters/mobile-fix-3.3.1
mobile: release v3.3.2
2025-10-06 09:44:45 +05:00
Ammar Ahmed
f40ccdae41 mobile: add null checks 2025-10-05 01:11:09 +05:00
Ammar Ahmed
0a0aa09eea mobile: update version to v3.3.2 2025-10-05 01:02:56 +05:00
Ammar Ahmed
e2c55fb758 mobile: fix crash on entering settings 2025-10-05 00:58:02 +05:00
Ammar Ahmed
12e3335d52 mobile: release v3.3.1 2025-10-04 23:57:09 +05:00
Ammar Ahmed
f29439539d mobile: misc bug fixes 2025-10-04 23:57:09 +05:00
Ammar Ahmed
13c9fdba52 mobile: update monograph publish sheet 2025-10-04 23:57:09 +05:00
Ammar Ahmed
2cb087972c Merge pull request #8638 from streetwriters/mobile-release-v3.3.1
release v3.3.1 on mobile
2025-10-04 23:56:33 +05:00
Ammar Ahmed
41a32ede15 mobile: release v3.3.1 2025-10-04 23:27:30 +05:00
Abdullah Atta
95f52fba51 Merge pull request #8633 from streetwriters/release/v3.3 2025-10-04 22:08:21 +05:00
Abdullah Atta
e2159b7614 Merge pull request #8633 from streetwriters/release/v3.3
Release v3.3
2025-10-04 22:07:18 +05:00
Ammar Ahmed
ee33875edf mobile: misc bug fixes 2025-10-04 12:54:51 +05:00
Ammar Ahmed
28681fb1b0 mobile: update monograph publish sheet 2025-10-04 12:54:51 +05:00
Abdullah Atta
33194dc9f0 setup: show script logs only in verbose mode 2025-10-04 10:37:51 +05:00
Abdullah Atta
7509766df2 desktop: fix sqlite extensions can't be found in dev 2025-10-04 10:22:11 +05:00
Abdullah Atta
30a02a4977 core: fix type errors 2025-10-04 10:21:38 +05:00
Abdullah Atta
f67f4138c3 core: minor fixes to monographs 2025-10-04 10:18:38 +05:00
Abdullah Atta
49d51da1bd web: fix toggles not working in publish view 2025-10-04 10:18:22 +05:00
Abdullah Atta
17bfe4e075 desktop: handle errors thrown during backup creation 2025-10-04 09:31:15 +05:00
Abdullah Atta
d5905a4e5f desktop: update electron to v36 2025-10-04 09:28:55 +05:00
Abdullah Atta
e1b46d33f4 desktop: enable asar 2025-10-04 09:20:10 +05:00
Ammar Ahmed
ce7c003c54 mobile: fix bottom padding 2025-10-04 08:37:07 +05:00
Abdullah Atta
7f473ce7c8 ci: use custom task executor instead of nx 2025-10-04 08:27:09 +05:00
Abdullah Atta
c239f490b0 setup: add custom task runner as an alternative to nx 2025-10-04 00:09:23 +05:00
Abdullah Atta
1ad1915fcc config: cache {projectRoot}/locales 2025-10-03 21:42:11 +05:00
Abdullah Atta
14029de484 misc: update nx 2025-10-03 18:47:15 +05:00
Abdullah Atta
5d07db366b desktop: add logs in build script for debugging 2025-10-03 18:40:47 +05:00
Abdullah Atta
9e265dbecf web: add new version highlights 2025-10-03 18:38:08 +05:00
Abdullah Atta
717bce36e6 desktop: regenerate lockfile 2025-10-03 18:30:39 +05:00
Abdullah Atta
17831cdd8c ci: install sqlite3-fts5-html for all platforms 2025-10-03 18:13:12 +05:00
Ammar Ahmed
02e37c6ed4 mobile: prepare release v3.3.0 2025-10-03 14:39:04 +05:00
Abdullah Atta
16b52e9633 web: update export snapshots 2025-10-03 14:12:10 +05:00
Abdullah Atta
77eee945ca web: bump version to 3.3.0 2025-10-03 14:03:14 +05:00
Abdullah Atta
f21f235d37 core: remove pricing tests 2025-10-03 13:58:22 +05:00
Abdullah Atta
2949fcde38 core: fix e2e tests 2025-10-03 13:54:17 +05:00
Abdullah Atta
6ae1674de5 web: fix tests 2025-10-03 11:59:53 +05:00
Abdullah Atta
2bd74e043a core: fix note history cleanup tests 2025-10-03 09:05:52 +05:00
Abdullah Atta
1a05acbe9a core: fix isProduction always returns false 2025-10-03 09:03:12 +05:00
Abdullah Atta
a0597e13fe Revert "Merge pull request #8493 from 01zulfi/editor/collapsible-headings"
This reverts commit 7241dce7a6, reversing
changes made to ae5b422965.
2025-10-03 08:54:28 +05:00
Ammar Ahmed
d11d665395 mobile: do not allow changing plan if user subscribed to legacy pro sub 2025-10-03 08:41:11 +05:00
Abdullah Atta
ab2758ac79 intl: Revert "intl: clarify what happens to user data on plan switch"
This reverts commit 4377b8b340.
2025-10-02 14:45:13 +05:00
01zulfi
bb682a6f6e web: reset default notebook & tag feature if applicable (#8628)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-10-02 14:22:34 +05:00
Abdullah Atta
4377b8b340 intl: clarify what happens to user data on plan switch 2025-10-02 14:21:12 +05:00
Abdullah Atta
eb0c9b823b common: File size -> Maximum file size 2025-10-02 13:38:18 +05:00
Abdullah Atta
a595b12431 common: rerun feature available hooks on user subscription update 2025-10-02 11:26:16 +05:00
Abdullah Atta
ebd9b45cac web: fix features reset on subscription change 2025-10-02 11:17:08 +05:00
Abdullah Atta
5ae024f20a Merge branch 'master' into beta 2025-10-02 10:40:56 +05:00
Abdullah Atta
9ae93dec4c Merge pull request #8432 from 01zulfi/docs/standard-notes-import
docs: add standard notes import instructions
2025-10-02 10:35:02 +05:00
Abdullah Atta
93ecc9b1ac Merge pull request #8587 from 01zulfi/web/fix-status-item
web: fix update & vault status items vertical alignment
2025-10-02 10:33:01 +05:00
Ammar Ahmed
28455f8b31 mobile: update icons in settings 2025-10-02 09:43:46 +05:00
Abdullah Atta
b49be89b06 Merge pull request #8570 from 01zulfi/editor/support-math-paste
editor: support pasting math
2025-10-02 09:30:51 +05:00
Abdullah Atta
23e0748137 Merge pull request #8581 from streetwriters/fix/error-not-shown-gift-card
Fix error not shown on redeem code failure
2025-10-02 09:30:14 +05:00
Abdullah Atta
2f6d222cca Merge pull request #8603 from 01zulfi/core/fix-leading-spaces-export
core: fix leading spaces in txt export && remove unneeded space at start of txt
2025-10-02 09:29:23 +05:00
Abdullah Atta
ba1cfe05c4 Merge pull request #8621 from 01zulfi/core/fix-tag-title-sorting
core: fix tag sort by title
2025-10-02 09:29:07 +05:00
Abdullah Atta
6f80334296 core: fix tests 2025-10-02 09:24:50 +05:00
Ammar Ahmed
86da8a3620 mobile: add limit on 2fa sms setup 2025-10-02 09:09:20 +05:00
Abdullah Atta
11702c9209 Merge pull request #8615 from streetwriters/fix/web-app-not-working-on-mobile
Fix web app not working on mobile devices
2025-10-02 08:38:05 +05:00
Abdullah Atta
240d9b533f web: reset restricted features on app startup 2025-10-02 08:37:17 +05:00
01zulfi
8dc12f01b9 web: enforce sms2FA feature limit (#8627)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-10-01 14:58:42 +05:00
Ammar Ahmed
3b0dce6c6f mobile: fix crash 2025-10-01 13:42:59 +05:00
Ammar Ahmed
901dc4fe6d mobile: show discount on web plan offer 2025-10-01 13:42:59 +05:00
01zulfi
61748f40b6 web: fix text in upgrade dialog (#8623)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-10-01 11:45:30 +05:00
Abdullah Atta
871824f857 common: fix off by one error when checking limits 2025-10-01 10:34:11 +05:00
Ammar Ahmed
032c321568 mobile: fix announcements ui 2025-10-01 09:51:03 +05:00
Abdullah Atta
4883f02b62 web: fix subscription settings not updating on downgrade 2025-09-30 14:03:55 +05:00
Abdullah Atta
b43a8cbafe web: improve plan change dialog to show full plan comparison 2025-09-30 11:53:45 +05:00
Abdullah Atta
11c1fe3853 web: refresh user on subscription change 2025-09-30 11:53:45 +05:00
Ammar Ahmed
4a4576ebd5 mobile: allow changing plan if not subscribed anymore 2025-09-30 11:25:36 +05:00
Abdullah Atta
0b5128b13b web: fix after trial period pricing ui 2025-09-30 10:21:37 +05:00
Abdullah Atta
d1dbb85459 web: prevent changing plans if user subscription from iOS/Android 2025-09-30 10:17:57 +05:00
Abdullah Atta
ae1005d5f9 web: show provider info in subscription settings 2025-09-30 10:08:59 +05:00
Abdullah Atta
11e6074e21 web: simplify change plan dialog 2025-09-30 09:45:18 +05:00
Abdullah Atta
ea9aa2a136 web: navigate to /notes on subscription update in checkout view 2025-09-30 09:45:18 +05:00
Ammar Ahmed
203fe5bee0 mobile: update sheet paywall 2025-09-30 08:56:37 +05:00
Ammar Ahmed
4262641567 mobile: add subscription paused case 2025-09-30 08:55:53 +05:00
Ammar Ahmed
c0f79be78c mobile: fix keyboard does not open with autoFocus 2025-09-30 08:55:28 +05:00
01zulfi
239e301042 core: fix tag sort by title
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-09-29 11:23:03 +05:00
Ammar Ahmed
23bb80bbd6 Merge branch 'fix-server-url-error' into beta 2025-09-29 10:05:08 +05:00
Abdullah Atta
d7232a4f1f Merge pull request #8576 from streetwriters/feature/new-pricing
New pricing
2025-09-29 10:02:43 +05:00
Abdullah Atta
2bfc1af8ff common: add monograph link & embeds and sms 2fa feature limits 2025-09-29 10:02:11 +05:00
Abdullah Atta
3ac6873be4 core: fix pause/resume legacy subscription 2025-09-29 10:02:11 +05:00
Abdullah Atta
ce487a108c web: enable full page mode in web clipper for all users 2025-09-29 10:02:11 +05:00
Abdullah Atta
827930e28f web: fix plan changing if subscription is trialing 2025-09-29 10:02:11 +05:00
Abdullah Atta
8a13cf01b4 web: fix trial info not shwon during checkout 2025-09-29 10:02:11 +05:00
Abdullah Atta
641c541305 web: fallback to created date if billed at date is not present 2025-09-29 10:02:11 +05:00
Abdullah Atta
9285bae0cc web: hide refund button if subscription is trialing 2025-09-29 10:02:10 +05:00
Abdullah Atta
954ac3154f web: only show billing history if provider is Paddle 2025-09-29 10:02:10 +05:00
Abdullah Atta
571f3242e2 web: show checkout page instead of dialog from plans page 2025-09-29 10:02:10 +05:00
Abdullah Atta
9052948b8a web: notesnook logo should be a link in checkout page 2025-09-29 10:02:10 +05:00
Ammar Ahmed
af91a6ee98 mobile: minor fixes 2025-09-29 10:02:10 +05:00
Ammar Ahmed
16633dbd05 mobile: fix welcome message sheet ui 2025-09-29 10:02:10 +05:00
Ammar Ahmed
8a506edd37 mobile: fix navigation when changing plan 2025-09-29 10:02:10 +05:00
Ammar Ahmed
fdbac8e608 mobile: paywall fixes 2025-09-29 10:02:10 +05:00
Ammar Ahmed
cdca90bd54 core: add googlePurchaseToken type 2025-09-29 10:02:10 +05:00
Ammar Ahmed
fb7d8b0893 mobile: allow users to change plan 2025-09-29 10:02:10 +05:00
Ammar Ahmed
a49bc92a13 mobile: pricing fixes 2025-09-29 10:02:10 +05:00
Abdullah Atta
58c1f5e3ca web: add support for education plan purchase 2025-09-29 10:02:10 +05:00
Ammar Ahmed
f1a0c1b447 mobile: minor refactor 2025-09-29 10:02:10 +05:00
Ammar Ahmed
d8534da4df mobile: fix gap between plan cards 2025-09-29 10:02:10 +05:00
Ammar Ahmed
28daa38d80 mobile: fix upgrade plan button not showing 2025-09-29 10:02:10 +05:00
Ammar Ahmed
5c275adda8 mobile: fix imports 2025-09-29 10:02:10 +05:00
Ammar Ahmed
26ecf2a7fd editor: fix build error 2025-09-29 10:02:10 +05:00
Abdullah Atta
e23c0f55b7 web: improve change plan ux 2025-09-29 10:02:10 +05:00
Ammar Ahmed
a6b03635c7 mobile: update vector icons patch 2025-09-29 10:02:10 +05:00
Abdullah Atta
6587541729 web: send email in custom data on purchase 2025-09-29 10:02:10 +05:00
Abdullah Atta
bc4bfa63f7 web: go back on overlay checkout closed 2025-09-29 10:02:10 +05:00
Abdullah Atta
bdda2d4987 web: add support for direct checkout 2025-09-29 10:02:10 +05:00
Ammar Ahmed
ab34073870 mobile: fix ui on ipad and tablets 2025-09-29 10:02:10 +05:00
Abdullah Atta
152a59fe26 web: improve attachment errors on upload/download 2025-09-29 10:02:10 +05:00
Ammar Ahmed
cf169eb6d6 mobile: fix inconsistent button sizes 2025-09-29 10:02:10 +05:00
Ammar Ahmed
16da396289 mobile: fix ui 2025-09-29 10:02:10 +05:00
Ammar Ahmed
7ad3fd4057 mobile: refactor 2025-09-29 10:02:10 +05:00
Ammar Ahmed
aecf4f1ee8 mobile: fix attachment uploading 2025-09-29 10:02:10 +05:00
Abdullah Atta
8f48fcd788 web: fix crash on opening checkout for new user 2025-09-29 10:02:10 +05:00
Ammar Ahmed
cf64fb3743 core: fix db.pricing.sku type 2025-09-29 10:02:10 +05:00
Ammar Ahmed
a21111368e mobile: fix pricing on gh release 2025-09-29 10:02:10 +05:00
Abdullah Atta
383b914c52 web: post success message on checkout complete on react native 2025-09-29 10:02:10 +05:00
Abdullah Atta
555255a923 web: minor fix 2025-09-29 10:02:10 +05:00
Abdullah Atta
cd5a2ab179 web: fix cannot read property ASK_EVERY_TIME of undefined 2025-09-29 10:02:10 +05:00
Ammar Ahmed
48903f924c mobile: cleanup 2025-09-29 10:02:10 +05:00
Ammar Ahmed
7d46dd4fb0 mobile: cleanup 2025-09-29 10:02:10 +05:00
Abdullah Atta
cfa9f11f44 web: replace usage of subscription.type to subscription.plan 2025-09-29 10:02:10 +05:00
Abdullah Atta
1377ac38db common: no need for isLegacyPro 2025-09-29 10:02:10 +05:00
Abdullah Atta
d88b30b538 core: get rid of subscription.type (all subs now use .plan) 2025-09-29 10:02:10 +05:00
Ammar Ahmed
cfe0cded15 mobile: minor improvements 2025-09-29 10:02:10 +05:00
Ammar Ahmed
322f6b7aae mobile: pricing fixes 2025-09-29 10:02:10 +05:00
Ammar Ahmed
62ae26c464 mobile: pricing fixes for ios 2025-09-29 10:02:10 +05:00
Abdullah Atta
c920c999eb web: fix subscription settings for legacy pro users 2025-09-29 10:02:10 +05:00
Abdullah Atta
288f601651 web: use trialExpiryDate for showing trial end date 2025-09-29 10:02:10 +05:00
Ammar Ahmed
d4f902f63d mobile: fix crash when user logged out 2025-09-29 10:02:10 +05:00
Ammar Ahmed
7dddebef2e mobile: pricing fixes 2025-09-29 10:02:10 +05:00
Abdullah Atta
dc1498d672 web: ask for reason when requesting refund 2025-09-29 10:02:10 +05:00
Abdullah Atta
eb36c1d7cb web: show billing history even if user is not subscribed 2025-09-29 10:02:09 +05:00
Abdullah Atta
29c119a945 web: fix Upgrade to Pro being shown in drop down 2025-09-29 10:02:09 +05:00
Abdullah Atta
860bc10747 web: fix cannot use IS_DEV before initialization error 2025-09-29 10:02:09 +05:00
Abdullah Atta
215ca23190 web: add support for changing plans 2025-09-29 10:02:09 +05:00
Abdullah Atta
4b9d9e4353 web: add comparison table & faqs to plans selection dialog 2025-09-29 10:02:09 +05:00
Ammar Ahmed
fd5d4e56ea mobile: route to login page from paywall 2025-09-29 10:02:09 +05:00
Ammar Ahmed
9801d117a1 mobile: minor fixes 2025-09-29 10:02:09 +05:00
Ammar Ahmed
3c4fb8cb53 mobile: localize 2025-09-29 10:02:09 +05:00
Ammar Ahmed
ae17b34be9 mobile: localize strings 2025-09-29 10:02:09 +05:00
Ammar Ahmed
1a544754ef mobile: handle web payments 2025-09-29 10:02:09 +05:00
Ammar Ahmed
1ddfd15ee9 mobile: render faqs 2025-09-29 10:02:09 +05:00
Ammar Ahmed
035126ab2f mobile: small fixes 2025-09-29 10:02:09 +05:00
Abdullah Atta
e157ae8bc8 web: add checkout faqs 2025-09-29 10:02:09 +05:00
Abdullah Atta
25b0503a25 web: show features usage details in subscription settings 2025-09-29 10:02:09 +05:00
Abdullah Atta
ef235dd0aa web: show plans on login & signup 2025-09-29 10:02:09 +05:00
Ammar Ahmed
699080048d mobile: fix login flow 2025-09-29 10:02:09 +05:00
Ammar Ahmed
3c9b315f78 mobile: updates 2025-09-29 10:02:09 +05:00
Ammar Ahmed
1464006531 mobile: fix unneeded sync calls 2025-09-29 10:02:09 +05:00
Abdullah Atta
6921fcb3ae web: fix checkout 2025-09-29 10:02:09 +05:00
Abdullah Atta
286f8dd7cc core: add endpoint for getting checkout url 2025-09-29 10:02:09 +05:00
Abdullah Atta
d3e3ef5986 core: add endpoints for getting all products for new plans 2025-09-29 10:02:09 +05:00
Ammar Ahmed
ea1ffc59b8 common: fix too many queries to db 2025-09-29 10:02:09 +05:00
Abdullah Atta
5524886868 common: add function to fetch features usage details 2025-09-29 10:02:09 +05:00
Abdullah Atta
68b63cf635 web: introduce new checkout dialog 2025-09-29 10:02:09 +05:00
Abdullah Atta
74de09e441 web: use checkFeature in multi-select 2025-09-29 10:02:09 +05:00
Abdullah Atta
b82e9598bd theme: add new tertiary button variant 2025-09-29 10:02:09 +05:00
Abdullah Atta
25889192c4 web: refactor toggles in setting store 2025-09-29 10:02:09 +05:00
Abdullah Atta
76eac69f94 web: remove limit checking from state stores 2025-09-29 10:02:09 +05:00
Abdullah Atta
97f8f1e3c3 web: use checkFeature 2025-09-29 10:02:09 +05:00
Abdullah Atta
8722b6bc68 web: add feature limit check when adding new tag from editor 2025-09-29 10:02:09 +05:00
Abdullah Atta
8e8d2a4083 web: refactor and fix feature limit checks on toolbar customization 2025-09-29 10:02:09 +05:00
Abdullah Atta
4caac77706 web: show upgrade dialog on triggering feature limit in editor 2025-09-29 10:02:09 +05:00
Abdullah Atta
0f73f266b2 web: fix customizableSidebar feature limit checks 2025-09-29 10:02:09 +05:00
Abdullah Atta
8c70abda04 web: add feature limit check when adding new tag 2025-09-29 10:02:09 +05:00
Abdullah Atta
6881a5f432 web: prefer to show upgrade dialog before opening new notebook/tag/color dialog 2025-09-29 10:02:09 +05:00
Abdullah Atta
22e9ae6bf8 web: use new api for adding limits on settings 2025-09-29 10:02:09 +05:00
Abdullah Atta
eb73de6d8d web: add support for adding feature limits on settings 2025-09-29 10:02:09 +05:00
Abdullah Atta
1af7f1bd7f web: show upgrade dialog from toast 2025-09-29 10:02:09 +05:00
Abdullah Atta
3a0273a12b web: add upgrade dialog 2025-09-29 10:02:09 +05:00
Abdullah Atta
05795ca052 web: add feature limit checks to tag & notebook functions 2025-09-29 10:02:09 +05:00
Abdullah Atta
a5746c56eb web: check for defaultNotebookAndTag limit in editor 2025-09-29 10:02:09 +05:00
Abdullah Atta
80f66ab0ba web: remove app lock on first unlock if not allowed on user plan 2025-09-29 10:02:09 +05:00
Abdullah Atta
44e62f0eb0 core: rebuild trash cache even if trash cleanup interval is set to never 2025-09-29 10:02:09 +05:00
Abdullah Atta
a6e107f61d ui: add support for showing premium icon on menu items 2025-09-29 10:02:09 +05:00
Abdullah Atta
31bb78bfca web: add onBeforeOpen hook to dialog manager 2025-09-29 10:02:09 +05:00
Abdullah Atta
8bb9308173 web: fix crash on saving note 2025-09-29 10:02:09 +05:00
Abdullah Atta
46d279ca3b common: fix use-is-feature-available hook types 2025-09-29 10:02:09 +05:00
Ammar Ahmed
0a5bdaaa7f mobile: add plan preview in settings 2025-09-29 10:02:09 +05:00
Ammar Ahmed
3480b8c5da mobile: add sync control and offline mode limits 2025-09-29 10:02:09 +05:00
Ammar Ahmed
32e1fb5f56 mobile: update plan comparison 2025-09-29 10:02:09 +05:00
Abdullah Atta
d94e8d04c8 common: add /mo to storage limit caption
also add limits for fullOfflineMode & syncControls
2025-09-29 10:02:09 +05:00
Abdullah Atta
26e2b380b3 common: add function for showing features as a table 2025-09-29 10:02:09 +05:00
Ammar Ahmed
06710ff416 mobile: pricing changes 2025-09-29 10:02:09 +05:00
Ammar Ahmed
32a7f866c3 mobile: add limits to UI 2025-09-29 10:02:09 +05:00
Abdullah Atta
86b650712e common: export getFeature 2025-09-29 10:02:09 +05:00
Ammar Ahmed
0178e455f9 mobile: update paywall sheet 2025-09-29 10:02:09 +05:00
Ammar Ahmed
39693966c1 mobile: add feature manager 2025-09-29 10:02:09 +05:00
Ammar Ahmed
dc08a39173 mobile: introduce plan limits 2025-09-29 10:02:09 +05:00
Ammar Ahmed
1be518510a mobile: update 2025-09-29 10:02:09 +05:00
Ammar Ahmed
e513081010 mobile: fix build 2025-09-29 10:02:09 +05:00
Ammar Ahmed
9bc8bddc12 common: fix esm imports 2025-09-29 10:02:09 +05:00
Abdullah Atta
986b99f62e web: show used/total storage on user profile 2025-09-29 10:02:08 +05:00
Abdullah Atta
16092a4185 core: add types for storage limits 2025-09-29 10:02:08 +05:00
Abdullah Atta
26eafcfee9 web: upload direct to s3 via proxy 2025-09-29 10:02:08 +05:00
Abdullah Atta
f20c1ef4f4 web: clicking on "auto backups disabled" notice should open settings 2025-09-29 10:02:08 +05:00
Abdullah Atta
3f076d90c8 common: make feature checking more type safe 2025-09-29 10:02:08 +05:00
Abdullah Atta
df70fee70e common: add storage to feature limits 2025-09-29 10:02:08 +05:00
Ammar Ahmed
4df9c7d9f7 mobile: fix intro flow 2025-09-29 10:02:08 +05:00
Abdullah Atta
59916b924c web: markdown shortcuts should be turned off by default 2025-09-29 10:02:08 +05:00
Abdullah Atta
aafce93117 web: limit max note versions 2025-09-29 10:02:08 +05:00
Abdullah Atta
97ef91abdb web: limit set as homepage 2025-09-29 10:02:08 +05:00
Abdullah Atta
b426d61c3a web: add limits to app lock 2025-09-29 10:02:08 +05:00
Abdullah Atta
f08c484d40 web: add limits to block-level note linking 2025-09-29 10:02:08 +05:00
Abdullah Atta
b03a4559c5 core: make max note versions configurable 2025-09-29 10:02:08 +05:00
Abdullah Atta
d2f491ed66 common: add feature limits for app lock and note versions 2025-09-29 10:02:08 +05:00
Abdullah Atta
1a2a1da086 web: add limit on notebook restoration 2025-09-29 10:02:08 +05:00
Abdullah Atta
872f4d7e91 core: remove usage of db.features 2025-09-29 10:02:08 +05:00
Abdullah Atta
bce063e1bd web: add feature limits in almost all places 2025-09-29 10:02:08 +05:00
Abdullah Atta
e6dc5ddfed common: add is feature available utility 2025-09-29 10:02:08 +05:00
Abdullah Atta
bcbcd516f6 mobile: initial pricing changes 2025-09-29 10:01:59 +05:00
Ammar Ahmed
24da82313e mobile: pricing changes 2025-09-29 10:00:29 +05:00
Abdullah Atta
5fe29af51a web: migrate to paddle billing + new plans 2025-09-29 10:00:29 +05:00
Abdullah Atta
fbe551eb29 core: add new subscription types 2025-09-29 10:00:29 +05:00
Abdullah Atta
c097c4d457 web: fix web app not working on mobile devices
i thought service workers would work on Android but unfortunately, they are
super flaky causing lots of issues. I might revisit it later.
2025-09-26 11:03:41 +05:00
Ammar Ahmed
a792a3d6e4 mobile: allow underscores in url validation 2025-09-25 12:26:48 +05:00
Ammar Ahmed
28f1f276ce Merge pull request #8611 from streetwriters/fix-server-url-error
mobile: allow underscores in url validation
2025-09-25 12:24:18 +05:00
Ammar Ahmed
9470d2b61f mobile: allow underscores in url validation 2025-09-25 12:19:16 +05:00
01zulfi
95795a20c2 core: fix leading spaces in txt export && remove unneeded space at start of txt
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-09-24 09:35:26 +05:00
Ammar Ahmed
64b7b57b3e Merge branch 'mobile-release-3.2.12' into beta 2025-09-19 10:48:47 +05:00
Ammar Ahmed
5e05d96487 Merge pull request #8588 from streetwriters/mobile-release-3.2.12
Mobile release 3.2.12
2025-09-19 10:41:45 +05:00
Ammar Ahmed
18c9912068 mobile: update changelog 2025-09-19 09:55:36 +05:00
01zulfi
cd85753252 web: fix update & vault status items vertical alignment
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-09-18 14:19:56 +05:00
Ammar Ahmed
bdb135036c mobile: release v3.2.12 2025-09-18 12:43:30 +05:00
Ammar Ahmed
5d70f58a0d mobile: fix editor styles 2025-09-18 12:42:40 +05:00
Ammar Ahmed
b7d2d66e82 mobile: fix add tag button not show when no tags 2025-09-18 12:42:28 +05:00
Ammar Ahmed
6b028ef850 mobile: fix localization 2025-09-18 12:42:18 +05:00
Ammar Ahmed
8f85795e53 mobile: fix notebook tree in notesnook sheet 2025-09-18 12:42:07 +05:00
Ammar Ahmed
a0b7dff5fd Merge pull request #8585 from streetwriters/mobile-release-3.2.11
Mobile release 3.2.11
2025-09-18 12:39:21 +05:00
Ammar Ahmed
352018c042 Merge branch 'master' into mobile-release-3.2.11
Signed-off-by: Ammar Ahmed <40239442+ammarahm-ed@users.noreply.github.com>
2025-09-18 12:39:10 +05:00
Abdullah Atta
2b1ac822ed editor: fix images not rendering 2025-09-18 11:19:36 +05:00
Abdullah Atta
b3c3890443 editor: fix type errors 2025-09-18 11:19:24 +05:00
Abdullah Atta
99e642780e web: fix error not shown on redeem code failure 2025-09-17 10:59:54 +05:00
Abdullah Atta
47088a0a66 Merge branch 'master' into beta 2025-09-16 13:04:21 +05:00
Abdullah Atta
fd48684396 Merge pull request #8568 from 01zulfi/web/attachment-navigate
web: fix settings not opening again after navigation from attachment manager
2025-09-16 13:03:25 +05:00
01zulfi
9b25ab8708 web: fix settings not opening again after navigation from attachment manager
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-09-16 12:37:36 +05:00
Abdullah Atta
c725ba8530 Merge pull request #8574 from streetwriters/ci/fix-desktop-tests-not-running
Fix desktop tests not triggering on PR/commit
2025-09-16 11:15:41 +05:00
Abdullah Atta
98287fbfc4 ci: fix desktop tests not triggering on PR/commit 2025-09-16 11:07:52 +05:00
Ammar Ahmed
3260695a09 Merge branch 'intl-fix-strings' into beta 2025-09-16 10:26:40 +05:00
Abdullah Atta
3a3434b021 Merge pull request #8562 from
streetwriters/fix/refresh-note-on-attachment-delete
2025-09-16 10:26:19 +05:00
Ammar Ahmed
9f24bd2250 Merge pull request #8573 from streetwriters/intl-fix-strings
intl: fix strings.ts
2025-09-16 10:12:13 +05:00
Ammar Ahmed
94f2a216ad intl: fix strings.ts 2025-09-16 10:11:43 +05:00
Ammar Ahmed
aeb4c984eb Merge branch 'fix-ipad-split-view' into beta 2025-09-16 10:10:17 +05:00
Ammar Ahmed
78e3ee5fd2 Merge pull request #8572 from streetwriters/fix-ipad-split-view
Fix keyboard in iPad split view
2025-09-16 10:10:05 +05:00
Ammar Ahmed
e94a2b2aa1 Merge branch 'mobile-editor-ui-update' into beta 2025-09-16 10:09:49 +05:00
Ammar Ahmed
1ddcf44eb0 Merge pull request #8551 from streetwriters/mobile-editor-ui-update
mobile: editor ui overhaul
2025-09-16 10:08:28 +05:00
Ammar Ahmed
5c5fb2ba2c Merge branch 'master' into mobile-editor-ui-update
Signed-off-by: Ammar Ahmed <40239442+ammarahm-ed@users.noreply.github.com>
2025-09-16 10:08:10 +05:00
Ammar Ahmed
9344eadf34 Merge branch 'mobile-reminder-fixes' into beta 2025-09-16 10:06:58 +05:00
Ammar Ahmed
aa4995d871 Merge pull request #8525 from streetwriters/mobile-reminder-fixes
Fix reminders on mobile
2025-09-16 10:06:54 +05:00
Ammar Ahmed
e40c42afc3 Merge branch 'mobile-fix-add-notebook-btn' into beta 2025-09-16 10:06:34 +05:00
Ammar Ahmed
f818c41a02 Merge pull request #8524 from streetwriters/mobile-fix-add-notebook-btn
Fix add notebook button in Notebooks sheet
2025-09-16 10:06:30 +05:00
Ammar Ahmed
178d7e7471 Merge branch 'mobile-fix-notebook-tree' into beta 2025-09-16 10:06:11 +05:00
Ammar Ahmed
3f9d954e2f Merge pull request #8508 from streetwriters/mobile-fix-notebook-tree
Fix Notebook Tree when Searching for Notebooks
2025-09-16 10:06:05 +05:00
Ammar Ahmed
48a3eee232 Merge branch 'mobile-fix-reset-navigation' into beta 2025-09-16 10:05:00 +05:00
Ammar Ahmed
f1fcd227e7 Merge pull request #8535 from streetwriters/mobile-fix-reset-navigation
mobile: fix resetting navigation
2025-09-16 10:04:54 +05:00
Ammar Ahmed
84af1a9411 Merge branch 'mobile-fix-string-email' into beta 2025-09-16 10:04:05 +05:00
Ammar Ahmed
44d910121c Merge pull request #8507 from streetwriters/mobile-fix-string-email
Fix email confirmed description
2025-09-16 10:03:40 +05:00
Abdullah Atta
1258a95aad Merge pull request #8562 from streetwriters/fix/refresh-note-on-attachment-delete
Refresh note on attachment permanent delete
2025-09-16 09:43:15 +05:00
Abdullah Atta
295ab2c073 editor: add migration to convert inline images into block nodes 2025-09-16 09:21:09 +05:00
Abdullah Atta
7aa350a9d2 editor: remove image float 2025-09-16 09:21:09 +05:00
Abdullah Atta
ee76e43fca editor: fix warnings when expanding all props into ToolButton 2025-09-16 09:21:09 +05:00
Ammar Ahmed
1379193065 mobile: fix keyboard in ipad split view 2025-09-16 09:11:34 +05:00
01zulfi
0fa3598783 web: add manage inbox api tokens section (#8552)
* web: add manage inbox api tokens section
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>

* web: add view inbox api key option
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>

* core: don't generate inbox api key on client
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>

* core: use separate class for inbox api keys && don't set created date on client
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-09-16 01:15:03 +05:00
01zulfi
02960fb5a9 editor: support pasting math
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-09-15 15:41:16 +05:00
Abdullah Atta
a7fa42e944 web: refresh note on attachment permanent delete 2025-09-13 13:07:02 +05:00
Ammar Ahmed
02ab8e3938 mobile: editor ui improvements 2025-09-12 10:57:18 +05:00
Abdullah Atta
01c629f612 Merge pull request #8550 from streetwriters/release/web/v3.2.4 2025-09-12 08:52:11 +05:00
Abdullah Atta
5c120676e1 Merge pull request #8550 from streetwriters/release/web/v3.2.4
Release v3.2.4
2025-09-12 08:47:48 +05:00
Abdullah Atta
3821dc29ef web: fix some editor tests on macos 2025-09-12 08:28:39 +05:00
Abdullah Atta
3c51f73427 web: fix cannot destructure property checkout of He as it is undefined 2025-09-12 08:28:39 +05:00
Abdullah Atta
8db373ee34 web: bump version to 3.2.4 2025-09-12 08:28:39 +05:00
Abdullah Atta
1be6e6b444 Merge pull request #8388 from streetwriters/fix/theme-issues-2 2025-09-12 08:28:13 +05:00
Abdullah Atta
adcb73a2fc Merge pull request #8388 from streetwriters/fix/theme-issues-2
Fix theme related issues
2025-09-12 08:27:44 +05:00
Ammar Ahmed
4c97b3481d mobile: editor ui overhaul 2025-09-11 15:49:00 +05:00
Abdullah Atta
38579c37e1 Merge pull request #8549 from 01zulfi/web/fix-toc-crash 2025-09-11 13:49:32 +05:00
Abdullah Atta
4785544e18 Merge pull request #8549 from 01zulfi/web/fix-toc-crash
web: fix crash when shift+click on toc item
2025-09-11 13:48:33 +05:00
01zulfi
7812c15b48 web: fix crash when shift+click on toc item
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-09-11 09:39:00 +05:00
01zulfi
251145ea74 global: add enable inbox setting to generate/discard inbox key pair (#8527)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-09-09 22:12:44 +05:00
Abdullah Atta
5e4972c1d0 web: bump version to v3.3.0-beta.1 2025-09-09 14:57:07 +05:00
Abdullah Atta
64bfc80a42 Merge pull request #8395 from 01zulfi/editor/image-resizing-dimensions 2025-09-09 14:52:30 +05:00
Abdullah Atta
b841c6e0eb Merge pull request #8395 from 01zulfi/editor/image-resizing-dimensions
editor: show image dimensions during drag resizing
2025-09-09 14:51:44 +05:00
Abdullah Atta
7241dce7a6 Merge pull request #8493 from 01zulfi/editor/collapsible-headings
editor: make headings collapsible
2025-09-09 14:50:27 +05:00
01zulfi
8f25f9ba3e editor: extract evaluating click bounds for collapsible nodes into a util
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-09-09 14:39:32 +05:00
01zulfi
6ab58c68e1 editor: make headings collapsible
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-09-09 14:39:32 +05:00
01zulfi
ae5b422965 editor: if selected text is link, autofill url field in insert link popup
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-09-09 13:07:55 +05:00
Abdullah Atta
55b6be0f15 Merge pull request #8542 from 01zulfi/editor/improve-insert-link-dialog
editor: if selected text is link, autofill url field in insert link popup
2025-09-09 13:07:18 +05:00
Abdullah Atta
f9324d9da5 Merge pull request #8489 from 01zulfi/editor/improve-table-styling
editor: improve table styling
2025-09-09 13:06:10 +05:00
Abdullah Atta
2362902675 Merge pull request #8546 from streetwriters/release/monograph/1.2.5 2025-09-09 12:53:44 +05:00
Abdullah Atta
dfe6a73ac1 Merge pull request #8546 from streetwriters/release/monograph/1.2.5
Release monographs v1.2.5
2025-09-09 12:53:20 +05:00
Abdullah Atta
afcb8835d2 ci: do not build for armv7 & armv8 platforms 2025-09-09 12:49:33 +05:00
Abdullah Atta
9dc9f186e1 monograph: use oven/bun:1.2.21-slim 2025-09-09 12:45:15 +05:00
Ammar Ahmed
875125cfe4 mobile: clear logs 2025-09-09 12:34:06 +05:00
Abdullah Atta
32d9cdd265 monograph: bump version to 1.2.5 2025-09-09 12:00:28 +05:00
Abdullah Atta
669f830dd7 Merge pull request #8545 from streetwriters/fix-monograph-report-not-working 2025-09-09 11:59:27 +05:00
Abdullah Atta
09deae9dbf Merge pull request #8545 from streetwriters/fix-monograph-report-not-working
Add report endpoint to connect-src content policy
2025-09-09 11:59:02 +05:00
Abdullah Atta
337582ac70 monograph: add report endpoint to connect-src content policy 2025-09-09 11:58:29 +05:00
01zulfi
820c78ce81 editor: if selected text is link, autofill url field in insert link popup
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-09-08 11:28:16 +05:00
Abdullah Atta
23924a34a3 editor: move selection to newly added row/column 2025-09-08 10:22:15 +05:00
Abdullah Atta
428f1e746a editor: make table 100% width 2025-09-08 10:21:45 +05:00
Ammar Ahmed
565e692af8 mobile: fix crash during navigation 2025-09-05 12:40:20 +05:00
Ammar Ahmed
94e4721663 mobile: fix resetting navigation 2025-09-05 12:11:39 +05:00
Ammar Ahmed
8157c0812a mobile: reminder fixes
1. Allow editing reminder without changing date
2. Fix colors of buttons
3. Allow picking date and time in date picker dialog
4. Fix auto focus of title and description inputs
2025-09-05 11:30:18 +05:00
Ammar Ahmed
bc36837cd0 mobile: add missing buttons in reminder sheet 2025-09-04 14:26:47 +05:00
Ammar Ahmed
33540b000c mobile: show reminder description in properties 2025-09-04 14:26:33 +05:00
Ammar Ahmed
5a63a45d00 mobile: fix add notebook button 2025-09-04 11:43:36 +05:00
01zulfi
6eb1f2a4a7 editor: install & use simplebar for table scroll bar
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-09-02 13:02:55 +05:00
01zulfi
8fce6b5eb6 editor: show image dimensions during drag resizing
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-09-02 10:18:36 +05:00
Abdullah Atta
5bd1999269 Merge pull request #8487 from 01zulfi/web/reminder-search-delete 2025-08-29 11:43:30 +05:00
Abdullah Atta
4e44661e1b Merge pull request #8487 from 01zulfi/web/reminder-search-delete
web: fix deleting a reminder not removing from search list
2025-08-29 11:43:15 +05:00
Abdullah Atta
827ca2e427 Merge pull request #8509 from 01zulfi/editor/handle-empty-link-hrefs 2025-08-29 11:42:16 +05:00
Abdullah Atta
81fd1c097e Merge pull request #8509 from 01zulfi/editor/handle-empty-link-hrefs
editor: don't show open & copy tools for empty links
2025-08-29 11:39:39 +05:00
01zulfi
aaf82f359b editor: don't show open & copy tools for empty links
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-08-28 11:45:12 +05:00
Ammar Ahmed
aa7f14ae79 mobile: fix email confirmed description 2025-08-28 10:12:32 +05:00
Ammar Ahmed
0ad63da4a2 mobile: fix tree items in search 2025-08-25 14:51:56 +05:00
Ammar Ahmed
2885b9ac3e mobile: fix notebook tree when searching notebooks 2025-08-25 13:08:29 +05:00
01zulfi
1ae9e04e7a editor: improve table styling
* make tool buttons more prominent
* match scroll styling to rest of app
* add padding to cells
* add bg to header row

Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-08-20 14:43:02 +05:00
01zulfi
693311a3db core: use RequestFetchV2 hub method (#8483)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-08-20 11:22:49 +05:00
Ammar Ahmed
a15ab99056 mobile: release v3.2.11 2025-08-20 10:32:54 +05:00
Ammar Ahmed
222cdbfa63 mobile: fix navigation 2025-08-20 10:01:19 +05:00
01zulfi
a1d8b34fb4 web: fix deleting a reminder not removing from search list
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-08-20 09:02:44 +05:00
Ammar Ahmed
35d08a6dfa Merge branch 'mobile-fix-open-note-notification' into beta 2025-08-20 08:49:59 +05:00
Ammar Ahmed
874352e753 Merge pull request #8400 from streetwriters/mobile-fix-open-note-notification
Fix opening pinned note from notification on android
2025-08-20 08:49:55 +05:00
Ammar Ahmed
6bb5e44442 Merge branch 'mobile-fix-notebook-tag-sorting-filter' into beta 2025-08-20 08:49:36 +05:00
Ammar Ahmed
49d1ab4be5 Merge pull request #8401 from streetwriters/mobile-fix-notebook-tag-sorting-filter
Fix filtered tags and notebooks not sorted correctly
2025-08-20 08:49:21 +05:00
Ammar Ahmed
54a0d0fd0c Merge branch 'mobile-fix-back-navigation' into beta 2025-08-20 08:48:58 +05:00
Ammar Ahmed
65a80dbd46 Merge pull request #8402 from streetwriters/mobile-fix-back-navigation
Fix back navigation on first app launch by resetting routes
2025-08-20 08:48:40 +05:00
Ammar Ahmed
dfeb01320d Merge branch 'fix-cache-clear-error' into beta 2025-08-20 08:48:20 +05:00
Ammar Ahmed
e55456f492 Merge pull request #8467 from streetwriters/fix-cache-clear-error
mobile: fix error when clearing cache on android
2025-08-20 08:48:01 +05:00
Ammar Ahmed
d33209afcc Merge branch 'fix-open-share-exported-notes-ios' into beta 2025-08-20 08:47:40 +05:00
Ammar Ahmed
3f9fce0d34 Merge pull request #8482 from streetwriters/fix-open-share-exported-notes-ios
mobile: fix sharing and opening exported notes on iOS
2025-08-20 08:47:21 +05:00
Ammar Ahmed
2ae094cf1f mobile: fix sharing and opening exported notes 2025-08-19 12:51:16 +05:00
Abdullah Atta
5530270b06 Merge pull request #8466 from 01zulfi/web/list-pane-max-size 2025-08-19 09:53:06 +05:00
Abdullah Atta
bc224f1674 Merge pull request #8466 from 01zulfi/web/list-pane-max-size
web: increase list pane max size to 1000 for large screens
2025-08-19 09:52:28 +05:00
01zulfi
8bb1582cca web: increase list pane max size to 1000
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-08-18 15:48:59 +05:00
01zulfi
c759408fdc core: add support for monographs sync 2025-08-18 13:16:12 +05:00
Ammar Ahmed
d02125a93c mobile: fix error when clearing cache on android 2025-08-18 13:15:45 +05:00
Abdullah Atta
30553ed0f1 Merge pull request #8389 from 01zulfi/common/update-keybindings 2025-08-13 13:31:34 +05:00
Abdullah Atta
d91ce4e936 Merge pull request #8389 from 01zulfi/common/update-keybindings
common: update keybindings for editor search, link, internal link, and command palette
2025-08-13 13:30:39 +05:00
Abdullah Atta
b315e70e1e Merge pull request #8392 from 01zulfi/web/fix-open-settings-shortcut 2025-08-13 13:30:11 +05:00
Abdullah Atta
deb902549b Merge pull request #8392 from 01zulfi/web/fix-open-settings-shortcut
web: fix open settings shortcut interfering with editor shortcut
2025-08-13 13:29:34 +05:00
Abdullah Atta
d6c6db68ba Merge pull request #8385 from Scott-will/master 2025-08-13 13:27:51 +05:00
Abdullah Atta
e41ed07805 Merge pull request #8385 from Scott-will/master
Handle pasting urls in html
2025-08-13 13:27:14 +05:00
Scott-will
f6e8dc0a88 editor: fix pasting html links with titles that look like links
Signed-off-by: Scott Williams scottwill1999@gmail.com

editor: update tests for html handling

Signed-off-by: Scott Williams scottwill1999@gmail.com

editor: add logic for markdown links

Signed-off-by: Scott Williams scottwill1999@gmail.com

editor: remove plugin in favour of markPasteRule

Signed-off-by: Scott Williams scottwill1999@gmail.com
2025-08-13 13:26:01 +05:00
01zulfi
0738b96161 docs: add missing instruction in desktop app dev setup
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-08-13 12:24:28 +05:00
Abdullah Atta
044dd5ce59 Merge pull request #8391 from 01zulfi/docs/update-desktop-instructions
docs: add missing instruction in desktop app dev setup
2025-08-13 12:21:12 +05:00
01zulfi
6cca06fcbc docs: add standard notes import instructions
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-08-07 12:09:23 +05:00
Ammar Ahmed
50feebc0b0 mobile: fix fdroid build 2025-07-31 09:10:52 +05:00
Ammar Ahmed
b24830666c Merge pull request #8409 from streetwriters/fix-fdroid-build
mobile: fix fdroid build
2025-07-31 09:10:13 +05:00
Ammar Ahmed
470802c3e2 mobile: fix fdroid build 2025-07-31 09:09:38 +05:00
Ammar Ahmed
0e869708f7 Merge branch 'mobile-fix-fdroid-build' into beta 2025-07-29 15:05:53 +05:00
Ammar Ahmed
7e0e1eac93 Merge pull request #8406 from streetwriters/mobile-fix-fdroid-build
mobile: compile lazysodium from source
2025-07-29 15:05:39 +05:00
Ammar Ahmed
58cbf653b2 mobile: compile lazysodium from source 2025-07-29 15:04:49 +05:00
Ammar Ahmed
4b35f2ecd2 mobile: fix back navigation on first app launch 2025-07-28 14:20:11 +05:00
Ammar Ahmed
48d9a863ec mobile: fix filtered tags and notebooks not sorted correctly 2025-07-28 13:42:46 +05:00
Ammar Ahmed
1d616cf68f mobile: fix opening note from notification on android 2025-07-28 11:56:54 +05:00
Ammar Ahmed
efda6f86ae Merge branch 'mobile-release-3.2.10-fix' into beta 2025-07-26 12:48:44 +05:00
Ammar Ahmed
cdf6a4bb5b Merge pull request #8398 from streetwriters/mobile-release-3.2.10-fix
mobile: release v3.2.10
2025-07-26 12:48:28 +05:00
Ammar Ahmed
1b3735e2b2 mobile: release v3.2.10 2025-07-26 12:19:13 +05:00
Ammar Ahmed
54008a0de2 Merge branch 'mobile-release-3.2.9' into beta 2025-07-26 11:58:43 +05:00
Ammar Ahmed
850fc6b066 Merge pull request #8397 from streetwriters/mobile-release-3.2.9
mobile: release v3.2.9
2025-07-26 11:58:20 +05:00
Ammar Ahmed
67a398f583 Merge branch 'mobile-editor-ux-improvement' into beta 2025-07-26 10:53:01 +05:00
Ammar Ahmed
8a62070c8e Merge pull request #8394 from streetwriters/mobile-editor-ux-improvement
Mobile editor ux improvement
2025-07-26 10:52:01 +05:00
Ammar Ahmed
8aa31b8380 mobile: fix exiting table not working 2025-07-25 14:24:14 +05:00
Ammar Ahmed
f445a963f9 mobile: improve ux when clicking empty area in editor 2025-07-25 12:44:55 +05:00
Ammar Ahmed
d6e3f27612 mobile: add scroll to top and bottom in editor 2025-07-25 12:44:34 +05:00
Ammar Ahmed
4688d74edb mobile: improvements to editor ux
1. Tapping on empty in editor opens the keyboard
2. Swiping to open the editor when editor is empty opens the keyboard automatically
2025-07-25 11:57:44 +05:00
Ammar Ahmed
e88c755ba8 Merge branch 'mobile-fix-edit-notebook' into beta 2025-07-25 11:01:20 +05:00
Ammar Ahmed
1985007039 Merge pull request #8393 from streetwriters/mobile-fix-edit-notebook
mobile: fix edit notebook button causes app freeze on iOS
2025-07-25 11:01:03 +05:00
Ammar Ahmed
039c8faabe mobile: fix edit notebook button causes app freeze 2025-07-25 10:57:14 +05:00
01zulfi
fb1eb234b6 web: fix open settings shortcut interfering with editor shortcut
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-07-25 08:25:01 +05:00
01zulfi
7e70cd96b9 docs: add missing instruction in desktop app dev setup
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-07-24 15:56:17 +05:00
01zulfi
f9a89783ed common: update keybindings for editor search, link, internal link, and command palette
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-07-23 09:45:12 +05:00
Abdullah Atta
26282352cb Merge pull request #8387 from 01zulfi/docs/keyboard-shortcuts-heading 2025-07-23 08:33:14 +05:00
Abdullah Atta
7f3c74b55b editor: fix theme related issues 2025-07-23 08:32:35 +05:00
Abdullah Atta
301ac781d6 Merge pull request #8387 from 01zulfi/docs/keyboard-shortcuts-heading
docs: add keyboard shortcuts heading
2025-07-23 08:31:41 +05:00
01zulfi
ce3c98ae9b docs: add keyboard shortcuts heading
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-07-22 16:28:07 +05:00
Abdullah Atta
1c3a6ffbde Merge pull request #7655 from 01zulfi/global/keyboard 2025-07-22 14:22:22 +05:00
Abdullah Atta
2447b3bea7 Merge pull request #7655 from 01zulfi/global/keyboard
global: keyboard shortcuts documentation && web dialog
2025-07-22 14:21:30 +05:00
Abdullah Atta
63888ff70e web: improve keyboard shortcuts dialog UI 2025-07-22 14:20:15 +05:00
Abdullah Atta
c6e3d1bd47 common: New note should be in the General category 2025-07-22 14:20:15 +05:00
Abdullah Atta
e03e02d702 common: add license header to keybindings.ts 2025-07-22 14:20:15 +05:00
Abdullah Atta
1abf51ae2b common: getGroupedKeybindings should return an array
this is so the groups are always ordered. It also makes it easier to iterate
over the groups.
2025-07-22 14:20:15 +05:00
Abdullah Atta
c41dfa3185 common: letter keys should be upper cased
this is common in a lot of places and it provides better readability as well.
2025-07-22 14:20:15 +05:00
01zulfi
52a07da230 editor: remove unneeded code
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-07-22 14:20:15 +05:00
01zulfi
f572bb1637 editor: fix insertParagraph keys
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-07-22 14:20:15 +05:00
01zulfi
773ede4b6c common: improve key formatting
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-07-22 14:20:15 +05:00
01zulfi
e4d42c8bac web: add command to show keyboard shortcuts in command palette
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-07-22 14:20:01 +05:00
01zulfi
5b85067e15 web: improve contrast of keys text in keyboard shortcuts dialog
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-07-22 14:20:01 +05:00
01zulfi
0d111f3a79 web: use keys from common/keybindings in command palette dialog
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-07-22 14:20:01 +05:00
01zulfi
f6b6f2b4b7 web: support mac key formatting in keyboard shortcuts dialog
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-07-22 14:20:01 +05:00
01zulfi
d55a2aa04d common: support mac keyboard formatting
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-07-22 14:20:01 +05:00
01zulfi
0185eea740 editor: remove hardcoded keybind definitions
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-07-22 14:20:01 +05:00
01zulfi
d44e8874b8 docs: move keyboard shortcuts script to docs/help
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-07-22 14:20:01 +05:00
01zulfi
e34d33dd61 web: update key maps registeration
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-07-22 14:20:01 +05:00
01zulfi
4b2fb80c23 global: add keyboard shortcuts
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>

global: (wip) move keyboard shortcuts metadata into common package
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>

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

global: (wip) more refactoring
* minor refactor dialog
* refactor logic out from script file to keybindings file

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

common: filter keybindings based on platform && minor ui changes

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

editor: use keyboard keys from common package
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>

web: remove unrelated title-box change
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>

editor: add TODO:remove comments
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-07-22 14:19:46 +05:00
Abdullah Atta
acbac95818 Merge pull request #8384 from streetwriters/themebuilder/release/1.4.0 2025-07-22 09:08:23 +05:00
Abdullah Atta
3c908ac079 Merge pull request #8384 from streetwriters/themebuilder/release/1.4.0
Update theme builder to new UI
2025-07-22 09:08:02 +05:00
Abdullah Atta
563f068948 theme-builder: bump version to 1.4.0 2025-07-22 09:03:09 +05:00
Abdullah Atta
6bf4300372 Merge pull request #8382 from 01zulfi/web/note-linking-dialog 2025-07-22 08:42:14 +05:00
Abdullah Atta
1344b958cb Merge pull request #8382 from 01zulfi/web/note-linking-dialog
web: migrate note linking dialog lists from tanstack virtual to virtuoso
2025-07-22 08:41:38 +05:00
01zulfi
32d7cab70c web: migrate note linking dialog lists from tanstack virtual to virtuoso
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-07-21 14:49:41 +05:00
Abdullah Atta
6f8f6d47f8 Merge pull request #8379 from streetwriters/docs/remove-onenote-sn-docs 2025-07-21 12:25:10 +05:00
Abdullah Atta
04a48979eb Merge pull request #8365 from 01zulfi/web/fix-nav-pane-on-small-screens 2025-07-21 12:24:17 +05:00
Abdullah Atta
1293fa2dec Merge pull request #8365 from 01zulfi/web/fix-nav-pane-on-small-screens
web: fix nav pane on small screens
2025-07-21 12:23:50 +05:00
Abdullah Atta
ff3a8fa738 Merge pull request #8381 from
streetwriters/fix/email-should-not-be-required-session-expiry
2025-07-21 12:20:27 +05:00
Abdullah Atta
8542cbf37e Merge pull request #8381 from streetwriters/fix/email-should-not-be-required-session-expiry
Email should not be required on session expiry
2025-07-21 12:19:42 +05:00
Abdullah Atta
62c6fba9a0 web: email should not be required on session expiry 2025-07-21 12:10:43 +05:00
Abdullah Atta
2d84154226 web: show hamburger menu button on mobile 2025-07-21 12:09:58 +05:00
01zulfi
c4e306d569 web: fix nav pane on small screens
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-07-21 11:56:45 +05:00
Abdullah Atta
83b6c6de1c Merge pull request #8380 from streetwriters/ci/run-tests-on-pr-ref 2025-07-21 11:48:01 +05:00
Abdullah Atta
e86f7491ef Merge pull request #8380 from streetwriters/ci/run-tests-on-pr-ref
Run tests on pr ref instead of base branch
2025-07-21 11:47:27 +05:00
Abdullah Atta
5151d83af9 ci: run tests on pr ref instead of base branch 2025-07-21 11:38:30 +05:00
Abdullah Atta
e462cb0596 Merge pull request #8379 from streetwriters/docs/remove-onenote-sn-docs
Remove standard notes and one note importer docs
2025-07-21 11:30:52 +05:00
Abdullah Atta
a30c0e4608 docs(help): remove standard notes and one note importer docs 2025-07-21 11:30:32 +05:00
Abdullah Atta
dbe8c1b9e6 Merge pull request #8378 from streetwriters/ci/migrate-to-pr-target 2025-07-21 11:29:01 +05:00
Abdullah Atta
f90e7982f7 Merge pull request #8378 from streetwriters/ci/migrate-to-pr-target
Fix tests from PRs opened from external forks
2025-07-21 11:28:11 +05:00
Abdullah Atta
40c69d7cba ci: use pull_request_target with authorization hook where required 2025-07-21 11:26:03 +05:00
Abdullah Atta
c9e6f3e532 Merge pull request #8372 from streetwriters/fix/web-tests 2025-07-21 09:54:05 +05:00
Abdullah Atta
23ee50f688 Merge pull request #8372 from streetwriters/fix/web-tests
Fix web E2E tests
2025-07-21 09:53:05 +05:00
Abdullah Atta
a7c857fb71 desktop: increase hookTimeout ton 120 seconds 2025-07-21 09:35:39 +05:00
Abdullah Atta
0f6622360c desktop: ignore error on failure to remove test artifacts 2025-07-21 09:28:26 +05:00
Abdullah Atta
578bc6e546 desktop: build app only once during tests 2025-07-21 09:19:53 +05:00
Abdullah Atta
70fd038207 desktop: add build retrying when running tests 2025-07-21 08:57:16 +05:00
Abdullah Atta
b30110a48a desktop: add support for running tests in parallel
we do this by copying the build directory instead of building it over and over
again for each test. This also makes the tests super fast.
2025-07-19 15:05:24 +05:00
Abdullah Atta
21978c4c1d desktop: patch better-sqlite3-multiple-ciphers on each test build 2025-07-19 12:32:22 +05:00
Abdullah Atta
ec48f2350d desktop: run tests sequentially
this is required since each test builds a new app and on linux & windows that
can cause issues if done in parallel
2025-07-19 11:02:32 +05:00
Abdullah Atta
fe1e3bb847 desktop: migrate tests to vitest 3 2025-07-19 11:01:57 +05:00
Abdullah Atta
69776f26d8 desktop: upgrade to vitest 3 2025-07-19 11:01:42 +05:00
Abdullah Atta
ab4092c088 desktop: fix dialog skipping in tests 2025-07-19 09:43:39 +05:00
Abdullah Atta
4948a8d7de desktop: add test artifacts cleanup on test finish 2025-07-19 09:43:23 +05:00
Abdullah Atta
0a607bce18 web: increase app lock test timeouts 2025-07-19 08:51:29 +05:00
Abdullah Atta
e59820e3d6 web: fix adding a one-time reminder before current time should not be possible 2025-07-19 08:50:22 +05:00
Abdullah Atta
85a2d25c1b web: wait for reminder dialog to close before proceeding in tests 2025-07-18 15:06:59 +05:00
Abdullah Atta
3bc7fc84f9 web: fix `if note is active in multiple tabs, moving the note to trash should
close those tabs` test
2025-07-18 14:45:06 +05:00
Abdullah Atta
249ce1ecbb web: remove new line at eof in test snapshots 2025-07-18 13:02:03 +05:00
Abdullah Atta
be7f8d9916 ci: run tests based on affected files on pr open 2025-07-18 12:59:04 +05:00
Abdullah Atta
0a0495f1a7 config: include editor/src/extensions/code-block/languages to build output 2025-07-18 12:51:11 +05:00
Abdullah Atta
2f7afa8556 web: update readonly edited note snapshots for linux & windows 2025-07-18 12:44:45 +05:00
Abdullah Atta
2f40905372 Merge pull request #8366 from Scott-will/master 2025-07-18 12:31:52 +05:00
Abdullah Atta
a6d0177153 Merge pull request #8366 from Scott-will/master
editor: maintain relative cursor location when list is sorted
2025-07-18 12:29:13 +05:00
Scott-will
b9e24888e7 editor: maintain relative cursor location when list is sorted
Signed-off-by: Scott Williams scottwill1999@gmail.com
2025-07-16 14:01:40 -07:00
Abdullah Atta
976199e5c6 Merge pull request #8364 from 01zulfi/editor/fix-readonly-links 2025-07-16 11:51:51 +05:00
Abdullah Atta
9017dae664 Merge pull request #8364 from 01zulfi/editor/fix-readonly-links
editor: fix internal links opening in new tab in readonly notes
2025-07-16 11:50:58 +05:00
01zulfi
94acc241d9 editor: fix internal links opening in new tab in readonly notes
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-07-16 11:47:09 +05:00
Ammar Ahmed
765f3a476d mobile: release v3.2.9 2025-07-16 11:26:19 +05:00
01zulfi
449287e25a common: fix archive export (#8362)
* fix "_archive" folder generation for each archive note
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-07-16 11:07:20 +05:00
Ammar Ahmed
db2669d699 Merge branch 'fix-app-lauch-crash-pixel-device' into beta 2025-07-16 10:48:37 +05:00
Ammar Ahmed
2cdb916233 Merge pull request #8363 from streetwriters/fix-app-lauch-crash-pixel-device
mobile: fix crash on app launch on pixel devices
2025-07-16 10:47:16 +05:00
Ammar Ahmed
5f14261aba mobile: fix crash on app launch on pixel devices 2025-07-16 10:11:05 +05:00
Ammar Ahmed
5ae7855c7f Merge branch 'mobile-release-3.2.8' into beta 2025-07-16 09:38:58 +05:00
Ammar Ahmed
20138505c4 Merge pull request #8361 from streetwriters/mobile-release-3.2.8
mobile: release v3.2.8
2025-07-16 09:37:35 +05:00
Ammar Ahmed
49c09bfd85 mobile: release v3.2.8 2025-07-15 11:07:33 +05:00
Ammar Ahmed
d8ed47ddb8 Merge branch 'mobile-fix-sidebar-items-update' into beta 2025-07-15 10:58:16 +05:00
Ammar Ahmed
39bfc41d33 Merge branch 'mobile-fix-android-nav-bar' into beta 2025-07-15 10:58:07 +05:00
Ammar Ahmed
68a8ac588f Merge branch 'mobile-fix-color-tag-long-press-crash' into beta 2025-07-15 10:58:01 +05:00
Ammar Ahmed
49d9ece15a Merge branch 'mobile-fix-crash-on-move-notebook' into beta 2025-07-15 10:57:51 +05:00
Ammar Ahmed
475edf6732 Merge pull request #8356 from streetwriters/mobile-fix-sidebar-items-update
mobile: Fix sidebar items do not update after sync
2025-07-15 10:56:47 +05:00
Ammar Ahmed
76ea89b668 Merge pull request #8351 from streetwriters/mobile-fix-color-tag-long-press-crash
mobile: fix crash on long press color tag
2025-07-15 10:56:34 +05:00
Ammar Ahmed
56b3a8df6b Merge pull request #8349 from streetwriters/mobile-fix-android-nav-bar
mobile: fix nav bar handling on android 15 and above
2025-07-15 10:56:15 +05:00
Ammar Ahmed
e02de0c0f6 Merge pull request #8336 from streetwriters/mobile-fix-crash-on-move-notebook
Fix crash on moving notebook when no notebooks selected
2025-07-15 10:55:58 +05:00
Ammar Ahmed
84bfab2a72 mobile: fix sidebar items do not update after sync 2025-07-15 09:36:00 +05:00
Ammar Ahmed
a6825a2df2 mobile: fix bottom insets 2025-07-14 15:19:15 +05:00
Abdullah Atta
f9dc539057 Merge pull request #8318 from 01zulfi/web/dont-close-note-after-attachment-delete
web: don't close note after deleting its attachment
2025-07-14 13:33:08 +05:00
Abdullah Atta
833b40bdc3 Merge pull request #8350 from 01zulfi/web/hide-spell-checker-languages-on-mac 2025-07-14 12:58:11 +05:00
Abdullah Atta
9ba58d1a46 Merge pull request #8350 from 01zulfi/web/hide-spell-checker-languages-on-mac
web: hide spell checker language selector on mac os
2025-07-14 12:57:33 +05:00
Ammar Ahmed
29a99d3f97 mobile: fix crash on long press color tag 2025-07-14 12:48:58 +05:00
01zulfi
a8b6fe78ba web: hide spell checker language selector on mac os
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-07-14 12:42:49 +05:00
Ammar Ahmed
4abd69b460 mobile: fix nav bar handling on android 15 and above 2025-07-14 12:21:43 +05:00
01zulfi
0ca1d82861 web: don't close note after deleting its attachment
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-07-14 12:20:11 +05:00
Abdullah Atta
3dd25b9f83 Merge pull request #8348 from 01zulfi/web/fix-link-in-importer 2025-07-14 11:55:06 +05:00
Abdullah Atta
5c55b49976 Merge pull request #8348 from 01zulfi/web/fix-link-in-importer
web: fix github link in importer setting
2025-07-14 11:53:39 +05:00
01zulfi
c932961dd4 web: fix github link in importer setting
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-07-14 11:31:30 +05:00
Abdullah Atta
20cd5bef16 Merge pull request #8346 from 01zulfi/web/middle-click-new-note-button 2025-07-14 11:08:08 +05:00
Abdullah Atta
9b058bb17f Merge pull request #8345 from 01zulfi/web/fix-toolbar-bug 2025-07-14 11:07:49 +05:00
Abdullah Atta
47357c3e25 Merge pull request #8346 from 01zulfi/web/middle-click-new-note-button
web: create new tab on create note button's middle click
2025-07-14 10:52:12 +05:00
Abdullah Atta
3ec5a1cf2c Merge pull request #8345 from 01zulfi/web/fix-toolbar-bug
web: fix toolbar crash
2025-07-14 10:49:54 +05:00
01zulfi
13d8a7baf7 web: create new tab on create note button's middle click
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-07-14 09:21:19 +05:00
01zulfi
19b1e74d06 web: fix toolbar crash
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-07-14 09:12:16 +05:00
Ammar Ahmed
82de9b9b94 mobile: fix crash on moving notebook when no notebooks selected 2025-07-12 14:31:00 +05:00
Ammar Ahmed
2325f4e31c Merge branch 'mobile-release-3.2.7' into beta 2025-07-12 14:29:51 +05:00
Ammar Ahmed
867af58695 Merge pull request #8335 from streetwriters/mobile-release-3.2.7
mobile: release v3.2.7
2025-07-12 14:29:22 +05:00
Ammar Ahmed
cdd50f0258 mobile: release v3.2.7 2025-07-11 14:01:22 +05:00
Ammar Ahmed
8c8b92cc4e Merge pull request #8333 from streetwriters/mobile-fix-empty-note-bug
Fix notes open empty from notes list randomly
2025-07-11 13:57:47 +05:00
Ammar Ahmed
c0a3df0aa8 Merge branch 'mobile-fix-empty-note-bug' into beta 2025-07-11 13:57:12 +05:00
Ammar Ahmed
31dd1619f6 mobile: fix notes open empty from notes list 2025-07-11 12:54:39 +05:00
Abdullah Atta
ba6be6c84d web: bump version to v3.3.0-beta.0 2025-07-11 11:22:38 +05:00
Ammar Ahmed
b126b98eb0 Merge branch 'release-mobile-3.2.6' into beta 2025-07-11 11:16:05 +05:00
Ammar Ahmed
afb010e3ae Merge pull request #8331 from streetwriters/release-mobile-3.2.6
mobile: release v3.2.6
2025-07-11 11:15:19 +05:00
Abdullah Atta
f14e3d0f5e Merge pull request #8330 from 01zulfi/monograph/fix-api-host-on-client 2025-07-11 10:52:06 +05:00
Abdullah Atta
ddebdcda43 Merge pull request #8330 from 01zulfi/monograph/fix-api-host-on-client 2025-07-11 10:51:35 +05:00
01zulfi
29c69418e9 monograph: fix API_HOST on client
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-07-11 09:44:09 +05:00
Ammar Ahmed
3e565e5195 mobile: release v3.2.6 2025-07-08 14:42:46 +05:00
Ammar Ahmed
a13878d4a8 Merge branch 'mobile-fix-crash-on-boot-android' into beta 2025-07-08 14:40:24 +05:00
Ammar Ahmed
1b352d6162 Merge pull request #8320 from streetwriters/mobile-fix-crash-on-boot-android
Fix boot crash on android
2025-07-08 14:40:08 +05:00
Ammar Ahmed
258aa77cdd mobile: fix boot crash on android 2025-07-08 14:23:25 +05:00
Ammar Ahmed
bc8de87cda Merge branch 'mobile-fix-duplicate-body-notification' into beta 2025-07-08 12:25:52 +05:00
Ammar Ahmed
7789bd145c Merge pull request #8319 from streetwriters/mobile-fix-duplicate-body-notification
Fix reminder description duplicated in notification on iOS
2025-07-08 12:24:52 +05:00
Ammar Ahmed
c1457cc83f mobile: show description in notification body only 2025-07-08 12:20:40 +05:00
01zulfi
3ca0089ee8 web: add character, spaces, paragraphs count in status bar popup (#8311)
* web: add character, spaces, paragraphs count in status bar popup
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>

* web: refactor selected text stats logic
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>

* web: use PopupPresenter for note statistics popup
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>

* web: improve gettng text for counting characters
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-07-07 11:54:01 +05:00
Abdullah Atta
29c9476c16 web: fix recovery key not getting set during account recovery 2025-07-04 19:54:17 +05:00
01zulfi
9e72f51851 web: disable reveal in list option when focus mode active (#8297)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-07-04 19:49:34 +05:00
01zulfi
a349611a30 web: fix scroll to search result (#8290)
* web: (wip) fix scroll to search result
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>

* web: fix scroll to search result
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-07-03 12:16:25 +05:00
01zulfi
1cd21087c2 common: include archive in export (#8279)
* common: include archive in export
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>

* core: include archive state in md-frontmatter export
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-07-01 10:25:57 +05:00
01zulfi
eecb8f9c05 web: show color name tooltip in note properties panel (#8280)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-07-01 10:25:57 +05:00
Abdullah Atta
e36fd28f47 core: add support for fields in search (#8261)
* core: add support for field based searching

* core: add more fields

* core: add `tagged`, `colored`, `in_notebook` fields
2025-07-01 10:25:57 +05:00
01zulfi
7ce44f4d84 web: support compact search results view (#8269)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-07-01 10:25:57 +05:00
01zulfi
6d8e4e8ebc web: fix note create option in quick open dialog (#8263)
* open new tab when query empty
* use editor-store methods for note creation

Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-07-01 10:25:57 +05:00
01zulfi
deb507859a core: don't generate headline title if title was set during note creation (#8266)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-07-01 10:25:57 +05:00
01zulfi
a165675b2a web: fix update status height (#8267)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-07-01 10:25:57 +05:00
Ammar Ahmed
8b316d0abf mobile: release v3.2.5 2025-06-30 13:54:35 +05:00
Ammar Ahmed
def5059ff1 mobile: fix app stuck on logout on ios 2025-06-30 13:44:30 +05:00
Ammar Ahmed
e1febfae31 mobile: fix loading pdf screen not showing 2025-06-30 13:37:13 +05:00
Ammar Ahmed
82aa506902 mobile: fix pdf view gets stuck 2025-06-30 12:40:18 +05:00
Ammar Ahmed
de1aa40ecf mobile: fix sqlite3-fts5-html lib loading error on ios 2025-06-30 12:39:12 +05:00
Ammar Ahmed
53724b437e mobile: fix app store error invalid swift support 2025-06-28 14:24:46 +05:00
Ammar Ahmed
1592620141 mobile: release v3.2.4 2025-06-28 13:35:21 +05:00
Ammar Ahmed
28ef87a95b mobile: fix ts error 2025-06-28 13:33:24 +05:00
Ammar Ahmed
d4019eea99 mobile: fix sync taking too long to complete 2025-06-28 13:33:24 +05:00
Ammar Ahmed
d13b46cbba mobile: do not embed framework in appex on ios 2025-06-28 08:50:31 +05:00
Ammar Ahmed
f1eb215bb9 mobile: release v3.2.3 2025-06-27 14:11:28 +05:00
Ammar Ahmed
92c7e1a0c1 mobile: wrap add-reminder screen in keyboard avoiding view on ios 2025-06-27 13:54:50 +05:00
Ammar Ahmed
b81cc178b5 mobile: make add-reminder sheet a screen 2025-06-27 12:56:50 +05:00
Abdullah Atta
dd42b82dbf web: bump version to v3.2.3 2025-06-27 09:49:40 +05:00
Abdullah Atta
ca6b50081a web: remove navigating to Monographs test 2025-06-27 09:48:44 +05:00
Abdullah Atta
4fa27046bb global: update lockfiles 2025-06-27 09:44:46 +05:00
01zulfi
8cadc6eaa4 web: fix scrolling toolbar also scrolling editor (#8256)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-27 09:43:36 +05:00
Abdullah Atta
ccae629833 web: update sqlite3-fts5-html to 0.0.4 2025-06-27 09:43:36 +05:00
Abdullah Atta
4a1cbe632c desktop: update sqlite3-fts5-html to 0.0.4 2025-06-27 09:43:36 +05:00
Abdullah Atta
579813d93a core: update sqlite3-fts5-html to 0.0.4 2025-06-27 09:43:36 +05:00
01zulfi
00d00c02ea editor: don't clear nodes in clear formatting option (#8260)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-27 09:43:36 +05:00
Abdullah Atta
765949cc40 web: only subscribe to note title if its generated 2025-06-27 09:43:36 +05:00
01zulfi
87cea6a120 web: hide monograph list for not logged in users (#8258)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-27 09:43:36 +05:00
Ammar Ahmed
83526d4d46 mobile: fix android toolbar 2025-06-27 09:37:17 +05:00
Ammar Ahmed
fca4faa114 mobile: convert sheets with input to screens or simple modals 2025-06-27 09:36:26 +05:00
Ammar Ahmed
171628c7b9 mobile: fix sqlite fts5 2025-06-27 09:34:16 +05:00
Ammar Ahmed
d456132dd6 mobile: release v3.2.2 2025-06-21 13:24:24 +05:00
Abdullah Atta
4ac7941b6c web: bump version to v3.2.2 2025-06-21 13:03:04 +05:00
Abdullah Atta
e7f5463917 web: make trash actions multi selectable 2025-06-21 13:00:46 +05:00
Abdullah Atta
6e41ce459d common: bulk resolve notebooks & tags 2025-06-21 13:00:46 +05:00
Abdullah Atta
f5095fa643 core: fix hang when resolving recursive nested notebooks 2025-06-21 13:00:46 +05:00
Abdullah Atta
e6a5b85011 web: register fts5 extensions after db decryption 2025-06-21 13:00:46 +05:00
Abdullah Atta
409c5a2517 web: update sqlite to v3.49.2 2025-06-21 13:00:46 +05:00
Abdullah Atta
35cd6b101d desktop: update better-sqlite3-multiple-ciphers to v11.10.0 2025-06-21 13:00:46 +05:00
Ammar Ahmed
2440e28168 mobile: fix android toolbar hidden behind keyboard on android 15 2025-06-20 14:49:15 +05:00
Ammar Ahmed
0078d509c5 mobile: release v3.2.1 2025-06-18 11:25:33 +05:00
Ammar Ahmed
0c2d57716d mobile: fix app crash on android 15 & 16 2025-06-18 11:16:07 +05:00
Abdullah Atta
678aeb98c3 ci: release snap to stable track (instead of release track) 2025-06-18 10:35:56 +05:00
Abdullah Atta
5f422f4eb7 web: bump version to v3.2.1 2025-06-18 10:27:50 +05:00
Abdullah Atta
2b26524fcd web: bump version to v3.2.1-beta.0 2025-06-18 10:27:13 +05:00
Abdullah Atta
7326533cc1 ci: publish snap beta 2025-06-18 10:27:13 +05:00
Abdullah Atta
c8aae5be61 desktop: change snap base to core22 2025-06-18 10:27:13 +05:00
Abdullah Atta
be1a8bf849 docs: remove mention of importer.notesnook.com (#8218) 2025-06-17 13:59:38 +05:00
Ammar Ahmed
2ffc2a27a5 mobile: fix android build 2025-06-17 12:49:38 +05:00
Ammar Ahmed
b0a9f3320b mobile: fix ios workflow
Signed-off-by: Ammar Ahmed <40239442+ammarahm-ed@users.noreply.github.com>
2025-06-17 12:17:36 +05:00
Ammar Ahmed
0ef844f08c mobile: update pods 2025-06-17 11:58:48 +05:00
Abdullah Atta
bbe00b0f9a ci: disable snap on arm64 2025-06-17 11:56:42 +05:00
Ammar Ahmed
4dcaf70346 mobile: release v3.2.0 2025-06-17 11:45:39 +05:00
Abdullah Atta
76e5e3758a desktop: fix `'environment/DISABLE_WAYLAND' property does not match the
required schema`
2025-06-17 11:42:58 +05:00
Abdullah Atta
f460772d75 web: bump version to v3.2.0 2025-06-17 11:01:02 +05:00
Abdullah Atta
1cf1605564 core: fix small tokens ignored from query 2025-06-17 10:49:42 +05:00
01zulfi
0abbd41ff2 web: fix archived notes showing in search results (#8216)
* web: fix archived notes showing in search results
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>

* core: make notes param required in lookup.notesWithHighlighting
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-17 10:26:15 +05:00
Abdullah Atta
f16818ea93 web: fix tag navigation from editor 2025-06-17 10:26:15 +05:00
Abdullah Atta
719ab6dff3 web: fix ui glitch in note linking dialog 2025-06-17 10:26:15 +05:00
01zulfi
ed50d8041e editor: fix failing snapshot tests (#8215)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-17 10:26:15 +05:00
01zulfi
9a0de8dff8 web: fix navigating to notebooks & tags from note item (#8211)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-17 10:26:15 +05:00
01zulfi
caba714798 core: fix notebooks parentId() tests (#8213)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-17 10:26:15 +05:00
01zulfi
154cf897b3 web: fix move notebook dialog (#8214)
* also use db.notebooks.parentId()

Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-17 10:26:15 +05:00
Abdullah Atta
323e53a1ef global: regenerate package-lock files to fix CI (#8212) 2025-06-17 09:44:35 +05:00
Ammar Ahmed
9b097cf233 mobile: update deps 2025-06-16 14:52:06 +05:00
Ammar Ahmed
75cb2fe194 mobile: fix pin and unpin from notifications 2025-06-16 14:09:45 +05:00
Ammar Ahmed
7aa975457c mobile: support android 16 2025-06-16 14:09:45 +05:00
Abdullah Atta
1932d27f1c core: fix group header for search results hidden 2025-06-16 14:09:45 +05:00
01zulfi
f226bdbff1 docs: add monograph size limit (#8206)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-16 14:09:45 +05:00
Abdullah Atta
7843943130 web: bump version to v3.2.0-beta.9 2025-06-16 14:09:45 +05:00
Abdullah Atta
a92afab3fc core: remove search results count
it was inaccurate and confused users
2025-06-16 14:09:45 +05:00
Abdullah Atta
1354ee683f web: reduce trial2pro discount to 30% 2025-06-16 14:09:45 +05:00
Abdullah Atta
891e311374 desktop: do not use native menu for tag suggestions on macos 2025-06-16 14:09:45 +05:00
Ammar Ahmed
881099c2c9 mobile: release beta 4 2025-06-16 14:09:45 +05:00
Ammar Ahmed
2dde6b6150 mobile: make adding notebook a dialog
* make manage tags sheet a screen
2025-06-16 14:09:45 +05:00
Abdullah Atta
a1f75dfed3 editor: fix search popup removed on link hover 2025-06-16 14:09:45 +05:00
Abdullah Atta
493ee81c42 core: fix search results sorting not working 2025-06-16 14:09:45 +05:00
Abdullah Atta
7109a36006 web: bump version to v3.2.0-beta.8 2025-06-16 14:09:45 +05:00
Abdullah Atta
6fccac9aea core: take into account boolean parameters in query 2025-06-16 14:09:45 +05:00
Ammar Ahmed
fa43f97bb4 mobile: default tag 2025-06-16 14:09:45 +05:00
01zulfi
e3a973d61e web: fix navigation commands in command palette (#8070)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-16 14:09:45 +05:00
01zulfi
542a628435 web: add move notebook dialog (#8099)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
Co-authored-by: Abdullah Atta <abdullahatta@streetwriters.co>
2025-06-16 14:09:45 +05:00
Ammar Ahmed
fdd25a11e7 mobile: fix ci build 2025-06-16 14:09:45 +05:00
Abdullah Atta
449ae78700 web: bump version to v3.2.0-beta.7 2025-06-16 14:09:45 +05:00
Ammar Ahmed
6bda4a9a73 mobile: fix mmkv patch 2025-06-16 14:09:27 +05:00
Ammar Ahmed
2d316ed1ec mobile: beta release 2025-06-16 14:09:27 +05:00
Abdullah Atta
570ae00453 core: fix false positives appearing in search 2025-06-16 14:09:27 +05:00
Ammar Ahmed
c845f7c1e1 mobile: update deps 2025-06-16 14:09:27 +05:00
Abdullah Atta
659e963b39 core: remove porter tokenizer for stemming
it didn't work very well. It was stemming things like "one" into "on"
2025-06-16 14:09:27 +05:00
Ammar Ahmed
63b8f7ef91 mobile: fix key missing warning in search-result item 2025-06-16 14:09:27 +05:00
Abdullah Atta
841e229866 core: fix lookup tests 2025-06-16 14:09:27 +05:00
Abdullah Atta
4098a27df0 core: update htmlparser2 2025-06-16 14:09:27 +05:00
Ammar Ahmed
918824f26b core: skip decodine entities when parsing html 2025-06-16 14:09:27 +05:00
Ammar Ahmed
83735705d2 mobile: update lockfiles 2025-06-16 14:09:27 +05:00
Ammar Ahmed
8ac6ccb701 mobile: fix android build 2025-06-16 14:09:27 +05:00
Ammar Ahmed
9ae00db676 mobile: fix ios build on rn 77 2025-06-16 14:09:27 +05:00
Ammar Ahmed
c389a1ce4d mobile: update fts5-html patch 2025-06-16 14:09:27 +05:00
Ammar Ahmed
817a58611e mobile: remove patch 2025-06-16 14:09:27 +05:00
Ammar Ahmed
bfa0f09fa0 mobile: update patches 2025-06-16 14:09:27 +05:00
Ammar Ahmed
0e461c19ed mobile: upgrade to RN 0.77.2 2025-06-16 14:09:27 +05:00
Abdullah Atta
7b289f8e58 core: sort content matches 2025-06-16 14:09:27 +05:00
Abdullah Atta
071052ce37 core: only expand matching callout & outline list items 2025-06-16 14:09:27 +05:00
Abdullah Atta
ec6ad79586 ci: fix prerelease not setting correctly on gh release 2025-06-16 14:09:27 +05:00
Abdullah Atta
96205fd5b7 web: bump version to 3.2.0-beta.6 2025-06-16 14:09:27 +05:00
01zulfi
4028a29bdb web: add support for setting a tag as default (#8060)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-16 14:09:27 +05:00
01zulfi
d812024c25 editor: remove styling for sibling elements of double spaced paragraphs (#8144)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-16 14:09:27 +05:00
Ammar Ahmed
92f4e33ac7 mobile: release new beta 2025-06-16 14:09:27 +05:00
Ammar Ahmed
ad056e0e3b mobile: skip rendering if query changed during search 2025-06-16 14:09:27 +05:00
Abdullah Atta
dc40601fb5 web: discard results if query changed during search 2025-06-16 14:09:27 +05:00
Abdullah Atta
65f3338df4 core: auto expand outline & callout in search result 2025-06-16 14:09:27 +05:00
Abdullah Atta
4f9a5cb074 core: fix phrase queries not getting highlighted 2025-06-16 14:09:27 +05:00
Abdullah Atta
eb550e95dc web: fix click on match no opening note at desired location 2025-06-16 14:09:27 +05:00
Ammar Ahmed
84dbab5bdf mobile: enable regexp in sqlite 2025-06-16 14:09:27 +05:00
Ammar Ahmed
c2aff26dfc mobile: fix tab gets focused in loop 2025-06-16 14:09:27 +05:00
Abdullah Atta
5dd9ce9f25 desktop: add SQLITE_ENABLE_REGEXP define to better-sqlite3 2025-06-16 14:09:27 +05:00
Abdullah Atta
e5998f51e9 desktop: do not gitignore *.patch 2025-06-16 14:09:27 +05:00
Abdullah Atta
538f1f1910 web: bump version to 3.2.0-beta.5 2025-06-16 14:09:27 +05:00
Abdullah Atta
9c2fa4eb30 core: use intl for showing search results count 2025-06-16 14:09:26 +05:00
Abdullah Atta
ab04b13582 core: install @notesnook/intl 2025-06-16 14:09:26 +05:00
Abdullah Atta
a6ef69905e web: use plain list instead of tree for showing search results 2025-06-16 14:09:26 +05:00
Abdullah Atta
565a2396f1 web: enable regexp in sqlite 2025-06-16 14:09:26 +05:00
Abdullah Atta
5a395aca3c desktop: enable regexp in sqlite 2025-06-16 14:09:26 +05:00
Abdullah Atta
f99ee88499 core: speed up search 2025-06-16 14:09:26 +05:00
Ammar Ahmed
dc7e5dfa50 core: fix stop-words import 2025-06-16 14:09:26 +05:00
Abdullah Atta
4f1bb994f2 core: filter out stop words in search query 2025-06-16 14:09:26 +05:00
Abdullah Atta
6357a8f3a1 web: bump version to v3.2.0-beta.4 2025-06-16 14:09:26 +05:00
Abdullah Atta
6c083bd76d ci: build desktop app on ubuntu-22-04
this fixes `Error: /lib/x86_64-linux-gnu/libm.so.6: version `GLIBC_2.38'
not found` error
2025-06-16 14:09:26 +05:00
Abdullah Atta
c53fbb7441 web: fix editor not jumping to search result 2025-06-16 14:09:26 +05:00
Abdullah Atta
6c28075070 web: fix various type errors causing crashes 2025-06-16 14:09:26 +05:00
Abdullah Atta
bb027c6f25 core: bring back limit in lookup 2025-06-16 14:09:12 +05:00
Ammar Ahmed
7dc5daffe8 mobile: release v3.2.0-beta.1 2025-06-16 14:09:12 +05:00
Ammar Ahmed
3e4862d768 mobile: fix note search 2025-06-16 14:09:12 +05:00
Abdullah Atta
29b0c2eeda web: use notesWithHighlighting for full notes search 2025-06-16 14:09:12 +05:00
Abdullah Atta
08e5f889f8 core: bring back old notes search 2025-06-16 14:09:12 +05:00
Ammar Ahmed
bc198b4cd7 mobile: release v3.2.0-beta.0 2025-06-16 14:09:12 +05:00
Abdullah Atta
5c71b77b98 web: bump version to 3.2.0-beta.3 2025-06-16 14:09:12 +05:00
Ammar Ahmed
5660178760 mobile: search and sorting 2025-06-16 14:08:56 +05:00
Abdullah Atta
8dac907ead web: localize search results count 2025-06-16 14:08:56 +05:00
Abdullah Atta
5b7c8eaa70 web: hide search results on editor focus & search cancel 2025-06-16 14:08:55 +05:00
Abdullah Atta
7ab4a2210a editor: make search results style toggleable 2025-06-16 14:08:55 +05:00
Abdullah Atta
c861b11c5f web: fix note not scrolling to selected match 2025-06-16 14:08:55 +05:00
Abdullah Atta
4f540dfdcb web: fix note not opening from search results if its already opened 2025-06-16 14:08:55 +05:00
Abdullah Atta
0e0add2f71 web: use same search ux for notes everywhere 2025-06-16 14:08:55 +05:00
Abdullah Atta
29edb3a3c3 web: improve search results ui 2025-06-16 14:08:55 +05:00
Abdullah Atta
ff723e5c78 core: improve prefix/suffix generation for matches 2025-06-16 14:08:55 +05:00
Abdullah Atta
ea76929c80 web: add full support for highlighting results in notes search 2025-06-16 14:08:55 +05:00
Abdullah Atta
5d4d84bded editor: add support for nn-search-result node 2025-06-16 14:08:55 +05:00
Abdullah Atta
0faf267735 core: add raw html content with highlighting in results 2025-06-16 14:08:55 +05:00
Abdullah Atta
197e95e66f web: add support for highlighting in search results 2025-06-16 14:08:55 +05:00
Abdullah Atta
9d4ae71bfe core: add console.time tracing for notes search 2025-06-16 14:08:55 +05:00
Abdullah Atta
422869c3d2 core: improve search results highlighting 2025-06-16 14:08:55 +05:00
Abdullah Atta
b7d478088b core: fix title matches not merged when query contains short tokens 2025-06-16 14:08:55 +05:00
Abdullah Atta
1827cbeb93 core: bring back search result sorting for notes 2025-06-16 14:08:55 +05:00
Abdullah Atta
66041a45f6 core: add support for highlighting search results 2025-06-16 14:08:55 +05:00
Ammar Ahmed
ccb0c858a2 mobile: fix archive count not shown 2025-06-16 14:08:55 +05:00
Ammar Ahmed
659b937852 mobile: update fts5-html lib 2025-06-16 14:08:55 +05:00
Ammar Ahmed
de48cea9eb mobile: support sorting search results 2025-06-16 14:08:55 +05:00
Abdullah Atta
404e3147b0 core: add a new migration to reindex fts5 2025-06-16 14:08:55 +05:00
Abdullah Atta
c0d64ff674 web: update sqlite3-fts5-html to v0.0.3 2025-06-16 14:08:55 +05:00
Abdullah Atta
bbcce64549 web: show date created on search results if sort by is set to date created 2025-06-16 14:08:55 +05:00
Abdullah Atta
1ca30b8a5b web: add support for sorting in search 2025-06-16 14:08:55 +05:00
Abdullah Atta
22b037ea1d core: add support for sortable search 2025-06-16 14:08:55 +05:00
01zulfi
2d74e3d4c0 editor: support ctrl/cmd+click to open internal links in new tab (#8131)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-16 14:08:55 +05:00
01zulfi
1be0e4790e web: add 'move to top' for sub-notebooks (#8066)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-16 14:08:55 +05:00
Ammar Ahmed
3770091b58 mobile: handle crash in background on device boot 2025-06-16 14:08:55 +05:00
Ammar Ahmed
0c86f11e21 mobile: fix new reminder title/headline is not autofill 2025-06-16 14:08:55 +05:00
Ammar Ahmed
73bf283fd7 mobile: add line break when appending to note 2025-06-16 14:08:55 +05:00
Ammar Ahmed
208bd13cdd mobile: fix crash in settings -> user subscription 2025-06-16 14:08:55 +05:00
01zulfi
42887a1dd5 web: persist double spaced lines config on logout (#8097)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-16 14:08:55 +05:00
01zulfi
0ec2f07be0 web: fix readonly note not locking when vault is locked (#8092)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-16 14:08:55 +05:00
01zulfi
82b70d2951 web: add support for drag/dropping notes on tab strip (#8090)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-16 14:08:55 +05:00
Abdullah Atta
8da961f300 web: bump version to 3.2.0-beta.2 2025-06-16 14:08:55 +05:00
Abdullah Atta
4fba380f2d core: fix `expected previously executed migration 2 to be at index 1 but
10 was found in its place.`
2025-06-16 14:08:54 +05:00
01zulfi
e1b046ec0c core: fix db.settings.getTrashCleanupInterval return type (#8076)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-16 14:08:54 +05:00
01zulfi
5d01159e20 web: add support for removing recents in command palette using delete key (#8069)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-16 14:08:54 +05:00
01zulfi
aeef53df55 web: press shift+enter to create note in quick open (#8068)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-16 14:08:54 +05:00
Ammar Ahmed
29433c4149 editor: fix alignment items in callout heading (#8101)
* editor: fix alignment items in callout heading

* Update packages/editor/styles/styles.css

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

---------

Signed-off-by: Abdullah Atta <thecodrr@protonmail.com>
Co-authored-by: Abdullah Atta <abdullahatta@streetwriters.co>
2025-06-16 14:08:54 +05:00
Abdullah Atta
0edac2ee9d desktop: update patched better-sqlite3-multiple-ciphers to 11.6.1 2025-06-16 14:08:54 +05:00
Abdullah Atta
4607dc3084 global: regenerate package-lock.json for theme & ui packages 2025-06-16 14:08:54 +05:00
Ammar Ahmed
41babda9b7 mobile: fix error in build 2025-06-16 14:08:54 +05:00
Ammar Ahmed
0fec38610c mobile: add option to disable auto update check 2025-06-16 14:08:54 +05:00
Abdullah Atta
3ecc43d976 misc: include @notesnook/theme package when generating flatpak sources 2025-06-16 14:08:54 +05:00
Abdullah Atta
9730560fb7 desktop: downgrade playwright 2025-06-16 14:08:54 +05:00
Abdullah Atta
6c0e51dc9d desktop: fix flatpak sources generation 2025-06-16 14:08:54 +05:00
Abdullah Atta
2a313a0026 desktop: regenerate package-lock.json 2025-06-16 14:08:54 +05:00
Abdullah Atta
5d4e60b829 web: update package-lock.json 2025-06-16 14:08:54 +05:00
Abdullah Atta
c0666d8547 global: fix dependencies version differences 2025-06-16 14:08:24 +05:00
Abdullah Atta
a5fa261e3b global: update package-lock.json 2025-06-16 14:08:24 +05:00
Ammar Ahmed
fa8aa4d88f mobile: archive notes 2025-06-16 14:08:24 +05:00
Abdullah Atta
b63be2de15 web: bump version to 3.2.0-beta.1 2025-06-16 14:08:24 +05:00
Abdullah Atta
173caf41d0 core: fix query-transformer tests 2025-06-16 14:08:24 +05:00
Ammar Ahmed
30e4f55218 mobile: add sqlite3-fts5-html module 2025-06-16 14:08:24 +05:00
Abdullah Atta
f3895f534e desktop: install sqlite3-fts5-html 2025-06-16 14:08:24 +05:00
Abdullah Atta
ea14db77de web: update wa-sqlite to use sqlite3-fts5-html for stripping html 2025-06-16 14:08:24 +05:00
Abdullah Atta
9bb48f4896 core: fix short queries search 2025-06-16 14:08:24 +05:00
Abdullah Atta
62b5cc853b core: remove @orama/stopwords 2025-06-16 14:08:24 +05:00
Abdullah Atta
90900628a2 core: strip html when searching notes
this commit also properly fixes search queries containing
words less than 3 characters in length
2025-06-16 14:08:24 +05:00
Abdullah Atta
ebf98bc652 core: fix warnings in tests 2025-06-16 14:08:24 +05:00
Ammar Ahmed
ddd3fe6ac5 mobile: update better trigram 2025-06-16 14:08:24 +05:00
Abdullah Atta
2964e7a8f0 core: fix db migration 2025-06-16 14:08:24 +05:00
Abdullah Atta
f6d1f5890a core: wrap query with invalid symbols in quotes 2025-06-16 14:08:24 +05:00
Abdullah Atta
1cc0cf19c8 core: update sqlite-better-trigram to v0.0.3 2025-06-16 14:08:24 +05:00
01zulfi
efc4f3566a core: fix trash cleanup interval setting retrieval (#8045)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-16 14:08:06 +05:00
01zulfi
85b7760e1e web: add more archive test cases (#8040)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-16 14:08:06 +05:00
Abdullah Atta
40ee0ecf47 desktop: no need to externalize @resvg/resvg-js 2025-06-16 14:08:06 +05:00
Abdullah Atta
513c9ee8a7 desktop: remove icon from native menu 2025-06-16 14:08:06 +05:00
Abdullah Atta
2aacadc24d desktop: only show native menus on macos 2025-06-16 14:08:06 +05:00
Abdullah Atta
716bb67b96 desktop: show native menus where possible 2025-06-16 14:08:06 +05:00
01zulfi
916b6a17aa web: assign accent color to links (#8041)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-16 14:08:06 +05:00
Abdullah Atta
813401ea91 desktop: update packages 2025-06-16 14:08:06 +05:00
01zulfi
70e5efbcea desktop: upgrade electron to v34.0.0 (#8038)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-16 14:07:44 +05:00
01zulfi
6c8dc223f2 web: fix automatic backup reminder setting reverting to never (#8037)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-16 14:07:44 +05:00
01zulfi
5b09528e7e web: fix focus last active tab method (#8034)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-16 14:07:44 +05:00
01zulfi
5de5ffe068 editor: improve hover link popup position (#8011)
* move it down so it doesn't block the link

Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-16 14:07:44 +05:00
Abdullah Atta
1b511c8ddd web: bump version to 3.2.0-beta.0 2025-06-16 14:07:44 +05:00
Abdullah Atta
68d1a3f50e web: update @notesnook-imoporter/core to 2.2.2 2025-06-16 14:06:37 +05:00
01zulfi
74edd466d4 web: fix notestore is not defined error (#8012)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-16 14:05:54 +05:00
Abdullah Atta
34aa21790c web: update @notesnook-importer/core to 2.2.1 2025-06-16 14:05:54 +05:00
01zulfi
e7ec9e2aa3 web: add support for archiving notes (#7810)
* web: archive notes
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>

* global: arhives -> archived
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-06-16 14:05:54 +05:00
tarynlucia
20bbb6dd5b ui: correct grammar in vault creation message (issue #7497) (#8188)
Signed-off-by: Taryn Eng <taryn.eng@gmail.com>
2025-06-10 11:18:11 +05:00
Abdullah Atta
f937b164e9 web: update lockfile 2025-06-06 11:16:34 +05:00
Abdullah Atta
5b4e888ddd web: fix infinite rerenders on checkout screen 2025-06-06 11:01:14 +05:00
Abdullah Atta
410d983842 web: chore bump version to v3.1.1 2025-05-22 11:27:10 +05:00
Abdullah Atta
16cd92f03a web: fix flicker when programatically updating title 2025-05-22 11:20:58 +05:00
Abdullah Atta
c6ee1e6303 core: do not allow empty titles 2025-05-22 11:20:44 +05:00
SB
0f00d0e508 docs: add missing '-' in build-steps for MacOS and Linux (AppImage) 2025-05-16 10:12:24 +05:00
01zulfi
21fdc39db7 web: fix list pane not expanding (#7963)
* web: fix list pane not expanding
* fix list pane not expanding to saved width on reload
* fix list pane not expanding to saved width on collapse

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

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

---------

Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-04-29 12:51:19 +05:00
01zulfi
bb5d5a5731 core: segregate logic for note headline and note headline title generation (#7968)
* core: segregate logic for note headline and note headline title generation
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>

* core: minor refactor note headline title
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-04-29 09:27:35 +05:00
Ammar Ahmed
bf5e68a82e ci: fix build ios
Signed-off-by: Ammar Ahmed <40239442+ammarahm-ed@users.noreply.github.com>
2025-04-28 14:03:48 +05:00
Ammar Ahmed
cc7f479627 ci: fix build ios
Signed-off-by: Ammar Ahmed <40239442+ammarahm-ed@users.noreply.github.com>
2025-04-28 13:53:21 +05:00
Ammar Ahmed
9eb183f6b5 ci: fix build ios
Signed-off-by: Ammar Ahmed <40239442+ammarahm-ed@users.noreply.github.com>
2025-04-28 13:42:39 +05:00
Ammar Ahmed
cb29d71619 mobile: fix crash when going from trash -> search 2025-04-28 12:30:50 +05:00
Ammar Ahmed
a6120ed90f mobile: release v3.1.1 2025-04-28 12:26:46 +05:00
Ammar Ahmed
48040c955d mobile: fix crash on delete item 2025-04-28 12:26:12 +05:00
Ammar Ahmed
18b43882e1 mobile: fix crash in list 2025-04-28 11:36:48 +05:00
Ammar Ahmed
37dc409b60 mobile: fix cursor bug on ios 2025-04-28 11:36:37 +05:00
Ammar Ahmed
8ab05c5a98 mobile: fix typing in editor title input 2025-04-28 11:36:27 +05:00
Abdullah Atta
38509c66c5 web: update @notesnook-importer/core to 2.2.0 2025-04-25 14:33:32 +05:00
Abdullah Atta
fc40a05254 web: open settings with importer page instead of importer.notesnook.com 2025-04-25 14:33:32 +05:00
Ammar Ahmed
8078c3ed3c mobile: fix default font setting not followed 2025-04-25 11:51:28 +05:00
01zulfi
57280f3ebb web: make nav menu header draggable (#7985)
* web: make part of nav menu header draggable
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>

* Update apps/web/src/app.css

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

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

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

---------

Signed-off-by: Abdullah Atta <thecodrr@protonmail.com>
Co-authored-by: Abdullah Atta <thecodrr@protonmail.com>
2025-04-25 11:21:16 +05:00
Ammar Ahmed
dc54644b4f mobile: remove READ_MEDIA_IMAGES permission 2025-04-24 15:29:58 +05:00
Abdullah Atta
ce31b0495d web: refresh app after import 2025-04-24 14:39:15 +05:00
Abdullah Atta
a62d4b5d4b web: move importer into web/desktop app (#7472)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-04-24 13:20:06 +05:00
Abdullah Atta
6f585c5e17 web: validate release track on app launch 2025-04-24 12:39:51 +05:00
Abdullah Atta
ffe7d944a6 web: use separate service worker cache for each app version 2025-04-24 12:39:51 +05:00
Abdullah Atta
bf0d6857d3 web: improve update installation 2025-04-24 12:39:51 +05:00
Ammar Ahmed
69f117bab7 mobile: fix swipe active offsets 2025-04-24 11:45:08 +05:00
Ammar Ahmed
cac945501d ci: fix release workflow
Signed-off-by: Ammar Ahmed <40239442+ammarahm-ed@users.noreply.github.com>
2025-04-22 16:34:21 +05:00
Abdullah Atta
85a0762ccf web: update test snapshots 2025-04-22 12:37:08 +05:00
Abdullah Atta
0ce51bf481 web: fix tests 2025-04-22 12:25:39 +05:00
Abdullah Atta
6adc5065fb Merge v3.1.0 from streetwriters/beta 2025-04-22 12:06:04 +05:00
Ammar Ahmed
3b90a6d90e mobile: release v3.1.0 2025-04-22 12:00:24 +05:00
Abdullah Atta
aa5e6e7199 web: remove duplicate item in changelog 2025-04-22 11:47:16 +05:00
Abdullah Atta
ca53ec38d1 web: add more items in changelog 2025-04-22 11:46:39 +05:00
Abdullah Atta
80a3cc2fc1 web: conform notebook header with mobile ui 2025-04-22 11:42:43 +05:00
Ammar Ahmed
32c4e987dc mobile: fix crash in reminder notify sheet 2025-04-22 11:16:35 +05:00
Ammar Ahmed
ce0ef0a1cf mobile: hide keyboard when app is locked 2025-04-22 11:16:35 +05:00
Abdullah Atta
95fc9bd3d0 web: bump version to 3.1.0 2025-04-22 11:10:04 +05:00
Ammar Ahmed
fb21fef82f mobile: fix invalid tags linked to note from share menu 2025-04-21 12:34:48 +05:00
Ammar Ahmed
7760f5e898 mobile: fix sorting trash 2025-04-21 12:34:48 +05:00
Ammar Ahmed
fcc9915b04 mobile: fix focused route id incorrect 2025-04-21 12:34:48 +05:00
Abdullah Atta
8347dd5db7 common: remove limit on resolve tags & notebook in note 2025-04-21 12:26:10 +05:00
01zulfi
c2d3ba087a web: reduce snapSize of nav & list panes (#7951)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-04-21 11:39:30 +05:00
Abdullah Atta
e5883f179c web: fix search tests 2025-04-21 11:26:35 +05:00
Abdullah Atta
f7f1d3b3f0 web: fix crash on entering focus mode 2025-04-21 11:26:21 +05:00
Abdullah Atta
df3674f570 web: check if user is premium in behavior settings 2025-04-21 10:54:20 +05:00
01zulfi
a62beab172 web: show reset search button only when query text present (#7950)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-04-21 10:54:04 +05:00
01zulfi
528810155f web: fix toc bugs (#7775)
* fix duplicate headings showing in toc view
* fix negative level for some headings

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

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

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

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

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

---------

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

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

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

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

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

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

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

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

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

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

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

---------

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

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

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

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

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

* web: only update title input if note title changes

---------

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

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

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

---------

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

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

* web: fix focusing pinned tab after reloading app

---------

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

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

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

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

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

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

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

---------

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

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

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

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

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

* web: remove newlines in title textarea

---------

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

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

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

Issue #7431

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

This PR fixes two issues:

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

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

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

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

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

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

* intl: fix `Cannot find module '@lingui/macro'`

* web: fix `I18n' is not assignable to parameter` type error

* setup: log post install cmd

* setup: more logging

* web: update lockfile
2025-01-21 09:35:38 +05:00
Ammar Ahmed
a13cbadd44 feat: new widgets on android (#7311)
- Added a new widget on android that allows you to put a note on your home screen.
- Added a new widget on android that allows you to see upcoming reminders on home screen
- Fixed new note widget freezing
2025-01-20 17:17:01 +05:00
Abdullah Atta
aa993a2fce web: bump version to 3.0.24 2025-01-20 13:26:50 +05:00
01zulfi
975af5701b web: fix reveal in list (#7297)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-01-20 12:08:13 +05:00
luis-411
3add56cfe4 global: fix search strings (#7302)
Signed-off-by: Luis Kriner <luis@kriner.info>
2025-01-20 11:47:48 +05:00
Abdullah Atta
522ea1520d web: fix tests failing on macos 2025-01-20 11:28:26 +05:00
Ammar Ahmed
c680121eb0 mobile: always load note content in editor 2025-01-20 10:38:16 +05:00
Ammar Ahmed
a9de0696c9 mobile: fix image previews not loading on ios 2025-01-20 10:38:00 +05:00
Ammar Ahmed
4a4c52e4c8 mobile: fix material menu 2025-01-20 10:37:39 +05:00
Ammar Ahmed
92f5e04788 mobile: fix lock state detection in sheets and dialogs 2025-01-20 10:37:26 +05:00
Ammar Ahmed
0cad098551 mobile: fix selecting image from gallery when applock is on 2025-01-20 10:37:26 +05:00
Abdullah Atta
46105b2175 web: fix web app on Safari 2025-01-20 10:35:23 +05:00
Abdullah Atta
8ffbda9626 Revert "editor: update tiptap to v2.10.4 (#6872)"
This reverts commit 800f3ca5d3.
2025-01-20 10:20:15 +05:00
Ammar Ahmed
1fc55a69c9 editor: fix clamped image size is larger than editor (#7324) 2025-01-20 10:07:20 +05:00
Ammar Ahmed
c417d4df91 core: fix DATE_TIME_STRIP_REGEX (#7325) 2025-01-20 10:06:26 +05:00
01zulfi
43ccf72773 intl: fix follow casing (#7342)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-01-18 11:38:20 +05:00
01zulfi
a177d36571 web: treat setting item descriptions as md and convert them to html (#7343)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-01-18 11:37:54 +05:00
01zulfi
4428ccd3a0 web: add lock app button in status bar (#7333)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-01-17 11:35:13 +05:00
01zulfi
218ffbd758 intl: fix referencedIn casing (#7334)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-01-17 11:24:11 +05:00
01zulfi
5ace95c9d1 web: fix canceling the edit profile dialog would set name to undefined (#7338)
* escaping or canceling the dialog would set profile's name to undefined

Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-01-17 11:21:18 +05:00
Ammar Ahmed
77a2f86119 mobile: fix trash interval picker text showing NaN 2025-01-14 12:02:16 +05:00
01zulfi
71db85458d web: add go to next/previous tab shortcut (#7109)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-01-02 15:13:49 +05:00
01zulfi
0be59c71de web: save image compression upload setting (#7089)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2025-01-02 15:10:58 +05:00
Abdullah Atta
2357e3de0b web: title bar underlay not showing on mac 2025-01-02 14:15:09 +05:00
Abdullah Atta
53b89a59ed web: fix integrated titlebar on windows 2025-01-02 14:15:09 +05:00
Abdullah Atta
202c9135c2 web: show exclusive titlebar in tablet/mobile mode 2025-01-02 14:15:09 +05:00
Abdullah Atta
69e6263d34 web: better integrated titlebar that looks same across platforms 2025-01-02 14:15:09 +05:00
Abdullah Atta
ebe830bbcc theme: add new borderless input variant 2025-01-02 14:15:09 +05:00
Abdullah Atta
44bb9752d2 web: improve slider ux on mobile & small screens 2025-01-02 14:15:09 +05:00
Abdullah Atta
2f6af50fe2 web: split pane now supports adding/removing panes in place 2025-01-02 14:15:09 +05:00
Ammar Ahmed
1d80ca7d3c mobile: release v3.0.26 2024-12-31 14:03:49 +05:00
Ammar Ahmed
d33baebac8 editor: fix frame around image on selection 2024-12-31 13:21:47 +05:00
Ammar Ahmed
25aaef361a mobile: throw error if db key not found in keychain 2024-12-31 12:50:38 +05:00
Abdullah Atta
f3af39a093 web: fix action bar ui on web 2024-12-30 16:12:19 +05:00
Abdullah Atta
149c2013a2 editor: fix multiple editor views being created 2024-12-30 16:05:28 +05:00
Ammar Ahmed
8fb0b6f94a mobile: fix build errors in editor-mobile 2024-12-30 15:44:57 +05:00
Ammar Ahmed
f09e5cadcf mobile: fix image and file uploads 2024-12-30 15:44:57 +05:00
Ammar Ahmed
724c69655b mobile: fix scroll jumping in realtime sync 2024-12-30 15:44:41 +05:00
Abdullah Atta
800f3ca5d3 editor: update tiptap to v2.10.4 (#6872)
* editor: update tiptap to v2.9.1

* editor: update tiptap & pkgs to 2.10.4

* editor: update test snapshots
2024-12-30 14:51:50 +05:00
Abdullah Atta
193007370a web: add experimental support for responsive pane resizing 2024-12-30 11:56:42 +05:00
Abdullah Atta
c8aff3764b web: lots of improvements 2024-12-30 11:56:42 +05:00
Abdullah Atta
d72b502977 web: fix snapping logic 2024-12-30 11:56:42 +05:00
Abdullah Atta
263c970320 web: add support for macOS like pane resizing logic 2024-12-30 11:56:42 +05:00
Abdullah Atta
aeebc9878d web: only reset size of doubled clicked pane 2024-12-30 11:56:42 +05:00
Abdullah Atta
4f37c92ecd web: add snapping support 2024-12-30 11:56:42 +05:00
Abdullah Atta
3180a88ef0 web: replace react-resizable-panels with custom implementation 2024-12-30 11:56:42 +05:00
01zulfi
6672db6ac2 editor: add markdown shortcut for checklist (#7087)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2024-12-30 11:17:18 +05:00
01zulfi
b6da62469e core: fix vault unlock event not sent when a note is unlocked (#7172)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2024-12-30 10:43:33 +05:00
Ammar Ahmed
e67e6374c3 mobile: set default widget size 2024-12-30 10:32:15 +05:00
Ammar Ahmed
ff1fc5b391 mobile: fix formatting 2024-12-30 10:32:15 +05:00
Ammar Ahmed
2f8bf191aa mobile: resizable and themeable android widget 2024-12-30 10:32:15 +05:00
Abdullah Atta
c4af2b2159 web: fix build on macos (by updating packages) 2024-12-30 10:13:40 +05:00
Abdullah Atta
690b157387 desktop: b/w when window is unfocused 2024-12-30 10:13:12 +05:00
Abdullah Atta
5a276a43a4 web: improve tab ui 2024-12-30 10:12:02 +05:00
Abdullah Atta
a364ae2e9d core: fix notes search in tags, colors & notebooks not working 2024-12-27 16:20:53 +05:00
Abdullah Atta
1e2055c81b web: fix Cannot start service: Host version "0.20.2" does not match binary version "0.23.1" on macos 2024-12-27 15:30:37 +05:00
01zulfi
31d110252c web: fix status bar size changing (#7143)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2024-12-27 11:50:40 +05:00
Ammar Ahmed
702976c6cf mobile: do not show progress when doing full auto backup 2024-12-26 12:44:54 +05:00
Ammar Ahmed
3ec8500515 mobile: add fdroid release notes 2024-12-26 12:32:27 +05:00
Ammar Ahmed
2c03420f33 mobile: release v3.0.25 2024-12-26 12:25:12 +05:00
Ammar Ahmed
868ae597ae mobile: fix ts errors 2024-12-26 12:25:12 +05:00
01zulfi
59d3e06935 intl: fix casing in legal & notebooks strings (#7142)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2024-12-26 11:29:57 +05:00
Ammar Ahmed
b296f5dd5c mobile: update export options 2024-12-24 15:59:33 +05:00
Abdullah Atta
2dc5e4fef5 docs(help): add notice on gift card page 2024-12-24 15:54:44 +05:00
Abdullah Atta
f836de3854 docs(help): clarify about expiry date on gift cards 2024-12-24 15:54:44 +05:00
Ammar Ahmed
631a591477 mobile: update ios provisioning 2024-12-24 15:31:06 +05:00
Ammar Ahmed
1bb27145ce mobile: release v3.0.24 2024-12-24 14:14:16 +05:00
Ammar Ahmed
79b89c2e85 mobile: skip migration progress during tests 2024-12-24 14:10:11 +05:00
Ammar Ahmed
ceb2a8c747 intl: fix locales data 2024-12-24 12:06:52 +05:00
Ammar Ahmed
bee06ecf18 mobile: fix multi file sharing 2024-12-24 12:06:52 +05:00
Ammar Ahmed
33c7eb5a74 mobile: fix imports 2024-12-24 12:06:52 +05:00
Abdullah Atta
2cb788712a web: fix editor toolbar scroll ui 2024-12-24 11:13:57 +05:00
Abdullah Atta
90d2338412 Revert "web: fix editor toolbar scroll styling (#7113)"
This reverts commit 5229408156.
2024-12-24 10:31:14 +05:00
01zulfi
4bebf5a7b5 editor: fix task list state & readonly bugs (#7117)
* fix task list complete state not showing on first load
* fix task list allowing paste when readonly

Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2024-12-24 10:18:23 +05:00
Ammar Ahmed
68eb5023f8 mobile: update deps 2024-12-24 10:10:56 +05:00
Abdullah Atta
8692c87ed7 intl: fix resend code string 2024-12-24 10:10:56 +05:00
Abdullah Atta
ea0623c6bc web: create backup on submit when changing password 2024-12-24 10:10:56 +05:00
Abdullah Atta
b526dc4d39 core: hash old password before deriving new crypto key 2024-12-24 10:10:56 +05:00
Ammar Ahmed
76a1025f59 mobile: do not call clearSessions when changing password 2024-12-24 10:10:56 +05:00
Ammar Ahmed
85e046a379 mobile: fix error in shortcut manager 2024-12-24 10:10:56 +05:00
Ammar Ahmed
58a6bbd262 mobile: fix logout handling 2024-12-24 10:10:56 +05:00
Ammar Ahmed
07aabf9a2a core: return false if no fallback key 2024-12-24 10:10:56 +05:00
Ammar Ahmed
8c7ba6b963 mobile: fix profile not rendered on home 2024-12-24 10:10:56 +05:00
Ammar Ahmed
d125e0f6d9 mobile: fix encryption 2024-12-24 10:10:56 +05:00
Ammar Ahmed
43d017d64a mobile: fix code input when changing email 2024-12-24 10:10:56 +05:00
Abdullah Atta
bc3e7c6a53 web: add noop fallback methods in storage 2024-12-24 10:10:56 +05:00
Abdullah Atta
6e8610c358 core: compute usesFallbackPWHash instead of storing it
this fixes the fallback logic for already logged in users
2024-12-24 10:10:56 +05:00
Abdullah Atta
ab00645c23 web: fix recovery view button text not wrapping 2024-12-23 18:29:10 +05:00
Abdullah Atta
e041976ae0 web: fix gift cards link 2024-12-23 18:06:09 +05:00
Abdullah Atta
9d7e6b40a0 web: bump version to 3.0.23 2024-12-23 18:05:43 +05:00
Abdullah Atta
db40a648ab web: fix Cannot read properties of undefined (reading 'instance') 2024-12-23 17:53:14 +05:00
Abdullah Atta
805e60a808 web: handle NetworkError when attempting to fetch resource. 2024-12-23 17:46:53 +05:00
Abdullah Atta
8c7093189b core: add support for sorting search results
search results are sorted by date created for now until
we add proper support for sorting search results
in the ui
2024-12-23 14:30:45 +05:00
Abdullah Atta
3092696c83 docs: add docs for gift cards 2024-12-23 14:30:25 +05:00
Ammar Ahmed
c2e7f7576e mobile: redeem gift code 2024-12-23 14:30:25 +05:00
Abdullah Atta
6b4f7900ec web: show subscription provider info in subscription settings 2024-12-23 14:30:25 +05:00
Abdullah Atta
523ae5b07b intl: add other subscription providers 2024-12-23 14:30:25 +05:00
Abdullah Atta
a628b3fd92 intl: add strings for gift redeeming 2024-12-23 14:30:25 +05:00
Abdullah Atta
e9f3037129 web: add gift redeem support 2024-12-23 14:30:25 +05:00
Abdullah Atta
46d4b9dece core: add api for redeeming gift codes 2024-12-23 14:30:25 +05:00
01zulfi
c701baaa2c web: better ux when autosave is off (#6610) (#6849)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
Co-authored-by: Abdullah Atta <abdullahatta@streetwriters.co>
2024-12-23 14:30:03 +05:00
Ammar Ahmed
a798f8e280 mobile: fix intro button position 2024-12-23 13:43:57 +05:00
Abdullah Atta
baebf79046 web: fix type errors 2024-12-23 12:29:07 +05:00
Abdullah Atta
5727aa6c4d web: fix checkout discounted snapshots 2024-12-21 16:41:16 +05:00
Abdullah Atta
36cf1feff9 web: fix crash on opening sort menu 2024-12-21 16:41:04 +05:00
Abdullah Atta
91a3b0f5ed web: fix imports with nested notebooks 2024-12-21 16:15:29 +05:00
Ammar Ahmed
293219d781 mobile: fix encryption on ios 2024-12-21 14:15:56 +05:00
Ammar Ahmed
2cd4f44a92 core: fix fallback key encryption 2024-12-21 14:15:56 +05:00
Abdullah Atta
4b9a95ded7 core: add support for fallback hashing
on ios some users using passwords with multi byte characters
generates the wrong hash. This commit adds support for fallback
to allow those users to continue to login once the fix has been applied.
2024-12-21 14:15:56 +05:00
Ammar Ahmed
565b0382f9 mobile: fix encryption on ios 2024-12-21 14:15:56 +05:00
Ammar Ahmed
1e837f2a9c mobile: fix undo/redo buttons in editor 2024-12-21 14:13:07 +05:00
Ammar Ahmed
765ebbe10c mobile: allow saving empty string input 2024-12-21 14:12:24 +05:00
Ammar Ahmed
e95d1601a6 mobile: fix sharing files on android 2024-12-21 14:10:55 +05:00
Ammar Ahmed
c6dd1d1615 mobile: fix snooze time not rendered properly 2024-12-21 14:10:34 +05:00
Ammar Ahmed
bb50850995 Merge pull request #7008 from streetwriters/fix-localization-error 2024-12-21 14:10:05 +05:00
Ammar Ahmed
83083134e9 Merge branch 'master' into fix-localization-error
Signed-off-by: Ammar Ahmed <40239442+ammarahm-ed@users.noreply.github.com>
2024-12-21 14:09:22 +05:00
01zulfi
61b8960aa5 web: fix mfa fallback string (#7123)
* also add selected style to mfa type selector button

Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2024-12-20 15:55:42 +05:00
01zulfi
5229408156 web: fix editor toolbar scroll styling (#7113)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2024-12-20 12:30:08 +05:00
01zulfi
0921fef267 web: show account password label in delete vault dialog (#7085)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2024-12-11 11:30:42 +05:00
luis-411
60989359e2 theme: make link color align with theme (#7077)
Signed-off-by: Luis Kriner <luis@kriner.info>
2024-12-10 11:01:04 +05:00
luis-411
8fe381afa9 editor: prevent creation of multiple empty notes (#6922)
Signed-off-by: Luis Kriner <luis@kriner.info>
2024-12-10 10:30:19 +05:00
01zulfi
fea9c4e42b web: fix links in report issue dialog (#7071)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2024-12-10 10:28:17 +05:00
01zulfi
1d78402d5d web: fix tags not showing in locked note (#7061)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2024-12-10 09:58:13 +05:00
01zulfi
aa72c33aea webclipper: handle default case in listener (#7058)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2024-12-10 09:57:23 +05:00
01zulfi
69504a150e core: handle error in parseInternalLink (#7065)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2024-12-10 09:56:47 +05:00
dyw770
a78a2e4ae2 core: fix object-id is sometimes less than 24 chars in length (#6991) (#6994)
Signed-off-by: dyw770 <dyw770@qq.com>
2024-12-06 10:11:57 +05:00
luis-411
0ffbf83141 editor: hide edit link button when in read only mode (#7018)
Signed-off-by: Luis Kriner <luis@kriner.info>
2024-12-06 09:46:44 +05:00
01zulfi
75c346a460 docs: add README.md for web clipper (#7054)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2024-12-05 10:55:28 +05:00
01zulfi
93af79926d editor: disable spellcheck for inline code (#7036)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2024-12-05 10:49:40 +05:00
01zulfi
1b354e4bca web: hide spin buttons in mfa code input (#7048)
* they overlap with the resend button

Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2024-12-05 10:26:54 +05:00
01zulfi
6d53b78f6a web: round off zoom value
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2024-11-28 09:59:32 +05:00
Ammar Ahmed
8e90adccab mobile: fix localization issues 2024-11-27 14:02:22 +05:00
Abdullah Atta
c19635b16a web: fix direct index access of strings 2024-11-27 13:14:44 +05:00
Abdullah Atta
94e4b00294 intl: fix direct access of strings in object 2024-11-27 13:14:12 +05:00
Abdullah Atta
76908b1fbd intl: generate action for when data type is unknown 2024-11-27 12:27:09 +05:00
Ammar Ahmed
7409c5382d mobile: fix localization error on searching notebook/tags 2024-11-27 10:41:52 +05:00
01zulfi
2462eb1631 monograph: remove callout headings from toc (#6875) (#6993)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2024-11-26 16:27:32 +05:00
Abdullah Atta
986ff32293 monograph: bump version to 1.2.2 2024-11-26 16:23:00 +05:00
Abdullah Atta
8f7fd9d8ee monograph: use fallback fonts when rendering og image 2024-11-26 16:22:48 +05:00
01zulfi
54d6a5c307 monograph: fix PUBLIC_URL on client
* use loader to get PUBLIC_URL

Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2024-11-26 15:27:43 +05:00
Abdullah Atta
d672a43a83 monograph: bump version to 1.2.1 2024-11-26 11:58:54 +05:00
Abdullah Atta
48343e5d5c web: do not zoom if e.deltaY is 0 2024-11-25 16:26:02 +05:00
Levi Ob
0d3a8c88c8 web: fix inconsistent zoom amount when adjusting with scroll wheel. (#6990)
Zoom steps are always in increments of 10 when using a mouse wheel or trackpad.

Signed-off-by: Levi Ob <leviob.msrni@slmail.me>
2024-11-25 12:36:32 +05:00
Abdullah Atta
31367066f7 web: run prerequisite checks on app start
this gives useful errors to users if their browser doesn't support something
2024-11-25 12:33:05 +05:00
Abdullah Atta
f7c097988a web: fix cannot read property clear of undefined when pressing fix it 2024-11-25 12:31:38 +05:00
Abdullah Atta
b7f1f36090 web: fix async sqlite
async sqlite mode uses indexeddb and has some limitations like:
- running 1 query at a time
This commit uses a mutex to run all queries sequentially
2024-11-25 12:31:11 +05:00
01zulfi
8756299d80 web: always show desktop backup directory path (#6867)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
2024-11-25 10:26:30 +05:00
dyw770
3525d60f8c monograph: add monograph response charset header
Signed-off-by: dyw770 <dyw770@qq.com>
2024-11-24 23:19:36 +05:00
Abdullah Atta
d08a485111 desktop: extract better-sqlite3 patching to its own module 2024-11-24 22:01:28 +05:00
Abdullah Atta
c203b035c4 monograph: bump version to 1.2.0 2024-11-24 15:38:20 +05:00
Abdullah Atta
0f4b2bdae7 monograph: fix Cannot find module '@remix-run/server-runtime' 2024-11-24 15:24:46 +05:00
Abdullah Atta
cb0bc39cd1 monograph: use bun in prod 2024-11-24 15:18:52 +05:00
Abdullah Atta
84abfa3478 monograph: speed up og image generation
this gets rid of satori and uses custom logic for drawing using @napi-rs/canvas
2024-11-24 15:18:52 +05:00
thecodrr
a40a48e2c1 server(theme): add installs.json to gitignore 2024-11-23 17:48:34 +00:00
Abdullah Atta
124499cabb monograph: use sharp output as buffer instead of stream 2024-11-23 22:23:42 +05:00
Ammar Ahmed
e874d1efd4 mobile: changelog 2024-11-23 22:20:05 +05:00
Ammar Ahmed
fb1a17566f mobile: release v3.0.23 2024-11-23 22:17:42 +05:00
Abdullah Atta
8dd8447212 monograph: cache satori output in lru cache
satori is sloooooow so we need to cache.
find another solution for og generation
2024-11-23 22:16:47 +05:00
Ammar Ahmed
eba7341d45 mobile: restore editor state only if not restored already 2024-11-23 22:15:57 +05:00
Ammar Ahmed
08bd36d518 mobile: fix deps 2024-11-23 22:15:57 +05:00
Ammar Ahmed
7a45522ff3 mobile: make attachment item pressable 2024-11-23 22:15:57 +05:00
Ammar Ahmed
4ee2923181 mobile: fix attachment downloads failing on mobile 2024-11-23 22:15:57 +05:00
Abdullah Atta
48459efdb1 monograph: mark sharp as external in ssr build 2024-11-23 21:45:44 +05:00
Abdullah Atta
c848f3c588 monograph: mark sharp as external dep in vite 2024-11-23 21:44:24 +05:00
Abdullah Atta
52a75cfdaf monograph: install sharp with optional deps during docker 2024-11-23 21:42:28 +05:00
Abdullah Atta
9331b5f919 monograph: bump version to 1.1.1 2024-11-23 21:33:37 +05:00
Abdullah Atta
2ff53d4650 monograph: use sharp for generating og images 2024-11-23 21:33:21 +05:00
Abdullah Atta
7f2c8ca05a web: fix checkout snapshots 2024-11-23 14:56:58 +05:00
Abdullah Atta
9e752e9406 web: bump version to 3.0.22 2024-11-23 14:53:31 +05:00
Abdullah Atta
b8c3e2098f web: fix one-time discount wrongly shown as recurring 2024-11-23 14:39:45 +05:00
Abdullah Atta
4308e3bf49 web: fix editor zoom on trackpads 2024-11-23 14:03:31 +05:00
Abdullah Atta
25956ccadb web: remove auto item reveal when opening items 2024-11-23 13:31:23 +05:00
Abdullah Atta
af3fba5176 core: lazily use db in config & kv stores 2024-11-23 13:28:55 +05:00
Ammar Ahmed
4afaa6a36e mobile: fix reminder visual issues 2024-11-23 13:00:57 +05:00
Ammar Ahmed
e98e1a5f36 mobile: fix pdf-preview crash 2024-11-23 12:24:17 +05:00
01zulfi
abfdad0fec web: fix setting item width (#6909) (#6935)
Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
Co-authored-by: Abdullah Atta <thecodrr@protonmail.com>
2024-11-23 12:16:26 +05:00
dyw770
99e50ddad6 monograph: fix monograph version endpoints cors
Signed-off-by: dyw770 <dyw770@qq.com>
2024-11-23 12:05:29 +05:00
Ammar Ahmed
67a61dd3f3 mobile: release v3.0.22 2024-11-20 12:40:37 +05:00
Ammar Ahmed
13df01d55a mobile: fix readonly editor not loading 2024-11-20 12:38:17 +05:00
Ammar Ahmed
af4ea036c8 mobile: fix sync on iOS 2024-11-20 12:37:38 +05:00
Abdullah Atta
97a75d9498 ci: generate & publish flatpak sources during desktop release 2024-11-20 11:51:04 +05:00
Abdullah Atta
950028e3b4 web: bump version to v3.0.21 2024-11-20 11:26:23 +05:00
Abdullah Atta
874726c712 global: update lockfiles 2024-11-20 11:25:28 +05:00
Abdullah Atta
0f380b9962 Revert "editor: fix heading and p gap (#6530)"
This reverts commit c26988134f.
2024-11-20 11:21:48 +05:00
Abdullah Atta
2ce569726c editor: fix image on load animation 2024-11-20 11:17:25 +05:00
Abdullah Atta
a38fe7da43 web: fix editor margins state reset on restart 2024-11-20 11:09:45 +05:00
Abdullah Atta
057b563608 web: fix password app lock stuck on "wrong password" 2024-11-20 11:07:05 +05:00
Ammar Ahmed
3741e26219 mobile: fix error when changing 2fa method 2024-11-20 10:25:11 +05:00
1218 changed files with 851707 additions and 301997 deletions

View File

@@ -10,7 +10,7 @@ const authors = readFileSync("AUTHORS", "utf-8");
const isAuthor = authors.includes(`<${authorEmail}>`);
const SCOPES = [
// for full list of scopes + details see: https://github.com/streetwriters/notesnook-private/blob/master/CONTRIBUTING.md#commit-guidelines
// for full list of scopes + details see: https://github.com/streetwriters/notesnook/blob/master/CONTRIBUTING.md#commit-guidelines
"mobile",
"web",
@@ -36,7 +36,8 @@ const SCOPES = [
"global",
"docs",
"themebuilder",
"intl"
"intl",
"webclipper"
];
module.exports = {

View File

@@ -7,13 +7,15 @@ runs:
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 20.x
node-version: 22.x
cache: "npm"
cache-dependency-path: |
package-lock.json
apps/mobile/package-lock.json
apps/desktop/package-lock.json
apps/web/package-lock.json
apps/monograph/package-lock.json
apps/theme-builder/package-lock.json
extensions/web-clipper/package-lock.json
packages/core/package-lock.json
packages/crypto/package-lock.json
@@ -24,3 +26,4 @@ runs:
packages/logger/package-lock.json
packages/streamable-fs/package-lock.json
packages/theme/package-lock.json
packages/intl/package-lock.json

View File

@@ -47,6 +47,11 @@ jobs:
- name: Install Detox CLI
run: npm install detox-cli --global
- name: Check for typescript errors
run: |
cd apps/mobile
npx tsc --noEmit
- name: Detox build
run: |
yarn build:android

View File

@@ -4,7 +4,7 @@ on: workflow_dispatch
jobs:
build:
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
timeout-minutes: 40
env:
CMAKE_C_COMPILER_LAUNCHER: ccache
@@ -22,7 +22,7 @@ jobs:
- name: Use specific Java version for the builds
uses: joschi/setup-jdk@v2
with:
java-version: "11"
java-version: "17"
architecture: "x64"
- name: Install node modules
@@ -58,7 +58,7 @@ jobs:
ccache -p
- name: Cache gradle
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: |
~/.gradle/caches
@@ -69,12 +69,16 @@ jobs:
run: |
sed -i -e 's/arguments/arguments "-DCMAKE_CXX_COMPILER_LAUNCHER=ccache",/g' apps/mobile/node_modules/react-native-mmkv-storage/android/build.gradle
sed -i -e 's/arguments/arguments "-DCMAKE_CXX_COMPILER_LAUNCHER=ccache",/g' apps/mobile/node_modules/react-native-reanimated/android/build.gradle
sed -i -e 's/defaultConfig {/ndkVersion safeExtGet('ndkVersion', "25.2.9519653")\n defaultConfig {/g' apps/mobile/node_modules/react-native-reanimated//android/build.gradle
sed -i -e 's/defaultConfig {/ndkVersion safeExtGet('ndkVersion', "25.2.9519653")\n defaultConfig {/g' apps/mobile/node_modules/react-native-mmkv-storage/android/build.gradle
- name: CCache Stats Before Build
run: ccache -sv
- name: Check for typescript errors
run: |
npm run tx mobile:build
cd apps/mobile
npx tsc --noEmit
- name: Build unsigned app bundle
run: yarn release:android:bundle
@@ -129,7 +133,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 +142,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 +150,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

@@ -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
@@ -58,7 +58,7 @@ jobs:
ccache -p
- name: Cache gradle
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: |
~/.gradle/caches
@@ -69,12 +69,16 @@ jobs:
run: |
sed -i -e 's/arguments/arguments "-DCMAKE_CXX_COMPILER_LAUNCHER=ccache",/g' apps/mobile/node_modules/react-native-mmkv-storage/android/build.gradle
sed -i -e 's/arguments/arguments "-DCMAKE_CXX_COMPILER_LAUNCHER=ccache",/g' apps/mobile/node_modules/react-native-reanimated/android/build.gradle
sed -i -e 's/defaultConfig {/ndkVersion safeExtGet('ndkVersion', "25.2.9519653")\n defaultConfig {/g' apps/mobile/node_modules/react-native-reanimated//android/build.gradle
sed -i -e 's/defaultConfig {/ndkVersion safeExtGet('ndkVersion', "25.2.9519653")\n defaultConfig {/g' apps/mobile/node_modules/react-native-mmkv-storage/android/build.gradle
- name: CCache Stats Before Build
run: ccache -sv
- name: Check for typescript errors
run: |
npm run tx mobile:build
cd apps/mobile
npx tsc --noEmit
- name: Build unsigned app bundle
run: yarn release:android:bundle

View File

@@ -9,7 +9,13 @@ on:
- "packages/core/**"
# re-run workflow if workflow file changes
- ".github/workflows/core.tests.yml"
pull_request:
pull_request_target:
branches:
- "master"
paths:
- "packages/core/**"
# re-run workflow if workflow file changes
- ".github/workflows/core.tests.yml"
types:
- "ready_for_review"
- "opened"
@@ -17,11 +23,21 @@ on:
- "reopened"
jobs:
test:
authorize:
environment: ${{ github.event_name == 'pull_request_target' &&
github.event.pull_request.head.repo.full_name != github.repository &&
'external' || 'internal' }}
runs-on: ubuntu-latest
steps:
- run: echo true
test:
needs: authorize
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha || github.ref }}
- name: Setup Node
uses: ./.github/actions/setup-node-with-cache
@@ -36,7 +52,6 @@ jobs:
echo "USER_PASSWORD=${{ secrets.USER_PASSWORD }}" >> $GITHUB_ENV
echo "USER_TOTP_SECRET=${{ secrets.USER_TOTP_SECRET }}" >> $GITHUB_ENV
echo "USER_HASHED_PASSWORD=${{ secrets.USER_HASHED_PASSWORD }}" >> $GITHUB_ENV
echo "NX_CLOUD_ACCESS_TOKEN=${{ secrets.NX_CLOUD_ACCESS_TOKEN }}" >> $GITHUB_ENV
- name: Run all @notesnook/core tests
run: npx nx test:e2e @notesnook/core
run: npm run tx @notesnook/core:test:e2e

View File

@@ -33,11 +33,19 @@ on:
required: true
default: true
description: "Build for macOS?"
release-track:
type: choice
required: true
default: stable
description: "Select the release track"
options:
- stable
- beta
jobs:
build:
name: Build
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -49,13 +57,25 @@ jobs:
run: |
npm ci --ignore-scripts --prefer-offline --no-audit
npm run bootstrap -- --scope=web
npm run bootstrap -- --scope=desktop
- name: Setup environment
- name: Install sqlite-better-trigram for all arch
run: |
echo "NX_CLOUD_ACCESS_TOKEN=${{ secrets.NX_CLOUD_ACCESS_TOKEN }}" >> $GITHUB_ENV
npm i --cpu arm64 sqlite-better-trigram
npm i --cpu x64 sqlite-better-trigram
working-directory: ./apps/desktop
- name: Generate desktop build
run: npx nx build:desktop @notesnook/web
- name: Generate desktop build (stable)
if: ${{ inputs.release-track == 'stable' }}
run: npm run tx @notesnook/web:build:desktop
- name: Generate desktop build (beta)
if: ${{ inputs.release-track == 'beta' }}
run: BETA=true npm run tx @notesnook/web:build:desktop
- name: Build desktop bundle
working-directory: ./apps/desktop
run: npm run bundle
- name: Archive build artifact
uses: actions/upload-artifact@v4
@@ -71,7 +91,8 @@ jobs:
- name: Package desktop build
run: |
zip -r ./notesnook_build_v${{ steps.app_metadata.outputs.app_version }}.zip ./apps/web/build/
cp -r ./apps/web/build ./apps/desktop/
zip -r ./notesnook_build_v${{ steps.app_metadata.outputs.app_version }}.zip ./apps/desktop/build/
echo "Build folder archived to ./notesnook_build_v${{ steps.app_metadata.outputs.app_version }}.zip"
- name: Upload desktop build
@@ -82,6 +103,28 @@ jobs:
name: Notesnook Desktop v${{ steps.app_metadata.outputs.app_version }}
tag_name: v${{ steps.app_metadata.outputs.app_version }}
files: ./notesnook_build_v${{ steps.app_metadata.outputs.app_version }}.zip
prerelease: ${{ inputs.release-track == 'beta' }}
target_commitish: ${{ github.ref }}
- name: Generate flatpak sources
if: inputs.publish-github && inputs.build-linux
run: |
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 .
cd -
node scripts/generate-sources.mjs
- name: Upload flatpak sources
uses: softprops/action-gh-release@v1
if: inputs.publish-github && inputs.build-linux
with:
draft: true
name: Notesnook Desktop v${{ steps.app_metadata.outputs.app_version }}
tag_name: v${{ steps.app_metadata.outputs.app_version }}
files: ./generated-sources.json
prerelease: ${{ endsWith(steps.app_metadata.outputs.app_version, '-beta') }}
build-macos:
@@ -152,9 +195,9 @@ jobs:
CSC_LINK: ${{ secrets.mac_certs }}
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
working-directory: ./apps/desktop
npm run tx @notesnook/desktop:release -- --variant=mas
cd apps/desktop
yarn electron-builder --config=electron-builder.config.js --mac mas --universal -p never
- name: Build zip and dmg
env:
@@ -165,13 +208,13 @@ jobs:
APPLE_API_KEY_ID: ${{ secrets.api_key_id }}
APPLE_API_ISSUER: ${{ secrets.api_key_issuer_id }}
run: |
npx nx run release --project @notesnook/desktop
npm run tx @notesnook/desktop:release
cd apps/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
- name: Deploy to Testflight
if: inputs.publish-apple && steps.appstore.outputs.app-version-latest != steps.app_metadata.outputs.app_version
@@ -186,8 +229,8 @@ jobs:
xcrun altool --upload-package $package -t osx --apiKey $API_KEY_ID --apiIssuer $API_KEY_ISSUER_ID --apple-id ${{ steps.app_metadata.outputs.apple_app_id }} --bundle-id ${{ steps.app_metadata.outputs.app_bundle_id }} --bundle-short-version-string ${{ steps.app_metadata.outputs.app_version }} --bundle-version ${{ steps.app_metadata.outputs.bundle_version }}
working-directory: ./apps/desktop
build-linux:
name: Build for Linux
build-linux-x64:
name: Build for Linux x64
needs: build
if: inputs.build-linux
runs-on: ubuntu-22.04
@@ -204,7 +247,7 @@ jobs:
run: echo "SNAPCRAFT_STORE_CREDENTIALS=${{ secrets.snapcraft_token }}" >> $GITHUB_ENV
- name: Install Snapcraft
uses: samuelmeuli/action-snapcraft@v1
uses: samuelmeuli/action-snapcraft@v3
if: inputs.publish-snap
- name: Download build
@@ -220,18 +263,16 @@ jobs:
- name: Install sqlite-better-trigram for all arch
run: |
npm i --cpu arm64 sqlite-better-trigram
npm i --cpu x64 sqlite-better-trigram
working-directory: ./apps/desktop
- name: Build Electron wrapper
run: npx nx run release --project @notesnook/desktop
working-directory: ./apps/desktop
run: npm run tx @notesnook/desktop:release
- 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
@@ -239,18 +280,85 @@ jobs:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
if [ ${{ inputs.publish-github }} == true ]; then
yarn electron-builder --linux AppImage:x64 AppImage:arm64 -p always
yarn electron-builder --config=electron-builder.config.js --linux AppImage:x64 -p always
else
yarn electron-builder --linux AppImage:x64 AppImage:arm64 -p never
yarn electron-builder --config=electron-builder.config.js --linux AppImage:x64 -p never
fi
working-directory: ./apps/desktop
- name: Publish on Snapcraft
if: inputs.publish-snap
run: |
snapcraft upload --release=stable ./output/notesnook_linux_amd64.snap
if [ ${{ inputs.release-track }} == 'beta' ]; then
snapcraft upload --release=beta ./output/notesnook_linux_amd64.snap
else
snapcraft upload --release=stable ./output/notesnook_linux_amd64.snap
fi
working-directory: ./apps/desktop
build-linux-arm64:
name: Build for Linux arm64
needs: build
if: inputs.build-linux
runs-on: ubuntu-22.04-arm
steps:
- name: Check out Git repository
uses: actions/checkout@v4
- name: Setup Node
uses: ./.github/actions/setup-node-with-cache
# - name: Setup Snapcraft Auth
# if: inputs.publish-snap
# run: echo "SNAPCRAFT_STORE_CREDENTIALS=${{ secrets.snapcraft_token }}" >> $GITHUB_ENV
# - name: Install Snapcraft
# uses: samuelmeuli/action-snapcraft@v1
# if: inputs.publish-snap
- name: Download build
uses: actions/download-artifact@v4
with:
name: build
path: ./apps/web/build
- name: Install packages
run: |
npm ci --ignore-scripts --prefer-offline --no-audit
npm run bootstrap -- --scope=desktop
- name: Install sqlite-better-trigram for all arch
run: |
npm i --cpu arm64 sqlite-better-trigram
working-directory: ./apps/desktop
- name: Build Electron wrapper
run: npm run tx @notesnook/desktop:release
# - name: Build snap
# if: inputs.publish-snap
# run: |
# yarn electron-builder --config=electron-builder.config.js --linux snap:arm64 -p never
# working-directory: ./apps/desktop
- name: Build AppImage
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
if [ ${{ inputs.publish-github }} == true ]; then
yarn electron-builder --config=electron-builder.config.js --linux AppImage:arm64 -p always
else
yarn electron-builder --config=electron-builder.config.js --linux AppImage:arm64 -p never
fi
working-directory: ./apps/desktop
# - name: Publish on Snapcraft
# if: inputs.publish-snap
# run: |
# snapcraft upload --release=stable ./output/notesnook_linux_arm64.snap
# working-directory: ./apps/desktop
build-windows:
name: Build for Windows
needs: build
@@ -288,10 +396,13 @@ jobs:
run: |
npm i --cpu arm64 sqlite-better-trigram
npm i --cpu x64 sqlite-better-trigram
npm i --cpu arm64 sqlite3-fts5-html
npm i --cpu x64 sqlite3-fts5-html
working-directory: ./apps/desktop
- name: Build
run: npx nx run release --project @notesnook/desktop
run: node scripts/execute.mjs @notesnook/desktop:release
- name: Publish
env:
@@ -301,8 +412,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

@@ -6,15 +6,21 @@ on:
branches:
- "master"
paths:
- "app/desktop/**"
- "apps/desktop/**"
# re-run workflow if workflow file changes
- ".github/workflows/desktop.tests.yml"
pull_request:
branches:
- "master"
paths:
- "apps/desktop/**"
# re-run workflow if workflow file changes
- ".github/workflows/desktop.tests.yml"
jobs:
build:
name: Build
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -27,12 +33,8 @@ jobs:
npm ci --ignore-scripts --prefer-offline --no-audit
npm run bootstrap -- --scope=web
- name: Setup environment
run: |
echo "NX_CLOUD_ACCESS_TOKEN=${{ secrets.NX_CLOUD_ACCESS_TOKEN }}" >> $GITHUB_ENV
- name: Generate desktop build
run: npx nx build:desktop @notesnook/web
run: npm run tx @notesnook/web:build:desktop
- name: Archive build artifact
uses: actions/upload-artifact@v4
@@ -64,17 +66,15 @@ jobs:
npm run bootstrap -- --scope=desktop
- name: Build Electron wrapper
run: npx nx run release --project @notesnook/desktop
working-directory: ./apps/desktop
run: npm run tx @notesnook/desktop:release
- 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
@@ -109,17 +109,15 @@ jobs:
npm run bootstrap -- --scope=desktop
- name: Build Electron wrapper
run: npx nx run release --project @notesnook/desktop
working-directory: ./apps/desktop
run: npm run tx @notesnook/desktop:release
- name: Build app
run: |
yarn electron-builder --mac --dir --arm64
yarn electron-builder --config=electron-builder.config.js --mac --dir --arm64
working-directory: ./apps/desktop
- name: Run tests arm64
run: |
EXECUTABLE_PATH=output/mac-arm64/Notesnook.app/Contents/MacOS/Notesnook npm run test
run: npm run test
working-directory: ./apps/desktop
- name: Upload test results
@@ -133,7 +131,7 @@ jobs:
test-linux:
name: Test for Linux
needs: build
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- name: Check out Git repository
@@ -160,17 +158,15 @@ jobs:
working-directory: ./apps/desktop
- name: Build Electron wrapper
run: npx nx run release --project @notesnook/desktop
working-directory: ./apps/desktop
run: npm run tx @notesnook/desktop:release
- 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
@@ -208,20 +204,21 @@ jobs:
run: |
npm i --cpu arm64 sqlite-better-trigram
npm i --cpu x64 sqlite-better-trigram
npm i --cpu arm64 sqlite3-fts5-html
npm i --cpu x64 sqlite3-fts5-html
working-directory: ./apps/desktop
- name: Build Electron wrapper
run: npx nx run release --project @notesnook/desktop
working-directory: ./apps/desktop
run: node scripts/execute.mjs @notesnook/desktop:release
- 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

@@ -10,6 +10,12 @@ on:
# re-run workflow if workflow file changes
- ".github/workflows/editor.tests.yml"
pull_request:
branches:
- "master"
paths:
- "packages/editor/**"
# re-run workflow if workflow file changes
- ".github/workflows/editor.tests.yml"
types:
- "ready_for_review"
- "opened"
@@ -19,7 +25,7 @@ on:
jobs:
build:
name: Build
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -32,12 +38,8 @@ jobs:
npm ci --ignore-scripts --prefer-offline --no-audit
npm run bootstrap -- --scope=editor
- name: Setup environment
run: |
echo "NX_CLOUD_ACCESS_TOKEN=${{ secrets.NX_CLOUD_ACCESS_TOKEN }}" >> $GITHUB_ENV
- name: Build editor
run: npx nx build @notesnook/editor
run: npm run tx @notesnook/editor:build
- name: Run all @notesnook/editor tests
run: npx nx test @notesnook/editor
run: npm run tx @notesnook/editor:test

View File

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

View File

@@ -4,23 +4,28 @@ on: workflow_dispatch
jobs:
build:
runs-on: macos-latest
runs-on: macos-14
timeout-minutes: 60
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Setup Node
uses: ./.github/actions/setup-node-with-cache
- name: Setup Xcode
uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: "16.1"
- name: Install node modules
run: |
npm ci --ignore-scripts --prefer-offline --no-audit
npm run bootstrap -- --scope=mobile
- name: Build packages
run: npx nx run @notesnook/mobile:build
run: npm run tx @notesnook/mobile:build
- name: ccache
uses: hendrikmuhs/ccache-action@v1.2.11
@@ -47,14 +52,23 @@ jobs:
ccache -p
- name: Cache Pods
uses: actions/cache@v2
uses: actions/cache@v3
id: pods-cache
with:
path: apps/mobile/native/ios/Pods
key: ${{ runner.os }}-pods-${{ hashFiles('apps/mobile/native/ios/Podfile.lock') }}
- name: Install Pods
run: npm run prepare:ios
run: |
cd apps/mobile/native/ios
bundle install
RCT_NEW_ARCH_ENABLED=0 bundle exec pod install
- name: Check for typescript errors
run: |
npm run tx mobile:build
cd apps/mobile
npx tsc --noEmit
- name: CCache Stats Before Build
run: ccache -sv

View File

@@ -14,7 +14,7 @@ on: workflow_dispatch
jobs:
push_to_registry:
name: Push Docker image to Docker Hub
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
permissions:
packages: write
contents: read
@@ -39,13 +39,13 @@ jobs:
echo ::set-output name=app_version::$(cat package.json | jq -r .version)
- name: Generate build
run: npx nx build @notesnook/monograph
run: npm run tx @notesnook/monograph:build
# Setup Buildx
- name: Docker Setup Buildx
uses: docker/setup-buildx-action@v3
with:
platforms: linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v8
platforms: linux/amd64,linux/arm64
- name: Log in to Docker Hub
uses: docker/login-action@v3
@@ -77,7 +77,7 @@ jobs:
context: apps/monograph
file: apps/monograph/Dockerfile
push: true
platforms: linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v8
platforms: linux/amd64,linux/arm64
tags: streetwriters/monograph:${{ steps.package_metadata.outputs.app_version }},streetwriters/monograph:latest
cache-from: streetwriters/monograph:latest

View File

@@ -5,7 +5,7 @@ on: workflow_dispatch
jobs:
build:
name: Build
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -20,7 +20,6 @@ jobs:
- name: Setup environment
run: |
echo "NX_CLOUD_ACCESS_TOKEN=${{ secrets.NX_CLOUD_ACCESS_TOKEN }}" >> $GITHUB_ENV
echo "CLOUDFLARE_ACCOUNT_ID=${{ secrets.CLOUDFLARE_ACCOUNT_ID }}" >> $GITHUB_ENV
echo "CLOUDFLARE_API_TOKEN=${{ secrets.CLOUDFLARE_API_TOKEN }}" >> $GITHUB_ENV

View File

@@ -5,7 +5,7 @@ on: workflow_dispatch
jobs:
build:
name: Build
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -20,7 +20,6 @@ jobs:
- name: Setup environment
run: |
echo "NX_CLOUD_ACCESS_TOKEN=${{ secrets.NX_CLOUD_ACCESS_TOKEN }}" >> $GITHUB_ENV
echo "CLOUDFLARE_ACCOUNT_ID=${{ secrets.CLOUDFLARE_ACCOUNT_ID }}" >> $GITHUB_ENV
echo "CLOUDFLARE_API_TOKEN=${{ secrets.CLOUDFLARE_API_TOKEN }}" >> $GITHUB_ENV

View File

@@ -14,7 +14,7 @@ on:
jobs:
bench:
name: Bench
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -27,10 +27,6 @@ jobs:
npm ci --ignore-scripts --prefer-offline --no-audit
npm run bootstrap -- --scope=web
- name: Setup environment
run: |
echo "NX_CLOUD_ACCESS_TOKEN=${{ secrets.NX_CLOUD_ACCESS_TOKEN }}" >> $GITHUB_ENV
- name: Build
run: npm run build:web

View File

@@ -1,11 +1,21 @@
name: Publish @notesnook/web
on: workflow_dispatch
on:
workflow_dispatch:
inputs:
release-track:
type: choice
required: true
default: stable
description: "Select the release track"
options:
- stable
- beta
jobs:
build:
name: Build
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -20,12 +30,23 @@ jobs:
- name: Setup environment
run: |
echo "NX_CLOUD_ACCESS_TOKEN=${{ secrets.NX_CLOUD_ACCESS_TOKEN }}" >> $GITHUB_ENV
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

@@ -9,7 +9,13 @@ on:
- "apps/web/**"
# re-run workflow if workflow file changes
- ".github/workflows/web.tests.yml"
pull_request:
pull_request_target:
branches:
- "master"
paths:
- "apps/web/**"
# re-run workflow if workflow file changes
- ".github/workflows/web.tests.yml"
types:
- "ready_for_review"
- "opened"
@@ -17,12 +23,23 @@ on:
- "reopened"
jobs:
build:
name: Build
authorize:
environment: ${{ github.event_name == 'pull_request_target' &&
github.event.pull_request.head.repo.full_name != github.repository &&
'external' || 'internal' }}
runs-on: ubuntu-latest
steps:
- run: echo true
build:
needs: authorize
name: Build
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha || github.ref }}
- name: Setup Node
uses: ./.github/actions/setup-node-with-cache
@@ -32,10 +49,6 @@ jobs:
npm ci --ignore-scripts --prefer-offline --no-audit
npm run bootstrap -- --scope=web
- name: Setup environment
run: |
echo "NX_CLOUD_ACCESS_TOKEN=${{ secrets.NX_CLOUD_ACCESS_TOKEN }}" >> $GITHUB_ENV
- name: Generate test build
run: npm run build:test:web
@@ -49,11 +62,13 @@ 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
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha || github.ref }}
- name: Download build
uses: actions/download-artifact@v4

2
.gitignore vendored
View File

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

View File

@@ -27,7 +27,6 @@ Notesnook is built using the following technologies:
3. React Native — For mobile apps we are using React Native
4. Electron — For desktop app
5. NPM — listed here because we **don't** use Yarn or PNPM or XYZ across any of our projects.
6. Nx — maintaining monorepos is hard but Nx makes it easier.
> **Note: Each project in the monorepo contains its own architecture details which you can refer to.**
@@ -66,7 +65,7 @@ We take all queries, issues and bug reports that you might have. Feel free to as
## Additional Resources
- [Migrating & Importing your data from other apps — Importer](https://importer.notesnook.com/)
- [Migrating & Importing your data from other apps — Importer](https://help.notesnook.com/importing-notes)
- [Privacy policy](https://notesnook.com/privacy) & [Terms of service](https://notesnook.com/terms)
- [Verify Notesnook encryption claims yourself — Vericrypt](https://vericrypt.notesnook.com/)
- [Why Notesnook requires an email address?](https://blog.notesnook.com/why-notesnook-requires-an-email-address/)

View File

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

View File

@@ -24,7 +24,7 @@ Requirements:
Before you can do anything, you'll need to [install Node.js](https://nodejs.org/en/download/) v16 or later on your system.
Once you have completed the setup, the first step is to `clone` the monorepo:
1. `clone` the monorepo:
```bash
git clone https://github.com/streetwriters/notesnook.git
@@ -33,19 +33,28 @@ git clone https://github.com/streetwriters/notesnook.git
cd notesnook
```
Once you are inside the `./notesnook` directory, run the preparation step:
2. Install dependencies:
```bash
# this might take a while to complete
npm install
```
Now you can finally start the desktop app for development:
3. Run the webapp for desktop environment:
```bash
cd apps/web
npm run start:desktop
```
4. In a separate terminal session, run the desktop app from the root of the project:
```bash
npm run start:desktop
```
### Release mode
To run the app in release mode:
```bash
@@ -58,13 +67,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,242 @@
/*
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 { testCleanup, test } from "./test-override.js";
import { writeFile } from "fs/promises";
import { Page } from "playwright";
import { gt, lt } from "semver";
import { describe } from "vitest";
test("update starts downloading if version is outdated", async ({
ctx: { page },
expect,
onTestFinished
}) => {
onTestFinished(testCleanup);
await page.waitForSelector("#authForm");
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" });
});
test("update is only shown if version is outdated and auto updates are disabled", async ({
ctx,
expect,
onTestFinished
}) => {
onTestFinished(testCleanup);
await ctx.app.close();
await writeFile(
ctx.configPath,
JSON.stringify({
automaticUpdates: false
})
);
await ctx.relaunch();
const { page } = ctx;
await page.waitForSelector("#authForm");
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" });
});
describe("update to stable if it is newer", () => {
test.scoped({ options: { version: "3.0.0-beta.0" } });
test("test", async ({ ctx, expect, onTestFinished }) => {
onTestFinished(testCleanup);
await ctx.app.close();
await writeFile(
ctx.configPath,
JSON.stringify({
automaticUpdates: false,
releaseTrack: "beta"
})
);
await ctx.relaunch();
const { page } = ctx;
await page.waitForSelector("#authForm");
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] || "";
expect(gt(version, "3.0.0-beta.0")).toBe(true);
});
});
describe("update is not available if it latest stable version is older", () => {
test.scoped({ options: { version: "99.0.0-beta.0" } });
test("test", async ({ ctx, expect, onTestFinished }) => {
onTestFinished(testCleanup);
await ctx.app.close();
await writeFile(
ctx.configPath,
JSON.stringify({
automaticUpdates: false,
releaseTrack: "beta"
})
);
await ctx.relaunch();
const { page } = ctx;
await page.waitForSelector("#authForm");
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" });
expect(
await page
.locator(".theme-scope-statusBar")
.getByRole("button", { name: /available/i })
.isHidden()
).toBe(true);
});
});
describe("downgrade to stable on switching to stable release track", () => {
test.scoped({ options: { version: "99.0.0-beta.0" } });
test("test", async ({ ctx, expect, onTestFinished }) => {
onTestFinished(testCleanup);
await ctx.app.close();
await writeFile(
ctx.configPath,
JSON.stringify({
automaticUpdates: false,
releaseTrack: "stable"
})
);
await ctx.relaunch();
const { page } = ctx;
await page.waitForSelector("#authForm");
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] || "";
expect(lt(version, "99.0.0-beta.0")).toBe(true);
});
});
async function skipDialog(page: Page) {
try {
const dialog = page.locator(".ReactModal__Content");
const positiveButton = dialog.locator(
"button[data-role='positive-button']"
);
const negativeButton = dialog.locator(
"button[data-role='negative-button']"
);
if (await positiveButton.isVisible())
await positiveButton.click({ timeout: 1000 });
else if (await negativeButton.isVisible())
await negativeButton.click({ timeout: 1000 });
} catch (e) {
// ignore error
}
}

View File

@@ -0,0 +1,24 @@
/*
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 { buildApp } from "./utils";
export default async function setup() {
await buildApp();
}

View File

@@ -1,53 +0,0 @@
/*
This file is part of the Notesnook project (https://notesnook.com/)
Copyright (C) 2023 Streetwriters (Private) Limited
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import test from "node:test";
import { launchApp } from "./utils.mjs";
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 page.waitForSelector("#authForm");
assert.ok(
await page.getByRole("button", { name: "Create account" }).isVisible()
);
await page
.getByRole("button", { name: "Skip & go directly to the app" })
.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,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 { testCleanup, test } from "./test-override.js";
test("make sure app loads", async ({
ctx: { page },
expect,
onTestFinished
}) => {
onTestFinished(testCleanup);
await page.waitForSelector("#authForm");
expect(
await page.getByRole("button", { name: "Create account" }).isVisible()
).toBe(true);
await page
.getByRole("button", { name: "Skip & go directly to the app" })
.click();
await page.waitForSelector(".ProseMirror");
});

View File

@@ -0,0 +1,64 @@
/*
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 as vitestTest, TestContext } from "vitest";
import { buildAndLaunchApp, Fixtures, TestOptions } from "./utils";
import { mkdir, rm } from "fs/promises";
import path from "path";
import slugify from "slugify";
export const test = vitestTest.extend<Fixtures>({
options: { version: "3.0.0" } as TestOptions,
ctx: async ({ options }, use) => {
const ctx = await buildAndLaunchApp(options);
await use(ctx);
}
});
export async function testCleanup(context: TestContext) {
const ctx = (context.task.context as unknown as Fixtures).ctx;
if (context.task.result?.state === "fail") {
await mkdir("test-results", { recursive: true });
await ctx.page.screenshot({
path: path.join(
"test-results",
`${slugify(context.task.name)}-${process.platform}-${
process.arch
}-error.png`
)
});
}
await ctx.app.close();
await rm(ctx.userDataDir, {
force: true,
recursive: true,
maxRetries: 3,
retryDelay: 5000
}).catch(() => {
/*ignore */
});
await rm(ctx.outputDir, {
force: true,
recursive: true,
maxRetries: 3,
retryDelay: 5000
}).catch(() => {
/*ignore */
});
}

View File

@@ -0,0 +1,226 @@
/*
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 { cp } from "fs/promises";
import { fileURLToPath } from "node:url";
import path, { join, resolve } from "path";
import { _electron as electron } from "playwright";
import { existsSync } from "fs";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const IS_DEBUG = process.env.NN_DEBUG === "true" || process.env.CI === "true";
const productName = `NotesnookTestHarness`;
const SOURCE_DIR = resolve("output", productName);
export interface AppContext {
app: import("playwright").ElectronApplication;
page: import("playwright").Page;
configPath: string;
userDataDir: string;
outputDir: string;
relaunch: () => Promise<void>;
}
export interface TestOptions {
version: string;
}
export interface Fixtures {
options: TestOptions;
ctx: AppContext;
}
export async function buildAndLaunchApp(
options?: TestOptions
): Promise<AppContext> {
const productName = `notesnooktest${makeid(10)}`;
const outputDir = path.join("test-artifacts", `${productName}-output`);
const executablePath = await copyBuild({
...options,
outputDir
});
const { app, page, configPath, userDataDir } = await launchApp(
executablePath,
productName,
options?.version
);
const ctx: AppContext = {
app,
page,
configPath,
userDataDir,
outputDir,
relaunch: async () => {
const { app, page, configPath, userDataDir } = await launchApp(
executablePath,
productName,
options?.version
);
ctx.app = app;
ctx.page = page;
ctx.userDataDir = userDataDir;
ctx.configPath = configPath;
}
};
return ctx;
}
async function launchApp(
executablePath: string,
packageName: string,
version?: string
) {
const userDataDir = resolve(
__dirname,
"..",
"test-artifacts",
"user_data_dirs",
packageName
);
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>)),
CUSTOM_USER_DATA_DIR: userDataDir,
...(version
? {
CUSTOM_APP_VERSION: version
}
: {})
}
});
const page = await app.firstWindow();
const configPath = path.join(userDataDir, "UserData", "config.json");
return {
app,
page,
configPath,
userDataDir
};
}
let MAX_RETRIES = 3;
export async function buildApp(version?: string) {
if (!existsSync(SOURCE_DIR)) {
const args = [
"electron-builder",
"--dir",
`--${process.arch}`,
`--config electron-builder.config.js`,
`--c.extraMetadata.productName=${productName}`,
`--c.compression=store`,
"--publish=never"
];
if (version) args.push(`--c.extraMetadata.version=${version}`);
try {
execSync(`npx ${args.join(" ")}`, {
stdio: IS_DEBUG ? "inherit" : "ignore",
env: {
...process.env,
NOTESNOOK_STAGING: "true",
NN_PRODUCT_NAME: productName,
NN_APP_ID: `com.notesnook.test.${productName}`,
NN_OUTPUT_DIR: SOURCE_DIR
}
});
} catch (e) {
if (--MAX_RETRIES) {
console.log("retrying...");
return await buildApp(version);
} else throw e;
}
}
}
async function copyBuild({ outputDir }: { outputDir: string }) {
return process.platform === "win32"
? await makeBuildCopyWindows(outputDir, productName)
: process.platform === "darwin"
? await makeBuildCopyMacOS(outputDir, productName)
: await makeBuildCopyLinux(outputDir, productName);
}
async function makeBuildCopyLinux(outputDir: string, productName: string) {
const platformDir =
process.arch === "arm64" ? "linux-arm64-unpacked" : "linux-unpacked";
const appDir = await makeBuildCopy(outputDir, platformDir);
return resolve(
__dirname,
"..",
appDir,
productName.toLowerCase().replace(/\s+/g, "-")
);
}
async function makeBuildCopyWindows(outputDir: string, productName: string) {
const platformDir =
process.arch === "arm64" ? "win-arm64-unpacked" : "win-unpacked";
const appDir = await makeBuildCopy(outputDir, platformDir);
return resolve(__dirname, "..", appDir, `${productName}.exe`);
}
async function makeBuildCopyMacOS(outputDir: string, productName: string) {
const platformDir = process.arch === "arm64" ? "mac-arm64" : "mac";
const appDir = await makeBuildCopy(outputDir, platformDir);
return resolve(
__dirname,
"..",
appDir,
`${productName}.app`,
"Contents",
"MacOS",
productName
);
}
async function makeBuildCopy(outputDir: string, platformDir: string) {
const appDir = outputDir;
await cp(join(SOURCE_DIR, platformDir), outputDir, {
recursive: true,
preserveTimestamps: true,
verbatimSymlinks: true,
dereference: false,
force: true
});
return appDir;
}
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,223 @@
/*
This file is part of the Notesnook project (https://notesnook.com/)
Copyright (C) 2023 Streetwriters (Private) Limited
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
const path = require("path");
const pkg = require("./package.json");
const buildRoot = process.env.NN_BUILD_ROOT || ".";
const buildFiles = [
`${buildRoot}/build/`,
`!${buildRoot}/build/screenshots\${/*}`,
`!${buildRoot}/build/banner.jpg`,
`!${buildRoot}/build/*.ico`,
`!${buildRoot}/build/*.png`
];
const productName = process.env.NN_PRODUCT_NAME || "Notesnook";
const appId = process.env.NN_APP_ID || "org.streetwriters.notesnook";
const outputDir = process.env.NN_OUTPUT_DIR || "output";
const linuxExecutableName = process.env.NN_PRODUCT_NAME
? process.env.NN_PRODUCT_NAME.toLowerCase().replace(/\s+/g, "-")
: "notesnook";
const year = new Date().getFullYear();
const isBeta = pkg.version.includes("-beta");
/**
* @type {import("app-builder-lib").Configuration}
*/
module.exports = {
appId: appId,
productName: productName,
copyright: `Copyright © ${year} Streetwriters (Private) Limited`,
artifactName: "notesnook_${os}_${arch}.${ext}",
generateUpdatesFilesForAllChannels: true,
asar: true,
asarUnpack: [
"node_modules/sqlite-better-trigram-@(linux|darwin|windows)-${arch}/**/*",
"node_modules/sqlite3-fts5-html-@(linux|darwin|windows)-${arch}/**/*"
],
files: [
"!*.chunk.js.map",
"!*.chunk.js.LICENSE.txt",
...buildFiles,
"!node_modules${/*}",
"node_modules/better-sqlite3-multiple-ciphers/build/Release/better_sqlite3.node",
"node_modules/better-sqlite3-multiple-ciphers/lib",
"node_modules/better-sqlite3-multiple-ciphers/package.json",
"node_modules/file-uri-to-path",
"node_modules/bindings",
"node_modules/node-gyp-build",
"node_modules/sqlite-better-trigram",
"node_modules/sqlite3-fts5-html",
"node_modules/sodium-native/prebuilds/${platform}-${arch}",
{
from: "node_modules/sqlite-better-trigram-linux-${arch}",
to: "node_modules/sqlite-better-trigram-linux-${arch}"
},
{
from: "node_modules/sqlite-better-trigram-darwin-${arch}",
to: "node_modules/sqlite-better-trigram-darwin-${arch}"
},
{
from: "node_modules/sqlite-better-trigram-windows-${arch}",
to: "node_modules/sqlite-better-trigram-windows-${arch}"
},
{
from: "node_modules/sqlite3-fts5-html-linux-${arch}",
to: "node_modules/sqlite3-fts5-html-linux-${arch}"
},
{
from: "node_modules/sqlite3-fts5-html-darwin-${arch}",
to: "node_modules/sqlite3-fts5-html-darwin-${arch}"
},
{
from: "node_modules/sqlite3-fts5-html-windows-${arch}",
to: "node_modules/sqlite3-fts5-html-windows-${arch}"
},
"node_modules/sodium-native/index.js",
"node_modules/sodium-native/package.json"
],
afterPack: "./scripts/removeLocales.js",
mac: {
bundleVersion: "240",
minimumSystemVersion: "10.12.0",
target: [
{
target: "dmg",
arch: ["arm64", "x64"]
},
{
target: "zip",
arch: ["arm64", "x64"]
}
],
category: "public.app-category.productivity",
darkModeSupport: true,
type: "distribution",
hardenedRuntime: true,
entitlements: "assets/entitlements.mac.plist",
entitlementsInherit: "assets/entitlements.mac.plist",
gatekeeperAssess: false,
icon: "assets/icons/app.icns",
notarize: true
},
dmg: {
contents: [
{
x: 130,
y: 220
},
{
x: 410,
y: 220,
type: "link",
path: "/Applications"
}
],
icon: "assets/icons/app.icns",
title: "Install Notesnook"
},
mas: {
entitlements: "assets/entitlements.mas.plist",
entitlementsInherit: "assets/entitlements.mas.inherit.plist",
entitlementsLoginHelper: "assets/entitlements.mas.loginhelper.plist",
hardenedRuntime: true
},
win: {
target: [
{
target: "nsis",
arch: ["x64", "arm64"]
},
{
target: "portable",
arch: ["x64", "arm64"]
}
],
signtoolOptions: {
signingHashAlgorithms: ["sha256"],
sign: "./scripts/sign.js"
},
icon: "assets/icons/app.ico"
},
portable: {
artifactName: "notesnook_${os}_${arch}_portable.${ext}"
},
nsis: {
oneClick: true,
createDesktopShortcut: "always",
deleteAppDataOnUninstall: true
},
linux: {
target: [
{
target: "AppImage",
arch: ["x64", "arm64"]
},
{
target: "snap",
arch: ["x64", "arm64"]
}
],
category: "Office",
icon: "assets/icons/app.icns",
description: "Your private note taking space",
executableName: linuxExecutableName,
desktop: {
desktopActions: {
"new-note": {
Name: "New note",
Exec: `${linuxExecutableName} new note`
},
"new-notebook": {
Name: "New notebook",
Exec: `${linuxExecutableName} new notebook`
},
"new-reminder": {
Name: "New reminder",
Exec: `${linuxExecutableName} new reminder`
}
}
}
},
snap: {
autoStart: false,
confinement: "strict",
allowNativeWayland: true,
base: "core22"
},
extraResources: ["app-update.yml", "./assets/**"],
extraMetadata: {
main: path.join(buildRoot, "build", "electron.js")
},
directories: {
buildResources: "assets",
output: outputDir
},
publish: [
{
provider: "github",
repo: "notesnook",
owner: "streetwriters",
channel: isBeta ? "beta" : "latest"
}
]
};

File diff suppressed because it is too large Load Diff

View File

@@ -2,13 +2,15 @@
"name": "@notesnook/desktop",
"productName": "Notesnook",
"description": "Your private note taking space",
"version": "3.0.20",
"version": "3.3.5",
"appAppleId": "1544027013",
"private": true,
"main": "./dist/cjs/index.js",
"module": "./dist/esm/index.js",
"types": "./dist/types/index.d.ts",
"sideEffects": false,
"sideEffects": [
"src/overrides.ts"
],
"exports": {
".": {
"require": {
@@ -25,241 +27,57 @@
"repository": "https://github.com/streetwriters/notesnook",
"license": "GPL-3.0-or-later",
"dependencies": {
"@lingui/core": "4.11.4",
"@lingui/core": "5.1.2",
"@notesnook/intl": "file:../../packages/intl",
"@notesnook/ui": "file:../../packages/ui",
"@trpc/client": "10.45.2",
"@trpc/server": "10.45.2",
"better-sqlite3-multiple-ciphers": "11.5.0",
"electron-trpc": "0.6.1",
"electron-updater": "^6.3.4",
"icojs": "^0.19.4",
"sqlite-better-trigram": "^0.0.2",
"better-sqlite3-multiple-ciphers": "^12.4.1",
"electron-trpc": "0.7.1",
"electron-updater": "^6.6.2",
"icojs": "^0.19.5",
"sqlite-better-trigram": "0.0.3",
"sqlite3-fts5-html": "^0.0.4",
"typed-emitter": "^2.1.0",
"yargs": "^17.7.2",
"zod": "^3.23.8"
"zod": "3.24.3"
},
"devDependencies": {
"@streetwriters/kysely": "^0.27.4",
"@types/node": "22.7.0",
"@types/node": "22.15.3",
"@types/yargs": "^17.0.33",
"chokidar": "^4.0.1",
"electron": "^31.7.4",
"electron-builder": "^25.1.8",
"esbuild": "^0.24.0",
"node-abi": "^3.68.0",
"node-gyp-build": "^4.8.2",
"playwright": "^1.48.2",
"chokidar": "^4.0.3",
"electron": "^37.0.0",
"electron-builder": "^26.0.12",
"esbuild": "0.21.5",
"node-abi": "^4.5.0",
"node-gyp-build": "^4.8.4",
"playwright": "1.48.2",
"prebuildify": "^6.0.1",
"slugify": "^1.6.6",
"slugify": "1.6.6",
"tree-kill": "^1.2.2",
"undici": "^6.19.8",
"vitest": "^2.1.5"
"undici": "^7.8.0",
"vitest": "^3.2.4"
},
"optionalDependencies": {
"dmg-license": "^1.0.11"
},
"overrides": {
"@electron/node-gyp": "^10.2.0-electron.2"
},
"scripts": {
"start": "node scripts/dev.mjs",
"staging": "node scripts/build.mjs --run",
"release": "node scripts/build.mjs",
"build": "node ../../scripts/build.mjs",
"bundle": "esbuild electron=./src/main.ts ./src/preload.ts --external:electron --external:fsevents --external:better-sqlite3-multiple-ciphers --external:sodium-native --minify --bundle --outdir=./build --platform=node --tsconfig=tsconfig.json --define:MAC_APP_STORE=false --define:RELEASE=true",
"bundle": "esbuild electron=./src/main.ts ./src/preload.ts --external:electron --external:fsevents --external:better-sqlite3-multiple-ciphers --external:sodium-native --bundle --outdir=./build --platform=node --tsconfig=tsconfig.json --define:MAC_APP_STORE=false --define:RELEASE=true",
"bundle:mas": "esbuild electron=./src/main.ts ./src/preload.ts --minify --external:electron --external:fsevents --bundle --outdir=./build --platform=node --tsconfig=tsconfig.json --define:MAC_APP_STORE=true --define:RELEASE=true",
"postinstall": "patch-package",
"test": "node --test --test-timeout 30000 --test-force-exit"
"test": "vitest run"
},
"author": {
"name": "Streetwriters (Private) Limited",
"email": "support@streetwriters.co",
"url": "https://streetwriters.co"
},
"build": {
"appId": "org.streetwriters.notesnook",
"productName": "Notesnook",
"copyright": "Copyright © 2023 Streetwriters (Private) Limited",
"artifactName": "notesnook_${os}_${arch}.${ext}",
"generateUpdatesFilesForAllChannels": true,
"asar": false,
"files": [
"!*.chunk.js.map",
"!*.chunk.js.LICENSE.txt",
"build/",
"!build/screenshots${/*}",
"!build/banner.jpg",
"!build/*.ico",
"!build/*.png",
"!node_modules${/*}",
"node_modules/better-sqlite3-multiple-ciphers/build/Release/better_sqlite3.node",
"node_modules/better-sqlite3-multiple-ciphers/lib",
"node_modules/better-sqlite3-multiple-ciphers/package.json",
"node_modules/file-uri-to-path",
"node_modules/bindings",
"node_modules/node-gyp-build",
"node_modules/sqlite-better-trigram",
"node_modules/sodium-native/prebuilds/${platform}-${arch}",
{
"from": "node_modules/sqlite-better-trigram-linux-${arch}",
"to": "node_modules/sqlite-better-trigram-linux-${arch}"
},
{
"from": "node_modules/sqlite-better-trigram-darwin-${arch}",
"to": "node_modules/sqlite-better-trigram-darwin-${arch}"
},
{
"from": "node_modules/sqlite-better-trigram-windows-${arch}",
"to": "node_modules/sqlite-better-trigram-windows-${arch}"
},
"node_modules/sodium-native/index.js",
"node_modules/sodium-native/package.json"
],
"afterPack": "./scripts/removeLocales.js",
"mac": {
"bundleVersion": "240",
"minimumSystemVersion": "10.12.0",
"target": [
{
"target": "dmg",
"arch": [
"arm64",
"x64"
]
},
{
"target": "zip",
"arch": [
"arm64",
"x64"
]
}
],
"category": "public.app-category.productivity",
"darkModeSupport": true,
"type": "distribution",
"hardenedRuntime": true,
"entitlements": "assets/entitlements.mac.plist",
"entitlementsInherit": "assets/entitlements.mac.plist",
"gatekeeperAssess": false,
"icon": "assets/icons/app.icns",
"notarize": true
},
"dmg": {
"contents": [
{
"x": 130,
"y": 220
},
{
"x": 410,
"y": 220,
"type": "link",
"path": "/Applications"
}
],
"icon": "assets/icons/app.icns",
"title": "Install Notesnook"
},
"mas": {
"entitlements": "assets/entitlements.mas.plist",
"entitlementsInherit": "assets/entitlements.mas.inherit.plist",
"entitlementsLoginHelper": "assets/entitlements.mas.loginhelper.plist",
"hardenedRuntime": true
},
"win": {
"target": [
{
"target": "nsis",
"arch": [
"x64",
"arm64"
]
},
{
"target": "portable",
"arch": [
"x64",
"arm64"
]
}
],
"signtoolOptions": {
"signingHashAlgorithms": [
"sha256"
],
"sign": "./scripts/sign.js"
},
"icon": "assets/icons/app.ico"
},
"portable": {
"artifactName": "notesnook_${os}_${arch}_portable.${ext}"
},
"nsis": {
"oneClick": true,
"createDesktopShortcut": "always",
"deleteAppDataOnUninstall": true
},
"linux": {
"target": [
{
"target": "AppImage",
"arch": [
"x64",
"arm64"
]
},
{
"target": "snap",
"arch": [
"x64",
"arm64"
]
}
],
"category": "Office",
"icon": "assets/icons/app.icns",
"description": "Your private note taking space",
"executableName": "notesnook",
"desktop": {
"actions": [
{
"id": "new-note",
"name": "New note",
"args": "new note"
},
{
"id": "new-notebook",
"name": "New notebook",
"args": "new notebook"
},
{
"id": "new-reminder",
"name": "New reminder",
"args": "new reminder"
}
]
}
},
"snap": {
"autoStart": false,
"confinement": "strict",
"allowNativeWayland": true
},
"extraResources": [
"app-update.yml",
"./assets/**"
],
"extraMetadata": {
"main": "./build/electron.js"
},
"directories": {
"buildResources": "assets",
"output": "./output/"
},
"publish": [
{
"provider": "github",
"repo": "notesnook",
"owner": "streetwriters"
}
]
}
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -17,60 +17,72 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
console.log("starting build...");
import path from "path";
import fs, { readFile, writeFile } from "fs/promises";
import { existsSync, readFileSync } from "fs";
import fs from "fs/promises";
import { existsSync } from "fs";
import yargs from "yargs-parser";
import os from "os";
import * as childProcess from "child_process";
import { fileURLToPath } from "url";
import { patchBetterSQLite3 } from "./patch-better-sqlite3.mjs";
console.log("imports done...");
const args = yargs(process.argv);
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const packageJson = JSON.parse(
readFileSync(path.join(__dirname, "..", "package.json"), "utf-8")
);
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 });
console.log("loaded args", {
args,
__filename,
__dirname,
root,
skipTscBuild,
webAppPath
});
await fs.rm(path.join(root, "build"), { force: true, recursive: true });
console.log("removed build folder");
if (args.rebuild || !existsSync(path.join(webAppPath, "build"))) {
console.log("rebuilding...");
await exec(
"yarn nx build:desktop @notesnook/web",
"node scripts/execute.mjs @notesnook/web:build:desktop",
path.join(__dirname, "..", "..", "..")
);
}
// temporary until there's support for prebuilt binaries for linux ARM
if (os.platform() === "linux") await patchBetterSQLite3();
await patchBetterSQLite3();
// if (os.platform() === "win32")
// await exec(
// `npx prebuildify --arch=arm64 --strip -t electron@${packageJson.devDependencies.electron}`,
// path.join(__dirname, "..", "node_modules", "sodium-native")
// );
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 --x64`);
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") {
await exec(`./output/mac/Notesnook.app/Contents/MacOS/Notesnook`);
if (process.arch === "arm64")
await exec(`./output/mac-arm64/Notesnook.app/Contents/MacOS/Notesnook`);
else await exec(`./output/mac/Notesnook.app/Contents/MacOS/Notesnook`);
} else {
await exec(`./output/linux-unpacked/Notesnook`);
}
@@ -83,21 +95,3 @@ async function exec(cmd, cwd) {
cwd: cwd || process.cwd()
});
}
async function patchBetterSQLite3() {
const jsonPath = path.join(
__dirname,
"..",
"node_modules",
"better-sqlite3-multiple-ciphers",
"package.json"
);
const json = JSON.parse(await readFile(jsonPath, "utf-8"));
json.version = "11.5.1";
json.homepage = "https://github.com/thecodrr/better-sqlite3-multiple-ciphers";
json.repository.url =
"git://github.com/thecodrr/better-sqlite3-multiple-ciphers.git";
await writeFile(jsonPath, JSON.stringify(json));
}

View File

@@ -70,8 +70,8 @@ async function onChange(first) {
if (first) {
await spawnAndWaitUntil(
["yarn", "nx", "start:desktop", "@notesnook/web"],
path.join(__dirname, "..", "..", ".."),
["npm", "run", "start:desktop"],
path.join(__dirname, "..", "..", "web"),
(data) => data.includes("Network: use --host to expose")
);
}

View File

@@ -0,0 +1,58 @@
/*
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 { readFile, rm, writeFile } from "fs/promises";
import path from "path";
import { fileURLToPath } from "url";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
export async function patchBetterSQLite3() {
console.log("Patching better-sqlite3");
const jsonPath = path.join(
__dirname,
"..",
"node_modules",
"better-sqlite3-multiple-ciphers",
"package.json"
);
const json = JSON.parse(await readFile(jsonPath, "utf-8"));
delete json.homepage;
delete json.repository;
await writeFile(jsonPath, JSON.stringify(json));
await rm(
path.join(
__dirname,
"..",
"node_modules",
"better-sqlite3-multiple-ciphers",
"build"
),
{ force: true, recursive: true }
);
}
if (process.argv[1] === __filename) {
patchBetterSQLite3();
}

View File

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

View File

@@ -33,6 +33,8 @@ export class SQLite {
initialized = false;
preparedStatements: Map<string, Statement<unknown[]>> = new Map();
retryCounter: Record<string, number> = {};
extensionsLoaded = false;
constructor() {
console.log("new sqlite worker");
}
@@ -46,8 +48,6 @@ export class SQLite {
this.sqlite = require("better-sqlite3-multiple-ciphers")(
filePath
).unsafeMode(true);
const betterTrigram = require("sqlite-better-trigram");
betterTrigram.load(this.sqlite);
}
/**
@@ -115,9 +115,29 @@ export class SQLite {
} catch (e) {
if (e instanceof Error) e.message += ` (query: ${sql})`;
throw e;
} finally {
// Since SQLite 3.48.0 (SQLite3MC v2.0.2) it's not possible to load fts5
// extensions before database has been decrypting. This is because
// executing a `SELECT` now accesses the underlying databases resulting in
// an error. Since FTS5 extensions depend on `SELECT fts5` to load the
// fts5 API, we must wait decrypt the database before we can load
// the extensions.
if (!this.extensionsLoaded && (await this.isDatabaseReady())) {
this.loadExtensions();
}
}
}
private loadExtensions() {
this.sqlite?.loadExtension(
getExtensionPath("sqlite-better-trigram", "better-trigram")
);
this.sqlite?.loadExtension(
getExtensionPath("sqlite3-fts5-html", "fts5-html")
);
this.extensionsLoaded = true;
}
async run<R>(
sql: string,
parameters?: SQLiteCompatibleType[]
@@ -142,4 +162,53 @@ export class SQLite {
retryDelay: 500
});
}
/**
* This just executes `SELECT 1` on the database to make sure its ready.
* On an encrypted database, this will fail until `PRAGMA key` has been
* called.
*/
private async isDatabaseReady() {
// return this.exec(`SELECT 1;`)
// .then(() => true)
// .catch(() => false);
if (!this.sqlite) return false;
try {
this.sqlite.prepare(`SELECT 1;`).run();
return true;
} catch {
return false;
}
}
}
function getExtensionPath(extensionName: string, entryPoint: string) {
const path = require("path");
const { statSync } = require("fs");
const os = process.platform === "win32" ? "windows" : process.platform;
const packageName = `${extensionName}-${os}-${process.arch}`;
const extensionSuffix =
process.platform === "win32"
? "dll"
: process.platform === "darwin"
? "dylib"
: "so";
let loadablePath = path.join(
require.resolve(extensionName),
"..",
"..",
packageName,
`${entryPoint}.${extensionSuffix}`
);
if (loadablePath.includes(".asar"))
loadablePath = loadablePath
.replace("electron.asar", "app.asar")
.replace(".asar", ".asar.unpacked");
if (!statSync(loadablePath, { throwIfNoEntry: false })) {
throw new Error(`${extensionName} not found at ${loadablePath}.`);
}
return loadablePath;
}

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

@@ -17,7 +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 { app, BrowserWindow, nativeTheme, shell } from "electron";
import "./overrides";
import { app, BrowserWindow, nativeTheme, shell, dialog } from "electron";
import { isDevelopment } from "./utils";
import { registerProtocol, PROTOCOL_URL } from "./utils/protocol";
import { configureAutoUpdater } from "./utils/autoupdater";
@@ -85,6 +86,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 +104,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 +148,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/"
);
@@ -171,6 +182,17 @@ async function createWindow() {
app.once("ready", async () => {
console.info("App ready. Opening window.");
if (app.runningUnderARM64Translation) {
console.log("App is running under ARM64 translation");
dialog.showMessageBoxSync({
message:
"Notesnook detected that it is running under ARM64 translation. For the best performance, please download the ARM64 build of Notesnook from our website.",
type: "warning",
buttons: ["Okay"],
title: "Degraded Performance Warning"
});
}
if (config.customDns) enableCustomDns();
else disableCustomDns();

View File

@@ -0,0 +1,41 @@
/*
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 { app } from "electron";
import path from "path";
const customVersion = process.env.CUSTOM_APP_VERSION;
if (customVersion) {
app.getVersion = () => customVersion;
console.log("setting custom version:", customVersion);
}
if (process.env.CUSTOM_USER_DATA_DIR) {
app.setPath(
"appData",
path.join(process.env.CUSTOM_USER_DATA_DIR, "AppData")
);
app.setPath(
"userData",
path.join(process.env.CUSTOM_USER_DATA_DIR, "UserData")
);
app.setPath(
"documents",
path.join(process.env.CUSTOM_USER_DATA_DIR, "Documents")
);
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,42 @@
/*
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: 120 * 1000,
hookTimeout: 120 * 1000,
sequence: {
concurrent: true,
shuffle: true
},
globalSetup: "./__tests__/global-setup.ts",
dir: "./__tests__/",
exclude: [
"**/node_modules/**",
"**/dist/**",
"**/cypress/**",
"**/.{idea,git,cache,output,temp}/**",
"**/{karma,rollup,webpack,vite,vitest,jest,ava,babel,nyc,cypress,tsup,build,eslint,prettier}.config.*",
"**/test-results/**",
"**/test-artifacts/**"
]
}
});

View File

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

View File

@@ -19,25 +19,30 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import { i18n } from "@lingui/core";
import { I18nProvider } from "@lingui/react";
import {
ScopedThemeProvider,
THEME_COMPATIBILITY_VERSION,
useThemeEngineStore
} from "@notesnook/theme";
import React, { useEffect } from "react";
import { I18nManager, View } from "react-native";
import { Appearance, I18nManager, StatusBar } from "react-native";
import "react-native-gesture-handler";
import { GestureHandlerRootView } from "react-native-gesture-handler";
import { SafeAreaProvider } from "react-native-safe-area-context";
import AppLockedOverlay from "./components/app-lock-overlay";
import DialogProvider from "./components/dialog-provider";
import { withErrorBoundry } from "./components/exception-handler";
import GlobalSafeAreaProvider from "./components/globalsafearea";
import { Toast } from "./components/toast";
import { useAppEvents } from "./hooks/use-app-events";
import { ApplicationHolder } from "./navigation";
import { NotePreviewConfigure } from "./screens/note-preview-configure";
import { RootNavigation } from "./navigation/navigation-stack";
import { themeTrpcClient } from "./screens/settings/theme-selector";
import Notifications from "./services/notifications";
import SettingsService from "./services/settings";
import { TipManager } from "./services/tip-manager";
import { useThemeStore } from "./stores/use-theme-store";
import { changeSystemBarColors, useThemeStore } from "./stores/use-theme-store";
import { useUserStore } from "./stores/use-user-store";
import RNBootSplash from "react-native-bootsplash";
import AppLocked from "./components/app-lock";
I18nManager.allowRTL(false);
I18nManager.forceRTL(false);
@@ -47,11 +52,13 @@ if (appLockEnabled || appLockMode !== "none") {
useUserStore.getState().lockApp(true);
}
const App = () => {
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();
@@ -61,39 +68,29 @@ const App = () => {
TipManager.init();
}, 100);
}, []);
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>
return (
<SafeAreaProvider>
<StatusBar translucent={true} backgroundColor="transparent" />
<GestureHandlerRootView
style={{
height: "100%",
width: "100%"
}}
>
<ApplicationHolder />
<GlobalSafeAreaProvider />
{props.configureMode === "note-preview" ? (
<NotePreviewConfigure />
) : (
<RootNavigation />
)}
<ScopedThemeProvider value="dialog">
<Toast />
</ScopedThemeProvider>
<DialogProvider />
<AppLocked />
</GestureHandlerRootView>
<AppLockedOverlay />
</View>
</SafeAreaProvider>
);
};
@@ -103,8 +100,8 @@ let currTheme =
: SettingsService.getProperty("lighTheme");
useThemeEngineStore.getState().setTheme(currTheme);
export const withTheme = (Element: () => JSX.Element) => {
return function AppWithThemeProvider() {
export const withTheme = (Element: (props: any) => JSX.Element) => {
return function AppWithThemeProvider(props: any) {
const [colorScheme, darkTheme, lightTheme] = useThemeStore((state) => [
state.colorScheme,
state.darkTheme,
@@ -123,28 +120,40 @@ export const withTheme = (Element: () => JSX.Element) => {
})
.then((theme) => {
if (theme) {
console.log(theme.version, "theme updated");
theme.colorScheme === "dark"
? useThemeStore.getState().setDarkTheme(theme)
: useThemeStore.getState().setLightTheme(theme);
}
})
.catch(console.log);
.catch(() => {
/* empty */
});
}, 1000);
const listener = Appearance.addChangeListener(({ colorScheme }) => {
if (colorScheme && SettingsService.getProperty("useSystemTheme")) {
useThemeStore.getState().setColorScheme(colorScheme);
}
});
return () => {
listener.remove();
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const nextTheme = colorScheme === "dark" ? darkTheme : lightTheme;
if (JSON.stringify(nextTheme) !== JSON.stringify(currTheme)) {
useThemeEngineStore
.getState()
.setTheme(colorScheme === "dark" ? darkTheme : lightTheme);
currTheme = nextTheme;
}
useEffect(() => {
const nextTheme = colorScheme === "dark" ? darkTheme : lightTheme;
if (JSON.stringify(nextTheme) !== JSON.stringify(currTheme)) {
useThemeEngineStore
.getState()
.setTheme(colorScheme === "dark" ? darkTheme : lightTheme);
currTheme = nextTheme;
}
}, [colorScheme, darkTheme, lightTheme]);
return (
<I18nProvider i18n={i18n}>
<Element />
<Element {...props} />
</I18nProvider>
);
};

File diff suppressed because one or more lines are too long

View File

@@ -1,385 +0,0 @@
/*
This file is part of the Notesnook project (https://notesnook.com/)
Copyright (C) 2023 Streetwriters (Private) Limited
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import Sodium from "@ammarahmed/react-native-sodium";
import { Platform } from "react-native";
import "react-native-get-random-values";
import * as Keychain from "react-native-keychain";
import { MMKVLoader, ProcessingModes } from "react-native-mmkv-storage";
import { generateSecureRandom } from "react-native-securerandom";
import { DatabaseLogger } from ".";
import { MMKV } from "./mmkv";
import { ToastManager } from "../../services/event-manager";
// Database key cipher is persisted across different user sessions hence it has
// it's independent storage which we will never clear. This is only used when application has
// app lock with password enabled.
export const CipherStorage = new MMKVLoader()
.withInstanceID("cipher_storage")
.setProcessingMode(
Platform.OS === "ios"
? ProcessingModes.MULTI_PROCESS
: ProcessingModes.SINGLE_PROCESS
)
.disableIndexing()
.initialize();
const IOS_KEYCHAIN_ACCESS_GROUP = "group.org.streetwriters.notesnook";
const IOS_KEYCHAIN_SERVICE_NAME = "org.streetwriters.notesnook";
const KEYCHAIN_SERVER_DBKEY = "notesnook:db";
const NOTESNOOK_APPLOCK_KEY_SALT = "kBwr1Kre86ebOZ8ThLu2OA";
const NOTESNOOK_DB_KEY_SALT = "SNuzOcEK3amoqL0WvPeKqw";
const DB_KEY_CIPHER = "databaseKeyCipher";
const USER_KEY_CIPHER = "userKeyCipher";
const APPLOCK_CIPHER = "applockCipher";
const KEYSTORE_CONFIG = Platform.select({
ios: {
accessible: Keychain.ACCESSIBLE.WHEN_UNLOCKED_THIS_DEVICE_ONLY,
accessGroup: IOS_KEYCHAIN_ACCESS_GROUP,
service: IOS_KEYCHAIN_SERVICE_NAME
},
android: {}
});
function generatePassword() {
const length = 80;
const crypto = window.crypto || window.msCrypto;
if (typeof crypto === "undefined") {
throw new Error(
"Crypto API is not supported. Please upgrade your web browser"
);
}
const charset =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!@#$%^&+_{}[]():<>/?;";
const indexes = crypto.getRandomValues(new Uint32Array(length));
let secret = "";
for (const index of indexes) {
secret += charset[index % charset.length];
}
return secret;
}
export async function encryptDatabaseKeyWithPassword(appLockPassword) {
const key = getDatabaseKey();
const appLockCredentials = await Sodium.deriveKey(
appLockPassword,
NOTESNOOK_APPLOCK_KEY_SALT
);
const databaseKeyCipher = await encrypt(appLockCredentials, key);
MMKV.setMap(DB_KEY_CIPHER, databaseKeyCipher);
// We reset the database key from keychain once app lock password is set.
await Keychain.resetInternetCredentials(KEYCHAIN_SERVER_DBKEY);
return true;
}
export async function restoreDatabaseKeyToKeyChain(appLockPassword) {
const databaseKeyCipher = CipherStorage.getMap(DB_KEY_CIPHER);
const databaseKey = await decrypt(
{
password: appLockPassword
},
databaseKeyCipher
);
await Keychain.setInternetCredentials(
KEYCHAIN_SERVER_DBKEY,
"notesnook",
databaseKey,
KEYSTORE_CONFIG
);
MMKV.removeItem(DB_KEY_CIPHER);
return true;
}
export async function setAppLockVerificationCipher(appLockPassword) {
try {
const appLockCredentials = await Sodium.deriveKey(
appLockPassword,
NOTESNOOK_APPLOCK_KEY_SALT
);
const encrypted = await encrypt(appLockCredentials, generatePassword());
CipherStorage.setMap(APPLOCK_CIPHER, encrypted);
DatabaseLogger.info("setAppLockVerificationCipher");
} catch (e) {
DatabaseLogger.error(e);
console.log(e);
}
}
export async function clearAppLockVerificationCipher() {
CipherStorage.removeItem(APPLOCK_CIPHER);
}
export async function validateAppLockPassword(appLockPassword) {
try {
const appLockCipher = CipherStorage.getMap(APPLOCK_CIPHER);
if (!appLockCipher) return true;
const key = await Sodium.deriveKey(appLockPassword, appLockCipher.salt);
const decrypted = await decrypt(key, appLockCipher);
DatabaseLogger.info(
`validateAppLockPassword: ${typeof decrypted === "string"}`
);
return typeof decrypted === "string";
} catch (e) {
DatabaseLogger.error(e);
return false;
}
}
let DB_KEY;
export function clearDatabaseKey() {
DB_KEY = undefined;
DatabaseLogger.info("Cleared database key");
}
export async function getDatabaseKey(appLockPassword) {
if (DB_KEY) return DB_KEY;
try {
if (appLockPassword) {
const databaseKeyCipher = CipherStorage.getMap("databaseKeyCipher");
const databaseKey = await decrypt(
{
password: appLockPassword
},
databaseKeyCipher
);
DatabaseLogger.info("Getting database key from cipher");
DB_KEY = databaseKey;
}
if (!DB_KEY) {
const hasKey = await Keychain.hasInternetCredentials(
KEYCHAIN_SERVER_DBKEY
);
if (hasKey) {
let credentials = await Keychain.getInternetCredentials(
KEYCHAIN_SERVER_DBKEY,
KEYSTORE_CONFIG
);
DatabaseLogger.info("Getting database key from Keychain");
DB_KEY = credentials.password;
}
}
if (!DB_KEY) {
DatabaseLogger.info("Generating new database key");
const password = generatePassword();
const derivedDatabaseKey = await Sodium.deriveKey(
password,
NOTESNOOK_DB_KEY_SALT
);
DB_KEY = derivedDatabaseKey.key;
await Keychain.setInternetCredentials(
KEYCHAIN_SERVER_DBKEY,
"notesnook",
DB_KEY,
KEYSTORE_CONFIG
);
}
if (await Keychain.hasInternetCredentials("notesnook")) {
const userKeyCredentials = await Keychain.getInternetCredentials(
"notesnook",
KEYSTORE_CONFIG
);
if (userKeyCredentials) {
const userKeyCipher = await encrypt(
{
key: DB_KEY,
salt: NOTESNOOK_DB_KEY_SALT
},
userKeyCredentials.password
);
// Store encrypted user key in MMKV
MMKV.setMap(USER_KEY_CIPHER, userKeyCipher);
await Keychain.resetInternetCredentials("notesnook");
}
DatabaseLogger.info("Migrated user credentials to cipher storage");
}
return DB_KEY;
} catch (e) {
ToastManager.error(e, "Error getting database key");
console.log(e, "error");
DatabaseLogger.error(e);
return null;
}
}
export async function deriveCryptoKey(data) {
try {
let credentials = await Sodium.deriveKey(data.password, data.salt);
const userKeyCipher = await encrypt(
{
key: await getDatabaseKey(),
salt: NOTESNOOK_DB_KEY_SALT
},
credentials.key
);
DatabaseLogger.info("User key stored: ", !!userKeyCipher);
// Store encrypted user key in MMKV
MMKV.setMap(USER_KEY_CIPHER, userKeyCipher);
return credentials.key;
} catch (e) {
DatabaseLogger.error(e);
}
}
export async function getCryptoKey(_name) {
try {
const keyCipher = MMKV.getMap(USER_KEY_CIPHER);
if (!keyCipher) {
DatabaseLogger.info("User key cipher is null");
return null;
}
const key = await decrypt(
{
key: await getDatabaseKey(),
salt: keyCipher.salt
},
keyCipher
);
return key;
} catch (e) {
console.log("getCryptoKey", e);
DatabaseLogger.error(e);
}
}
export async function removeCryptoKey(_name) {
try {
MMKV.removeItem(USER_KEY_CIPHER);
await Keychain.resetInternetCredentials("notesnook");
return true;
} catch (e) {
DatabaseLogger.error(e);
}
}
export async function getRandomBytes(length) {
return await generateSecureRandom(length);
}
export async function hash(password, email) {
let result = await Sodium.hashPassword(password, email);
return result;
}
export async function generateCryptoKey(password, salt) {
try {
let credentials = await Sodium.deriveKey(password, salt || null);
return credentials;
} catch (e) {
DatabaseLogger.error(e);
}
}
export function getAlgorithm(base64Variant) {
return `xcha-argon2i13-${base64Variant}`;
}
export async function decrypt(password, data) {
if (!password.password && !password.key) return undefined;
if (password.password && password.password === "" && !password.key)
return undefined;
let _data = { ...data };
_data.output = "plain";
if (!password.salt) password.salt = data.salt;
return await Sodium.decrypt(password, _data);
}
export async function decryptMulti(password, data) {
if (!password.password && !password.key) return undefined;
if (password.password && password.password === "" && !password.key)
return undefined;
data = data.map((d) => {
d.output = "plain";
return d;
});
if (data.length && !password.salt) {
password.salt = data[0].salt;
}
return await Sodium.decryptMulti(password, data);
}
export function parseAlgorithm(alg) {
if (!alg) return {};
const [enc, kdf, compressed, compressionAlg, base64variant] = alg.split("-");
return {
encryptionAlgorithm: enc,
kdfAlgorithm: kdf,
compressionAlgorithm: compressionAlg,
isCompress: compressed === "1",
base64_variant: base64variant
};
}
export async function encrypt(password, data) {
if (!password.password && !password.key) return undefined;
if (password.password && password.password === "" && !password.key)
return undefined;
let message = {
type: "plain",
data: data
};
let result = await Sodium.encrypt(password, message);
return {
...result,
alg: getAlgorithm(7)
};
}
export async function encryptMulti(password, data) {
if (!password.password && !password.key) return undefined;
if (password.password && password.password === "" && !password.key)
return undefined;
let results = await Sodium.encryptMulti(
password,
data.map((item) => ({
type: "plain",
data: item
}))
);
return !results
? []
: results.map((result) => ({
...result,
alg: getAlgorithm(7)
}));
}

View File

@@ -0,0 +1,479 @@
/*
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 Sodium, { Cipher, Password } from "@ammarahmed/react-native-sodium";
import { SerializedKey } from "@notesnook/crypto";
import { Platform } from "react-native";
import "react-native-get-random-values";
import * as Keychain from "react-native-keychain";
import { MMKVLoader, ProcessingModes } from "react-native-mmkv-storage";
import { generateSecureRandom } from "react-native-securerandom";
import { DatabaseLogger } from ".";
import { ToastManager } from "../../services/event-manager";
import { MMKV } from "./mmkv";
// Database key cipher is persisted across different user sessions hence it has
// it's independent storage which we will never clear. This is only used when application has
// app lock with password enabled.
export const CipherStorage = new MMKVLoader()
.withInstanceID("cipher_storage")
.setProcessingMode(
Platform.OS === "ios"
? ProcessingModes.MULTI_PROCESS
: ProcessingModes.SINGLE_PROCESS
)
.disableIndexing()
.initialize();
const IOS_KEYCHAIN_ACCESS_GROUP = "group.org.streetwriters.notesnook";
const IOS_KEYCHAIN_SERVICE_NAME = "org.streetwriters.notesnook";
const KEYCHAIN_SERVER_DBKEY = "notesnook:db";
const NOTESNOOK_APPLOCK_KEY_SALT = "kBwr1Kre86ebOZ8ThLu2OA";
const NOTESNOOK_DB_KEY_SALT = "SNuzOcEK3amoqL0WvPeKqw";
const DB_KEY_CIPHER = "databaseKeyCipher";
const USER_KEY_CIPHER = "userKeyCipher";
const APPLOCK_CIPHER = "applockCipher";
const KEYSTORE_CONFIG = Platform.select({
ios: {
accessible: Keychain.ACCESSIBLE.WHEN_UNLOCKED_THIS_DEVICE_ONLY,
accessGroup: IOS_KEYCHAIN_ACCESS_GROUP,
service: IOS_KEYCHAIN_SERVICE_NAME
},
android: {}
});
function generatePassword() {
const length = 80;
//@ts-ignore
const crypto = window.crypto || window.msCrypto;
if (typeof crypto === "undefined") {
throw new Error(
"Crypto API is not supported. Please upgrade your web browser"
);
}
const charset =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!@#$%^&+_{}[]():<>/?;";
const indexes = crypto.getRandomValues(new Uint32Array(length));
let secret = "";
for (const index of indexes) {
secret += charset[index % charset.length];
}
return secret;
}
export async function encryptDatabaseKeyWithPassword(appLockPassword: string) {
const key = (await getDatabaseKey()) as string;
const appLockCredentials = await Sodium.deriveKey(
appLockPassword,
NOTESNOOK_APPLOCK_KEY_SALT
);
const databaseKeyCipher = (await encrypt(appLockCredentials, key)) as Cipher;
MMKV.setMap(DB_KEY_CIPHER, databaseKeyCipher);
// We reset the database key from keychain once app lock password is set.
await Keychain.resetInternetCredentials(KEYCHAIN_SERVER_DBKEY);
return true;
}
export async function restoreDatabaseKeyToKeyChain(appLockPassword: string) {
const databaseKeyCipher: Cipher = CipherStorage.getMap(
DB_KEY_CIPHER
) as Cipher;
const databaseKey = (await decrypt(
{
password: appLockPassword
},
databaseKeyCipher
)) as string;
await Keychain.setInternetCredentials(
KEYCHAIN_SERVER_DBKEY,
"notesnook",
databaseKey,
KEYSTORE_CONFIG
);
MMKV.removeItem(DB_KEY_CIPHER);
return true;
}
export async function setAppLockVerificationCipher(appLockPassword: string) {
try {
const appLockCredentials = await Sodium.deriveKey(
appLockPassword,
NOTESNOOK_APPLOCK_KEY_SALT
);
const encrypted = (await encrypt(
appLockCredentials,
generatePassword()
)) as Cipher;
CipherStorage.setMap(APPLOCK_CIPHER, encrypted);
DatabaseLogger.info("setAppLockVerificationCipher");
} catch (e) {
DatabaseLogger.error(e);
}
}
export async function clearAppLockVerificationCipher() {
CipherStorage.removeItem(APPLOCK_CIPHER);
}
export async function validateAppLockPassword(appLockPassword: string) {
try {
const appLockCipher: Cipher = CipherStorage.getMap(
APPLOCK_CIPHER
) as Cipher;
if (!appLockCipher) return true;
const key = await Sodium.deriveKey(appLockPassword, appLockCipher.salt);
const decrypted = await decrypt(key, appLockCipher);
DatabaseLogger.info(
`validateAppLockPassword: ${typeof decrypted === "string"}`
);
return typeof decrypted === "string";
} catch (e) {
DatabaseLogger.error(e);
return false;
}
}
let DB_KEY: string | undefined;
export function clearDatabaseKey() {
DB_KEY = undefined;
DatabaseLogger.info("Cleared database key");
}
export async function getDatabaseKey(appLockPassword?: string) {
if (DB_KEY) return DB_KEY;
if (appLockPassword) {
const databaseKeyCipher: Cipher = CipherStorage.getMap(
"databaseKeyCipher"
) as Cipher;
const databaseKey = await decrypt(
{
password: appLockPassword
},
databaseKeyCipher
);
DatabaseLogger.info("Getting database key from cipher");
DB_KEY = databaseKey;
}
if (!DB_KEY) {
const hasKey = await Keychain.hasInternetCredentials(KEYCHAIN_SERVER_DBKEY);
if (hasKey) {
const credentials = await Keychain.getInternetCredentials(
KEYCHAIN_SERVER_DBKEY
);
DatabaseLogger.info("Getting database key from Keychain");
DB_KEY = (credentials as Keychain.UserCredentials).password;
}
}
if (!DB_KEY) {
DatabaseLogger.info("Generating new database key");
const password = generatePassword();
const derivedDatabaseKey = await Sodium.deriveKey(
password,
NOTESNOOK_DB_KEY_SALT
);
DB_KEY = derivedDatabaseKey.key as string;
await Keychain.setInternetCredentials(
KEYCHAIN_SERVER_DBKEY,
"notesnook",
DB_KEY,
KEYSTORE_CONFIG
);
}
if (await Keychain.hasInternetCredentials("notesnook")) {
const userKeyCredentials = await Keychain.getInternetCredentials(
"notesnook"
);
if (userKeyCredentials) {
const userKeyCipher: Cipher = (await encrypt(
{
key: DB_KEY,
salt: NOTESNOOK_DB_KEY_SALT
},
userKeyCredentials.password
)) as Cipher;
// Store encrypted user key in MMKV
MMKV.setMap(USER_KEY_CIPHER, userKeyCipher);
await Keychain.resetInternetCredentials("notesnook");
}
DatabaseLogger.info("Migrated user credentials to cipher storage");
}
if (!DB_KEY) {
throw new Error(
`Failed to get database key, ${await Keychain.hasInternetCredentials(
KEYCHAIN_SERVER_DBKEY
)}`
);
}
return DB_KEY;
}
export async function deriveCryptoKeyFallback(data: SerializedKey) {
if (Platform.OS !== "ios") return;
try {
if (!data.password || !data.salt)
throw new Error(
"Invalid password and salt provided to deriveCryptoKeyFallback"
);
const credentials = await Sodium.deriveKeyFallback?.(
data.password,
data.salt
);
if (!credentials) return;
const userKeyCipher = (await encrypt(
{
key: (await getDatabaseKey()) as string,
salt: NOTESNOOK_DB_KEY_SALT
},
credentials.key as string
)) as Cipher<"base64">;
DatabaseLogger.info("User key fallback stored: ", {
userKeyCipher: !!userKeyCipher
});
// Store encrypted user key in MMKV
MMKV.setMap(USER_KEY_CIPHER, userKeyCipher);
} catch (e) {
DatabaseLogger.error(e);
}
}
export async function deriveCryptoKey(data: SerializedKey) {
try {
if (!data.password || !data.salt)
throw new Error("Invalid password and salt provided to deriveCryptoKey");
const credentials = (await Sodium.deriveKey(
data.password,
data.salt
)) as Password;
const userKeyCipher = (await encrypt(
{
key: (await getDatabaseKey()) as string,
salt: NOTESNOOK_DB_KEY_SALT
},
credentials.key as string
)) as Cipher<"base64">;
DatabaseLogger.info("User key stored: ", {
userKeyCipher: !!userKeyCipher
});
// Store encrypted user key in MMKV
MMKV.setMap(USER_KEY_CIPHER, userKeyCipher);
} catch (e) {
DatabaseLogger.error(e);
}
}
export async function getCryptoKey() {
try {
const keyCipher: Cipher = MMKV.getMap(USER_KEY_CIPHER) as Cipher;
if (!keyCipher) {
DatabaseLogger.info("User key cipher is null");
return undefined;
}
const key = await decrypt(
{
key: (await getDatabaseKey()) as string,
salt: keyCipher.salt
},
keyCipher
);
return key;
} catch (e) {
DatabaseLogger.error(e);
}
}
export async function removeCryptoKey() {
try {
MMKV.removeItem(USER_KEY_CIPHER);
await Keychain.resetInternetCredentials("notesnook");
return true;
} catch (e) {
DatabaseLogger.error(e);
}
}
export async function getRandomBytes(length: number) {
return await generateSecureRandom(length);
}
export async function hash(
password: string,
email: string,
options?: { usesFallback?: boolean }
) {
DatabaseLogger.log(`Hashing password: fallback: ${options?.usesFallback}`);
if (options?.usesFallback && Platform.OS !== "ios") {
return "";
}
return (
options?.usesFallback
? await Sodium.hashPasswordFallback?.(password, email)
: await Sodium.hashPassword(password, email)
) as string;
}
export async function generateCryptoKey(password: string, salt?: string) {
return Sodium.deriveKey(password, salt) as Promise<SerializedKey>;
}
export async function generateCryptoKeyFallback(
password: string,
salt?: string
): Promise<SerializedKey> {
return Sodium.deriveKeyFallback?.(
password,
salt as string
) as Promise<SerializedKey>;
}
export function getAlgorithm(base64Variant: number) {
return `xcha-argon2i13-${base64Variant}`;
}
export async function decrypt(password: SerializedKey, data: Cipher<"base64">) {
const _data = { ...data };
_data.output = "plain";
if (!password.salt) password.salt = data.salt;
if (Platform.OS === "ios" && !password.key && password.password) {
const key = await Sodium.deriveKey(password.password, password.salt);
try {
return await Sodium.decrypt(key, _data);
} catch (e) {
const fallbackKey = await Sodium.deriveKeyFallback?.(
password.password,
password.salt
);
if (Platform.OS === "ios" && fallbackKey) {
DatabaseLogger.info("Using fallback key for decryption");
}
if (fallbackKey) {
return await Sodium.decrypt(fallbackKey, _data);
} else {
throw e;
}
}
}
return await Sodium.decrypt(password, _data);
}
export async function decryptMulti(
password: Password,
data: Cipher<"base64">[]
) {
data = data.map((d) => {
d.output = "plain";
return d;
});
if (data.length && !password.salt) {
password.salt = data[0].salt;
}
if (Platform.OS === "ios" && !password.key && password.password) {
const key = await Sodium.deriveKey(password.password, password.salt);
try {
return await Sodium.decryptMulti(key, data);
} catch (e) {
const fallbackKey = await Sodium.deriveKeyFallback?.(
password.password,
password.salt as string
);
if (Platform.OS === "ios" && fallbackKey) {
DatabaseLogger.info("Using fallback key for decryption");
}
if (fallbackKey) {
return await Sodium.decryptMulti(fallbackKey, data);
} else {
throw e;
}
}
}
return await Sodium.decryptMulti(password, data);
}
export function parseAlgorithm(alg: string) {
if (!alg) return {};
const [enc, kdf, compressed, compressionAlg, base64variant] = alg.split("-");
return {
encryptionAlgorithm: enc,
kdfAlgorithm: kdf,
compressionAlgorithm: compressionAlg,
isCompress: compressed === "1",
base64_variant: base64variant
};
}
export async function encrypt(password: SerializedKey, plainText: string) {
const result = await Sodium.encrypt<"base64">(password, {
type: "plain",
data: plainText
});
return {
...result,
alg: getAlgorithm(7)
};
}
export async function encryptMulti(
password: SerializedKey,
plainText: string[]
) {
const results = await Sodium.encryptMulti<"base64">(
password,
plainText.map((item) => ({
type: "plain",
data: item
}))
);
return !results
? []
: results.map((result) => ({
...result,
alg: getAlgorithm(7)
}));
}

View File

@@ -16,30 +16,40 @@ 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 "./logger";
import { database } from "@notesnook/common";
import { logger as dbLogger } from "@notesnook/core";
import { Platform } from "react-native";
import * as Gzip from "react-native-gzip";
import EventSource from "../../utils/sse/even-source-ios";
import AndroidEventSource from "../../utils/sse/event-source";
import { database, getFeature, getFeatureLimit } from "@notesnook/common";
import { logger as dbLogger, ICompressor } from "@notesnook/core";
import { strings } from "@notesnook/intl";
import {
SqliteAdapter,
SqliteIntrospector,
SqliteQueryCompiler
} from "@streetwriters/kysely";
import filesystem from "../filesystem";
import Storage from "./storage";
import { RNSqliteDriver } from "./sqlite.kysely";
import { Platform } from "react-native";
import * as Gzip from "react-native-gzip";
import EventSource from "../../utils/sse/even-source-ios";
import AndroidEventSource from "../../utils/sse/event-source";
import { FileStorage } from "../filesystem";
import { getDatabaseKey } from "./encryption";
import "./logger";
import { RNSqliteDriver } from "./sqlite.kysely";
import { Storage } from "./storage";
import SettingsService from "../../services/settings";
import { strings } from "@notesnook/intl";
export async function setupDatabase(password) {
export async function setupDatabase(password?: string) {
const key = await getDatabaseKey(password);
if (!key) throw new Error(strings.databaseSetupFailed());
console.log("Opening database with key:", !!key);
// const base = `http://192.168.100.92`;
// database.host({
// API_HOST: `${base}:5264`,
// AUTH_HOST: `${base}:8264`,
// SSE_HOST: `${base}:7264`,
// ISSUES_HOST: `${base}:2624`,
// SUBSCRIPTIONS_HOST: `${base}:9264`,
// MONOGRAPH_HOST: `${base}:6264`,
// NOTESNOOK_HOST: `${base}:8788`
// });
database.host({
API_HOST: "https://api.notesnook.com",
@@ -47,17 +57,22 @@ export async function setupDatabase(password) {
SSE_HOST: "https://events.streetwriters.co",
SUBSCRIPTIONS_HOST: "https://subscriptions.streetwriters.co",
ISSUES_HOST: "https://issues.streetwriters.co",
MONOGRAPH_HOST: "https://monogr.ph",
NOTESNOOK_HOST: "https://notesnook.com",
...(SettingsService.getProperty("serverUrls") || {})
});
database.setup({
storage: Storage,
eventsource: Platform.OS === "ios" ? EventSource : AndroidEventSource,
fs: filesystem,
compressor: () => ({
compress: Gzip.deflate,
decompress: Gzip.inflate
}),
eventsource: (Platform.OS === "ios"
? EventSource
: AndroidEventSource) as any,
fs: FileStorage,
compressor: async () =>
({
compress: Gzip.deflate,
decompress: Gzip.inflate
} as ICompressor),
batchSize: 100,
sqliteOptions: {
dialect: (name) => ({
@@ -71,6 +86,10 @@ export async function setupDatabase(password) {
tempStore: "memory",
journalMode: Platform.OS === "ios" ? "DELETE" : "WAL",
password: key
},
maxNoteVersions: async () => {
const limit = await getFeatureLimit(getFeature("maxNoteVersions"));
return typeof limit.caption === "number" ? limit.caption : undefined;
}
});
}

View File

@@ -26,7 +26,7 @@ import { CompiledQuery } from "@streetwriters/kysely";
import { QuickSQLiteConnection, open } from "react-native-quick-sqlite";
import { strings } from "@notesnook/intl";
type Config = { dbName: string; async: boolean; location: string };
type Config = { dbName: string; async: boolean; location?: string };
export class RNSqliteDriver implements Driver {
private connection?: DatabaseConnection;

View File

@@ -16,58 +16,52 @@ 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 { Platform } from "react-native";
import RNFetchBlob from "react-native-blob-util";
import { IStorage } from "@notesnook/core";
import { MMKVInstance } from "react-native-mmkv-storage";
import {
decrypt,
decryptMulti,
deriveCryptoKey,
deriveCryptoKeyFallback,
encrypt,
encryptMulti,
generateCryptoKey,
getCryptoKey,
getRandomBytes,
hash,
removeCryptoKey
generateCryptoKeyFallback
} from "./encryption";
import { MMKV } from "./mmkv";
export class KV {
/**
* @type {typeof MMKV}
*/
storage = null;
constructor(storage) {
storage: MMKVInstance;
constructor(storage: MMKVInstance) {
this.storage = storage;
}
async read(key) {
if (!key) return null;
let data = this.storage.getString(key);
if (!data) return null;
async read<T>(key: string, isArray?: boolean) {
if (!key) return undefined;
const data = this.storage.getString(key);
if (!data) return undefined;
try {
let parse = JSON.parse(data);
return parse;
return JSON.parse(data) as T;
} catch (e) {
return data;
return data as T;
}
}
async write(key, data) {
async write<T>(key: string, data: T) {
this.storage.setString(
key,
typeof data === "string" ? data : JSON.stringify(data)
);
return true;
}
async readMulti(keys) {
async readMulti<T>(keys: string[]) {
if (keys.length <= 0) {
return [];
} else {
try {
let data = await this.storage.getMultipleItemsAsync(
const data = await this.storage.getMultipleItemsAsync<any>(
keys.slice(),
"string"
);
@@ -79,24 +73,24 @@ export class KV {
obj = value;
}
return [key, obj];
});
}) as [string, T][];
} catch (e) {
console.log(e);
return [];
}
}
}
async remove(key) {
return this.storage.removeItem(key);
async remove(key: string) {
this.storage.removeItem(key);
}
async removeMulti(keys) {
if (!keys) return true;
return this.storage.removeItems(keys);
async removeMulti(keys: string[]) {
if (!keys) return;
this.storage.removeItems(keys);
}
async clear() {
return this.storage.clearStore();
this.storage.clearStore();
}
async getAllKeys() {
@@ -113,54 +107,52 @@ export class KV {
return keys;
}
async writeMulti(items) {
return this.storage.setMultipleItemsAsync(items, "object");
async writeMulti(items: [string, any][]) {
await this.storage.setMultipleItemsAsync(items, "object");
}
}
const DefaultStorage = new KV(MMKV);
async function requestPermission() {
if (Platform.OS === "ios") return true;
return true;
}
async function checkAndCreateDir(path) {
let dir =
Platform.OS === "ios"
? RNFetchBlob.fs.dirs.DocumentDir + path
: RNFetchBlob.fs.dirs.SDCardDir + "/Notesnook/" + path;
try {
let exists = await RNFetchBlob.fs.exists(dir);
let isDir = await RNFetchBlob.fs.isDir(dir);
if (!exists || !isDir) {
await RNFetchBlob.fs.mkdir(dir);
}
} catch (e) {
await RNFetchBlob.fs.mkdir(dir);
}
return dir;
}
export default {
read: (key) => DefaultStorage.read(key),
write: (key, value) => DefaultStorage.write(key, value),
readMulti: (keys) => DefaultStorage.readMulti(keys),
remove: (key) => DefaultStorage.remove(key),
clear: () => DefaultStorage.clear(),
getAllKeys: () => DefaultStorage.getAllKeys(),
writeMulti: (items) => DefaultStorage.writeMulti(items),
removeMulti: (keys) => DefaultStorage.removeMulti(keys),
export const Storage: IStorage = {
write<T>(key: string, data: T): Promise<void> {
return DefaultStorage.write(key, data);
},
writeMulti<T>(entries: [string, T][]): Promise<void> {
return DefaultStorage.writeMulti(entries);
},
readMulti<T>(keys: string[]): Promise<[string, T][]> {
return DefaultStorage.readMulti(keys);
},
read<T>(key: string, isArray?: boolean): Promise<T | undefined> {
return DefaultStorage.read(key, isArray);
},
remove(key: string): Promise<void> {
return DefaultStorage.remove(key);
},
removeMulti(keys: string[]): Promise<void> {
return DefaultStorage.removeMulti(keys);
},
clear(): Promise<void> {
return DefaultStorage.clear();
},
generateCryptoKeyPair() {
throw new Error("Not implemented");
},
decryptAsymmetric() {
throw new Error("Not implemented");
},
getAllKeys(): Promise<string[]> {
return DefaultStorage.getAllKeys();
},
hash,
getCryptoKey,
encrypt,
encryptMulti,
decrypt,
decryptMulti,
getRandomBytes,
checkAndCreateDir,
requestPermission,
deriveCryptoKey,
getCryptoKey,
removeCryptoKey,
hash,
generateCryptoKey,
encryptMulti
generateCryptoKeyFallback,
deriveCryptoKeyFallback
};

View File

@@ -27,13 +27,9 @@ import RNFetchBlob from "react-native-blob-util";
*/
export async function compressToBase64(path, type) {
const { width: screenWidth, scale } = Dimensions.get("window");
console.log("COMPRESSING TO BASE64...");
return new Promise((resolve) => {
console.log(path, "image path...");
Image.getSize(path, async (width) => {
console.log("image width", width);
const response = await ImageResizer.createResizedImage(
path,
screenWidth * scale,
@@ -55,10 +51,12 @@ export async function compressToBase64(path, type) {
: response.uri,
"base64"
);
RNFetchBlob.fs.unlink(path.replace("file://", "")).catch(console.log);
RNFetchBlob.fs
.unlink(response.uri.replace("file://", ""))
.catch(console.log);
RNFetchBlob.fs.unlink(path.replace("file://", "")).catch(() => {
/* empty */
});
RNFetchBlob.fs.unlink(response.uri.replace("file://", "")).catch(() => {
/* empty */
});
resolve(base64);
});
@@ -80,6 +78,8 @@ export async function compressToFile(path, type) {
onlyScaleDown: true
}
);
RNFetchBlob.fs.unlink(path.replace("file://", "")).catch(console.log);
RNFetchBlob.fs.unlink(path.replace("file://", "")).catch(() => {
/* empty */
});
return response.uri;
}

View File

@@ -16,7 +16,6 @@ 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 Sodium from "@ammarahmed/react-native-sodium";
import { getFileNameWithExtension } from "@notesnook/core";
import { strings } from "@notesnook/intl";
@@ -25,12 +24,12 @@ import { Platform } from "react-native";
import RNFetchBlob from "react-native-blob-util";
import * as ScopedStorage from "react-native-scoped-storage";
import { subscribe, zip } from "react-native-zip-archive";
import filesystem from ".";
import { ShareComponent } from "../../components/sheets/export-notes/share";
import { ToastManager, presentSheet } from "../../services/event-manager";
import { presentSheet, ToastManager } from "../../services/event-manager";
import { useAttachmentStore } from "../../stores/use-attachment-store";
import { IOS_APPGROUPID } from "../../utils/constants";
import { DatabaseLogger, db } from "../database";
import Storage from "../database/storage";
import { createCacheDir, exists } from "./io";
import { cacheDir, copyFileAsync, releasePermissions } from "./utils";
@@ -51,23 +50,23 @@ export async function downloadAllAttachments() {
/**
* Downloads provided attachments to a .zip file
* on user's device.
* @param {string[]} attachments
* @param {string[]} attachmentIds
* @param onProgress
* @returns
*/
export async function downloadAttachments(attachments) {
export async function downloadAttachments(attachmentIds: string[]) {
await createCacheDir();
if (!attachments || !attachments.length) return;
if (!attachmentIds || !attachmentIds.length) return;
const groupId = `download-all-${Date.now()}`;
let outputFolder;
if (Platform.OS === "android") {
// Ask the user to select a directory to store the file
let file = await ScopedStorage.openDocumentTree(true);
const file = await ScopedStorage.openDocumentTree(true);
outputFolder = file.uri;
if (!outputFolder) return;
} else {
outputFolder = await Storage.checkAndCreateDir("/downloads/");
outputFolder = await filesystem.checkAndCreateDir("/downloads/");
}
// Create the folder to zip;
@@ -83,8 +82,10 @@ export async function downloadAttachments(attachments) {
await RNFetchBlob.fs.mkdir(zipSourceFolder);
const isCancelled = () => {
if (useAttachmentStore.getState().downloading[groupId]?.canceled) {
RNFetchBlob.fs.unlink(zipSourceFolder).catch(console.log);
if (useAttachmentStore.getState().downloading?.[groupId]?.canceled) {
RNFetchBlob.fs.unlink(zipSourceFolder).catch(() => {
/* empty */
});
useAttachmentStore.getState().setDownloading({
groupId,
current: 0,
@@ -97,19 +98,21 @@ export async function downloadAttachments(attachments) {
}
};
for (let i = 0; i < attachments.length; i++) {
for (let i = 0; i < attachmentIds.length; i++) {
if (isCancelled()) return;
let attachment = await db.attachments.attachment(attachments[i]);
const attachment = await db.attachments.attachment(attachmentIds[i]);
if (!attachment) continue;
const hash = attachment.hash;
try {
useAttachmentStore.getState().setDownloading({
groupId: groupId,
current: i + 1,
total: attachments.length,
total: attachmentIds.length,
filename: attachment.hash
});
// Download to cache
let uri = await downloadAttachment(hash, false, {
const uri = await downloadAttachment(hash, false, {
silent: true,
cache: true,
groupId: groupId
@@ -184,59 +187,85 @@ export async function downloadAttachments(attachments) {
});
releasePermissions(outputFolder);
sub?.remove();
ToastManager.error(e, "Error zipping attachments");
ToastManager.error(e as Error, "Error zipping attachments");
}
// Remove source & zip file from cache.
RNFetchBlob.fs.unlink(zipSourceFolder).catch(console.log);
RNFetchBlob.fs.unlink(zipSourceFolder).catch(() => {
/* empty */
});
if (Platform.OS === "android") {
RNFetchBlob.fs.unlink(zipOutputFile).catch(console.log);
RNFetchBlob.fs.unlink(zipOutputFile).catch(() => {
/* empty */
});
}
}
export default async function downloadAttachment(
hash,
hashOrId: string,
global = true,
options = {
silent: false,
cache: false,
throwError: false,
groupId: undefined,
base64: false,
text: false
options?: {
silent?: boolean;
cache?: boolean;
throwError?: boolean;
groupId?: string;
base64?: boolean;
text?: boolean;
}
) {
await createCacheDir();
let attachment = await db.attachments.attachment(hash);
const attachment = await db.attachments.attachment(hashOrId);
if (!attachment) {
DatabaseLogger.log("Attachment not found");
DatabaseLogger.log("Attachment not found", {
hash: hashOrId
});
return;
}
let folder = {};
if (!options.cache) {
let folder: {
uri: string;
} | null = null;
if (!options?.cache) {
if (Platform.OS === "android") {
folder = await ScopedStorage.openDocumentTree();
if (!folder) return;
} else {
folder.uri = await Storage.checkAndCreateDir("/downloads/");
folder = {
uri: await filesystem.checkAndCreateDir("/downloads/")
};
}
}
try {
useAttachmentStore.getState().setDownloading({
groupId: options?.groupId || attachment.hash,
current: 0,
total: 1,
filename: attachment.filename
});
await db
.fs()
.downloadFile(
options.groupId || attachment.hash,
options?.groupId || attachment.hash,
attachment.hash,
attachment.chunkSize
);
useAttachmentStore.getState().setDownloading({
groupId: options?.groupId || attachment.hash,
current: 1,
total: 1,
filename: attachment.filename,
success: true
});
if (!(await exists(attachment.hash))) {
DatabaseLogger.log("Attachment does not exist after download.");
return;
}
if (options.base64 || options.text) {
if (options?.base64 || options?.text) {
DatabaseLogger.log(`Starting to decrypt... hash: ${attachment.hash}`);
return await db.attachments.read(
attachment.hash,
@@ -244,14 +273,16 @@ export default async function downloadAttachment(
);
}
let filename = await getFileNameWithExtension(
const filename = await getFileNameWithExtension(
attachment.filename,
attachment.mimeType
);
let key = await db.attachments.decryptKey(attachment.key);
const key = await db.attachments.decryptKey(attachment.key);
let info = {
if (!key) return;
const info = {
iv: attachment.iv,
salt: attachment.salt,
length: attachment.size,
@@ -259,18 +290,18 @@ export default async function downloadAttachment(
hash: attachment.hash,
hashType: attachment.hashType,
mime: attachment.mimeType,
fileName: options.cache ? undefined : filename,
uri: options.cache ? undefined : folder.uri,
fileName: options?.cache ? undefined : filename,
uri: options?.cache ? undefined : folder?.uri,
chunkSize: attachment.chunkSize,
appGroupId: IOS_APPGROUPID
};
let fileUri = await Sodium.decryptFile(
key,
info,
options.cache ? "cache" : "file"
options?.cache ? "cache" : "file"
);
if (!options.silent) {
if (!options?.silent) {
ToastManager.show({
heading: strings.network.downloadSuccess(),
message: strings.network.fileDownloaded(filename),
@@ -278,15 +309,15 @@ export default async function downloadAttachment(
});
}
if (Platform.OS === "ios" && !options.cache) {
fileUri = folder.uri + `/${filename}`;
if (Platform.OS === "ios" && !options?.cache) {
fileUri = folder?.uri + `/${filename}`;
}
if (!options.silent) {
if (!options?.silent) {
presentSheet({
title: strings.network.fileDownloaded(),
paragraph: strings.fileSaved(filename, Platform.OS),
icon: "download",
context: global ? null : attachment.hash,
context: global ? "global" : attachment.hash,
component: <ShareComponent uri={fileUri} name={filename} padding={12} />
});
}
@@ -296,14 +327,26 @@ export default async function downloadAttachment(
if (attachment.dateUploaded) {
RNFetchBlob.fs
.unlink(RNFetchBlob.fs.dirs.CacheDir + `/${attachment.hash}`)
.catch(console.log);
.catch(() => {
/* empty */
});
RNFetchBlob.fs
.unlink(RNFetchBlob.fs.dirs.CacheDir + `/${attachment.hash}_dcache`)
.catch(console.log);
.catch(() => {
/* empty */
});
}
useAttachmentStore.getState().setDownloading({
groupId: options?.groupId || attachment.hash,
current: 0,
total: 0,
filename: attachment.filename,
success: false
});
DatabaseLogger.error(e);
useAttachmentStore.getState().remove(attachment.hash);
if (options.throwError) {
if (options?.throwError) {
throw e;
}
}

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 { RequestOptions } from "@notesnook/core";
import { strings } from "@notesnook/intl";
import NetInfo from "@react-native-community/netinfo";
import RNFetchBlob from "react-native-blob-util";
@@ -26,7 +27,13 @@ import { DatabaseLogger, db } from "../database";
import { createCacheDir, exists } from "./io";
import { ABYTES, cacheDir, getUploadedFileSize, parseS3Error } from "./utils";
export async function downloadFile(filename, requestOptions, cancelToken) {
export async function downloadFile(
filename: string,
requestOptions: RequestOptions,
cancelToken: {
cancel: (reason?: string) => Promise<void>;
}
) {
if (!requestOptions) {
DatabaseLogger.log(
`Error downloading file: ${filename}, reason: No requestOptions`
@@ -36,9 +43,11 @@ export async function downloadFile(filename, requestOptions, cancelToken) {
DatabaseLogger.log(`Downloading ${filename}`);
await createCacheDir();
let { url, headers, chunkSize } = requestOptions;
let tempFilePath = `${cacheDir}/${filename}_temp`;
let originalFilePath = `${cacheDir}/${filename}`;
const { url, headers, chunkSize } = requestOptions;
const tempFilePath = `${cacheDir}/${filename}_temp`;
const originalFilePath = `${cacheDir}/${filename}`;
try {
if (await exists(filename)) {
DatabaseLogger.log(`File Exists already: ${filename}`);
@@ -46,6 +55,8 @@ export async function downloadFile(filename, requestOptions, cancelToken) {
}
const attachment = await db.attachments.attachment(filename);
if (!attachment) return false;
const size = await getUploadedFileSize(filename);
if (size === -1) {
@@ -71,21 +82,21 @@ export async function downloadFile(filename, requestOptions, cancelToken) {
throw new Error(error);
}
let res = await fetch(url, {
const resolveUrlResponse = await fetch(url, {
method: "GET",
headers
});
if (!res.ok) {
if (!resolveUrlResponse.ok) {
DatabaseLogger.log(
`Error downloading file: ${filename}, ${res.status}, ${res.statusText}, reason: Unable to resolve download url`
`Error downloading file: ${filename}, ${resolveUrlResponse.status}, ${resolveUrlResponse.statusText}, reason: Unable to resolve download url`
);
throw new Error(
`${res.status}: ${strings.failedToResolvedDownloadUrl()}`
`${resolveUrlResponse.status}: ${strings.failedToResolvedDownloadUrl()}`
);
}
const downloadUrl = await res.text();
const downloadUrl = await resolveUrlResponse.text();
if (!downloadUrl) {
DatabaseLogger.log(
@@ -95,12 +106,12 @@ export async function downloadFile(filename, requestOptions, cancelToken) {
}
DatabaseLogger.log(`Download starting: ${filename}`);
let request = RNFetchBlob.config({
const request = RNFetchBlob.config({
path: tempFilePath,
IOSBackgroundTask: true,
overwrite: true
})
.fetch("GET", downloadUrl, null)
.fetch("GET", downloadUrl)
.progress(async (recieved, total) => {
useAttachmentStore
.getState()
@@ -109,15 +120,16 @@ export async function downloadFile(filename, requestOptions, cancelToken) {
DatabaseLogger.log(`Downloading: ${filename}, ${recieved}/${total}`);
});
cancelToken.cancel = () => {
cancelToken.cancel = async (reason) => {
useAttachmentStore.getState().remove(filename);
request.cancel();
RNFetchBlob.fs.unlink(tempFilePath).catch(console.log);
DatabaseLogger.log(`Download cancelled: ${filename}`);
RNFetchBlob.fs.unlink(tempFilePath).catch(() => {
/* empty */
});
DatabaseLogger.log(`Download cancelled: ${reason} ${filename}`);
};
let response = await request;
console.log(response.info().headers);
const response = await request;
const contentType =
response.info().headers?.["content-type"] ||
@@ -128,14 +140,18 @@ export async function downloadFile(filename, requestOptions, cancelToken) {
throw new Error(`[${error.Code}] ${error.Message}`);
}
let status = response.info().status;
const status = response.info().status;
useAttachmentStore.getState().remove(filename);
if (exists(originalFilePath)) {
await RNFetchBlob.fs.unlink(originalFilePath).catch(console.log);
if (await exists(originalFilePath)) {
await RNFetchBlob.fs.unlink(originalFilePath).catch(() => {
/* empty */
});
}
await RNFetchBlob.fs.mv(tempFilePath, originalFilePath);
await RNFetchBlob.fs.mv(tempFilePath, originalFilePath).catch(() => {
/* empty */
});
if (!(await exists(filename))) {
throw new Error("File size mismatch");
@@ -143,11 +159,14 @@ export async function downloadFile(filename, requestOptions, cancelToken) {
return status >= 200 && status < 300;
} catch (e) {
if (e.message !== "canceled" && !e.message.includes("NoSuchKey")) {
if (
(e as Error).message !== "canceled" &&
!(e as Error).message.includes("NoSuchKey")
) {
const toast = {
heading: strings.downloadError(),
message: e.message,
type: "error",
heading: strings.downloadError((e as Error).message),
message: (e as Error).message,
type: "error" as const,
context: "global"
};
ToastManager.show(toast);
@@ -156,17 +175,20 @@ export async function downloadFile(filename, requestOptions, cancelToken) {
}
useAttachmentStore.getState().remove(filename);
RNFetchBlob.fs.unlink(tempFilePath).catch(console.log);
RNFetchBlob.fs.unlink(originalFilePath).catch(console.log);
DatabaseLogger.error(e, {
url,
headers
RNFetchBlob.fs.unlink(tempFilePath).catch(() => {
/* empty */
});
RNFetchBlob.fs.unlink(originalFilePath).catch(() => {
/* empty */
});
DatabaseLogger.error(e, "Download failed: ", {
url
});
return false;
}
}
export async function checkAttachment(hash) {
export async function checkAttachment(hash: string) {
const internetState = await NetInfo.fetch();
const isInternetReachable =
internetState.isConnected && internetState.isInternetReachable;
@@ -176,7 +198,7 @@ export async function checkAttachment(hash) {
try {
const size = await getUploadedFileSize(hash);
console.log("File Size", size);
if (size === -1) return { success: true };
if (size === 0)
@@ -184,7 +206,7 @@ export async function checkAttachment(hash) {
failed: `File length is 0. Please upload this file again from the attachment manager. (File hash: ${hash})`
};
} catch (e) {
return { failed: e?.message };
return { failed: (e as Error)?.message };
}
return { success: true };
}

View File

@@ -17,24 +17,41 @@ 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 { IFileStorage } from "@notesnook/core";
import { checkAttachment, downloadFile } from "./download";
import {
bulkExists,
clearCache,
clearFileStorage,
deleteCacheFileByName,
deleteCacheFileByPath,
deleteFile,
exists,
readEncrypted,
writeEncryptedBase64,
getCacheSize,
hashBase64,
readEncrypted,
writeEncryptedBase64
} from "./io";
import { uploadFile } from "./upload";
import {
cancelable,
checkAndCreateDir,
getUploadedFileSize,
requestPermission
} from "./utils";
export default {
checkAttachment,
clearCache,
deleteCacheFileByName,
deleteCacheFileByPath,
bulkExists,
getCacheSize
} from "./io";
import { uploadFile } from "./upload";
import { cancelable, getUploadedFileSize } from "./utils";
getCacheSize,
requestPermission,
checkAndCreateDir,
getUploadedFileSize
};
export default {
export const FileStorage: IFileStorage = {
readEncrypted,
writeEncryptedBase64,
hashBase64,
@@ -44,10 +61,5 @@ export default {
exists,
clearFileStorage,
getUploadedFileSize,
checkAttachment,
clearCache,
deleteCacheFileByName,
deleteCacheFileByPath,
bulkExists,
getCacheSize
bulkExists
};

View File

@@ -18,6 +18,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import Sodium from "@ammarahmed/react-native-sodium";
import {
FileEncryptionMetadataWithHash,
FileEncryptionMetadataWithOutputType,
Output,
RequestOptions
} from "@notesnook/core";
import { DataFormat, SerializedKey } from "@notesnook/crypto";
import { Platform } from "react-native";
import RNFetchBlob from "react-native-blob-util";
import { eSendEvent } from "../../services/event-manager";
@@ -25,17 +32,21 @@ import { IOS_APPGROUPID } from "../../utils/constants";
import { DatabaseLogger, db } from "../database";
import { ABYTES, cacheDir, cacheDirOld, getRandomId } from "./utils";
export async function readEncrypted(filename, key, cipherData) {
export async function readEncrypted<TOutputFormat extends DataFormat>(
filename: string,
key: SerializedKey,
cipherData: FileEncryptionMetadataWithOutputType<TOutputFormat>
) {
await migrateFilesFromCache();
DatabaseLogger.log("Read encrypted file...");
let path = `${cacheDir}/${filename}`;
const path = `${cacheDir}/${filename}`;
try {
if (!(await exists(filename))) {
return false;
return;
}
let output = await Sodium.decryptFile(
const output = await Sodium.decryptFile(
key,
{
...cipherData,
@@ -47,15 +58,16 @@ export async function readEncrypted(filename, key, cipherData) {
DatabaseLogger.log("File decrypted...");
return output;
return output as Output<TOutputFormat>;
} catch (e) {
RNFetchBlob.fs.unlink(path).catch(console.log);
RNFetchBlob.fs.unlink(path).catch(() => {
/* empty */
});
DatabaseLogger.error(e);
return false;
}
}
export async function hashBase64(data) {
export async function hashBase64(data: string) {
const hash = await Sodium.hashFile({
type: "base64",
data,
@@ -67,61 +79,80 @@ export async function hashBase64(data) {
};
}
export async function writeEncryptedBase64(data, key) {
export async function writeEncryptedBase64(
data: string,
encryptionKey: SerializedKey,
mimeType: string
): Promise<FileEncryptionMetadataWithHash> {
await createCacheDir();
let filepath = cacheDir + `/${getRandomId("imagecache_")}`;
const filepath = cacheDir + `/${getRandomId("imagecache_")}`;
await RNFetchBlob.fs.writeFile(filepath, data, "base64");
let output = await Sodium.encryptFile(key, {
const output = await Sodium.encryptFile(encryptionKey, {
uri: Platform.OS === "ios" ? filepath : "file://" + filepath,
type: "url"
});
RNFetchBlob.fs.unlink(filepath).catch(console.log);
console.log("encrypted file output: ", output);
output.size = output.length;
delete output.length;
RNFetchBlob.fs.unlink(filepath).catch(() => {
/* empty */
});
return {
...output,
alg: "xcha-stream"
};
}
export async function deleteFile(filename, data) {
export async function deleteFile(
filename: string,
requestOptions?: RequestOptions
): Promise<boolean> {
await createCacheDir();
let delFilePath = cacheDir + `/${filename}`;
if (!data) {
if (!filename) return;
RNFetchBlob.fs.unlink(delFilePath).catch(console.log);
const localFilePath = cacheDir + `/${filename}`;
if (!requestOptions) {
RNFetchBlob.fs.unlink(localFilePath).catch(() => {
/* empty */
});
return true;
}
let { url, headers } = data;
const { url, headers } = requestOptions;
try {
let response = await RNFetchBlob.fetch("DELETE", url, headers);
let status = response.info().status;
let ok = status >= 200 && status < 300;
const response = await RNFetchBlob.fetch("DELETE", url, headers);
const status = response.info().status;
const ok = status >= 200 && status < 300;
if (ok) {
RNFetchBlob.fs.unlink(delFilePath).catch(console.log);
RNFetchBlob.fs.unlink(localFilePath).catch(() => {
/* empty */
});
}
return ok;
} catch (e) {
console.log("delete file: ", e, url, headers);
DatabaseLogger.error(e, "Delete file", {
url: url
});
return false;
}
}
export async function clearFileStorage() {
try {
let files = await RNFetchBlob.fs.ls(cacheDir);
let oldCache = await RNFetchBlob.fs.ls(cacheDirOld);
await createCacheDir();
const files = await RNFetchBlob.fs.ls(cacheDir);
const oldCache = await RNFetchBlob.fs.ls(cacheDirOld);
for (let file of files) {
await RNFetchBlob.fs.unlink(cacheDir + `/${file}`).catch(console.log);
for (const file of files) {
await RNFetchBlob.fs.unlink(cacheDir + `/${file}`).catch(() => {
/* empty */
});
}
for (let file of oldCache) {
await RNFetchBlob.fs.unlink(cacheDirOld + `/${file}`).catch(console.log);
for (const file of oldCache) {
await RNFetchBlob.fs.unlink(cacheDirOld + `/${file}`).catch(() => {
/* empty */
});
}
} catch (e) {
console.log("clearFileStorage", e);
DatabaseLogger.error(e, "clearFileStorage");
}
}
@@ -142,62 +173,92 @@ export async function migrateFilesFromCache() {
const migratedFilesPath = cacheDir + "/.migrated_1";
const migrated = await RNFetchBlob.fs.exists(migratedFilesPath);
if (migrated) {
console.log("Files migrated already");
return;
}
let files = await RNFetchBlob.fs.ls(cacheDir);
console.log("Files to migrate:", files.join(","));
const files = await RNFetchBlob.fs.ls(cacheDir);
let oldCache = await RNFetchBlob.fs.ls(cacheDirOld);
for (let file of oldCache) {
const oldCache = await RNFetchBlob.fs.ls(cacheDirOld);
for (const file of oldCache) {
if (file.startsWith("org.") || file.startsWith("com.")) continue;
RNFetchBlob.fs
.mv(cacheDirOld + `/${file}`, cacheDir + `/${file}`)
.catch(console.log);
console.log("Moved", file);
.catch(() => {
/* empty */
});
}
await RNFetchBlob.fs.createFile(migratedFilesPath, "1", "utf8");
} catch (e) {
console.log("migrateFilesFromCache", e);
DatabaseLogger.error(e, "migrateFilesFromCache");
}
}
export async function clearCache() {
await RNFetchBlob.fs.unlink(cacheDir).catch(console.log);
await RNFetchBlob.fs.unlink(cacheDir).catch(() => {
/* empty */
});
await createCacheDir();
eSendEvent("cache-cleared");
}
export async function deleteCacheFileByPath(path) {
await RNFetchBlob.fs.unlink(path).catch(console.log);
export async function deleteCacheFileByPath(path: string) {
await RNFetchBlob.fs.unlink(path).catch(() => {
/* empty */
});
}
export async function deleteCacheFileByName(name) {
export async function deleteCacheFileByName(name: string) {
const iosAppGroup =
Platform.OS === "ios"
? await RNFetchBlob.fs.pathForAppGroup(IOS_APPGROUPID)
? await (RNFetchBlob.fs as any).pathForAppGroup(IOS_APPGROUPID)
: null;
const appGroupPath = `${iosAppGroup}/${name}`;
await RNFetchBlob.fs.unlink(appGroupPath).catch(console.log);
await RNFetchBlob.fs.unlink(`${cacheDir}/${name}`).catch(console.log);
await RNFetchBlob.fs.unlink(appGroupPath).catch(() => {
/* empty */
});
await RNFetchBlob.fs.unlink(`${cacheDir}/${name}`).catch(() => {
/* empty */
});
}
export async function deleteDCacheFiles() {
await createCacheDir();
const files = await RNFetchBlob.fs.ls(cacheDir);
for (const file of files) {
if (file.includes("_dcache")) {
await RNFetchBlob.fs.unlink(file).catch(console.log);
if (file.includes("_dcache") || file.startsWith("NN_")) {
await RNFetchBlob.fs.unlink(file).catch(() => {
/* empty */
});
}
}
}
export async function exists(filename) {
let path = `${cacheDir}/${filename}`;
export async function getCachePathForFile(filename: string) {
const path = `${cacheDir}/${filename}`;
const iosAppGroup =
Platform.OS === "ios"
? await RNFetchBlob.fs.pathForAppGroup(IOS_APPGROUPID)
? 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}`;
const iosAppGroup =
Platform.OS === "ios"
? await (RNFetchBlob.fs as any).pathForAppGroup(IOS_APPGROUPID)
: null;
const appGroupPath = `${iosAppGroup}/${filename}`;
@@ -211,6 +272,7 @@ export async function exists(filename) {
if (exists || existsInAppGroup) {
const attachment = await db.attachments.attachment(filename);
if (!attachment) return false;
const totalChunks = Math.ceil(attachment.size / attachment.chunkSize);
const totalAbytes = totalChunks * ABYTES;
const expectedFileSize = attachment.size + totalAbytes;
@@ -225,7 +287,9 @@ export async function exists(filename) {
);
RNFetchBlob.fs
.unlink(existsInAppGroup ? appGroupPath : path)
.catch(console.log);
.catch(() => {
/* empty */
});
return false;
}
@@ -234,7 +298,7 @@ export async function exists(filename) {
return exists;
}
export async function bulkExists(files) {
export async function bulkExists(files: string[]) {
try {
await createCacheDir();
const cacheFiles = await RNFetchBlob.fs.ls(cacheDir);
@@ -243,7 +307,7 @@ export async function bulkExists(files) {
if (Platform.OS === "ios") {
const iosAppGroup =
Platform.OS === "ios"
? await RNFetchBlob.fs.pathForAppGroup(IOS_APPGROUPID)
? await (RNFetchBlob.fs as any).pathForAppGroup(IOS_APPGROUPID)
: null;
const appGroupFiles = await RNFetchBlob.fs.ls(iosAppGroup);
missingFiles = missingFiles.filter(
@@ -261,9 +325,9 @@ export async function getCacheSize() {
await createCacheDir();
const stat = await RNFetchBlob.fs.lstat(`file://` + cacheDir);
let total = 0;
console.log("Total files", stat.length);
stat.forEach((s) => {
total += parseInt(s.size);
stat.forEach((file) => {
total += parseInt(file.size as unknown as string);
});
return total;
}

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 { RequestOptions } from "@notesnook/core";
import { Platform } from "react-native";
import RNFetchBlob from "react-native-blob-util";
import { ToastManager } from "../../services/event-manager";
@@ -24,11 +25,22 @@ import { useAttachmentStore } from "../../stores/use-attachment-store";
import { IOS_APPGROUPID } from "../../utils/constants";
import { DatabaseLogger, db } from "../database";
import { createCacheDir } from "./io";
import { cacheDir, checkUpload, getUploadedFileSize } from "./utils";
import {
cacheDir,
checkUpload,
FileSizeResult,
getUploadedFileSize
} from "./utils";
export async function uploadFile(filename, requestOptions, cancelToken) {
export async function uploadFile(
filename: string,
requestOptions: RequestOptions,
cancelToken: {
cancel: (reason?: string) => Promise<void>;
}
) {
if (!requestOptions) return false;
let { url, headers } = requestOptions;
const { url, headers } = requestOptions;
await createCacheDir();
DatabaseLogger.info(`Preparing to upload file: ${filename}`);
@@ -39,7 +51,7 @@ export async function uploadFile(filename, requestOptions, cancelToken) {
if (!exists && Platform.OS === "ios") {
const iosAppGroup =
Platform.OS === "ios"
? await RNFetchBlob.fs.pathForAppGroup(IOS_APPGROUPID)
? await (RNFetchBlob.fs as any).pathForAppGroup(IOS_APPGROUPID)
: null;
const appGroupPath = `${iosAppGroup}/${filename}`;
filePath = appGroupPath;
@@ -54,37 +66,25 @@ export async function uploadFile(filename, requestOptions, cancelToken) {
const fileSize = (await RNFetchBlob.fs.stat(filePath)).size;
let remoteFileSize = await getUploadedFileSize(filename);
if (remoteFileSize === -1) return false;
if (remoteFileSize > 0 && remoteFileSize === fileSize) {
const remoteFileSize = await getUploadedFileSize(filename);
if (remoteFileSize === FileSizeResult.Error) return false;
if (remoteFileSize > FileSizeResult.Empty && remoteFileSize === fileSize) {
DatabaseLogger.log(`File ${filename} is already uploaded.`);
return true;
}
let uploadUrlResponse = await fetch(url, {
method: "PUT",
headers
});
const uploadUrl = uploadUrlResponse.ok
? await uploadUrlResponse.text()
: await uploadUrlResponse.json();
if (typeof uploadUrl !== "string") {
throw new Error(
uploadUrl.error || "Unable to resolve attachment upload url."
);
}
DatabaseLogger.info(`Starting upload: ${filename}`);
let uploadRequest = RNFetchBlob.config({
const uploadRequest = RNFetchBlob.config({
//@ts-ignore
IOSBackgroundTask: !globalThis["IS_SHARE_EXTENSION"]
})
.fetch(
"PUT",
uploadUrl,
url,
{
...headers,
"content-type": ""
},
RNFetchBlob.wrap(filePath)
@@ -98,14 +98,14 @@ export async function uploadFile(filename, requestOptions, cancelToken) {
);
});
cancelToken.cancel = () => {
cancelToken.cancel = async () => {
useAttachmentStore.getState().remove(filename);
uploadRequest.cancel();
};
let uploadResponse = await uploadRequest;
let status = uploadResponse.info().status;
let uploaded = status >= 200 && status < 300;
const uploadResponse = await uploadRequest;
const status = uploadResponse.info().status;
const uploaded = status >= 200 && status < 300;
useAttachmentStore.getState().remove(filename);
@@ -118,12 +118,13 @@ export async function uploadFile(filename, requestOptions, cancelToken) {
);
}
const attachment = await db.attachments.attachment(filename);
if (!attachment) return false;
await checkUpload(filename, requestOptions.chunkSize, attachment.size);
DatabaseLogger.info(`File upload status: ${filename}, ${status}`);
return uploaded;
} catch (e) {
useAttachmentStore.getState().remove(filename);
ToastManager.error(e, "File upload failed");
ToastManager.error(e as Error, "File upload failed");
DatabaseLogger.error(e, "File upload failed", {
filename
});

View File

@@ -17,11 +17,11 @@ 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 { hosts, RequestOptions } from "@notesnook/core";
import { Platform } from "react-native";
import RNFetchBlob from "react-native-blob-util";
import * as ScopedStorage from "react-native-scoped-storage";
import { DatabaseLogger, db } from "../database";
import { hosts } from "@notesnook/core";
export const ABYTES = 17;
export const cacheDirOld = RNFetchBlob.fs.dirs.CacheDir;
@@ -31,18 +31,13 @@ export const cacheDir =
? RNFetchBlob.fs.dirs.LibraryDir + "/.cache"
: RNFetchBlob.fs.dirs.DocumentDir + "/.cache";
export function getRandomId(prefix) {
export function getRandomId(prefix: string) {
return Math.random()
.toString(36)
.replace("0.", prefix || "");
}
/**
*
* @param {string | undefined} data
* @returns
*/
export function parseS3Error(data) {
export function parseS3Error(data?: string) {
const xml = typeof data === "string" ? data : null;
const error = {
@@ -70,11 +65,19 @@ export function parseS3Error(data) {
}
}
export function cancelable(operation) {
export function cancelable(
operation: (
filename: string,
requestOptions: RequestOptions,
cancelToken: {
cancel: (reason?: string) => Promise<void>;
}
) => Promise<boolean>
) {
const cancelToken = {
cancel: () => {}
cancel: async (reason?: string) => {}
};
return (filename, requestOptions) => {
return (filename: string, requestOptions: RequestOptions) => {
return {
execute: () => operation(filename, requestOptions, cancelToken),
cancel: async () => {
@@ -84,29 +87,35 @@ export function cancelable(operation) {
};
}
export function copyFileAsync(source, dest) {
export function copyFileAsync(source: string, dest: string) {
return new Promise((resolve, reject) => {
ScopedStorage.copyFile(source, dest, (e, r) => {
//@ts-ignore
ScopedStorage.copyFile(source, dest, (e: any, r: any) => {
if (e) {
reject(e);
return;
}
resolve();
resolve(true);
});
});
}
export async function releasePermissions(path) {
export async function releasePermissions(path: string) {
if (Platform.OS === "ios") return;
const uris = await ScopedStorage.getPersistedUriPermissions();
for (let uri of uris) {
for (const uri of uris) {
if (path.startsWith(uri)) {
await ScopedStorage.releasePersistableUriPermission(uri);
}
}
}
export async function getUploadedFileSize(hash) {
export const FileSizeResult = {
Empty: 0,
Error: -1
};
export async function getUploadedFileSize(hash: string, retry = 0) {
try {
const url = `${hosts.API_HOST}/s3?name=${hash}`;
const token = await db.tokenManager.getAccessToken();
@@ -114,17 +123,37 @@ export async function getUploadedFileSize(hash) {
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")
attachmentInfo.headers?.get("content-length") as string
);
return isNaN(contentLength) ? 0 : contentLength;
return isNaN(contentLength) ? FileSizeResult.Empty : contentLength;
} catch (e) {
DatabaseLogger.error(e);
return -1;
return FileSizeResult.Error;
}
}
export async function checkUpload(filename, chunkSize, expectedSize) {
export async function checkUpload(
filename: string,
chunkSize: number,
expectedSize: number
) {
const size = await getUploadedFileSize(filename);
const totalChunks = Math.ceil(size / chunkSize);
const decryptedLength = size - totalChunks * ABYTES;
@@ -138,3 +167,25 @@ export async function checkUpload(filename, chunkSize, expectedSize) {
: undefined;
if (error) throw new Error(error);
}
export async function requestPermission() {
if (Platform.OS === "ios") return true;
return true;
}
export async function checkAndCreateDir(path: string) {
const dir =
Platform.OS === "ios"
? RNFetchBlob.fs.dirs.DocumentDir + path
: RNFetchBlob.fs.dirs.SDCardDir + "/Notesnook/" + path;
try {
const exists = await RNFetchBlob.fs.exists(dir);
const isDir = await RNFetchBlob.fs.isDir(dir);
if (!exists || !isDir) {
await RNFetchBlob.fs.mkdir(dir);
}
} catch (e) {
await RNFetchBlob.fs.mkdir(dir);
}
return dir;
}

View File

@@ -17,9 +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/>.
*/
function info(context: string, ...logs: unknown[]) {
console.log(`${new Date().toLocaleDateString()}::info::${context}:`, ...logs);
}
function info(context: string, ...logs: unknown[]) {}
function error(context: string, ...logs: unknown[]) {
console.log(

View File

@@ -24,10 +24,18 @@ 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";
import Heading from "../ui/typography/heading";
import { AppFontSize } from "../../utils/size";
import { Button } from "../ui/button";
import { strings } from "@notesnook/intl";
export const Announcement = ({ color }) => {
const { colors } = useThemeColors();
const announcements = useMessageStore((state) => state.announcements);
const [announcements, remove] = useMessageStore((state) => [
state.announcements,
state.remove
]);
let announcement = announcements.length > 0 ? announcements[0] : null;
const selectionMode = useSelectionStore((state) => state.selectionMode);
@@ -36,9 +44,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,9 +61,41 @@ export const Announcement = ({ color }) => {
<View
style={{
width: "100%",
marginTop: 12
marginTop: DefaultAppStyles.GAP_VERTICAL
}}
>
<View
style={{
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
paddingHorizontal: DefaultAppStyles.GAP,
borderBottomWidth: 1,
borderBottomColor: colors.primary.border,
paddingBottom: DefaultAppStyles.GAP_VERTICAL_SMALL
}}
>
<Heading color={colors.secondary.heading} size={AppFontSize.xxs}>
{strings.announcement()}
</Heading>
<Button
type="plain"
icon="close"
height={null}
onPress={() => {
remove(announcement.id);
}}
iconSize={20}
fontSize={AppFontSize.xs}
style={{
paddingVertical: 0,
paddingHorizontal: 0,
zIndex: 10
}}
/>
</View>
{announcement?.body
.filter((item) => allowedOnPlatform(item.platforms))
.map((item, index) =>

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,12 @@ 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();
@@ -41,27 +41,18 @@ export const Cta = ({ actions, style = {}, color, inline }) => {
await sleep(500);
}
if (item.type === "link") {
Linking.openURL(item.data).catch(console.log);
} else if (item.type === "promo") {
presentSheet({
component: (
<PricingPlans
marginTop={1}
promo={{
promoCode: item.data,
text: item.title
}}
/>
)
Linking.openURL(item.data).catch(() => {
/* empty */
});
}
};
return (
<View
style={{
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
...getStyle(style),
flexDirection: inline ? "row" : "column"
flexDirection: inline ? "row" : "column",
gap: DefaultAppStyles.GAP_SMALL
}}
>
<SheetProvider context="premium_cta" />
@@ -73,7 +64,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"
@@ -81,7 +72,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
}}
@@ -93,15 +84,13 @@ 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}
height={30}
style={{
paddingVertical: DefaultAppStyles.GAP_VERTICAL_SMALL,
alignSelf: "flex-start",
paddingHorizontal: 0,
marginLeft: 12
paddingHorizontal: 0
}}
textStyle={{
textDecorationLine: "underline"
@@ -116,7 +105,6 @@ export const Cta = ({ actions, style = {}, color, inline }) => {
<Button
key={item.title}
title={item.title}
fontSize={SIZE.md}
buttonType={{
color: color ? color : colors.primary.accent,
text: color
@@ -126,10 +114,8 @@ export const Cta = ({ actions, style = {}, color, inline }) => {
opacity: 1
}}
onPress={() => onPress(item)}
width={250}
style={{
marginBottom: 5,
borderRadius: 100
width: "100%"
}}
/>
))}
@@ -139,14 +125,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
width: "100%"
}}
textStyle={{
textDecorationLine: "underline"

View File

@@ -18,19 +18,20 @@ 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";
import { DefaultAppStyles } from "../../utils/styles";
export const Description = ({ text, style = {}, inline }) => {
return (
<Paragraph
style={{
marginHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
...getStyle(style),
textAlign: inline ? "left" : style?.textAlign
}}
size={inline ? SIZE.sm : SIZE.md}
size={AppFontSize.sm}
>
{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

@@ -33,6 +33,7 @@ import {
import BaseDialog from "../dialog/base-dialog";
import { allowedOnPlatform, renderItem } from "./functions";
import { useCallback } from "react";
import { DefaultAppStyles } from "../../utils/styles";
/**
* Test announcement
@@ -138,9 +139,9 @@ export const AnnouncementDialog = () => {
maxHeight: DDS.isTab ? "90%" : "100%",
borderRadius: DDS.isTab ? 10 : 0,
overflow: "hidden",
marginBottom: DDS.isTab ? 20 : 0,
borderTopRightRadius: 10,
borderTopLeftRadius: 10
paddingVertical: DefaultAppStyles.GAP,
borderTopRightRadius: 15,
borderTopLeftRadius: 15
}}
>
<FlatList

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,69 +20,41 @@ 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);
let announcement = announcements.length > 0 ? announcements[0] : null;
const remove = useMessageStore((state) => state.remove);
return inline ? (
<View
style={{
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
marginBottom: inline ? 5 : 0
marginBottom: inline ? DefaultAppStyles.GAP_VERTICAL_SMALL : 0
}}
>
<Heading
style={{
marginHorizontal: 12,
marginTop: 12,
paddingHorizontal: 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>
<Button
type="plain"
icon="close"
height={null}
onPress={() => {
remove(announcement.id);
}}
hitSlop={{
left: 15,
top: 10,
bottom: 10,
right: 0
}}
iconSize={24}
fontSize={SIZE.xs}
style={{
borderRadius: 100,
paddingVertical: 0,
paddingHorizontal: 0,
marginRight: 12,
zIndex: 10
}}
/>
</View>
) : (
<Heading
style={{
marginHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
...getStyle(style),
marginTop: style?.marginTop || 12
marginTop: style?.marginTop || DefaultAppStyles.GAP_VERTICAL
}}
>
{text}

View File

@@ -44,7 +44,6 @@ import SettingsService from "../../services/settings";
import { useSettingStore } from "../../stores/use-setting-store";
import { useUserStore } from "../../stores/use-user-store";
import { NotesnookModule } from "../../utils/notesnook-module";
import { SIZE } from "../../utils/size";
import { Toast } from "../toast";
import { Button } from "../ui/button";
import { IconButton } from "../ui/icon-button";
@@ -54,6 +53,9 @@ import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import { KeyboardAwareScrollView } from "react-native-keyboard-aware-scroll-view";
import { strings } from "@notesnook/intl";
import { AppFontSize } from "../../utils/size";
import { editorController } from "../../screens/editor/tiptap/utils";
import { useTabStore } from "../../screens/editor/tiptap/use-tab-store";
const getUser = () => {
const user = MMKV.getString("user");
@@ -82,7 +84,7 @@ const verifyUserPassword = async (password: string) => {
}
};
const AppLockedOverlay = () => {
const AppLocked = () => {
const initialLaunchBiometricRequest = useRef(true);
const { colors } = useThemeColors();
const user = getUser();
@@ -109,17 +111,25 @@ const AppLockedOverlay = () => {
);
const onUnlockAppRequested = useCallback(async () => {
editorController.current?.commands.blur(useTabStore.getState().currentTab);
editorController.current?.commands.blurPassInput();
if (
!biometricsAuthEnabled ||
!(await BiometricService.isBiometryAvailable())
)
) {
return;
}
biometricUnlockAwaitingUserInput.current = true;
if (Platform.OS === "android") {
const activityName = await NotesnookModule.getActivityName();
if (activityName !== "MainActivity") return;
if (
activityName !== "MainActivity" &&
activityName !== "NotePreviewConfigureActivity"
)
return;
}
useSettingStore.getState().setRequestBiometrics(true);
@@ -177,10 +187,15 @@ const AppLockedOverlay = () => {
(prevState === "background" || initialLaunchBiometricRequest.current)
) {
if (SettingsService.shouldLockAppOnEnterForeground()) {
if (useSettingStore.getState().appDidEnterBackgroundForAction) {
useSettingStore.getState().setAppDidEnterBackgroundForAction(false);
return;
}
DatabaseLogger.info("Locking app on entering foreground");
useUserStore.getState().lockApp(true);
}
if (
!(
biometricUnlockAwaitingUserInput.current ||
@@ -279,6 +294,16 @@ const AppLockedOverlay = () => {
keyboardType={
appLockHasPasswordSecurity ? keyboardType : "default"
}
onLayout={async () => {
if (
!biometricsAuthEnabled ||
!(await BiometricService.isBiometryAvailable())
) {
setTimeout(() => {
passwordInputRef.current?.focus();
}, 32);
}
}}
placeholder={
appLockHasPasswordSecurity
? keyboardType === "numeric"
@@ -311,7 +336,6 @@ const AppLockedOverlay = () => {
borderRadius: 150,
marginBottom: 10
}}
fontSize={SIZE.md}
/>
</>
) : null}
@@ -332,4 +356,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,14 +58,17 @@ 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,
close,
setAttachments,
fwdRef
fwdRef,
context
}: {
attachment: Attachment;
context: string;
setAttachments: (attachments?: VirtualizedGrouping<Attachment>) => void;
close?: () => void;
fwdRef: RefObject<ActionSheetRef>;
@@ -79,7 +82,6 @@ const Actions = ({
const [loading, setLoading] = useState<{
name?: string;
}>({});
const actions = [
{
name: strings.network.download(),
@@ -88,7 +90,7 @@ const Actions = ({
await db.fs().cancel(attachment.hash);
useAttachmentStore.getState().remove(attachment.hash);
}
downloadAttachment(attachment.hash, false);
downloadAttachment(attachment.hash, context === "global");
fwdRef.current?.hide();
},
icon: "download"
@@ -165,6 +167,7 @@ const Actions = ({
setAttachments();
eSendEvent(eDBItemUpdate, attachment.id);
}
return true;
},
positiveText: strings.rename()
});
@@ -181,18 +184,17 @@ const Actions = ({
relations
.map((relation) => relation.fromId)
.forEach(async (id) => {
const tab = useTabStore.getState().getTabForNote(id);
if (tab !== undefined) {
const isFocused = useTabStore.getState().currentTab === tab;
useTabStore.getState().forEachNoteTab(id, async (tab) => {
const isFocused = useTabStore.getState().currentTab === tab.id;
if (isFocused) {
eSendEvent(eOnLoadNote, {
item: await db.notes.note(id),
forced: true
});
} else {
editorController.current.commands.setLoading(true, tab);
editorController.current.commands.setLoading(true, tab.id);
}
}
});
});
close?.();
},
@@ -226,14 +228,15 @@ const Actions = ({
style={{
borderBottomWidth: 1,
borderBottomColor: colors.primary.border,
marginBottom: notes && notes.length > 0 ? 0 : 12
marginBottom:
notes && notes.length > 0 ? 0 : DefaultAppStyles.GAP_VERTICAL
}}
>
<Heading
style={{
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
size={SIZE.lg}
size={AppFontSize.lg}
>
{filename}
</Heading>
@@ -241,21 +244,21 @@ const Actions = ({
<View
style={{
flexDirection: "row",
marginBottom: 10,
paddingHorizontal: 12,
marginTop: 6,
marginBottom: DefaultAppStyles.GAP_VERTICAL,
paddingHorizontal: DefaultAppStyles.GAP,
marginTop: DefaultAppStyles.GAP_VERTICAL_SMALL,
gap: 10
}}
>
<Paragraph size={SIZE.xs} color={colors.secondary.paragraph}>
<Paragraph size={AppFontSize.xs} color={colors.secondary.paragraph}>
{attachment.mimeType}
</Paragraph>
<Paragraph size={SIZE.xs} color={colors.secondary.paragraph}>
<Paragraph size={AppFontSize.xs} color={colors.secondary.paragraph}>
{formatBytes(attachment.size)}
</Paragraph>
{notes.length ? (
<Paragraph size={SIZE.xs} color={colors.secondary.paragraph}>
<Paragraph size={AppFontSize.xs} color={colors.secondary.paragraph}>
{strings.notes(notes.length)}
</Paragraph>
) : null}
@@ -268,7 +271,7 @@ const Actions = ({
context: "local"
});
}}
size={SIZE.xs}
size={AppFontSize.xs}
color={colors.secondary.paragraph}
>
{attachment.hash}
@@ -283,16 +286,16 @@ const Actions = ({
style={{
borderBottomWidth: 1,
borderBottomColor: colors.primary.border,
marginBottom: 12,
paddingVertical: 12
marginBottom: DefaultAppStyles.GAP_VERTICAL,
paddingVertical: DefaultAppStyles.GAP_VERTICAL
}}
>
<>
<Heading
style={{
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
size={SIZE.sm}
size={AppFontSize.sm}
>
{strings.listOf()} {strings.dataTypesPlural.note()}:
</Heading>
@@ -307,14 +310,14 @@ const Actions = ({
openNote(item, (item as any).type === "trash");
}}
style={{
paddingVertical: 12,
paddingVertical: DefaultAppStyles.GAP_VERTICAL,
alignItems: "flex-start",
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
key={item.id}
>
<Paragraph size={SIZE.xs}>{item.title}</Paragraph>
<Paragraph size={AppFontSize.xs}>{item.title}</Paragraph>
</Pressable>
))}
</>
@@ -335,7 +338,7 @@ const Actions = ({
icon={item.icon}
loading={loading?.name === item.name}
type="plain"
fontSize={SIZE.sm}
fontSize={AppFontSize.sm}
style={{
borderRadius: 0,
justifyContent: "flex-start",
@@ -347,7 +350,7 @@ const Actions = ({
<View
style={{
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
>
{failed ? (
@@ -375,6 +378,7 @@ Actions.present = (
setAttachments={set}
close={close}
attachment={attachment}
context={context || "global"}
/>
)
});

View File

@@ -25,12 +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);
@@ -69,15 +71,14 @@ export const AttachmentItem = ({
};
return errorOnly && attachment && !attachment?.failed ? null : (
<TouchableOpacity
activeOpacity={0.9}
<Pressable
onPress={onPress}
style={{
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
}
@@ -186,6 +190,6 @@ export const AttachmentItem = ({
)}
</>
)}
</TouchableOpacity>
</Pressable>
);
};

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",
@@ -206,7 +207,7 @@ export const AttachmentDialog = ({
errorOnly={currentFilter === "errors"}
attachments={attachments}
id={index}
context="global"
context={!isSheet ? "global" : "attachments-list"}
/>
);
@@ -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
}}
@@ -528,7 +524,9 @@ export const AttachmentDialog = ({
setAttachments(results);
setLoading(false);
})
.catch(console.log);
.catch(() => {
/* empty */
});
}}
/>
)

View File

@@ -19,9 +19,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import { useThemeColors } from "@notesnook/theme";
import React, { useEffect, useRef, useState } from "react";
import { Platform, View } from "react-native";
import { KeyboardAwareScrollView } from "react-native-keyboard-aware-scroll-view";
import useGlobalSafeAreaInsets from "../../hooks/use-global-safe-area-insets";
import {
eSubscribeEvent,
eUnSubscribeEvent
@@ -31,12 +28,11 @@ import { eCloseLoginDialog, eOpenLoginDialog } from "../../utils/events";
import { sleep } from "../../utils/time";
import BaseDialog from "../dialog/base-dialog";
import { Toast } from "../toast";
import { Button } from "../ui/button";
import { IconButton } from "../ui/icon-button";
import { hideAuth, initialAuthMode } from "./common";
import { 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,
@@ -50,7 +46,6 @@ const AuthModal = () => {
const [visible, setVisible] = useState(false);
const [currentAuthMode, setCurrentAuthMode] = useState(AuthMode.login);
const actionSheetRef = useRef();
const insets = useGlobalSafeAreaInsets();
useEffect(() => {
eSubscribeEvent(eOpenLoginDialog, open);
@@ -98,81 +93,18 @@ const AuthModal = () => {
centered={false}
enableSheetKeyboardHandler
>
<KeyboardAwareScrollView
style={{
width: "100%"
}}
enableAutomaticScroll={false}
keyboardShouldPersistTaps="handled"
>
{currentAuthMode !== AuthMode.login ? (
<Signup
changeMode={(mode) => setCurrentAuthMode(mode)}
trial={AuthMode.trialSignup === currentAuthMode}
welcome={initialAuthMode.current === AuthMode.welcomeSignup}
/>
) : (
<Login
welcome={initialAuthMode.current === AuthMode.welcomeSignup}
changeMode={(mode) => setCurrentAuthMode(mode)}
/>
)}
</KeyboardAwareScrollView>
<View
style={{
position: "absolute",
paddingTop: Platform.OS === "android" ? 0 : insets.top,
top: 0,
zIndex: 999,
backgroundColor: colors.secondary.background,
width: "100%"
}}
>
<View
style={{
flexDirection: "row",
alignItems: "center",
paddingHorizontal: 12,
width: "100%",
height: 50,
justifyContent:
initialAuthMode.current !== AuthMode.welcomeSignup
? "space-between"
: "flex-end"
}}
>
{initialAuthMode.current === AuthMode.welcomeSignup ? null : (
<IconButton
name="arrow-left"
onPress={() => {
hideAuth();
}}
color={colors.primary.paragraph}
/>
)}
{initialAuthMode.current !== AuthMode.welcomeSignup ? null : (
<Button
title={strings.skip()}
onPress={() => {
hideAuth();
}}
iconSize={16}
type="plain"
iconPosition="right"
icon="chevron-right"
height={25}
iconStyle={{
marginTop: 2
}}
style={{
paddingHorizontal: 6
}}
/>
)}
</View>
</View>
{currentAuthMode !== AuthMode.login ? (
<Signup
changeMode={(mode) => setCurrentAuthMode(mode)}
trial={AuthMode.trialSignup === currentAuthMode}
welcome={initialAuthMode.current === AuthMode.welcomeSignup}
/>
) : (
<Login
welcome={initialAuthMode.current === AuthMode.welcomeSignup}
changeMode={(mode) => setCurrentAuthMode(mode)}
/>
)}
<Toast context="local" />
</BaseDialog>

View File

@@ -17,25 +17,20 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { strings } from "@notesnook/intl";
import React, { useRef, useState } from "react";
import { View } from "react-native";
import { db } from "../../common/database";
import {
eSendEvent,
presentSheet,
ToastManager
} from "../../services/event-manager";
import BackupService from "../../services/backup";
import { eSendEvent, ToastManager } from "../../services/event-manager";
import Navigation from "../../services/navigation";
import { useUserStore } from "../../stores/use-user-store";
import { eCloseSheet, eOpenRecoveryKeyDialog } from "../../utils/events";
import DialogHeader from "../dialog/dialog-header";
import { eOpenRecoveryKeyDialog } from "../../utils/events";
import { DefaultAppStyles } from "../../utils/styles";
import { Dialog } from "../dialog";
import { Button } from "../ui/button";
import Input from "../ui/input";
import { Notice } from "../ui/notice";
import Seperator from "../ui/seperator";
import { Dialog } from "../dialog";
import BackupService from "../../services/backup";
import { sleep } from "../../utils/time";
import { strings } from "@notesnook/intl";
export const ChangePassword = () => {
const passwordInputRef = useRef();
@@ -68,11 +63,15 @@ export const ChangePassword = () => {
}
setLoading(true);
try {
const result = await BackupService.run(false, "change-password-dialog");
if (!result.error)
const result = await BackupService.run(
false,
"change-password-dialog",
"partial"
);
if (result.error) {
throw new Error(strings.backupFailed() + `: ${result.error}`);
}
await db.user.clearSessions();
await db.user.changePassword(oldPassword.current, password.current);
ToastManager.show({
heading: strings.passwordChangedSuccessfully(),
@@ -80,8 +79,7 @@ export const ChangePassword = () => {
context: "global"
});
setLoading(false);
eSendEvent(eCloseSheet);
await sleep(300);
Navigation.goBack();
eSendEvent(eOpenRecoveryKeyDialog);
} catch (e) {
setLoading(false);
@@ -99,13 +97,10 @@ export const ChangePassword = () => {
<View
style={{
width: "100%",
padding: 12
padding: DefaultAppStyles.GAP
}}
>
<Dialog context="change-password-dialog" />
<DialogHeader title={strings.changePassword()} />
<Seperator />
<Input
fwdRef={oldPasswordInputRef}
onChangeText={(value) => {
@@ -144,7 +139,7 @@ export const ChangePassword = () => {
<Button
style={{
marginTop: 10,
marginTop: DefaultAppStyles.GAP_VERTICAL,
width: "100%"
}}
loading={loading}
@@ -155,9 +150,3 @@ export const ChangePassword = () => {
</View>
);
};
ChangePassword.present = () => {
presentSheet({
component: <ChangePassword />
});
};

View File

@@ -20,23 +20,25 @@ 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,
welcomeLogin: 3,
trialSignup: 4
};
export const initialAuthMode = createRef(0);
export function hideAuth() {
export function hideAuth(context) {
eSendEvent(eCloseLoginDialog);
// if (initialAuthMode.current === 2) {
// Navigation.replace(
// {
// name: 'Notes'
// },
// {
// menu: true
// }
// );
// } else {
// Navigation.goBack();
// }
// tabBarRef.current?.unlock();
if (
initialAuthMode.current === AuthMode.welcomeSignup ||
initialAuthMode.current === AuthMode.welcomeLogin ||
context === "intro"
) {
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

@@ -0,0 +1,78 @@
/*
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 { useThemeColors } from "@notesnook/theme";
import { useRoute } from "@react-navigation/native";
import React from "react";
import { View } from "react-native";
import { Button } from "../ui/button";
import { IconButton } from "../ui/icon-button";
import { hideAuth } from "./common";
export const AuthHeader = (props: { welcome?: boolean }) => {
const { colors } = useThemeColors();
const route = useRoute();
return (
<View
style={{
width: "100%"
}}
>
<View
style={{
flexDirection: "row",
alignItems: "center",
paddingHorizontal: 12,
width: "100%",
height: 50,
justifyContent: !props.welcome ? "space-between" : "flex-end"
}}
>
{props.welcome ? null : (
<IconButton
name="arrow-left"
onPress={() => {
hideAuth((route.params as any)?.context);
}}
color={colors.primary.paragraph}
/>
)}
{!props.welcome ? null : (
<Button
title="Skip"
onPress={() => {
hideAuth();
}}
iconSize={16}
type="plain"
iconPosition="right"
icon="chevron-right"
height={25}
iconStyle={{
marginTop: 2
}}
style={{
paddingHorizontal: 6
}}
/>
)}
</View>
</View>
);
};

View File

@@ -18,35 +18,28 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import React, { useState } from "react";
import { View } from "react-native";
import { SafeAreaView } from "react-native-safe-area-context";
import { useNavigationFocus } from "../../hooks/use-navigation-focus";
import { Toast } from "../toast";
import { initialAuthMode } from "./common";
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 { useThemeColors } from "@notesnook/theme";
const Auth = ({ navigation, route }) => {
const [currentAuthMode, setCurrentAuthMode] = useState(
route?.params?.mode || AuthMode.login
);
const { colors } = useThemeColors();
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 }}>
{currentAuthMode !== AuthMode.login ? (
<SafeAreaView
style={{ flex: 1, backgroundColor: colors.primary.background }}
>
{currentAuthMode !== AuthMode.login &&
currentAuthMode !== AuthMode.welcomeLogin ? (
<Signup
changeMode={(mode) => setCurrentAuthMode(mode)}
trial={AuthMode.trialSignup === currentAuthMode}
@@ -60,7 +53,7 @@ const Auth = ({ navigation, route }) => {
)}
<Toast context="local" />
</View>
</SafeAreaView>
);
};

View File

@@ -17,19 +17,24 @@ 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 { useRoute } from "@react-navigation/native";
import React, { useEffect, useState } from "react";
import { TouchableOpacity, View, useWindowDimensions } from "react-native";
import { SheetManager } from "react-native-actions-sheet";
import { KeyboardAwareScrollView } from "react-native-keyboard-aware-scroll-view";
import { DDS } from "../../services/device-detection";
import { eSendEvent } from "../../services/event-manager";
import Navigation from "../../services/navigation";
import PremiumService from "../../services/premium";
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 { DefaultAppStyles } from "../../utils/styles";
import { sleep } from "../../utils/time";
import SheetProvider from "../sheet-provider";
import { Dialog } from "../dialog";
import { Progress } from "../sheets/progress";
import { Button } from "../ui/button";
import Input from "../ui/input";
@@ -37,8 +42,9 @@ import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import { hideAuth } from "./common";
import { ForgotPassword } from "./forgot-password";
import { AuthHeader } from "./header";
import { useLogin } from "./use-login";
import { strings } from "@notesnook/intl";
import SettingsService from "../../services/settings";
const LoginSteps = {
emailAuth: 1,
@@ -49,6 +55,7 @@ const LoginSteps = {
export const Login = ({ changeMode }) => {
const { colors } = useThemeColors();
const [focused, setFocused] = useState(false);
const route = useRoute();
const {
step,
setStep,
@@ -61,18 +68,27 @@ export const Login = ({ changeMode }) => {
setError,
login
} = useLogin(async () => {
hideAuth();
eSendEvent(eUserLoggedIn, true);
await sleep(500);
Progress.present();
hideAuth();
setTimeout(() => {
if (!useUserStore.getState().syncing) {
Sync.run("global", false, "full");
}
}, 5000);
if (!PremiumService.get() && !SettingsService.getProperty("serverUrls")) {
Navigation.navigate("PayWall", {
context: "signup",
state: route.params.state,
canGoBack: false
});
} else {
Progress.present();
}
});
const deviceMode = useSettingStore((state) => state.deviceMode);
const { width, height } = useWindowDimensions();
const isTablet = width > 600;
useEffect(() => {
async () => {
setStep(LoginSteps.emailAuth);
@@ -88,222 +104,227 @@ export const Login = ({ changeMode }) => {
return (
<>
<AuthHeader />
<ForgotPassword />
<SheetProvider context="two_factor_verify" />
<View
<Dialog context="two_factor_verify" />
<KeyboardAwareScrollView
style={{
borderRadius: DDS.isTab ? 5 : 0,
backgroundColor: colors.primary.background,
zIndex: 10,
width: "100%",
alignSelf: "center"
width: "100%"
}}
contentContainerStyle={{
minHeight: "90%"
}}
nestedScrollEnabled
enableAutomaticScroll={false}
keyboardShouldPersistTaps="handled"
>
<View
style={{
justifyContent: "flex-end",
paddingHorizontal: 20,
backgroundColor: colors.secondary.background,
borderBottomWidth: 0.8,
marginBottom: 12,
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%",
minHeight: height * 0.4
}}
>
<View
style={{
flexDirection: "row"
}}
>
<View
style={{
width: 100,
height: 5,
backgroundColor: colors.primary.accent,
borderRadius: 2,
marginRight: 7
}}
/>
<View
style={{
width: 20,
height: 5,
backgroundColor: colors.secondary.background,
borderRadius: 2
}}
/>
</View>
<Heading
style={{
marginBottom: 25,
marginTop: 10
}}
extraBold
size={SIZE.xxl}
>
{strings.loginToYourAccount()}
</Heading>
</View>
<View
style={{
width: DDS.isTab
? focused
? "50%"
: "49.99%"
: focused
? "100%"
: "99.9%",
borderRadius: DDS.isTab ? 5 : 0,
backgroundColor: colors.primary.background,
alignSelf: "center",
paddingHorizontal: 20
zIndex: 10,
width: "100%",
height: "100%",
alignSelf: "center"
}}
>
<Input
fwdRef={emailInputRef}
onChangeText={(value) => {
email.current = value;
<View
style={{
justifyContent: "flex-end",
paddingHorizontal: DefaultAppStyles.GAP,
borderBottomWidth: 0.8,
marginBottom: DefaultAppStyles.GAP_VERTICAL,
borderBottomColor: colors.primary.border,
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 : "50%",
minHeight: height * 0.4
}}
testID="input.email"
onErrorCheck={(e) => setError(e)}
returnKeyLabel="Next"
returnKeyType="next"
autoComplete="email"
validationType="email"
autoCorrect={false}
autoCapitalize="none"
errorMessage={strings.emailInvalid()}
placeholder={strings.email()}
defaultValue={email.current}
editable={step === LoginSteps.emailAuth && !loading}
onSubmit={() => {
if (step === LoginSteps.emailAuth) {
login();
} else {
passwordInputRef.current?.focus();
}
}}
/>
{step === LoginSteps.passwordAuth && (
<>
<Input
fwdRef={passwordInputRef}
onChangeText={(value) => {
password.current = value;
}}
testID="input.password"
returnKeyLabel={strings.done()}
returnKeyType="done"
secureTextEntry
autoComplete="password"
autoCapitalize="none"
autoCorrect={false}
placeholder={strings.password()}
marginBottom={0}
editable={!loading}
defaultValue={password.current}
onSubmit={() => login()}
/>
<Button
title={strings.forgotPassword()}
>
<View
style={{
flexDirection: "row"
}}
>
<View
style={{
alignSelf: "flex-end",
height: 30,
paddingHorizontal: 0
width: 100,
height: 5,
backgroundColor: colors.primary.accent,
borderRadius: 2,
marginRight: 7
}}
onPress={() => {
if (loading) return;
SheetManager.show("forgotpassword_sheet", email.current);
}}
textStyle={{
textDecorationLine: "underline"
}}
fontSize={SIZE.xs}
type="plain"
/>
</>
)}
<View
style={{
width: 20,
height: 5,
backgroundColor: colors.secondary.background,
borderRadius: 2
}}
/>
</View>
<Heading
style={{
marginBottom: 25,
marginTop: DefaultAppStyles.GAP_VERTICAL
}}
extraBold
size={AppFontSize.xxl}
>
{strings.loginToYourAccount()}
</Heading>
</View>
<View
style={{
marginTop: 25
width: DDS.isTab
? focused
? "50%"
: "49.99%"
: focused
? "100%"
: "99.9%",
backgroundColor: colors.primary.background,
alignSelf: "center",
paddingHorizontal: DDS.isTab ? 0 : DefaultAppStyles.GAP,
gap: DefaultAppStyles.GAP_VERTICAL
}}
>
<Button
loading={loading}
onPress={() => {
if (loading) return;
login();
<Input
fwdRef={emailInputRef}
onChangeText={(value) => {
email.current = value;
}}
style={{
width: 250,
borderRadius: 100
testID="input.email"
onErrorCheck={(e) => setError(e)}
returnKeyLabel="Next"
returnKeyType="next"
autoComplete="email"
validationType="email"
marginBottom={0}
autoCorrect={false}
autoCapitalize="none"
errorMessage={strings.emailInvalid()}
placeholder={strings.email()}
defaultValue={email.current}
editable={step === LoginSteps.emailAuth && !loading}
onSubmit={() => {
if (step === LoginSteps.emailAuth) {
login();
} else {
passwordInputRef.current?.focus();
}
}}
height={50}
fontSize={SIZE.md}
type="accent"
title={!loading ? strings.continue() : null}
/>
{step === LoginSteps.passwordAuth && (
<Button
title={strings.cancelLogin()}
style={{
alignSelf: "center",
height: 30,
marginTop: 10
}}
onPress={() => {
if (loading) return;
setStep(LoginSteps.emailAuth);
setLoading(false);
}}
textStyle={{
textDecorationLine: "underline"
}}
fontSize={SIZE.xs}
type="errorShade"
/>
<>
<Input
fwdRef={passwordInputRef}
onChangeText={(value) => {
password.current = value;
}}
testID="input.password"
returnKeyLabel={strings.done()}
returnKeyType="done"
secureTextEntry
autoComplete="password"
autoCapitalize="none"
autoCorrect={false}
placeholder={strings.password()}
marginBottom={0}
editable={!loading}
defaultValue={password.current}
onSubmit={() => login()}
/>
<Button
title={strings.forgotPassword()}
style={{
alignSelf: "flex-end",
paddingVertical: DefaultAppStyles.GAP_VERTICAL_SMALL,
paddingHorizontal: 0
}}
onPress={() => {
if (loading) return;
SheetManager.show("forgotpassword_sheet", email.current);
}}
textStyle={{
textDecorationLine: "underline"
}}
fontSize={AppFontSize.xs}
type="plain"
/>
</>
)}
{!loading ? (
<TouchableOpacity
<View>
<Button
loading={loading}
onPress={() => {
if (loading) return;
changeMode(1);
login();
}}
activeOpacity={0.8}
style={{
alignSelf: "center",
marginTop: 12,
paddingVertical: 12
width: "100%"
}}
>
<Paragraph
size={SIZE.xs + 1}
color={colors.secondary.paragraph}
type="accent"
title={!loading ? strings.continue() : null}
fontSize={AppFontSize.sm}
/>
{step === LoginSteps.passwordAuth && (
<Button
title={strings.cancelLogin()}
style={{
alignSelf: "center",
marginTop: DefaultAppStyles.GAP_VERTICAL,
width: "100%"
}}
onPress={() => {
if (loading) return;
setStep(LoginSteps.emailAuth);
setLoading(false);
}}
type="secondaryAccented"
/>
)}
{!loading ? (
<TouchableOpacity
onPress={() => {
if (loading) return;
changeMode(1);
}}
activeOpacity={0.8}
style={{
alignSelf: "center",
marginTop: DefaultAppStyles.GAP_VERTICAL,
paddingVertical: DefaultAppStyles.GAP_VERTICAL
}}
>
{strings.dontHaveAccount()}{" "}
<Paragraph
size={SIZE.xs + 1}
style={{ color: colors.primary.accent }}
size={AppFontSize.xs}
color={colors.secondary.paragraph}
>
{strings.signUp()}
{strings.dontHaveAccount()}{" "}
<Paragraph
size={AppFontSize.xs}
style={{ color: colors.primary.accent }}
>
{strings.signUp()}
</Paragraph>
</Paragraph>
</Paragraph>
</TouchableOpacity>
) : null}
</TouchableOpacity>
) : null}
</View>
</View>
</View>
</View>
</KeyboardAwareScrollView>
</>
);
};

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

@@ -0,0 +1,27 @@
/*
This file is part of the Notesnook project (https://notesnook.com/)
Copyright (C) 2023 Streetwriters (Private) Limited
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import React, { useContext } from "react";
export const SignupContext = React.createContext<{
signup?: () => Promise<boolean>;
}>({
signup: undefined
});
export const useSignupContext = () => useContext(SignupContext);

View File

@@ -17,28 +17,38 @@ 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 { useRoute } from "@react-navigation/native";
import React, { useRef, useState } from "react";
import { TouchableOpacity, View, useWindowDimensions } from "react-native";
import { KeyboardAwareScrollView } from "react-native-keyboard-aware-scroll-view";
import { db } from "../../common/database";
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 Navigation from "../../services/navigation";
import { useUserStore } from "../../stores/use-user-store";
import { openLinkInBrowser } from "../../utils/functions";
import { SIZE } from "../../utils/size";
import { sleep } from "../../utils/time";
import { AppFontSize } from "../../utils/size";
import { DefaultAppStyles } from "../../utils/styles";
import { Loading } from "../loading";
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 { AuthHeader } from "./header";
import { SignupContext } from "./signup-context";
import SettingsService from "../../services/settings";
import { strings } from "@notesnook/intl";
export const Signup = ({ changeMode, trial }) => {
const SignupSteps = {
signup: 0,
selectPlan: 1,
createAccount: 2
};
export const Signup = ({ changeMode, welcome }) => {
const [currentStep, setCurrentStep] = useState(SignupSteps.signup);
const { colors } = useThemeColors();
const email = useRef();
const emailInputRef = useRef();
@@ -50,8 +60,10 @@ 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 route = useRoute();
const validateInfo = () => {
if (!password.current || !email.current || !confirmPassword.current) {
ToastManager.show({
@@ -70,23 +82,26 @@ export const Signup = ({ changeMode, trial }) => {
const signup = async () => {
if (!validateInfo() || error) return;
if (loading) return;
setLoading(true);
try {
setCurrentStep(SignupSteps.createAccount);
await db.user.signup(email.current.toLowerCase(), password.current);
let user = await db.user.getUser();
setUser(user);
setLastSynced(await db.lastSynced());
clearMessage();
setEmailVerifyMessage();
hideAuth();
SettingsService.setProperty("encryptedBackup", true);
await sleep(300);
if (trial) {
PremiumService.sheet(null, null, true);
} else {
PremiumService.showVerifyEmailDialog();
if (!SettingsService.getProperty("serverUrls")) {
Navigation.navigate("PayWall", {
canGoBack: false,
state: route.params.state,
context: "signup"
});
}
return true;
} catch (e) {
setCurrentStep(SignupSteps.signup);
setLoading(false);
ToastManager.show({
heading: strings.signupFailed(),
@@ -94,214 +109,264 @@ export const Signup = ({ changeMode, trial }) => {
type: "error",
context: "local"
});
return false;
}
};
return (
<>
<View
style={{
borderRadius: DDS.isTab ? 5 : 0,
backgroundColor: colors.primary.background,
zIndex: 10,
width: "100%",
alignSelf: "center"
}}
>
<View
style={{
justifyContent: "flex-end",
paddingHorizontal: 20,
backgroundColor: colors.secondary.background,
marginBottom: 20,
borderBottomWidth: 0.8,
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%",
minHeight: height * 0.4
}}
>
<View
<SignupContext.Provider
value={{
signup: signup
}}
>
{currentStep === SignupSteps.signup ? (
<>
<AuthHeader welcome={welcome} />
<KeyboardAwareScrollView
style={{
flexDirection: "row"
width: "100%"
}}
contentContainerStyle={{
minHeight: "90%"
}}
nestedScrollEnabled
enableAutomaticScroll={false}
keyboardShouldPersistTaps="handled"
>
<View
style={{
width: 100,
height: 5,
backgroundColor: colors.primary.accent,
borderRadius: 2,
marginRight: 7
borderRadius: DDS.isTab ? 5 : 0,
backgroundColor: colors.primary.background,
zIndex: 10,
width: "100%",
alignSelf: "center",
height: "100%"
}}
/>
<View
style={{
width: 20,
height: 5,
backgroundColor: colors.secondary.background,
borderRadius: 2
}}
/>
</View>
<Heading
extraBold
style={{
marginBottom: 25,
marginTop: 10
}}
size={SIZE.xxl}
>
{strings.createYourAccount()}
</Heading>
</View>
<View
style={{
width: DDS.isTab ? "50%" : "100%",
paddingHorizontal: 20,
backgroundColor: colors.primary.background,
alignSelf: "center"
}}
>
<Input
fwdRef={emailInputRef}
onChangeText={(value) => {
email.current = value;
}}
testID="input.email"
onErrorCheck={(e) => setError(e)}
returnKeyLabel={strings.next()}
returnKeyType="next"
autoComplete="email"
validationType="email"
autoCorrect={false}
autoCapitalize="none"
errorMessage={strings.email()}
placeholder={strings.email()}
onSubmit={() => {
passwordInputRef.current?.focus();
}}
/>
<Input
fwdRef={passwordInputRef}
onChangeText={(value) => {
password.current = value;
}}
testID="input.password"
onErrorCheck={(e) => setError(e)}
returnKeyLabel={strings.next()}
returnKeyType="next"
secureTextEntry
autoComplete="password"
autoCapitalize="none"
validationType="password"
autoCorrect={false}
placeholder={strings.password()}
onSubmit={() => {
confirmPasswordInputRef.current?.focus();
}}
/>
<Input
fwdRef={confirmPasswordInputRef}
onChangeText={(value) => {
confirmPassword.current = value;
}}
testID="input.confirmPassword"
onErrorCheck={(e) => setError(e)}
returnKeyLabel={strings.done()}
returnKeyType="done"
secureTextEntry
autoComplete="password"
autoCapitalize="none"
autoCorrect={false}
validationType="confirmPassword"
customValidator={() => password.current}
placeholder={strings.confirmPassword()}
marginBottom={12}
onSubmit={signup}
/>
<Paragraph
style={{
marginBottom: 25
}}
size={SIZE.xs}
color={colors.secondary.paragraph}
>
{strings.signupAgreement[0]()}
<Paragraph
size={SIZE.xs}
onPress={() => {
openLinkInBrowser("https://notesnook.com/tos", colors);
}}
style={{
textDecorationLine: "underline"
}}
color={colors.primary.accent}
>
{strings.signupAgreement[1]()}
</Paragraph>
{strings.signupAgreement[2]()}
<Paragraph
size={SIZE.xs}
onPress={() => {
openLinkInBrowser("https://notesnook.com/privacy", colors);
}}
style={{
textDecorationLine: "underline"
}}
color={colors.primary.accent}
>
{strings.signupAgreement[3]()}
</Paragraph>
{strings.signupAgreement[4]()}
</Paragraph>
<Button
title={!loading ? strings.continue() : null}
type="accent"
loading={loading}
onPress={signup}
fontSize={SIZE.md}
style={{
marginRight: 12,
width: 250,
borderRadius: 100
}}
/>
<TouchableOpacity
onPress={() => {
if (loading) return;
changeMode(0);
}}
activeOpacity={0.8}
style={{
alignSelf: "center",
marginTop: 12,
paddingVertical: 12
}}
>
<Paragraph size={SIZE.xs + 1} color={colors.secondary.paragraph}>
{strings.alreadyHaveAccount()}{" "}
<Paragraph
size={SIZE.xs + 1}
style={{ color: colors.primary.accent }}
<View
style={{
justifyContent: "flex-end",
paddingHorizontal: 16,
marginBottom: DefaultAppStyles.GAP_VERTICAL,
borderBottomWidth: 0.8,
borderBottomColor: colors.primary.border,
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 : "50%",
minHeight: height * 0.25
}}
>
{strings.login()}
</Paragraph>
</Paragraph>
</TouchableOpacity>
</View>
</View>
</>
<View
style={{
flexDirection: "row"
}}
>
<View
style={{
width: 100,
height: 5,
backgroundColor: colors.primary.accent,
borderRadius: 2,
marginRight: 7
}}
/>
<View
style={{
width: 20,
height: 5,
backgroundColor: colors.secondary.background,
borderRadius: 2
}}
/>
</View>
<Heading
extraBold
style={{
marginBottom: 25,
marginTop: 10
}}
size={AppFontSize.xxl}
>
{strings.createAccount()}
</Heading>
</View>
<View
style={{
width: DDS.isTab ? "50%" : "100%",
paddingHorizontal: DDS.isTab ? 0 : 16,
backgroundColor: colors.primary.background,
flexGrow: 1,
alignSelf: "center"
}}
>
<Input
fwdRef={emailInputRef}
onChangeText={(value) => {
email.current = value;
}}
defaultValue={email.current}
testID="input.email"
onErrorCheck={(e) => setError(e)}
returnKeyLabel="Next"
returnKeyType="next"
autoComplete="email"
validationType="email"
autoCorrect={false}
autoCapitalize="none"
errorMessage={strings.emailInvalid()}
placeholder={strings.email()}
blurOnSubmit={false}
onSubmit={() => {
if (!email.current) return;
passwordInputRef.current?.focus();
}}
/>
<Input
fwdRef={passwordInputRef}
onChangeText={(value) => {
password.current = value;
}}
defaultValue={password.current}
testID="input.password"
onErrorCheck={(e) => setError(e)}
returnKeyLabel="Next"
returnKeyType="next"
secureTextEntry
autoComplete="password"
autoCapitalize="none"
blurOnSubmit={false}
validationType="password"
autoCorrect={false}
placeholder={strings.password()}
onSubmit={() => {
if (!password.current) return;
confirmPasswordInputRef.current?.focus();
}}
/>
<Input
fwdRef={confirmPasswordInputRef}
onChangeText={(value) => {
confirmPassword.current = value;
}}
defaultValue={confirmPassword.current}
testID="input.confirmPassword"
onErrorCheck={(e) => setError(e)}
returnKeyLabel="Signup"
returnKeyType="done"
secureTextEntry
autoComplete="password"
autoCapitalize="none"
autoCorrect={false}
blurOnSubmit={false}
validationType="confirmPassword"
customValidator={() => password.current}
placeholder={strings.confirmPassword()}
marginBottom={12}
onSubmit={signup}
/>
<Button
title={!loading ? "Continue" : null}
type="accent"
loading={loading}
onPress={() => {
signup();
}}
width="100%"
/>
<TouchableOpacity
onPress={() => {
if (loading) return;
changeMode(0);
}}
activeOpacity={0.8}
style={{
alignSelf: "center",
marginTop: 12,
paddingVertical: 12
}}
>
<Paragraph
size={AppFontSize.xs + 1}
color={colors.secondary.paragraph}
>
{strings.alreadyHaveAccount()}{" "}
<Paragraph
size={AppFontSize.xs + 1}
style={{ color: colors.primary.accent }}
>
{strings.login()}
</Paragraph>
</Paragraph>
</TouchableOpacity>
</View>
<View
style={{
paddingHorizontal: DefaultAppStyles.GAP
}}
>
<Paragraph
style={{
marginBottom: 25,
textAlign: "center"
}}
size={AppFontSize.xxs}
color={colors.secondary.paragraph}
>
{strings.signupAgreement[0]()}
<Paragraph
size={AppFontSize.xxs}
onPress={() => {
openLinkInBrowser("https://notesnook.com/tos", colors);
}}
style={{
textDecorationLine: "underline"
}}
color={colors.primary.accent}
>
{" "}
{strings.signupAgreement[1]()}
</Paragraph>{" "}
{strings.signupAgreement[2]()}
<Paragraph
size={AppFontSize.xxs}
onPress={() => {
openLinkInBrowser(
"https://notesnook.com/privacy",
colors
);
}}
style={{
textDecorationLine: "underline"
}}
color={colors.primary.accent}
>
{" "}
{strings.signupAgreement[3]()}
</Paragraph>{" "}
{strings.signupAgreement[4]()}
</Paragraph>
</View>
</View>
</KeyboardAwareScrollView>
</>
) : (
<>
<Loading
title={"Setting up your account..."}
description="Your account is almost ready, please wait..."
/>
</>
)}
</SignupContext.Provider>
);
};

View File

@@ -24,19 +24,17 @@ import { View } from "react-native";
import { ScrollView } from "react-native-actions-sheet";
import { db } from "../../common/database/index";
import useTimer from "../../hooks/use-timer";
import {
eSendEvent,
presentSheet,
ToastManager
} from "../../services/event-manager";
import { eCloseSheet } from "../../utils/events";
import { SIZE } from "../../utils/size";
import { eSendEvent, ToastManager } from "../../services/event-manager";
import { eCloseSimpleDialog } from "../../utils/events";
import { AppFontSize } from "../../utils/size";
import { Button } from "../ui/button";
import { IconButton } from "../ui/icon-button";
import Input from "../ui/input";
import { Pressable } from "../ui/pressable";
import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import { DefaultAppStyles } from "../../utils/styles";
import { presentDialog } from "../dialog/functions";
const TwoFactorVerification = ({ onMfaLogin, mfaInfo, onCancel }) => {
const { colors } = useThemeColors();
@@ -45,7 +43,7 @@ const TwoFactorVerification = ({ onMfaLogin, mfaInfo, onCancel }) => {
method: mfaInfo?.primaryMethod,
isPrimary: true
});
const { seconds, start } = useTimer(currentMethod.method);
const { seconds, start, reset } = useTimer(currentMethod.method);
const [loading, setLoading] = useState(false);
const inputRef = useRef();
const [sending, setSending] = useState(false);
@@ -61,7 +59,7 @@ const TwoFactorVerification = ({ onMfaLogin, mfaInfo, onCancel }) => {
},
(result) => {
if (result) {
eSendEvent(eCloseSheet, "two_factor_verify");
eSendEvent(eCloseSimpleDialog, "two_factor_verify");
}
setLoading(false);
}
@@ -132,6 +130,17 @@ const TwoFactorVerification = ({ onMfaLogin, mfaInfo, onCancel }) => {
<ScrollView
keyboardShouldPersistTaps="handled"
keyboardDismissMode="interactive"
style={{
width: "100%",
height: "100%",
backgroundColor: colors.primary.background,
paddingTop: 60
}}
onLayout={() => {
setTimeout(() => {
inputRef.current?.focus();
}, 500);
}}
>
<View
style={{
@@ -162,7 +171,7 @@ const TwoFactorVerification = ({ onMfaLogin, mfaInfo, onCancel }) => {
textAlign: "center"
}}
>
{strings["2faCodeHelpText"][currentMethod.method]() ||
{strings["2faCodeHelpText"][currentMethod.method]?.() ||
strings.select2faCodeHelpText()}
</Paragraph>
@@ -202,13 +211,15 @@ const TwoFactorVerification = ({ onMfaLogin, mfaInfo, onCancel }) => {
code.current = value;
//onNext();
}}
cursorColor={colors.selected.accent}
selectionHandleColor={colors.selected.accent}
selectionColor={colors.selected.accent}
onSubmitEditing={onNext}
caretHidden
height={60}
inputStyle={{
fontSize: SIZE.lg,
height: 60,
fontSize: AppFontSize.lg,
textAlign: "center",
letterSpacing: 10,
letterSpacing: 7,
width: 250
}}
keyboardType={
@@ -216,11 +227,11 @@ const TwoFactorVerification = ({ onMfaLogin, mfaInfo, onCancel }) => {
}
enablesReturnKeyAutomatically
containerStyle={{
height: 60,
borderWidth: 0,
width: undefined,
minWidth: "50%"
}}
wrapperStyle={{
height: 60
}}
/>
<Button
@@ -229,9 +240,15 @@ const TwoFactorVerification = ({ onMfaLogin, mfaInfo, onCancel }) => {
width={250}
loading={loading}
onPress={onNext}
style={{
borderRadius: 100
/>
<Button
title={strings.cancel()}
type="secondaryAccented"
onPress={() => {
reset();
onCancel();
}}
width={250}
/>
<Button
@@ -242,13 +259,6 @@ const TwoFactorVerification = ({ onMfaLogin, mfaInfo, onCancel }) => {
onPress={onRequestSecondaryMethod}
height={30}
/>
<Button
title={strings.cancel()}
type="plain"
onPress={onCancel}
height={30}
/>
</>
) : (
<>
@@ -262,8 +272,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 +285,6 @@ const TwoFactorVerification = ({ onMfaLogin, mfaInfo, onCancel }) => {
<IconButton
type="secondaryAccented"
style={{
width: 40,
height: 40,
marginRight: 10
}}
size={15}
@@ -288,7 +296,7 @@ const TwoFactorVerification = ({ onMfaLogin, mfaInfo, onCancel }) => {
flexShrink: 1
}}
>
<Paragraph size={SIZE.md}>{item.title}</Paragraph>
<Paragraph size={AppFontSize.md}>{item.title}</Paragraph>
</View>
</Pressable>
))}
@@ -300,7 +308,7 @@ const TwoFactorVerification = ({ onMfaLogin, mfaInfo, onCancel }) => {
};
TwoFactorVerification.present = (onMfaLogin, data, onCancel, context) => {
presentSheet({
presentDialog({
component: () => (
<TwoFactorVerification
onMfaLogin={onMfaLogin}
@@ -309,7 +317,9 @@ TwoFactorVerification.present = (onMfaLogin, data, onCancel, context) => {
/>
),
context: context || "two_factor_verify",
disableClosing: true
disableClosing: true,
transparent: false,
statusBarTranslucent: true
});
};

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 { useRef, useState } from "react";
import { TextInput } from "react-native";
import { db } from "../../common/database";
import { eSendEvent, ToastManager } from "../../services/event-manager";
import { ToastManager, eSendEvent } from "../../services/event-manager";
import { clearMessage } from "../../services/message";
import PremiumService from "../../services/premium";
import SettingsService from "../../services/settings";
import { useUserStore } from "../../stores/use-user-store";
import { eCloseSheet } from "../../utils/events";
import { eCloseSimpleDialog } from "../../utils/events";
import TwoFactorVerification from "./two-factor";
import { strings } from "@notesnook/intl";
export const LoginSteps = {
emailAuth: 1,
@@ -34,15 +35,18 @@ export const LoginSteps = {
passwordAuth: 3
};
export const useLogin = (onFinishLogin, sessionExpired = false) => {
export const useLogin = (
onFinishLogin?: () => void,
sessionExpired = false
) => {
const [error, setError] = useState(false);
const [loading, setLoading] = useState(false);
const setUser = useUserStore((state) => state.setUser);
const [step, setStep] = useState(LoginSteps.emailAuth);
const email = useRef();
const password = useRef();
const emailInputRef = useRef();
const passwordInputRef = useRef();
const email = useRef<string>();
const password = useRef<string>();
const emailInputRef = useRef<TextInput>(null);
const passwordInputRef = useRef<TextInput>(null);
const validateInfo = () => {
if (
@@ -69,11 +73,15 @@ export const useLogin = (onFinishLogin, sessionExpired = false) => {
setLoading(true);
switch (step) {
case LoginSteps.emailAuth: {
if (!email.current) {
setLoading(false);
return;
}
const mfaInfo = await db.user.authenticateEmail(email.current);
console.log("email auth", mfaInfo);
if (mfaInfo) {
TwoFactorVerification.present(
async (mfa, callback) => {
async (mfa: any, callback: (success: boolean) => void) => {
try {
const success = await db.user.authenticateMultiFactorCode(
mfa.code,
@@ -91,8 +99,8 @@ export const useLogin = (onFinishLogin, sessionExpired = false) => {
callback && callback(false);
} catch (e) {
callback && callback(false);
if (e.message === "invalid_grant") {
eSendEvent(eCloseSheet, "two_factor_verify");
if ((e as Error).message === "invalid_grant") {
eSendEvent(eCloseSimpleDialog, "two_factor_verify");
setLoading(false);
setStep(LoginSteps.emailAuth);
}
@@ -100,7 +108,7 @@ export const useLogin = (onFinishLogin, sessionExpired = false) => {
},
mfaInfo,
() => {
eSendEvent(eCloseSheet, "two_factor_verify");
eSendEvent(eCloseSimpleDialog, "two_factor_verify");
setLoading(false);
setStep(LoginSteps.emailAuth);
}
@@ -111,10 +119,14 @@ export const useLogin = (onFinishLogin, sessionExpired = false) => {
break;
}
case LoginSteps.passwordAuth: {
if (!email.current || !password.current) {
setLoading(false);
return;
}
await db.user.authenticatePassword(
email.current,
password.current,
null,
undefined,
sessionExpired
);
finishLogin();
@@ -123,11 +135,11 @@ export const useLogin = (onFinishLogin, sessionExpired = false) => {
}
setLoading(false);
} catch (e) {
finishWithError(e);
finishWithError(e as Error);
}
};
const finishWithError = async (e) => {
const finishWithError = async (e: Error) => {
if (e.message === "invalid_grant") setStep(LoginSteps.emailAuth);
setLoading(false);
ToastManager.show({
@@ -146,7 +158,7 @@ export const useLogin = (onFinishLogin, sessionExpired = false) => {
clearMessage();
ToastManager.show({
heading: strings.loginSuccess(),
message: strings.loginSuccessDesc(),
message: strings.loginSuccessDesc(user.email),
type: "success",
context: "global"
});

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,32 @@ import { editorState } from "../../screens/editor/tiptap/utils";
import { useSelectionStore } from "../../stores/use-selection-store";
import { useSettingStore } from "../../stores/use-setting-store";
import { getElevationStyle } from "../../utils/elevation";
import { SIZE, normalize } from "../../utils/size";
import { Pressable } from "../ui/pressable";
import { AppFontSize, normalize } from "../../utils/size";
import { DefaultAppStyles } from "../../utils/styles";
import { hexToRGBA, RGB_Linear_Shade } from "../../utils/colors";
import useKeyboard from "../../hooks/use-keyboard";
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 +120,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 +147,29 @@ const FloatingButton = ({
style={{
alignItems: "center",
justifyContent: "center",
height: normalize(60),
width: normalize(60)
height: normalize(size === "small" ? 40 : 60),
width: normalize(size === "small" ? 40 : 60),
backgroundColor: color
? RGB_Linear_Shade(0.87, hexToRGBA(color))
: colors.primary.shade,
borderRadius: size === "small" ? 15 : 20
}}
>
<Icon
name={
route.name === "Notebooks"
icon
? icon
: route.name === "Notebooks"
? "notebook-plus"
: route.name === "Trash"
? "delete"
: "plus"
}
color={colors.primary.accentForeground}
size={SIZE.xxl}
color={color || colors.primary.accent}
size={size === "small" ? AppFontSize.xl : AppFontSize.xxxl}
/>
</View>
</Pressable>
</TouchableOpacity>
</Animated.View>
);
};

View File

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

View File

@@ -17,11 +17,10 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import React from "react";
import { ViewProps } from "react-native";
import Animated, { FadeOutUp } from "react-native-reanimated";
import { useDelayLayout } from "../../hooks/use-delay-layout";
import { useThemeColors } from "@notesnook/theme";
import React from "react";
import { View, ViewProps } from "react-native";
import { useDelayLayout } from "../../hooks/use-delay-layout";
import { DefaultPlaceholder } from "./default-placeholder";
import { SettingsPlaceholder } from "./settings-placeholder";
@@ -49,8 +48,7 @@ export default function DelayLayout({
const Placeholder = placeholder[props.type || "default"];
return loading || props.wait ? (
<Animated.View
exiting={animated ? FadeOutUp : undefined}
<View
style={{
backgroundColor: colors.primary.background,
flex: 1,
@@ -58,7 +56,7 @@ export default function DelayLayout({
}}
>
<Placeholder color={props.color || colors.primary.accent} />
</Animated.View>
</View>
) : (
<>{props.children}</>
);

View File

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

View File

@@ -31,37 +31,39 @@ import ResultDialog from "../dialogs/result";
import { VaultDialog } from "../dialogs/vault";
import ImagePreview from "../image-preview";
import MergeConflicts from "../merge-conflicts";
import PremiumDialog from "../premium";
import { Expiring } from "../premium/expiring";
import SheetProvider from "../sheet-provider";
import RateAppSheet from "../sheets/rate-app";
import RecoveryKeySheet from "../sheets/recovery-key";
import Progress from "../dialogs/progress";
import { useSettingStore } from "../../stores/use-setting-store";
const DialogProvider = () => {
const { colors } = useThemeColors();
const isAppLoading = useSettingStore((state) => state.isAppLoading);
return (
<>
<AppLockPassword />
<LoadingDialog />
<Dialog context="global" />
<PremiumDialog colors={colors} />
<AuthModal colors={colors} />
<MergeConflicts />
<RecoveryKeySheet colors={colors} />
<SheetProvider />
<SheetProvider context="sync_progress" />
<ResultDialog />
<VaultDialog colors={colors} />
<RateAppSheet />
<ImagePreview />
<Expiring />
<AnnouncementDialog />
<SessionExpired />
<PDFPreview />
<JumpToSectionDialog />
<Dialog context="global" />
<Progress />
{isAppLoading ? null : (
<>
<MergeConflicts />
<RecoveryKeySheet colors={colors} />
<ResultDialog />
<VaultDialog colors={colors} />
<RateAppSheet />
<ImagePreview />
<AnnouncementDialog />
<SessionExpired />
<PDFPreview />
<JumpToSectionDialog />
</>
)}
</>
);
};

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,15 +31,12 @@ 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;
visible: boolean;
visible?: boolean;
onRequestClose?: () => void;
onShow?: () => void;
premium?: boolean;
@@ -75,9 +73,9 @@ const BaseDialog = ({
background
}: BaseDialogProps) => {
const floating = useIsFloatingKeyboard();
const appState = useAppState();
const lockEvents = useRef(false);
const [internalVisible, setIntervalVisible] = useState(true);
const locked = useUserStore((state) => state.appLocked);
useEffect(() => {
return () => {
@@ -86,26 +84,20 @@ const BaseDialog = ({
}, []);
useEffect(() => {
if (useUserStore.getState().disableAppLockRequests) return;
if (SettingsService.canLockAppInBackground()) {
if (appState === "background") {
setIntervalVisible(false);
if (useUserStore.getState().appLocked) {
lockEvents.current = true;
const unsub = useUserStore.subscribe((state) => {
if (!state.appLocked) {
setIntervalVisible(true);
unsub();
setTimeout(() => {
lockEvents.current = false;
});
}
if (locked) {
setIntervalVisible(false);
lockEvents.current = true;
const unsub = useUserStore.subscribe((state) => {
if (!state.appLocked) {
setIntervalVisible(true);
unsub();
setTimeout(() => {
lockEvents.current = false;
});
}
}
});
}
}, [appState]);
}, [locked]);
const Wrapper = useSafeArea ? SafeAreaView : View;

View File

@@ -17,16 +17,17 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { strings } from "@notesnook/intl";
import { useThemeColors } from "@notesnook/theme";
import React from "react";
import { ActivityIndicator, StyleSheet, View } from "react-native";
import { StyleSheet, View } from "react-native";
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
import { notesnook } from "../../../e2e/test.ids";
import { useThemeColors } from "@notesnook/theme";
import { SIZE } from "../../utils/size";
import { Button } from "../ui/button";
import Paragraph from "../ui/typography/paragraph";
import { getColorLinearShade } from "../../utils/colors";
import { strings } from "@notesnook/intl";
import { AppFontSize } from "../../utils/size";
import { DefaultAppStyles } from "../../utils/styles";
import { Button, ButtonProps } from "../ui/button";
import Paragraph from "../ui/typography/paragraph";
const DialogButtons = ({
onPressPositive,
@@ -36,6 +37,14 @@ const DialogButtons = ({
loading,
doneText,
positiveType
}: {
onPressPositive?: () => void;
onPressNegative: () => void;
positiveTitle: string;
negativeTitle?: string;
loading?: boolean;
doneText?: string;
positiveType?: ButtonProps["type"];
}) => {
const { colors, isDark } = useThemeColors();
@@ -46,9 +55,7 @@ const DialogButtons = ({
{
backgroundColor: colors.secondary.background,
height: 60,
borderBottomRightRadius: 5,
borderBottomLeftRadius: 5,
paddingHorizontal: 12,
paddingHorizontal: DefaultAppStyles.GAP,
borderTopWidth: 0.7,
borderTopColor: getColorLinearShade(
colors.secondary.background,
@@ -58,9 +65,7 @@ const DialogButtons = ({
}
]}
>
{loading ? (
<ActivityIndicator color={colors.primary.accent} size={SIZE.lg} />
) : doneText ? (
{doneText ? (
<View
style={{
flexDirection: "row",
@@ -70,7 +75,7 @@ const DialogButtons = ({
<Icon
color={colors.primary.accent}
name="check-circle-outline"
size={SIZE.md}
size={AppFontSize.md}
/>
<Paragraph color={colors.primary.accent}>{" " + doneText}</Paragraph>
</View>
@@ -86,7 +91,7 @@ const DialogButtons = ({
>
<Button
onPress={onPressNegative}
fontSize={SIZE.md}
fontSize={AppFontSize.sm}
testID={notesnook.ids.default.dialog.no}
type="plain"
bold
@@ -95,11 +100,12 @@ const DialogButtons = ({
{onPressPositive ? (
<Button
onPress={onPressPositive}
fontSize={SIZE.md}
fontSize={AppFontSize.sm}
testID={notesnook.ids.default.dialog.yes}
style={{
marginLeft: 10
}}
loading={loading}
bold
type={positiveType || "transparent"}
title={positiveTitle}
@@ -117,6 +123,6 @@ const styles = StyleSheet.create({
justifyContent: "space-between",
alignItems: "center",
flexDirection: "row",
marginTop: 10
marginTop: DefaultAppStyles.GAP_VERTICAL
}
});

View File

@@ -20,23 +20,18 @@ 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 { Button } from "../ui/button";
import { AppFontSize } from "../../utils/size";
import { Button, ButtonProps } 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;
title?: string;
paragraph?: string;
button?: {
onPress?: () => void;
loading?: boolean;
title?: string;
type?: PressableProps["type"];
icon?: string;
};
button?: ButtonProps;
paragraphColor?: string;
padding?: number;
centered?: boolean;
@@ -82,7 +77,7 @@ const DialogHeader = ({
>
<Heading
style={{ textAlign: centered ? "center" : "left" }}
size={SIZE.lg}
size={AppFontSize.lg}
>
{title}{" "}
{titlePart ? (
@@ -94,17 +89,14 @@ const DialogHeader = ({
{button ? (
<Button
onPress={button.onPress}
style={{
borderRadius: 100,
paddingHorizontal: 12
paddingHorizontal: DefaultAppStyles.GAP
}}
loading={button.loading}
fontSize={13}
title={button.title}
icon={button.icon}
type={button.type || "secondary"}
height={30}
{...button}
/>
) : null}
</View>

View File

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

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