Compare commits

...

206 Commits

Author SHA1 Message Date
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
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
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
Abdullah Atta
95f52fba51 Merge pull request #8633 from streetwriters/release/v3.3 2025-10-04 22:08:21 +05:00
235 changed files with 8829 additions and 8909 deletions

View File

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

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

@@ -73,6 +73,12 @@ jobs:
- 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

@@ -73,6 +73,12 @@ jobs:
- 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

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

@@ -65,17 +65,13 @@ jobs:
npm i --cpu x64 sqlite-better-trigram
working-directory: ./apps/desktop
- name: Setup environment
run: |
echo "NX_CLOUD_ACCESS_TOKEN=${{ secrets.NX_CLOUD_ACCESS_TOKEN }}" >> $GITHUB_ENV
- name: Generate desktop build (stable)
if: ${{ inputs.release-track == 'stable' }}
run: npx nx build:desktop @notesnook/web
run: npm run tx @notesnook/web:build:desktop
- name: Generate desktop build (beta)
if: ${{ inputs.release-track == 'beta' }}
run: BETA=true npx nx build:desktop @notesnook/web
run: BETA=true npm run tx @notesnook/web:build:desktop
- name: Build desktop bundle
working-directory: ./apps/desktop
@@ -199,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
npm run tx @notesnook/desktop:release -- --variant=mas
cd apps/desktop
yarn electron-builder --config=electron-builder.config.js --mac mas --universal -p never
working-directory: ./apps/desktop
- name: Build zip and dmg
env:
@@ -212,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 --config=electron-builder.config.js --mac zip dmg --arm64 --x64 -p always
else
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
@@ -271,8 +267,7 @@ 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 snap
if: inputs.publish-snap
@@ -339,8 +334,7 @@ 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 snap
# if: inputs.publish-snap

View File

@@ -33,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
@@ -70,8 +66,7 @@ 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: |
@@ -114,8 +109,7 @@ 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: |
@@ -164,8 +158,7 @@ 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: |

View File

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

@@ -25,7 +25,7 @@ jobs:
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
@@ -64,6 +64,12 @@ jobs:
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

@@ -39,7 +39,7 @@ 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

View File

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

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

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

@@ -30,7 +30,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

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

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.**

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,7 @@
"name": "@notesnook/desktop",
"productName": "Notesnook",
"description": "Your private note taking space",
"version": "3.3.0",
"version": "3.3.3",
"appAppleId": "1544027013",
"private": true,
"main": "./dist/cjs/index.js",
@@ -47,7 +47,7 @@
"@types/node": "22.15.3",
"@types/yargs": "^17.0.33",
"chokidar": "^4.0.3",
"electron": "^36.0.0",
"electron": "^37.0.0",
"electron-builder": "^26.0.12",
"esbuild": "0.21.5",
"node-abi": "^4.5.0",

View File

@@ -18,7 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import "./overrides";
import { app, BrowserWindow, nativeTheme, shell } from "electron";
import { app, BrowserWindow, nativeTheme, shell, dialog } from "electron";
import { isDevelopment } from "./utils";
import { registerProtocol, PROTOCOL_URL } from "./utils/protocol";
import { configureAutoUpdater } from "./utils/autoupdater";
@@ -182,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

@@ -94,7 +94,9 @@ export async function encryptDatabaseKeyWithPassword(appLockPassword: string) {
}
export async function restoreDatabaseKeyToKeyChain(appLockPassword: string) {
const databaseKeyCipher: Cipher = CipherStorage.getMap(DB_KEY_CIPHER);
const databaseKeyCipher: Cipher = CipherStorage.getMap(
DB_KEY_CIPHER
) as Cipher;
const databaseKey = (await decrypt(
{
password: appLockPassword
@@ -135,7 +137,9 @@ export async function clearAppLockVerificationCipher() {
export async function validateAppLockPassword(appLockPassword: string) {
try {
const appLockCipher: Cipher = CipherStorage.getMap(APPLOCK_CIPHER);
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);
@@ -159,7 +163,9 @@ export function clearDatabaseKey() {
export async function getDatabaseKey(appLockPassword?: string) {
if (DB_KEY) return DB_KEY;
if (appLockPassword) {
const databaseKeyCipher: Cipher = CipherStorage.getMap("databaseKeyCipher");
const databaseKeyCipher: Cipher = CipherStorage.getMap(
"databaseKeyCipher"
) as Cipher;
const databaseKey = await decrypt(
{
password: appLockPassword
@@ -293,7 +299,7 @@ export async function deriveCryptoKey(data: SerializedKey) {
export async function getCryptoKey() {
try {
const keyCipher: Cipher = MMKV.getMap(USER_KEY_CIPHER);
const keyCipher: Cipher = MMKV.getMap(USER_KEY_CIPHER) as Cipher;
if (!keyCipher) {
DatabaseLogger.info("User key cipher is null");
return undefined;

View File

@@ -39,7 +39,7 @@ export async function setupDatabase(password?: string) {
const key = await getDatabaseKey(password);
if (!key) throw new Error(strings.databaseSetupFailed());
// const base = `http://192.168.100.88`;
// const base = `http://192.168.100.92`;
// database.host({
// API_HOST: `${base}:5264`,

View File

@@ -136,6 +136,12 @@ export const Storage: IStorage = {
clear(): Promise<void> {
return DefaultStorage.clear();
},
generateCryptoKeyPair() {
throw new Error("Not implemented");
},
decryptAsymmetric() {
throw new Error("Not implemented");
},
getAllKeys(): Promise<string[]> {
return DefaultStorage.getAllKeys();
},

View File

@@ -38,9 +38,6 @@ export function hideAuth(context) {
context === "intro"
) {
Navigation.replace("FluidPanelsView");
setTimeout(() => {
Navigation.resetRootState();
}, 1000);
} else {
Navigation.goBack();
}

View File

@@ -19,14 +19,11 @@ 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 {
ScrollView,
TouchableOpacity,
View,
useWindowDimensions
} from "react-native";
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";
@@ -47,8 +44,7 @@ import { hideAuth } from "./common";
import { ForgotPassword } from "./forgot-password";
import { AuthHeader } from "./header";
import { useLogin } from "./use-login";
import { useRoute } from "@react-navigation/native";
import { KeyboardAwareScrollView } from "react-native-keyboard-aware-scroll-view";
import SettingsService from "../../services/settings";
const LoginSteps = {
emailAuth: 1,
@@ -81,7 +77,7 @@ export const Login = ({ changeMode }) => {
}
}, 5000);
if (!PremiumService.get()) {
if (!PremiumService.get() && !SettingsService.getProperty("serverUrls")) {
Navigation.navigate("PayWall", {
context: "signup",
state: route.params.state,

View File

@@ -19,6 +19,7 @@ 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";
@@ -38,7 +39,7 @@ import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import { AuthHeader } from "./header";
import { SignupContext } from "./signup-context";
import { useRoute } from "@react-navigation/native";
import SettingsService from "../../services/settings";
const SignupSteps = {
signup: 0,
@@ -91,11 +92,13 @@ export const Signup = ({ changeMode, welcome }) => {
setLastSynced(await db.lastSynced());
clearMessage();
setEmailVerifyMessage();
Navigation.navigate("PayWall", {
canGoBack: false,
state: route.params.state,
context: "signup"
});
if (!SettingsService.getProperty("serverUrls")) {
Navigation.navigate("PayWall", {
canGoBack: false,
state: route.params.state,
context: "signup"
});
}
return true;
} catch (e) {
setCurrentStep(SignupSteps.signup);

View File

@@ -99,7 +99,7 @@ export const useLogin = (
callback && callback(false);
} catch (e) {
callback && callback(false);
if (e.message === "invalid_grant") {
if ((e as Error).message === "invalid_grant") {
eSendEvent(eCloseSimpleDialog, "two_factor_verify");
setLoading(false);
setStep(LoginSteps.emailAuth);

View File

@@ -35,29 +35,35 @@ 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" />
<AuthModal colors={colors} />
<MergeConflicts />
<RecoveryKeySheet colors={colors} />
<SheetProvider />
<SheetProvider context="sync_progress" />
<ResultDialog />
<VaultDialog colors={colors} />
<RateAppSheet />
<ImagePreview />
<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

@@ -244,7 +244,7 @@ const PDFPreview = () => {
textAlign: "center",
marginRight: 4,
borderRadius: 3,
fontFamily: "OpenSans-Regular"
fontFamily: "Inter-Regular"
}}
selectTextOnFocus
keyboardType="decimal-pad"

View File

@@ -41,7 +41,7 @@ export const openNotebook = (item: Notebook | BaseTrashItem<Notebook>) => {
positiveText: strings.restore(),
negativeText: strings.delete(),
positivePress: async () => {
if ((await db.trash.restore(item.id)) === false) return;
await db.trash.restore(item.id);
Navigation.queueRoutesForUpdate();
useSelectionStore.getState().setSelectionMode(undefined);
ToastManager.show({

View File

@@ -117,7 +117,8 @@ export default function NotePreview({ session, content, note }) {
{!session?.locked && !locked ? (
<View
style={{
flex: 1
flex: 1,
backgroundColor: colors.primary.background
}}
>
<ReadonlyEditor

View File

@@ -44,6 +44,7 @@ import Config from "react-native-config";
import * as RNIap from "react-native-iap";
import { SafeAreaView } from "react-native-safe-area-context";
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
//@ts-ignore
import ToggleSwitch from "toggle-switch-react-native";
import {
ANDROID_POLICE_SVG,
@@ -60,6 +61,7 @@ import usePricingPlans, {
PricingPlan
} from "../../hooks/use-pricing-plans";
import Navigation, { NavigationProps } from "../../services/navigation";
import PremiumService from "../../services/premium";
import { getElevationStyle } from "../../utils/elevation";
import { openLinkInBrowser } from "../../utils/functions";
import { AppFontSize, defaultBorderRadius } from "../../utils/size";
@@ -74,7 +76,6 @@ import { IconButton } from "../ui/icon-button";
import { SvgView } from "../ui/svg";
import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
import PremiumService from "../../services/premium";
const Steps = {
select: 1,
@@ -114,15 +115,8 @@ const PayWall = (props: NavigationProps<"PayWall">) => {
routeParams.state?.planId,
routeParams.state?.productId
);
console.log(
"selectPlan",
routeParams.state?.planId,
routeParams.state?.productId,
(pricingPlans.selectedProduct as any).productId
);
}
setStep(Steps.buy);
console.log("Buy step");
}
}, [routeParams.state]);
@@ -926,7 +920,6 @@ const ReviewItem = (props: {
</View>
);
};
const PricingPlanCard = ({
plan,
pricingPlans,
@@ -939,7 +932,6 @@ const PricingPlanCard = ({
setStep: (step: number) => void;
}) => {
const { colors } = useThemeColors();
const isFreePlan = plan.id === "free";
const [regionalDiscount, setRegionaDiscount] = useState<SKUResponse>();
const { width } = useWindowDimensions();
const isTablet = width > 600;
@@ -949,19 +941,22 @@ const PricingPlanCard = ({
regionalDiscount?.sku ||
`notesnook.${plan.id}.${annualBilling ? "yearly" : "monthly"}`
];
console.log(regionalDiscount?.sku);
const price = pricingPlans?.getPrice(
product as RNIap.Subscription,
pricingPlans.hasTrialOffer(plan.id, product?.productId) ? 1 : 0,
annualBilling
);
const WebPlan = pricingPlans?.getWebPlan(
plan.id,
annualBilling ? "yearly" : "monthly"
);
const price = pricingPlans?.getPrice(
pricingPlans.isGithubRelease && WebPlan
? WebPlan
: (product as RNIap.Subscription),
pricingPlans.hasTrialOffer(plan.id, product?.productId) ? 1 : 0,
annualBilling
);
useEffect(() => {
if (pricingPlans?.isGithubRelease || !annualBilling) return;
pricingPlans
?.getRegionalDiscount(
plan.id,
@@ -972,7 +967,13 @@ const PricingPlanCard = ({
.then((value) => {
setRegionaDiscount(value);
});
}, []);
}, [annualBilling]);
useEffect(() => {
if (!annualBilling) {
setRegionaDiscount(undefined);
}
}, [annualBilling]);
const isSubscribed =
product?.productId &&
@@ -980,7 +981,7 @@ const PricingPlanCard = ({
pricingPlans.isSubscribed();
const isNotReady =
pricingPlans?.loadingPlans || (!price && !WebPlan?.price.gross);
pricingPlans?.loadingPlans || (!price && !WebPlan?.price?.gross);
return (
<TouchableOpacity
@@ -1112,29 +1113,26 @@ const PricingPlanCard = ({
</View>
</View>
{pricingPlans?.loadingPlans || (!price && !WebPlan?.price.gross) ? (
{pricingPlans?.loadingPlans || (!price && !WebPlan?.price?.gross) ? (
<ActivityIndicator size="small" color={colors.primary.accent} />
) : (
<View>
<Paragraph size={AppFontSize.lg}>
{isFreePlan
? "0.00"
: price ||
`${WebPlan?.price.currency} ${WebPlan?.price.gross}`}{" "}
{price || `${WebPlan?.price?.currency} ${WebPlan?.price?.gross}`}{" "}
<Paragraph>/{strings.month()}</Paragraph>
</Paragraph>
{isFreePlan || !product ? null : (
{!product && !WebPlan ? null : (
<Paragraph color={colors.secondary.paragraph} size={AppFontSize.xs}>
{annualBilling
? strings.billedAnnually(
pricingPlans?.getStandardPrice(
product as RNIap.Subscription
(product || WebPlan) as any
) as string
)
: strings.billedMonthly(
pricingPlans?.getStandardPrice(
product as RNIap.Subscription
(product || WebPlan) as any
) as string
)}
</Paragraph>

View File

@@ -21,7 +21,13 @@ import { strings } from "@notesnook/intl";
import { useThemeColors } from "@notesnook/theme";
import dayjs from "dayjs";
import React, { useEffect, useState } from "react";
import { ScrollView, Text, TouchableOpacity, View } from "react-native";
import {
Linking,
ScrollView,
Text,
TouchableOpacity,
View
} from "react-native";
import Config from "react-native-config";
import * as RNIap from "react-native-iap";
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
@@ -60,27 +66,24 @@ export const BuyPlan = (props: {
return checkoutUrl ? (
<View
style={{
flex: 1
flex: 1,
justifyContent: "center",
alignItems: "center",
gap: DefaultAppStyles.GAP_VERTICAL
}}
>
<WebView
source={{
uri: checkoutUrl
<Paragraph>{strings.finishPurchaseInBrowser()}</Paragraph>
<Button
title={strings.next()}
type="accent"
onPress={() => {
pricingPlans.finish();
}}
onMessage={(message) => {
try {
const data = JSON.parse(message.nativeEvent.data);
if (data.success) {
pricingPlans.finish();
}
} catch (e) {}
}}
domStorageEnabled
javaScriptEnabled
cacheEnabled
enabled
style={{
flex: 1
/>
<Button
title={strings.goBack()}
onPress={() => {
setCheckoutUrl(undefined);
}}
/>
</View>
@@ -245,12 +248,14 @@ export const BuyPlan = (props: {
}
onPress={async () => {
if (isGithubRelease) {
setCheckoutUrl(
await db.subscriptions.checkoutUrl(
(pricingPlans.selectedProduct as Plan).plan,
(pricingPlans.selectedProduct as Plan).period
)
const url = await db.subscriptions.checkoutUrl(
(pricingPlans.selectedProduct as Plan).plan,
(pricingPlans.selectedProduct as Plan).period
);
if (url) {
setCheckoutUrl(url);
Linking.openURL(url);
}
return;
}

View File

@@ -39,9 +39,7 @@ import {
presentSheet
} from "../../../services/event-manager";
import Exporter from "../../../services/exporter";
import PremiumService from "../../../services/premium";
import { useSettingStore } from "../../../stores/use-setting-store";
import { useUserStore } from "../../../stores/use-user-store";
import { getElevationStyle } from "../../../utils/elevation";
import { AppFontSize, defaultBorderRadius } from "../../../utils/size";
import { DefaultAppStyles } from "../../../utils/styles";
@@ -83,7 +81,6 @@ const ExportNotesSheet = ({
type: "pdf" | "txt" | "md" | "html" | "md-frontmatter"
) => {
if (exporting) return;
if (!PremiumService.get() && type !== "txt") return;
setExporting(true);
update?.({ disableClosing: true } as PresentSheetOptions);
setComplete(false);
@@ -145,8 +142,7 @@ const ExportNotesSheet = ({
await exportNoteAs("txt");
},
icon: "card-text",
id: notesnook.ids.dialogs.export.text,
pro: true
id: notesnook.ids.dialogs.export.text
},
{
title: "HTML",
@@ -194,8 +190,7 @@ const ExportNotesSheet = ({
paddingVertical: DefaultAppStyles.GAP_VERTICAL,
justifyContent: "flex-start",
borderRadius: 0,
paddingHorizontal: DefaultAppStyles.GAP,
opacity: item.pro ? 1 : 0.5
paddingHorizontal: DefaultAppStyles.GAP
}}
>
<View

View File

@@ -36,6 +36,7 @@ import Heading from "../../ui/typography/heading";
import Paragraph from "../../ui/typography/paragraph";
import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../../utils/styles";
import Config from "react-native-config";
export const Issue = ({ defaultTitle, defaultBody, issueTitle }) => {
const { colors } = useThemeColors();
@@ -67,7 +68,8 @@ App version: ${getVersion()}
Platform: ${Platform.OS}
Device: ${getBrand() || ""}-${getModel() || ""}-${getSystemVersion() || ""}
Pro: ${PremiumService.get()}
Logged in: ${user ? "yes" : "no"}`,
Logged in: ${user ? "yes" : "no"}
Github Release: ${Config.GITHUB_RELEASE === "true" ? "Yes" : "No"}`,
userId: user?.id
});
if (!issueUrl.current) {
@@ -159,7 +161,7 @@ Logged in: ${user ? "yes" : "no"}`,
borderColor: colors.primary.border,
borderRadius: defaultBorderRadius,
padding: DefaultAppStyles.GAP,
fontFamily: "OpenSans-Regular",
fontFamily: "Inter-Regular",
marginBottom: DefaultAppStyles.GAP_VERTICAL,
fontSize: AppFontSize.md,
color: colors.primary.heading
@@ -192,7 +194,7 @@ Logged in: ${user ? "yes" : "no"}`,
borderColor: colors.primary.border,
borderRadius: defaultBorderRadius,
padding: DefaultAppStyles.GAP,
fontFamily: "OpenSans-Regular",
fontFamily: "Inter-Regular",
maxHeight: 200,
fontSize: AppFontSize.sm,
marginBottom: 2.5,

View File

@@ -15,6 +15,7 @@ import {
} from "../../../services/event-manager";
import Navigation from "../../../services/navigation";
import PremiumService from "../../../services/premium";
import SettingsService from "../../../services/settings";
import { useUserStore } from "../../../stores/use-user-store";
import { eCloseSheet } from "../../../utils/events";
import { AppFontSize } from "../../../utils/size";
@@ -37,7 +38,6 @@ export default function PaywallSheet<Tid extends FeatureId>(props: {
const { colors } = useThemeColors();
const pricingPlans = usePricingPlans();
useEffect(() => {
console.log("PaywallSheet mounted with feature:", props.feature);
ToastManager.hide();
if (!props.feature.availableOn) return;
const plan = pricingPlans.pricingPlans.find(
@@ -55,11 +55,11 @@ export default function PaywallSheet<Tid extends FeatureId>(props: {
}, []);
const isSubscribedOnWeb =
(PremiumService.get() &&
PremiumService.get() &&
(pricingPlans.user?.subscription?.provider ===
SubscriptionProvider.PADDLE ||
pricingPlans.user?.subscription?.provider ===
SubscriptionProvider.PADDLE) ||
pricingPlans.user?.subscription?.provider ===
SubscriptionProvider.STREETWRITERS;
SubscriptionProvider.STREETWRITERS);
const isCurrentPlatform =
(pricingPlans.user?.subscription?.provider === SubscriptionProvider.APPLE &&
@@ -194,25 +194,28 @@ export default function PaywallSheet<Tid extends FeatureId>(props: {
width: "100%"
}}
onPress={() => {
if (
pricingPlans.user?.subscription.plan ===
SubscriptionPlan.LEGACY_PRO ||
!isCurrentPlatform
) {
ToastManager.show({
message: strings.cannotChangePlan(),
context: "local"
});
return;
if (PremiumService.get()) {
if (
pricingPlans.user?.subscription.plan ===
SubscriptionPlan.LEGACY_PRO ||
!isCurrentPlatform
) {
ToastManager.show({
message: strings.cannotChangePlan(),
context: "local"
});
return;
}
if (isSubscribedOnWeb) {
ToastManager.show({
message: strings.changePlanOnWeb(),
context: "local"
});
return;
}
}
if (isSubscribedOnWeb) {
ToastManager.show({
message: strings.changePlanOnWeb(),
context: "local"
});
return;
}
eSendEvent(eCloseSheet);
if (!useUserStore.getState().user) {
Navigation.navigate("Auth", {
@@ -256,6 +259,7 @@ export default function PaywallSheet<Tid extends FeatureId>(props: {
}
PaywallSheet.present = <Tid extends FeatureId>(feature: FeatureResult<Tid>) => {
if (SettingsService.getProperty("serverUrls")) return;
presentSheet({
component: <PaywallSheet feature={feature} />
});

View File

@@ -20,6 +20,7 @@ import Paragraph from "../../ui/typography/paragraph";
import { SubscriptionPlan, SubscriptionProvider } from "@notesnook/core";
import { useUserStore } from "../../../stores/use-user-store";
import PremiumService from "../../../services/premium";
import SettingsService from "../../../services/settings";
export function PlanLimits() {
const { colors } = useThemeColors();
@@ -84,10 +85,11 @@ export function PlanLimits() {
</View>
))}
{(user?.subscription?.provider === SubscriptionProvider.PADDLE ||
{((user?.subscription?.provider === SubscriptionProvider.PADDLE ||
user?.subscription?.provider === SubscriptionProvider.STREETWRITERS ||
!isCurrentPlatform) &&
PremiumService.get() ? null : (
PremiumService.get()) ||
SettingsService.getProperty("serverUrls") ? null : (
<Button
title={strings.changePlan()}
onPress={() => {

View File

@@ -29,6 +29,7 @@ import {
View
} from "react-native";
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
//@ts-ignore
import ToggleSwitch from "toggle-switch-react-native";
import { db } from "../../../common/database";
import { requestInAppReview } from "../../../services/app-review";

View File

@@ -24,10 +24,11 @@ import { FlatList, View } from "react-native";
import { DraxProvider, DraxScrollView } from "react-native-drax";
import { db } from "../../common/database";
import Navigation from "../../services/navigation";
import SettingsService from "../../services/settings";
import { useMenuStore } from "../../stores/use-menu-store";
import { useSettingStore } from "../../stores/use-setting-store";
import { useUserStore } from "../../stores/use-user-store";
import { SUBSCRIPTION_STATUS } from "../../utils/constants";
import { MenuItemsList } from "../../utils/menu-items";
import { DefaultAppStyles } from "../../utils/styles";
import ReorderableList from "../list/reorderable-list";
import { MenuItemProperties } from "../sheets/menu-item-properties";
@@ -36,7 +37,6 @@ import { ColorSection } from "./color-section";
import { MenuItem } from "./menu-item";
import { PinnedSection } from "./pinned-section";
import { SideMenuHeader } from "./side-menu-header";
import { MenuItemsList } from "../../utils/menu-items";
const pro = {
title: strings.upgradePlan(),
@@ -140,9 +140,10 @@ export function SideMenuHome() {
paddingVertical: DefaultAppStyles.GAP_VERTICAL
}}
>
{subscriptionType === SubscriptionPlan.FREE ||
!subscriptionType ||
!user ? (
{(subscriptionType === SubscriptionPlan.FREE ||
!subscriptionType ||
!user) &&
!SettingsService.getProperty("serverUrls") ? (
<Button
title={pro.title}
style={{

View File

@@ -239,7 +239,7 @@ const Input = ({
flexShrink: 1,
paddingBottom: DefaultAppStyles.GAP_VERTICAL - 4,
paddingTop: DefaultAppStyles.GAP_VERTICAL - 4,
fontFamily: "OpenSans-Regular",
fontFamily: "Inter-Regular",
...(inputStyle as ViewStyle)
};

View File

@@ -132,7 +132,10 @@ const SheetWrapper = ({
width: 100,
backgroundColor: colors.secondary.background
}}
safeAreaInsets={insets}
safeAreaInsets={{
...insets,
bottom: Platform.OS === "android" ? 0 : insets.bottom
}}
statusBarTranslucent
drawUnderStatusBar={true}
containerStyle={style}

View File

@@ -171,7 +171,7 @@ const onAppOpenedFromURL = async (event: { url: string }) => {
eSendEvent(eOnLoadNote, { newNote: true });
fluidTabsRef.current?.goToPage("editor", false);
return;
} else if (url.startsWith("https://notesnook.com/open_note")) {
} else if (url.startsWith("https://app.notesnook.com/open_note")) {
const id = new URL(url).searchParams.get("id");
if (id) {
const note = await db.notes.note(id);
@@ -182,13 +182,13 @@ const onAppOpenedFromURL = async (event: { url: string }) => {
fluidTabsRef.current?.goToPage("editor", false);
}
}
} else if (url.startsWith("https://notesnook.com/open_reminder")) {
} else if (url.startsWith("https://app.notesnook.com/open_reminder")) {
const id = new URL(url).searchParams.get("id");
if (id) {
const reminder = await db.reminders.reminder(id);
if (reminder) AddReminder.present(reminder);
}
} else if (url.startsWith("https://notesnook.com/new_reminder")) {
} else if (url.startsWith("https://app.notesnook.com/new_reminder")) {
const reminderFeature = await isFeatureAvailable("activeReminders");
if (!reminderFeature.isAllowed) {
ToastManager.show({
@@ -780,13 +780,11 @@ export const useAppEvents = () => {
if (!isAppLoading && !appLocked) {
setTimeout(() => {
sub = AppState.addEventListener("change", onAppStateChanged);
if (
refValues.current.initialUrl &&
!refValues.current.initialUrl?.includes("open_note")
) {
if (refValues.current.initialUrl) {
onAppOpenedFromURL({
url: refValues.current.initialUrl!
});
refValues.current.initialUrl = undefined;
}
}, 1000);

View File

@@ -69,35 +69,6 @@ export default function useFeatureManager() {
db.settings.setDefaultTag(undefined);
}
}
const isAppLocked = useUserStore.getState().appLocked;
let unsub: () => void;
if (isAppLocked) {
unsub = useUserStore.subscribe((state) => {
if (!state.appLocked && !features?.appLock?.isAllowed) {
unsub();
SettingsService.setProperty("appLockEnabled", false);
setTimeout(() => {
presentDialog({
title: "App Lock Disabled",
paragraph: features?.appLock?.error,
positiveText: strings.upgrade(),
negativeText: strings.cancel(),
positivePress: async () => {
eSendEvent(eCloseSimpleDialog);
Navigation.navigate("PayWall", {
context: "logged-in"
});
}
});
}, 1000);
}
});
}
return () => {
unsub?.();
};
}, [features, plan]);
return true;

View File

@@ -25,6 +25,7 @@ import { DatabaseLogger, db } from "../common/database";
import PremiumService from "../services/premium";
import { useSettingStore } from "../stores/use-setting-store";
import { useUserStore } from "../stores/use-user-store";
import SettingsService from "../services/settings";
function numberWithCommas(x: string) {
const parts = x.toString().split(".");
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
@@ -201,7 +202,7 @@ const usePricingPlans = (options?: PricingPlansOptions) => {
if (productId?.includes("5year")) return false;
if (isGithubRelease) {
if (
user?.subscription.trialsAvailed?.some(
user?.subscription?.trialsAvailed?.some(
(plan) => plan === planIdToIndex(planId || currentPlan)
)
) {
@@ -246,7 +247,10 @@ const usePricingPlans = (options?: PricingPlansOptions) => {
});
setPlans([...pricingPlans]);
setUserCanRequestTrial(hasTrialOffer());
if (Config.GITHUB_RELEASE === "true") {
if (
Config.GITHUB_RELEASE === "true" &&
!SettingsService.getProperty("serverUrls")
) {
try {
const products = WebPlanCache || (await db.pricing.products());
WebPlanCache = products;
@@ -264,14 +268,18 @@ const usePricingPlans = (options?: PricingPlansOptions) => {
if (!product) return;
if (Platform.OS === "android") {
if (isGithubRelease)
return `${(product as Plan).price.currency} ${
if (isGithubRelease) {
if (!(product as Plan)?.price) return null;
return `${
(product as Plan).currencySymbol || (product as Plan).currency
} ${
(product as Plan).period === "yearly"
? ((product as Plan).price.gross / 12).toFixed(2)
? (product as Plan).price.gross
: (product as Plan).period === "5-year"
? ((product as Plan).price.gross / (12 * 5)).toFixed(2)
? (product as Plan).price.gross
: (product as Plan).price.gross
}`;
}
const pricingPhaseListItem =
(product as RNIap.SubscriptionAndroid)?.subscriptionOfferDetails?.[0]
@@ -414,7 +422,7 @@ const usePricingPlans = (options?: PricingPlansOptions) => {
offerIndex: number
) => {
if (isGithubRelease) {
return (product as Plan).period;
return (product as Plan)?.period;
}
if (Platform.OS === "android") {
@@ -444,7 +452,7 @@ const usePricingPlans = (options?: PricingPlansOptions) => {
if (isGithubRelease) {
return {
duration: 1,
type: (product as Plan).period
type: (product as Plan)?.period
};
}
@@ -591,14 +599,18 @@ const usePricingPlans = (options?: PricingPlansOptions) => {
) => {
if (!product) return null;
if (isGithubRelease)
return `${(product as Plan).price.currency} ${
if (isGithubRelease) {
if (!(product as Plan)?.price) return null;
return `${
(product as Plan).currencySymbol || (product as Plan).currency
} ${
(product as Plan).period === "yearly"
? ((product as Plan).price.gross / 12).toFixed(2)
: (product as Plan).period === "5-year"
? ((product as Plan).price.gross / (12 * 5)).toFixed(2)
: (product as Plan).price.gross
}`;
}
const androidPricingPhase = (product as RNIap.SubscriptionAndroid)
?.subscriptionOfferDetails?.[0].pricingPhases?.pricingPhaseList?.[

View File

@@ -1,67 +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 { useEffect, useState } from "react";
import { Platform } from "react-native";
import { Subscription } from "react-native-iap";
import PremiumService from "../services/premium";
import { db } from "../common/database";
import { Product } from "@notesnook/core";
const skuInfos: { [name: string]: Product | undefined } = {};
export const usePricing = (period: "monthly" | "yearly") => {
const [current, setCurrent] = useState<{
period: string;
info?: Product;
product?: Subscription;
}>();
const getDefaultSku = (period: "monthly" | "yearly") => {
return period === "monthly"
? "com.streetwriters.notesnook.sub.mo"
: "com.streetwriters.notesnook.sub.yr";
};
useEffect(() => {
(async () => {
const skuInfo =
skuInfos[period] ||
(await db.pricing?.sku(
Platform.OS === "android" ? "android" : "ios",
period
));
skuInfos[period] = skuInfo;
const products = (await (
await PremiumService.loadProductsAndSubs()
).subs) as Subscription[];
let product = products.find((p) => p.productId === skuInfo?.sku);
if (!product)
product = products.find((p) => p.productId === getDefaultSku(period));
setCurrent({
info: skuInfo,
period,
product
});
})();
}, [period]);
return current;
};

View File

@@ -21,6 +21,7 @@ import React, { useCallback, useEffect } from "react";
import { db } from "../common/database";
import BiometricService from "../services/biometrics";
import { eSubscribeEvent, eUnSubscribeEvent } from "../services/event-manager";
import { useSettingStore } from "../stores/use-setting-store";
const VaultStatusDefaults = {
exists: false,
@@ -36,6 +37,7 @@ export type VaultStatusType = {
export const useVaultStatus = () => {
const [vaultStatus, setVaultStatus] = React.useState(VaultStatusDefaults);
const isAppLoading = useSettingStore((state) => state.isAppLoading);
const checkVaultStatus = useCallback(() => {
db.vault?.exists().then(async (exists) => {
@@ -50,12 +52,13 @@ export const useVaultStatus = () => {
}, []);
useEffect(() => {
if (isAppLoading) return;
checkVaultStatus();
eSubscribeEvent("vaultUpdated", () => checkVaultStatus());
return () => {
eUnSubscribeEvent("vaultUpdated", () => checkVaultStatus());
};
}, [checkVaultStatus]);
}, [checkVaultStatus, isAppLoading]);
return vaultStatus;
};

View File

@@ -258,12 +258,14 @@ export const RootNavigation = () => {
(state) => state.settings.introCompleted
);
const clearSelection = useSelectionStore((state) => state.clearSelection);
const resetTimer = React.useRef<NodeJS.Timeout>(undefined);
const onStateChange = React.useCallback(
(state: any) => {
if (useSelectionStore.getState().selectionMode) {
clearSelection();
}
setTimeout(() => {
clearTimeout(resetTimer.current);
resetTimer.current = setTimeout(() => {
Navigation.resetRootState(state);
}, 1000);
hideAllTooltips();

View File

@@ -44,7 +44,8 @@
"@trpc/react-query": "^10.45.2",
"@trpc/server": "^10.45.2",
"@tanstack/react-query": "^4.36.1",
"async-mutex": "0.5.0"
"async-mutex": "0.5.0",
"react-async-hook": "^4.0.0"
},
"sideEffects": false
}

View File

@@ -49,6 +49,7 @@ import { AppFontSize, defaultBorderRadius } from "../../utils/size";
import { DefaultAppStyles } from "../../utils/styles";
import { getFormattedDate, useIsFeatureAvailable } from "@notesnook/common";
import PaywallSheet from "../../components/sheets/paywall";
import { useNavigationFocus } from "../../hooks/use-navigation-focus";
const ReminderModes =
Platform.OS === "ios"
@@ -89,6 +90,7 @@ const ReminderNotificationModes = {
export default function AddReminder(props: NavigationProps<"AddReminder">) {
const { reminder, reference } = props.route.params;
useNavigationFocus(props.navigation, { focusOnInit: true });
const { colors, isDark } = useThemeColors();
const [reminderMode, setReminderMode] = useState<Reminder["mode"]>(
reminder?.mode || "once"

View File

@@ -61,6 +61,7 @@ import {
import { fluidTabsRef } from "../../utils/global-refs";
import { strings } from "@notesnook/intl";
import { i18n } from "@lingui/core";
import { useVaultStatus } from "../../hooks/use-vault-status";
const style: ViewStyle = {
height: "100%",
@@ -197,6 +198,7 @@ const Editor = React.memo(
export default Editor;
const useLockedNoteHandler = () => {
const vaultStatus = useVaultStatus();
const tab = useTabStore((state) => state.getTab(state.currentTab));
const tabRef = useRef(tab);
tabRef.current = tab;
@@ -217,15 +219,13 @@ const useLockedNoteHandler = () => {
useEffect(() => {
(async () => {
const biometry = await BiometricService.isBiometryAvailable();
const fingerprint = await BiometricService.hasInternetCredentials();
useTabStore.setState({
biometryAvailable: !!biometry,
biometryEnrolled: !!fingerprint
biometryAvailable: !!vaultStatus.isBiometryAvailable,
biometryEnrolled: !!vaultStatus.biometryEnrolled
});
syncTabs("biometry");
})();
}, [tab?.id]);
}, [tab?.id, vaultStatus.biometryEnrolled, vaultStatus.isBiometryAvailable]);
useEffect(() => {
const unlockWithBiometrics = async () => {

View File

@@ -59,6 +59,7 @@ export type Settings = {
fontScale: number;
markdownShortcuts: boolean;
features: Record<any, any>;
loggedIn: boolean;
};
export type EditorProps = {

View File

@@ -82,6 +82,7 @@ import { editorState, openInternalLink } from "./utils";
import AddReminder from "../../add-reminder";
import { isFeatureAvailable, useAreFeaturesAvailable } from "@notesnook/common";
import PaywallSheet from "../../../components/sheets/paywall";
import useNavigationStore from "../../../stores/use-navigation-store";
const publishNote = async () => {
const user = useUserStore.getState().user;
@@ -164,6 +165,7 @@ export const useEditorEvents = (
state.timeFormat
]);
const handleBack = useRef<NativeEventSubscription>();
const loggedIn = useUserStore((state) => !!state.user);
const { fontScale } = useWindowDimensions();
const doubleSpacedLines = useSettingStore(
@@ -223,7 +225,8 @@ export const useEditorEvents = (
timeFormat: db.settings?.getTimeFormat(),
fontScale,
markdownShortcuts,
features
features,
loggedIn
});
}, [
fullscreen,
@@ -241,7 +244,8 @@ export const useEditorEvents = (
timeFormat,
loading,
fontScale,
markdownShortcuts
markdownShortcuts,
loggedIn
]);
const onBackPress = useCallback(async () => {
@@ -274,7 +278,15 @@ export const useEditorEvents = (
const onHardwareBackPress = useCallback(() => {
if (fluidTabsRef.current?.page() === "editor") {
onBackPress();
if (
useNavigationStore.getState().currentRoute === "ManageTags" ||
useNavigationStore.getState().currentRoute === "LinkNotebooks" ||
useNavigationStore.getState().currentRoute === "AddReminder"
) {
Navigation.goBack();
} else {
onBackPress();
}
return true;
}
}, [onBackPress]);
@@ -547,9 +559,17 @@ export const useEditorEvents = (
if (editor.state.current?.isFocused) {
editor.state.current.isFocused = true;
}
PaywallSheet.present(
await isFeatureAvailable(editorMessage.value.feature)
);
if (editorMessage.value.feature === "insertAttachment") {
ToastManager.show({
type: "info",
message: strings.loginRequired()
});
} else {
PaywallSheet.present(
await isFeatureAvailable(editorMessage.value.feature)
);
}
break;
case EditorEvents.monograph:
publishNote();

View File

@@ -19,7 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import { strings } from "@notesnook/intl";
import { useThemeColors } from "@notesnook/theme";
import React, { useRef } from "react";
import React, { useRef, useState } from "react";
import { View } from "react-native";
import { TextInput } from "react-native-gesture-handler";
import { IconButton } from "../../components/ui/icon-button";
@@ -36,6 +36,7 @@ export const SearchBar = ({
onChangeText: (value: string) => void;
loading?: boolean;
}) => {
const [clearButton, setClearButton] = useState(false);
const selectionMode = useSelectionStore((state) => state.selectionMode);
const isFocused = useNavigationStore(
(state) => state.focusedRouteId === "Search"
@@ -45,6 +46,7 @@ export const SearchBar = ({
const inputRef = useRef<TextInput>(null);
const _onChangeText = (value: string) => {
onChangeText(value);
setClearButton(!!value);
};
return selectionMode && isFocused ? null : (
@@ -84,7 +86,7 @@ export const SearchBar = ({
testID="search-input"
style={{
fontSize: AppFontSize.sm,
fontFamily: "OpenSans-Regular",
fontFamily: "Inter-Regular",
flexGrow: 1,
color: colors.primary.paragraph,
paddingTop: 0,
@@ -100,6 +102,23 @@ export const SearchBar = ({
autoCorrect={false}
placeholderTextColor={colors.primary.placeholder}
/>
{clearButton ? (
<IconButton
name="close"
size={AppFontSize.xxl}
top={10}
testID="clear-search"
bottom={10}
onPress={() => {
inputRef.current?.clear();
onChangeText("");
setClearButton(false);
}}
color={colors.primary.paragraph}
type="plain"
/>
) : null}
</View>
</View>
);

View File

@@ -43,6 +43,7 @@ import { ServersConfiguration } from "./server-config";
import SoundPicker from "./sound-picker";
import ThemeSelector from "./theme-selector";
import { TitleFormat } from "./title-format";
import { NotesnookCircle } from "./notesnook-circle";
export const components: { [name: string]: ReactElement } = {
homeselector: <HomePicker />,
@@ -69,5 +70,6 @@ export const components: { [name: string]: ReactElement } = {
),
"sidebar-tab-selector": <SidebarTabPicker />,
"change-password": <ChangePassword />,
"change-email": <ChangeEmail />
"change-email": <ChangeEmail />,
"notesnook-circle": <NotesnookCircle />
};

View File

@@ -185,7 +185,7 @@ export default function DebugLogs() {
paragraph: strings.clearLogsConfirmation(currentLog.key),
negativeText: strings.cancel(),
positiveText: strings.clear(),
positivePress: () => {
positivePress: async () => {
const index = logs.findIndex((l) => (l.key = currentLog.key));
logManager?.delete(currentLog.key);
if (logs.length > 1) {

View File

@@ -0,0 +1,213 @@
import { CirclePartner, SubscriptionStatus } from "@notesnook/core";
import { strings } from "@notesnook/intl";
import { useThemeColors } from "@notesnook/theme";
import Clipboard from "@react-native-clipboard/clipboard";
import { useState } from "react";
import { useAsync } from "react-async-hook";
import {
ActivityIndicator,
Image,
ScrollView,
TouchableOpacity,
View
} from "react-native";
import { db } from "../../common/database";
import AppIcon from "../../components/ui/AppIcon";
import { Button } from "../../components/ui/button";
import { Notice } from "../../components/ui/notice";
import Heading from "../../components/ui/typography/heading";
import Paragraph from "../../components/ui/typography/paragraph";
import { ToastManager } from "../../services/event-manager";
import Navigation from "../../services/navigation";
import PremiumService from "../../services/premium";
import { useUserStore } from "../../stores/use-user-store";
import { AppFontSize, defaultBorderRadius } from "../../utils/size";
import { DefaultAppStyles } from "../../utils/styles";
import { openLinkInBrowser } from "../../utils/functions";
import { Pressable } from "../../components/ui/pressable";
export const NotesnookCircle = () => {
const user = useUserStore((state) => state.user);
const isOnTrial =
PremiumService.get() &&
user?.subscription?.status === SubscriptionStatus.TRIAL;
const isFree = !PremiumService.get();
const partners = useAsync(db.circle.partners, []);
return (
<ScrollView
contentContainerStyle={{
gap: DefaultAppStyles.GAP_VERTICAL,
paddingHorizontal: DefaultAppStyles.GAP,
paddingTop: DefaultAppStyles.GAP_VERTICAL
}}
>
{!isFree && !isOnTrial ? null : (
<View>
<Paragraph>
{isFree
? strings.freeUserCircleNotice()
: strings.trialUserCircleNotice()}
</Paragraph>
{!isOnTrial ? null : (
<Button
title={strings.upgradePlan()}
onPress={() => {
Navigation.navigate("PayWall", {
canGoBack: true,
context: useUserStore.getState().user
? "logged-in"
: "logged-out"
});
}}
style={{
alignSelf: "flex-start",
paddingHorizontal: 0
}}
/>
)}
</View>
)}
{partners.loading ? <ActivityIndicator /> : null}
{partners.error ? (
<Notice type="alert" text={partners.error.message} />
) : null}
{partners.result?.map((item) => (
<Partner item={item} available={!isFree && !isOnTrial} />
))}
</ScrollView>
);
};
const Partner = ({
item,
available
}: {
item: CirclePartner;
available: boolean;
}) => {
const { colors } = useThemeColors();
const [code, setCode] = useState<string>();
return (
<View
style={{
borderRadius: defaultBorderRadius,
borderWidth: 1,
borderColor: colors.primary.border,
padding: DefaultAppStyles.GAP,
gap: DefaultAppStyles.GAP_VERTICAL
}}
>
<View
style={{
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center"
}}
>
<Heading>{item.name}</Heading>
<Image
src={item.logoBase64}
style={{
width: 40,
height: 40
}}
/>
</View>
<Paragraph style={{ textAlign: "justify" }}>
{item.longDescription.trim()}
</Paragraph>
<Paragraph
style={{
alignSelf: "center"
}}
color={colors.primary.accent}
>
{item.offerDescription}
</Paragraph>
{available ? (
<>
{!code ? (
<Button
type="accent"
title={strings.redeemCode()}
width="100%"
onPress={() => {
if (!PremiumService.get()) {
Navigation.navigate("PayWall", {
canGoBack: true,
context: useUserStore.getState().user
? "logged-in"
: "logged-out"
});
return;
}
db.circle
.redeem(item.id)
.then((result) => setCode(result?.code))
.catch((e) => ToastManager.error(e));
}}
/>
) : (
<>
<TouchableOpacity
style={{
backgroundColor: colors.secondary.background,
borderRadius: defaultBorderRadius,
alignItems: "center",
justifyContent: "center",
padding: DefaultAppStyles.GAP_SMALL,
borderWidth: 0.5,
borderColor: colors.secondary.border,
flexDirection: "row",
gap: DefaultAppStyles.GAP_SMALL
}}
activeOpacity={0.9}
onPress={() => {
Clipboard.setString(code);
}}
>
<Paragraph
size={AppFontSize.lg}
color={colors.secondary.paragraph}
>
{code}
</Paragraph>
<AppIcon name="content-copy" />
</TouchableOpacity>
{item.codeRedeemUrl ? (
<Pressable
onPress={() => {
if (item.codeRedeemUrl) {
openLinkInBrowser(
item.codeRedeemUrl.replace("{{code}}", code)
);
}
}}
>
<Paragraph
color={colors.secondary.paragraph}
size={AppFontSize.xxs}
>
{strings.clickToDirectlyClaimPromo()}
</Paragraph>
</Pressable>
) : null}
</>
)}
</>
) : null}
</View>
);
};

View File

@@ -26,18 +26,17 @@ import {
import React, { useEffect, useRef, useState } from "react";
import { ActivityIndicator, TextInput, View } from "react-native";
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
//@ts-ignore
import { FeatureResult, useIsFeatureAvailable } from "@notesnook/common";
import { strings } from "@notesnook/intl";
//@ts-ignore
import ToggleSwitch from "toggle-switch-react-native";
import PaywallSheet from "../../components/sheets/paywall";
import AppIcon from "../../components/ui/AppIcon";
import { IconButton } from "../../components/ui/icon-button";
import Input from "../../components/ui/input";
import { Pressable } from "../../components/ui/pressable";
import Seperator from "../../components/ui/seperator";
import Heading from "../../components/ui/typography/heading";
import Paragraph from "../../components/ui/typography/paragraph";
import { ToastManager } from "../../services/event-manager";
import SettingsService from "../../services/settings";
import useNavigationStore from "../../stores/use-navigation-store";
import { SettingStore, useSettingStore } from "../../stores/use-setting-store";
@@ -45,7 +44,6 @@ import { AppFontSize } from "../../utils/size";
import { DefaultAppStyles } from "../../utils/styles";
import { components } from "./components";
import { RouteParams, SettingSection } from "./types";
import AppIcon from "../../components/ui/AppIcon";
const _SectionItem = ({ item }: { item: SettingSection }) => {
const { colors } = useThemeColors();

View File

@@ -32,6 +32,7 @@ import React from "react";
import { Appearance, Linking, Platform } from "react-native";
import { getVersion } from "react-native-device-info";
import * as RNIap from "react-native-iap";
//@ts-ignore
import { enabled } from "react-native-privacy-snapshot";
import ScreenGuardModule from "react-native-screenguard";
import { DatabaseLogger, db } from "../../common/database";
@@ -81,15 +82,22 @@ export const settingsGroups: SettingSection[] = [
{
id: "subscription-status",
useHook: () => useUserStore((state) => state.user),
hidden: (current) =>
!current ||
(current as User).subscription?.plan === SubscriptionPlan.FREE,
hidden: (current) => {
const user = current as User;
return (
!user ||
!user.subscription ||
user.subscription.provider === undefined ||
!strings.subscriptionProviderInfo[user?.subscription?.provider] ||
user.subscription?.plan === SubscriptionPlan.FREE
);
},
name: (current) => {
const user = (current as User) || useUserStore.getState().user;
return (
strings.subscriptionProviderInfo[
user?.subscription?.provider
].title() || "Unknown provider"
]?.title() || `Unknown provider id: ${user?.subscription?.provider}`
);
},
icon: "credit-card",
@@ -99,6 +107,8 @@ export const settingsGroups: SettingSection[] = [
const subscriptionProviderInfo =
strings.subscriptionProviderInfo[user?.subscription?.provider];
if (!subscriptionProviderInfo) return;
const isCurrentPlatform =
(user.subscription?.provider === SubscriptionProvider.APPLE &&
Platform.OS === "ios") ||
@@ -615,6 +625,14 @@ export const settingsGroups: SettingSection[] = [
}
}
]
},
{
id: "notesnook-circle",
name: strings.notesnookCircle(),
icon: "circle-outline",
type: "screen",
description: strings.notesnookCircleDesc(),
component: "notesnook-circle"
}
]
},

View File

@@ -43,6 +43,7 @@ import { planToDisplayName } from "../../utils/constants";
import { AppFontSize } from "../../utils/size";
import { DefaultAppStyles } from "../../utils/styles";
import { SectionItem } from "./section-item";
import SettingsService from "../../services/settings";
export const getTimeLeft = (t2) => {
let daysRemaining = dayjs(t2).diff(dayjs(), "days");
@@ -339,11 +340,13 @@ const SettingsUserSection = ({ item }) => {
</Paragraph>
</TouchableOpacity>
{(user.subscription?.provider === SubscriptionProvider.PADDLE ||
{((user.subscription?.provider ===
SubscriptionProvider.PADDLE ||
user.subscription?.provider ===
SubscriptionProvider.STREETWRITERS ||
!isCurrentPlatform) &&
PremiumService.get() ? null : (
PremiumService.get()) ||
SettingsService.getProperty("serverUrls") ? null : (
<Button
title={
user.subscription?.plan !== SubscriptionPlan.FREE

View File

@@ -580,7 +580,7 @@ function openSettingsDialog(context: string) {
positivePress:
Platform.OS === "ios"
? undefined
: () => {
: async () => {
resolve(true);
},
onClose: () => {

View File

@@ -58,6 +58,7 @@ async function setPremiumStatus() {
async function loadProductsAndSubs() {
try {
if (Config.GITHUB_RELEASE === "true") throw new Error("Github release");
if (!subs || subs.length === 0) {
subs = await RNIap.getSubscriptions({
skus: itemSkus

View File

@@ -17,8 +17,15 @@ 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 { isFeatureAvailable } from "@notesnook/common";
import { Profile, User } from "@notesnook/core";
import create, { State } from "zustand";
import SettingsService from "../services/settings";
import { presentDialog } from "../components/dialog/functions";
import { strings } from "@notesnook/intl";
import { eSendEvent } from "../services/event-manager";
import { eCloseSimpleDialog } from "../utils/events";
import Navigation from "../services/navigation";
export enum SyncStatus {
Passed,
@@ -57,6 +64,28 @@ export const useUserStore = create<UserStore>((set) => ({
setLastSynced: (lastSynced) => set({ lastSynced: lastSynced }),
lockApp: (appLocked) => {
set({ appLocked });
if (!appLocked) {
isFeatureAvailable("appLock").then((feature) => {
if (!feature.isAllowed) {
SettingsService.setProperty("appLockEnabled", false);
setTimeout(() => {
presentDialog({
title: "App Lock Disabled",
paragraph: feature?.error,
positiveText: strings.upgrade(),
negativeText: strings.cancel(),
positivePress: async () => {
eSendEvent(eCloseSimpleDialog);
if (SettingsService.getProperty("serverUrls")) return;
Navigation.navigate("PayWall", {
context: "logged-in"
});
}
});
}, 1000);
}
});
}
},
lastSyncStatus: SyncStatus.Never,
disableAppLockRequests: false,

View File

@@ -71,6 +71,7 @@ export function planToDisplayName(plan: SubscriptionPlan): string {
return strings.freePlan();
case SubscriptionPlan.ESSENTIAL:
return strings.essentialPlan();
case SubscriptionPlan.LEGACY_PRO:
case SubscriptionPlan.PRO:
return strings.proPlan();
case SubscriptionPlan.BELIEVER:

View File

@@ -33,6 +33,7 @@ import { useNotebookStore } from "../stores/use-notebook-store";
import { useRelationStore } from "../stores/use-relation-store";
import { useTagStore } from "../stores/use-tag-store";
import { eUpdateNoteInEditor } from "./events";
import { unlockVault } from "./unlock-vault";
export function getObfuscatedEmail(email: string) {
if (!email) return "";
@@ -56,7 +57,7 @@ function confirmDeleteAllNotes(
title: strings.doActions.delete.notebook(items.length),
positiveText: strings.delete(),
negativeText: strings.cancel(),
positivePress: (_inputValue, value) => {
positivePress: async (_inputValue, value) => {
setTimeout(() => {
resolve({ delete: true, deleteNotes: value });
});
@@ -98,6 +99,30 @@ export const deleteItems = async (
await db.reminders.remove(...itemIds);
useRelationStore.getState().update();
} else if (type === "note") {
let someNotesLocked = false;
for (const id of itemIds) {
if (
await db.vaults.itemExists({
id: id,
type: "note"
})
) {
someNotesLocked = true;
break;
}
}
if (someNotesLocked) {
const unlocked = await unlockVault({
title: strings.unlockVault(),
paragraph: strings.unlockVaultDesc(),
context: "global",
requirePassword: true
});
if (!unlocked) return;
}
for (const id of itemIds) {
if (db.monographs.isPublished(id)) {
ToastManager.show({
@@ -108,6 +133,7 @@ export const deleteItems = async (
});
continue;
}
await db.notes.moveToTrash(id);
eSendEvent(
@@ -157,7 +183,7 @@ export const deleteItems = async (
heading: message,
type: "success",
func: async () => {
if ((await db.trash.restore(...deletedIds)) === false) return;
await db.trash.restore(...deletedIds);
Navigation.queueRoutesForUpdate();
useMenuStore.getState().setMenuPins();
useMenuStore.getState().setColorNotes();

View File

@@ -27,18 +27,20 @@ let unlockPromise: Promise<any> | undefined = undefined;
export async function unlockVault({
context,
title,
paragraph
paragraph,
requirePassword
}: {
context?: string;
title: string;
paragraph: string;
requirePassword?: boolean;
}) {
if (unlockPromise) {
return unlockPromise;
}
unlockPromise = new Promise(async (resolve) => {
const result = await (async () => {
if (db.vault.unlocked) return true;
if (db.vault.unlocked && !requirePassword) return true;
const biometry = await BiometricService.isBiometryAvailable();
const fingerprint = await BiometricService.hasInternetCredentials();
if (biometry && fingerprint) {

View File

@@ -1,5 +1,5 @@
import { execSync } from "child_process";
//@ts-ignore
import { pathExists, ensureDir } from "fs-extra";
import { resolveConfig } from "detox/internals";

View File

@@ -1,22 +1,3 @@
/*
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 { notesnook } from "../test.ids";
import { TestBuilder } from "./utils";

View File

@@ -28,6 +28,9 @@ describe("Search", () => {
.typeTextById("search-input", "Test")
.wait(1000)
.isVisibleByText("1")
.waitAndTapById("clear-search")
.wait(2000)
.isNotVisibleByText("1")
.run();
});
});

View File

@@ -20,6 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import { expect as jestExpect } from "@jest/globals";
import { device as _device, expect } from "detox";
import { readFileSync } from "fs";
//@ts-ignore
import { toMatchImageSnapshot } from "jest-image-snapshot";
import type { RouteName } from "../../app/stores/use-navigation-store";
import { notesnook } from "../test.ids";

View File

@@ -124,7 +124,7 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
multiDexEnabled true
versionCode 3071
versionCode 3076
versionName getNpmVersion()
testBuildType System.getProperty('testBuildType', 'debug')
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'

View File

@@ -152,7 +152,7 @@
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="com.streetwriters.notesnook" />
<data android:scheme="notesnook" />
</intent-filter>
</activity>

View File

@@ -33,7 +33,7 @@ public class NotePreviewWidget extends AppWidgetProvider {
intent.putExtra(OpenNoteId, note.getId());
intent.setAction(Intent.ACTION_VIEW);
intent.putExtra(RCTNNativeModule.IntentType, "OpenNote");
intent.setData(Uri.parse("https://notesnook.com/open_note?id=" + note.getId()));
intent.setData(Uri.parse("https://app.notesnook.com/open_note?id=" + note.getId()));
PendingIntent pendingIntent = PendingIntent.getActivity(context, appWidgetId, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE, getActivityOptionsBundle());
views.setOnClickPendingIntent(R.id.open_note, pendingIntent);

View File

@@ -75,7 +75,7 @@ class ReminderRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactor
final Intent fillInIntent = new Intent();
final Bundle extras = new Bundle();
extras.putString(ReminderViewsService.OpenReminderId, reminder.getId());
fillInIntent.setData(Uri.parse("https://notesnook.com/open_reminder?id=" + reminder.getId()));
fillInIntent.setData(Uri.parse("https://app.notesnook.com/open_reminder?id=" + reminder.getId()));
fillInIntent.putExtra(RCTNNativeModule.IntentType, "OpenReminder");
fillInIntent.putExtras(extras);
views.setOnClickFillInIntent(R.id.reminder_item_btn, fillInIntent);

View File

@@ -43,7 +43,7 @@ public class ReminderWidgetProvider extends AppWidgetProvider {
new_reminder_intent.putExtra(NewReminder, NewReminder);
new_reminder_intent.setAction(Intent.ACTION_VIEW);
new_reminder_intent.putExtra(RCTNNativeModule.IntentType, "NewReminder");
new_reminder_intent.setData(Uri.parse("https://notesnook.com/new_reminder"));
new_reminder_intent.setData(Uri.parse("https://app.notesnook.com/new_reminder"));
PendingIntent pendingIntent2 = PendingIntent.getActivity(context, appWidgetId, new_reminder_intent, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE, getActivityOptionsBundle());
views.setOnClickPendingIntent(R.id.add_button, pendingIntent2);

View File

@@ -2,6 +2,7 @@
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingVertical="10dp"
android:id="@+id/reminder_item_btn">
<TextView

View File

@@ -2,6 +2,7 @@
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingVertical="10dp"
android:id="@+id/reminder_item_btn">
<TextView

View File

@@ -25,9 +25,9 @@
android:text="Upcoming Reminders"/>
<ImageButton
android:layout_width="30dp"
android:layout_width="35dp"
android:id="@+id/add_button"
android:layout_height="30dp"
android:layout_height="35dp"
android:layout_alignParentRight="true"
android:background="@drawable/ic_newnote" />
</RelativeLayout>

View File

@@ -1,5 +1,3 @@
- We have launches new pricing plans, Essential, Pro and Believer
- Free users can now upload attachments and create private vault
- Minor bug fixes and improvements
- Bug fixes and minor improvements
Thank you for using Notesnook!

View File

@@ -56,9 +56,10 @@
<string>group.org.streetwriters.notesnook</string>
<key>UIAppFonts</key>
<array>
<string>OpenSans-Bold.ttf</string>
<string>OpenSans-SemiBold.ttf</string>
<string>OpenSans-Regular.ttf</string>
<string>Inter-Bold.ttf</string>
<string>Inter-SemiBold.ttf</string>
<string>Inter-Regular.ttf</string>
<string>Inter-Italic.ttf</string>
<string>MaterialCommunityIcons.ttf</string>
</array>
<key>UISupportedInterfaceOrientations</key>

View File

@@ -17,14 +17,15 @@
2E4BF736C2EB268ED3FD9C29 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = B5216B66C0B4A91C0A69128B /* PrivacyInfo.xcprivacy */; };
6510E6D72877215700DACAA9 /* build.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 6510E6D62877215700DACAA9 /* build.bundle */; };
6515C42F2580AA3000E83E39 /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6515C42E2580AA2F00E83E39 /* StoreKit.framework */; };
6517B7C12B6838EB0079FF37 /* OpenSans-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 6517B7BE2B6838EB0079FF37 /* OpenSans-Regular.ttf */; };
6517B7C22B6838EB0079FF37 /* OpenSans-SemiBold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 6517B7BF2B6838EB0079FF37 /* OpenSans-SemiBold.ttf */; };
6517B7C32B6838EB0079FF37 /* OpenSans-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 6517B7C02B6838EB0079FF37 /* OpenSans-Bold.ttf */; };
6529A13E279BC4C70048D4A8 /* BootSplash.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6529A13D279BC4C70048D4A8 /* BootSplash.storyboard */; };
656835812BB29A9800144BAB /* OpenSans-Italic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 656835802BB29A8300144BAB /* OpenSans-Italic.ttf */; };
6569927F2C5754F10041CD41 /* OpenSans-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 6517B7C02B6838EB0079FF37 /* OpenSans-Bold.ttf */; };
656992802C5754F10041CD41 /* OpenSans-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 6517B7BE2B6838EB0079FF37 /* OpenSans-Regular.ttf */; };
656992812C5754F10041CD41 /* OpenSans-SemiBold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 6517B7BF2B6838EB0079FF37 /* OpenSans-SemiBold.ttf */; };
653F4E082EA3887C009A42A2 /* Inter-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 653F4E042EA3887C009A42A2 /* Inter-Bold.ttf */; };
653F4E092EA3887C009A42A2 /* Inter-Italic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 653F4E052EA3887C009A42A2 /* Inter-Italic.ttf */; };
653F4E0A2EA3887C009A42A2 /* Inter-SemiBold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 653F4E072EA3887C009A42A2 /* Inter-SemiBold.ttf */; };
653F4E0B2EA3887C009A42A2 /* Inter-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 653F4E062EA3887C009A42A2 /* Inter-Regular.ttf */; };
653F4E0C2EA3887C009A42A2 /* Inter-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 653F4E042EA3887C009A42A2 /* Inter-Bold.ttf */; };
653F4E0D2EA3887C009A42A2 /* Inter-Italic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 653F4E052EA3887C009A42A2 /* Inter-Italic.ttf */; };
653F4E0E2EA3887C009A42A2 /* Inter-SemiBold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 653F4E072EA3887C009A42A2 /* Inter-SemiBold.ttf */; };
653F4E0F2EA3887C009A42A2 /* Inter-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 653F4E062EA3887C009A42A2 /* Inter-Regular.ttf */; };
6593E4A3281C345400492C50 /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6593E4A2281C345400492C50 /* AppDelegate.mm */; };
659BE46725E11A5100E05671 /* notesnook-text.png in Resources */ = {isa = PBXBuildFile; fileRef = 659BE46625E11A5100E05671 /* notesnook-text.png */; };
65AA857925E6DDEC00772A01 /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 65AA857825E6DDEC00772A01 /* WidgetKit.framework */; };
@@ -117,12 +118,12 @@
4C4AF691C324D95337F2FB0A /* libPods-Make Note.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Make Note.a"; sourceTree = BUILT_PRODUCTS_DIR; };
6510E6D62877215700DACAA9 /* build.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; name = build.bundle; path = "../../../../packages/editor-mobile/build.bundle"; sourceTree = "<group>"; };
6515C42E2580AA2F00E83E39 /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; };
6517B7BE2B6838EB0079FF37 /* OpenSans-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "OpenSans-Regular.ttf"; path = "../../../../packages/editor-mobile/public/fonts/OpenSans-Regular.ttf"; sourceTree = "<group>"; };
6517B7BF2B6838EB0079FF37 /* OpenSans-SemiBold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "OpenSans-SemiBold.ttf"; path = "../../../../packages/editor-mobile/public/fonts/OpenSans-SemiBold.ttf"; sourceTree = "<group>"; };
6517B7C02B6838EB0079FF37 /* OpenSans-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "OpenSans-Bold.ttf"; path = "../../../../packages/editor-mobile/public/fonts/OpenSans-Bold.ttf"; sourceTree = "<group>"; };
6529A13D279BC4C70048D4A8 /* BootSplash.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = BootSplash.storyboard; path = Notesnook/BootSplash.storyboard; sourceTree = "<group>"; };
6529D2B0257B4A2900B49BC3 /* NotesnookDebug.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = NotesnookDebug.entitlements; path = Notesnook/NotesnookDebug.entitlements; sourceTree = "<group>"; };
656835802BB29A8300144BAB /* OpenSans-Italic.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "OpenSans-Italic.ttf"; path = "../../../../packages/editor-mobile/public/fonts/OpenSans-Italic.ttf"; sourceTree = "<group>"; };
653F4E042EA3887C009A42A2 /* Inter-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "Inter-Bold.ttf"; path = "../../../../packages/editor-mobile/public/fonts/Inter-Bold.ttf"; sourceTree = SOURCE_ROOT; };
653F4E052EA3887C009A42A2 /* Inter-Italic.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "Inter-Italic.ttf"; path = "../../../../packages/editor-mobile/public/fonts/Inter-Italic.ttf"; sourceTree = SOURCE_ROOT; };
653F4E062EA3887C009A42A2 /* Inter-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "Inter-Regular.ttf"; path = "../../../../packages/editor-mobile/public/fonts/Inter-Regular.ttf"; sourceTree = SOURCE_ROOT; };
653F4E072EA3887C009A42A2 /* Inter-SemiBold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "Inter-SemiBold.ttf"; path = "../../../../packages/editor-mobile/public/fonts/Inter-SemiBold.ttf"; sourceTree = SOURCE_ROOT; };
6593E4A2281C345400492C50 /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = Notesnook/AppDelegate.mm; sourceTree = "<group>"; };
659BE46625E11A5100E05671 /* notesnook-text.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "notesnook-text.png"; path = "Notesnook/Images.xcassets/notesnook-text.png"; sourceTree = "<group>"; };
65A7F34F255689AD00699170 /* Notesnook.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = Notesnook.entitlements; path = Notesnook/Notesnook.entitlements; sourceTree = "<group>"; };
@@ -303,10 +304,10 @@
83CBB9F61A601CBA00E9B192 = {
isa = PBXGroup;
children = (
656835802BB29A8300144BAB /* OpenSans-Italic.ttf */,
6517B7C02B6838EB0079FF37 /* OpenSans-Bold.ttf */,
6517B7BE2B6838EB0079FF37 /* OpenSans-Regular.ttf */,
6517B7BF2B6838EB0079FF37 /* OpenSans-SemiBold.ttf */,
653F4E042EA3887C009A42A2 /* Inter-Bold.ttf */,
653F4E052EA3887C009A42A2 /* Inter-Italic.ttf */,
653F4E062EA3887C009A42A2 /* Inter-Regular.ttf */,
653F4E072EA3887C009A42A2 /* Inter-SemiBold.ttf */,
65C400DD2A80B68D00AA3DF5 /* MaterialCommunityIcons.ttf */,
65C149862A61151B005C40F1 /* extension.bundle */,
6510E6D62877215700DACAA9 /* build.bundle */,
@@ -555,15 +556,15 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
656835812BB29A9800144BAB /* OpenSans-Italic.ttf in Resources */,
65C400DE2A80B68D00AA3DF5 /* MaterialCommunityIcons.ttf in Resources */,
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
6517B7C32B6838EB0079FF37 /* OpenSans-Bold.ttf in Resources */,
6517B7C22B6838EB0079FF37 /* OpenSans-SemiBold.ttf in Resources */,
6529A13E279BC4C70048D4A8 /* BootSplash.storyboard in Resources */,
6510E6D72877215700DACAA9 /* build.bundle in Resources */,
6517B7C12B6838EB0079FF37 /* OpenSans-Regular.ttf in Resources */,
659BE46725E11A5100E05671 /* notesnook-text.png in Resources */,
653F4E0C2EA3887C009A42A2 /* Inter-Bold.ttf in Resources */,
653F4E0D2EA3887C009A42A2 /* Inter-Italic.ttf in Resources */,
653F4E0E2EA3887C009A42A2 /* Inter-SemiBold.ttf in Resources */,
653F4E0F2EA3887C009A42A2 /* Inter-Regular.ttf in Resources */,
E7F9D56665C2F19F4A97BF49 /* PrivacyInfo.xcprivacy in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -596,10 +597,11 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
6569927F2C5754F10041CD41 /* OpenSans-Bold.ttf in Resources */,
656992802C5754F10041CD41 /* OpenSans-Regular.ttf in Resources */,
656992812C5754F10041CD41 /* OpenSans-SemiBold.ttf in Resources */,
65C400DF2A80B6B600AA3DF5 /* MaterialCommunityIcons.ttf in Resources */,
653F4E082EA3887C009A42A2 /* Inter-Bold.ttf in Resources */,
653F4E092EA3887C009A42A2 /* Inter-Italic.ttf in Resources */,
653F4E0A2EA3887C009A42A2 /* Inter-SemiBold.ttf in Resources */,
653F4E0B2EA3887C009A42A2 /* Inter-Regular.ttf in Resources */,
65C149872A61151B005C40F1 /* extension.bundle in Resources */,
65B5014725A672B200E2D264 /* MainInterface.storyboard in Resources */,
);
@@ -652,6 +654,7 @@
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Notesnook/Pods-Notesnook-resources.sh",
"${PODS_CONFIGURATION_BUILD_DIR}/RCT-Folly/RCT-Folly_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/RNImageCropPicker/RNImageCropPickerPrivacyInfo.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/RNImageCropPicker/QBImagePicker.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/RNSVG/RNSVGFilters.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/React-Core_privacy.bundle",
@@ -663,6 +666,7 @@
name = "[CP] Copy Pods Resources";
outputPaths = (
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RCT-Folly_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RNImageCropPickerPrivacyInfo.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/QBImagePicker.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RNSVGFilters.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/React-Core_privacy.bundle",
@@ -819,6 +823,7 @@
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Notesnook-NotesnookTests/Pods-Notesnook-NotesnookTests-resources.sh",
"${PODS_CONFIGURATION_BUILD_DIR}/RCT-Folly/RCT-Folly_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/RNImageCropPicker/RNImageCropPickerPrivacyInfo.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/RNImageCropPicker/QBImagePicker.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/RNSVG/RNSVGFilters.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/React-Core_privacy.bundle",
@@ -830,6 +835,7 @@
name = "[CP] Copy Pods Resources";
outputPaths = (
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RCT-Folly_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RNImageCropPickerPrivacyInfo.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/QBImagePicker.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RNSVGFilters.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/React-Core_privacy.bundle",
@@ -1089,7 +1095,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2150;
CURRENT_PROJECT_VERSION = 2155;
DEVELOPMENT_TEAM = 53CWBG3QUC;
ENABLE_BITCODE = NO;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
@@ -1163,7 +1169,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 3.3.2;
MARKETING_VERSION = 3.3.7;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
@@ -1194,7 +1200,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 2150;
CURRENT_PROJECT_VERSION = 2155;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 53CWBG3QUC;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
@@ -1268,7 +1274,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 3.3.2;
MARKETING_VERSION = 3.3.7;
ONLY_ACTIVE_ARCH = NO;
OTHER_LDFLAGS = (
"$(inherited)",
@@ -1427,7 +1433,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2150;
CURRENT_PROJECT_VERSION = 2155;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = 53CWBG3QUC;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
@@ -1439,7 +1445,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 3.3.2;
MARKETING_VERSION = 3.3.7;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.notewidget;
@@ -1470,7 +1476,7 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 2150;
CURRENT_PROJECT_VERSION = 2155;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 53CWBG3QUC;
@@ -1483,7 +1489,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 3.3.2;
MARKETING_VERSION = 3.3.7;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.notewidget;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -1513,7 +1519,7 @@
CODE_SIGN_ENTITLEMENTS = "Make Note/Make Note.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2150;
CURRENT_PROJECT_VERSION = 2155;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = 53CWBG3QUC;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
@@ -1587,14 +1593,14 @@
"\"$(PODS_ROOT)/Headers/Private/React-Core\"",
);
INFOPLIST_FILE = "Make Note/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
IPHONEOS_DEPLOYMENT_TARGET = 12.4;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift$(inherited)";
MARKETING_VERSION = 3.3.2;
MARKETING_VERSION = 3.3.7;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.share;
@@ -1625,7 +1631,7 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 2150;
CURRENT_PROJECT_VERSION = 2155;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 53CWBG3QUC;
@@ -1700,14 +1706,14 @@
"\"$(PODS_ROOT)/Headers/Private/React-Core\"",
);
INFOPLIST_FILE = "Make Note/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
IPHONEOS_DEPLOYMENT_TARGET = 12.4;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift$(inherited)";
MARKETING_VERSION = 3.3.2;
MARKETING_VERSION = 3.3.7;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.share;
PRODUCT_NAME = "$(TARGET_NAME)";

View File

@@ -74,7 +74,7 @@
<RemoteRunnable
runnableDebuggingMode = "1"
BundleIdentifier = "com.apple.mobilesafari"
RemotePath = "/Applications/MobileSafari.app">
RemotePath = "/Library/Developer/CoreSimulator/Volumes/iOS_22G86/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 18.6.simruntime/Contents/Resources/RuntimeRoot/Applications/MobileSafari.app">
</RemoteRunnable>
<MacroExpansion>
<BuildableReference
@@ -92,6 +92,7 @@
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES"
askForAppToLaunch = "Yes"
launchAutomaticallySubstyle = "2">
<BuildableProductRunnable
runnableDebuggingMode = "0">

View File

@@ -71,7 +71,6 @@
<true/>
<key>NSAppTransportSecurity</key>
<dict>
<!-- Do not change NSAllowsArbitraryLoads to true, or you will risk app rejection! -->
<key>NSAllowsArbitraryLoads</key>
<false/>
<key>NSAllowsLocalNetworking</key>
@@ -89,9 +88,10 @@
<string>group.org.streetwriters.notesnook</string>
<key>UIAppFonts</key>
<array>
<string>OpenSans-Italic.ttf</string>
<string>OpenSans-SemiBold.ttf</string>
<string>OpenSans-Regular.ttf</string>
<string>Inter-Italic.ttf</string>
<string>Inter-SemiBold.ttf</string>
<string>Inter-Regular.ttf</string>
<string>Inter-Bold.ttf</string>
<string>MaterialCommunityIcons.ttf</string>
</array>
<key>UIApplicationSceneManifest</key>

View File

@@ -9,6 +9,7 @@
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>3B52.1</string>
<string>C617.1</string>
</array>
</dict>

View File

@@ -1273,11 +1273,11 @@ PODS:
- React-Core
- react-native-keep-awake (1.3.1):
- React-Core
- react-native-mmkv-storage (0.11.2):
- react-native-mmkv-storage (12.0.0):
- DoubleConversion
- glog
- hermes-engine
- MMKV (~> 1.3.9)
- MMKV (~> 1.3.14)
- RCT-Folly (= 2024.11.18.00)
- RCTRequired
- RCTTypeSafety
@@ -1372,7 +1372,7 @@ PODS:
- react-native-screenguard (1.0.0):
- React-Core
- SDWebImage (~> 5.11.1)
- react-native-share-extension (2.9.0):
- react-native-share-extension (2.9.5):
- React
- react-native-sodium (1.6.5):
- React
@@ -1770,15 +1770,53 @@ PODS:
- Yoga
- RNIap (12.16.2):
- React-Core
- RNImageCropPicker (0.40.2):
- RNImageCropPicker (0.51.1):
- DoubleConversion
- glog
- hermes-engine
- RCT-Folly (= 2024.11.18.00)
- RCTRequired
- RCTTypeSafety
- React-Core
- React-debug
- React-Fabric
- React-featureflags
- React-graphics
- React-ImageManager
- React-NativeModulesApple
- React-RCTFabric
- React-RCTImage
- RNImageCropPicker/QBImagePickerController (= 0.40.2)
- TOCropViewController
- RNImageCropPicker/QBImagePickerController (0.40.2):
- React-rendererdebug
- React-utils
- ReactCodegen
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- RNImageCropPicker/QBImagePickerController (= 0.51.1)
- TOCropViewController (~> 2.8.0)
- Yoga
- RNImageCropPicker/QBImagePickerController (0.51.1):
- DoubleConversion
- glog
- hermes-engine
- RCT-Folly (= 2024.11.18.00)
- RCTRequired
- RCTTypeSafety
- React-Core
- React-debug
- React-Fabric
- React-featureflags
- React-graphics
- React-ImageManager
- React-NativeModulesApple
- React-RCTFabric
- React-RCTImage
- TOCropViewController
- React-rendererdebug
- React-utils
- ReactCodegen
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- TOCropViewController (~> 2.8.0)
- Yoga
- RNKeychain (4.0.5):
- React
- RNNotifee (7.4.9):
@@ -1975,7 +2013,7 @@ PODS:
- SwiftyRSA (1.7.0):
- SwiftyRSA/ObjC (= 1.7.0)
- SwiftyRSA/ObjC (1.7.0)
- TOCropViewController (2.7.4)
- TOCropViewController (2.8.0)
- toolbar-android (0.2.1):
- React
- Yoga (0.0.0)
@@ -2425,7 +2463,7 @@ SPEC CHECKSUMS:
react-native-image-resizer: 24c5d06fae2176dc0caed4b6396e02befb44064a
react-native-in-app-review: b3d1eed3d1596ebf6539804778272c4c65e4a400
react-native-keep-awake: 03b74eebe4f2bb5e8478fc8f420651a92463b6f8
react-native-mmkv-storage: 51c33c6f6678d67061059cce8189a57c3e47192e
react-native-mmkv-storage: 935d661dc3913a41be70d041aa3ff860d6aa4873
react-native-netinfo: 66c9ac0d0ae92a57a9ed99ab8a75429740700c73
react-native-notification-sounds: ce106d58df0dd384bccbd2e84fb53accab7cc068
react-native-orientation-locker: cc6f357b289a2e0dd2210fea0c52cb8e0727fdaa
@@ -2434,7 +2472,7 @@ SPEC CHECKSUMS:
react-native-quick-sqlite: 1bfc7f1e9acbe9a5aa5c4cc81712e9bde3ab7672
react-native-safe-area-context: 9d72abf6d8473da73033b597090a80b709c0b2f1
react-native-screenguard: 82437eeb0086a90b5e5d7e54130bb04fb406373e
react-native-share-extension: bcb7e466390a9e50c742f4b1019d6f181aedd7ad
react-native-share-extension: fdc6aaab51591a2d445df239c446aaa3a99658ec
react-native-sodium: 285eec063e4232cb67347ef6a434b85e588d38cb
react-native-theme-switch-animation: d90fe2de0d9e87a63cd6235d98cba6e7054e9a10
react-native-webview: 079eca50edf657503318b66687dadfb903731aa8
@@ -2479,7 +2517,7 @@ SPEC CHECKSUMS:
RNFlashList: ff5a0b3113c4cda0eaf4b94df8572ccad3c40fd5
RNGestureHandler: 92e89a04cd0d1c77f383a55d14c15e7f423f4c00
RNIap: f94647b3a3dbd5fa08ad7ed847eb588aa5fe95fe
RNImageCropPicker: 30d770b383d84e1067d82ea7b5ed4fff851bbbb2
RNImageCropPicker: aa81bda9f887e20542b569938cde5ce50a4ec404
RNKeychain: ffd0513e676445c637410b47249460cbf56bc9cb
RNNotifee: dabf3cdd7bfd9340bb84358cc78f635af4bc80e2
RNPrivacySnapshot: ccad3a548338c2f526bb7b1789af3fb0618b7d1d
@@ -2495,7 +2533,7 @@ SPEC CHECKSUMS:
SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748
SSZipArchive: fe6a26b2a54d5a0890f2567b5cc6de5caa600aef
SwiftyRSA: 8c6dd1ea7db1b8dc4fb517a202f88bb1354bc2c6
TOCropViewController: 80b8985ad794298fb69d3341de183f33d1853654
TOCropViewController: 797deaf39c90e6e9ddd848d88817f6b9a8a09888
toolbar-android: c426ed5bd3dcccfed20fd79533efc0d1ae0ef018
Yoga: 31a098f74c16780569aebd614a0f37a907de0189

File diff suppressed because one or more lines are too long

View File

@@ -21,6 +21,7 @@
"@react-navigation/native": "^6.0.10",
"@react-navigation/native-stack": "6.6.2",
"@sayem314/react-native-keep-awake": "^1.3.1",
"react-native-image-crop-picker": "^0.51.1",
"react": "18.2.0",
"react-native": "0.77.2",
"react-native-actions-shortcuts": "^1.0.1",
@@ -48,7 +49,7 @@
"react-native-navigation-bar-color": "2.0.2",
"react-native-notification-sounds": "0.5.5",
"@shopify/flash-list": "^1.8.0",
"react-native-mmkv-storage": "^0.11.2",
"react-native-mmkv-storage": "^12.0.0",
"react-native-quick-sqlite": "^8.2.7",
"react-native-svg": "^15.12.0",
"react-native-webview": "^13.13.5",
@@ -61,7 +62,6 @@
"react-native-zip-archive": "6.0.9",
"react-native-theme-switch-animation": "^0.6.0",
"@ammarahmed/react-native-background-fetch": "^4.2.2",
"react-native-image-crop-picker": "^0.40.2",
"react-native-url-polyfill": "^2.0.0",
"react-native-screenguard": "^1.0.0",
"@formatjs/intl-locale": "4.0.0",
@@ -72,10 +72,10 @@
"react-native-begin-background-task": "github:blockfirm/react-native-begin-background-task",
"react-native-privacy-snapshot": "github:standardnotes/react-native-privacy-snapshot",
"@ammarahmed/react-native-fingerprint-scanner": "^5.0.0",
"@ammarahmed/react-native-share-extension": "^2.9.0",
"react-native-pager-view": "^6.5.1",
"react-native-tab-view": "^4.0.2",
"react-native-orientation-locker": "^1.7.0"
"react-native-orientation-locker": "^1.7.0",
"@ammarahmed/react-native-share-extension": "^2.9.5"
},
"devDependencies": {
"@babel/core": "^7.27.1",

View File

@@ -1,12 +1,12 @@
{
"name": "@notesnook/mobile",
"version": "3.2.12",
"version": "3.3.7",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@notesnook/mobile",
"version": "3.2.12",
"version": "3.3.7",
"hasInstallScript": true,
"license": "GPL-3.0-or-later",
"workspaces": [
@@ -3730,7 +3730,7 @@
"hasInstallScript": true,
"license": "GPL-3.0-or-later",
"dependencies": {
"@notesnook-importer/core": "^2.2.2",
"@notesnook-importer/core": "^2.2.5",
"@notesnook/common": "file:../common",
"@notesnook/intl": "file:../intl",
"@notesnook/theme": "file:../theme",
@@ -3797,6 +3797,7 @@
"happy-dom": "16.0.1",
"isomorphic-fetch": "^3.0.0",
"nodemon": "^3.1.7",
"prismjs": "^1.30.0",
"prosemirror-test-builder": "^1.1.1",
"react": "18.3.1",
"react-dom": "18.3.1",
@@ -28296,6 +28297,7 @@
"pathe": "1.1.2",
"phone": "^3.1.14",
"qclone": "^1.2.0",
"react-async-hook": "^4.0.0",
"react-native-actions-sheet": "0.9.7",
"react-native-check-version": "^1.3.0",
"react-native-drax": "^0.10.2",
@@ -28324,7 +28326,7 @@
"@ammarahmed/react-native-background-fetch": "^4.2.2",
"@ammarahmed/react-native-eventsource": "1.1.0",
"@ammarahmed/react-native-fingerprint-scanner": "^5.0.0",
"@ammarahmed/react-native-share-extension": "^2.9.0",
"@ammarahmed/react-native-share-extension": "^2.9.5",
"@ammarahmed/react-native-sodium": "^1.6.5",
"@bam.tech/react-native-image-resizer": "3.0.11",
"@callstack/repack": "~5.1.2",
@@ -28359,10 +28361,10 @@
"react-native-gzip": "1.1.0",
"react-native-html-to-pdf-lite": "^0.9.1",
"react-native-iap": "12.16.2",
"react-native-image-crop-picker": "^0.40.2",
"react-native-image-crop-picker": "^0.51.1",
"react-native-in-app-review": "4.3.3",
"react-native-keychain": "4.0.5",
"react-native-mmkv-storage": "^0.11.2",
"react-native-mmkv-storage": "^12.0.0",
"react-native-modal-datetime-picker": "14.0.0",
"react-native-navigation-bar-color": "2.0.2",
"react-native-notification-sounds": "0.5.5",
@@ -28470,9 +28472,9 @@
}
},
"node_modules/@ammarahmed/react-native-share-extension": {
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/@ammarahmed/react-native-share-extension/-/react-native-share-extension-2.9.0.tgz",
"integrity": "sha512-iEkpJQFZL5/WDPh7iRCLZREANgaaAHthDsPaAYT6sI4wieQcHZMBAnfRMwBEnC0BZ0WVxbQZdzJYez+dmwpr2g==",
"version": "2.9.5",
"resolved": "https://registry.npmjs.org/@ammarahmed/react-native-share-extension/-/react-native-share-extension-2.9.5.tgz",
"integrity": "sha512-UTE8TSxkx+RFNgSJCCfD5FSdQ5IuMOsZzuuy0BVy46emRrpPw1fedJTtDbqyKrU8fwtKEIbzJWeQtjjRZlHxjQ==",
"license": "MIT",
"dependencies": {
"react-native": "^0.63.1"
@@ -44133,6 +44135,19 @@
"node": ">=0.10.0"
}
},
"node_modules/react-async-hook": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/react-async-hook/-/react-async-hook-4.0.0.tgz",
"integrity": "sha512-97lgjFkOcHCTYSrsKBpsXg3iVWM0LnzedB749iP76sb3/8Ouu4nHIkCLEOrQWHVYqrYxjF05NN6GHoXWFkB3Kw==",
"license": "MIT",
"engines": {
"node": ">=8",
"npm": ">=5"
},
"peerDependencies": {
"react": ">=16.8"
}
},
"node_modules/react-devtools-core": {
"version": "6.1.2",
"resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-6.1.2.tgz",
@@ -44504,10 +44519,13 @@
}
},
"node_modules/react-native-image-crop-picker": {
"version": "0.40.2",
"version": "0.51.1",
"resolved": "https://registry.npmjs.org/react-native-image-crop-picker/-/react-native-image-crop-picker-0.51.1.tgz",
"integrity": "sha512-GIFRyXJgv1dPceKd/hraK9q9V38v45rSg2ONR6RiSePcOJemkHpc/PMU86pq6lWPilDYHSxbZmea2pNMk85ayw==",
"license": "MIT",
"peerDependencies": {
"react-native": ">=0.40.0"
"react": "*",
"react-native": "*"
}
},
"node_modules/react-native-image-pan-zoom": {
@@ -44575,9 +44593,9 @@
}
},
"node_modules/react-native-mmkv-storage": {
"version": "0.11.2",
"resolved": "https://registry.npmjs.org/react-native-mmkv-storage/-/react-native-mmkv-storage-0.11.2.tgz",
"integrity": "sha512-/jbYNOUrwgVU09WyXDK6lFGXqBs+23oR9X37z3N68rwHNiXF5WDyXnT38dU2tF07ZlvmsobNHgdxgTu4kGQUKQ==",
"version": "12.0.0",
"resolved": "https://registry.npmjs.org/react-native-mmkv-storage/-/react-native-mmkv-storage-12.0.0.tgz",
"integrity": "sha512-sssZInILQBquytDDfjosjEdvevwMPk3fqQQjdjfnH362IcsBsApvtT8yJS406Mz9aJ6VhqVsZw/awltsUuPSYg==",
"license": "MIT",
"bin": {
"mmkv-link": "autolink/postlink/run.js"

View File

@@ -1,6 +1,6 @@
{
"name": "@notesnook/mobile",
"version": "3.3.2",
"version": "3.3.7",
"private": true,
"license": "GPL-3.0-or-later",
"workspaces": [
@@ -56,4 +56,4 @@
"react": "18.2.0",
"react-native": "0.77.2"
}
}
}

View File

@@ -1,27 +1,27 @@
diff --git a/node_modules/react-native-image-crop-picker/android/src/main/java/com/reactnative/ivpusic/imagepicker/PickerModule.java b/node_modules/react-native-image-crop-picker/android/src/main/java/com/reactnative/ivpusic/imagepicker/PickerModule.java
index 5de0845..1b158d8 100644
--- a/node_modules/react-native-image-crop-picker/android/src/main/java/com/reactnative/ivpusic/imagepicker/PickerModule.java
+++ b/node_modules/react-native-image-crop-picker/android/src/main/java/com/reactnative/ivpusic/imagepicker/PickerModule.java
@@ -692,6 +692,7 @@ class PickerModule extends ReactContextBaseJavaModule implements ActivityEventLi
image.putString("mime", options.outMimeType);
diff --git a/node_modules/react-native-image-crop-picker/android/src/main/java/com/reactnative/ivpusic/imagepicker/ImageCropPicker.java b/node_modules/react-native-image-crop-picker/android/src/main/java/com/reactnative/ivpusic/imagepicker/ImageCropPicker.java
index b9c494e..34ef800 100644
--- a/node_modules/react-native-image-crop-picker/android/src/main/java/com/reactnative/ivpusic/imagepicker/ImageCropPicker.java
+++ b/node_modules/react-native-image-crop-picker/android/src/main/java/com/reactnative/ivpusic/imagepicker/ImageCropPicker.java
@@ -679,6 +679,7 @@ class ImageCropPicker implements ActivityEventListener {
image.putInt("size", (int) new File(compressedImagePath).length());
image.putString("modificationDate", String.valueOf(modificationDate));
image.putString("filename", new File(path).getName());
+ image.putString("sourceURL", path);
if (includeBase64) {
image.putString("data", getBase64StringFromFile(compressedImagePath));
diff --git a/node_modules/react-native-image-crop-picker/ios/src/ImageCropPicker.m b/node_modules/react-native-image-crop-picker/ios/src/ImageCropPicker.m
index 9f20973..5e14da8 100644
--- a/node_modules/react-native-image-crop-picker/ios/src/ImageCropPicker.m
+++ b/node_modules/react-native-image-crop-picker/ios/src/ImageCropPicker.m
@@ -595,8 +595,10 @@ - (void)qb_imagePickerController:
NSString *mimeType = [self determineMimeTypeFromImageData:imageData];
diff --git a/node_modules/react-native-image-crop-picker/ios/src/ImageCropPicker.mm b/node_modules/react-native-image-crop-picker/ios/src/ImageCropPicker.mm
index 354ad09..622f779 100644
--- a/node_modules/react-native-image-crop-picker/ios/src/ImageCropPicker.mm
+++ b/node_modules/react-native-image-crop-picker/ios/src/ImageCropPicker.mm
@@ -603,7 +603,10 @@ - (void)qb_imagePickerController:(QBImagePickerController *)imagePickerControlle
Boolean isKnownMimeType = [mimeType length] > 0;
+ Boolean isHeicOrHeif = [mimeType isEqualToString:@"image/heic"] || [mimeType isEqualToString:@"image/heif"];
+
ImageResult *imageResult = [[ImageResult alloc] init];
- if (isLossless && useOriginalWidth && useOriginalHeight && isKnownMimeType && !forceJpg) {
+
+ Boolean isHeicOrHeif = [mimeType isEqualToString:@"image/heic"] || [mimeType isEqualToString:@"image/heif"];
+
+ if (isLossless && useOriginalWidth && useOriginalHeight && isKnownMimeType && !forceJpg && !isHeicOrHeif) {
// Use original, unmodified image
imageResult.data = imageData;

View File

@@ -0,0 +1,169 @@
diff --git a/node_modules/react-native-keychain/android/build.gradle b/node_modules/react-native-keychain/android/build.gradle
index bd2fe04..53ce4b1 100755
--- a/node_modules/react-native-keychain/android/build.gradle
+++ b/node_modules/react-native-keychain/android/build.gradle
@@ -51,5 +51,4 @@ dependencies {
//noinspection GradleDynamicVersion
implementation 'com.facebook.react:react-native:+' // From node_modules
implementation 'androidx.annotation:annotation:1.1.0'
- implementation 'com.facebook.conceal:conceal:1.1.3@aar'
}
diff --git a/node_modules/react-native-keychain/android/src/main/java/com/oblador/keychain/KeychainModule.java b/node_modules/react-native-keychain/android/src/main/java/com/oblador/keychain/KeychainModule.java
index 61d061e..be49f8a 100644
--- a/node_modules/react-native-keychain/android/src/main/java/com/oblador/keychain/KeychainModule.java
+++ b/node_modules/react-native-keychain/android/src/main/java/com/oblador/keychain/KeychainModule.java
@@ -15,7 +15,6 @@ import com.oblador.keychain.PrefsStorage.ResultSet;
import com.oblador.keychain.cipherStorage.CipherStorage;
import com.oblador.keychain.cipherStorage.CipherStorage.DecryptionResult;
import com.oblador.keychain.cipherStorage.CipherStorage.EncryptionResult;
-import com.oblador.keychain.cipherStorage.CipherStorageFacebookConceal;
import com.oblador.keychain.cipherStorage.CipherStorageKeystoreAESCBC;
import com.oblador.keychain.exceptions.CryptoFailedException;
import com.oblador.keychain.exceptions.EmptyParameterException;
@@ -48,7 +47,6 @@ public class KeychainModule extends ReactContextBaseJavaModule {
super(reactContext);
prefsStorage = new PrefsStorage(reactContext);
- addCipherStorageToMap(new CipherStorageFacebookConceal(reactContext));
addCipherStorageToMap(new CipherStorageKeystoreAESCBC());
}
diff --git a/node_modules/react-native-keychain/android/src/main/java/com/oblador/keychain/PrefsStorage.java b/node_modules/react-native-keychain/android/src/main/java/com/oblador/keychain/PrefsStorage.java
index 99448b1..792c24c 100644
--- a/node_modules/react-native-keychain/android/src/main/java/com/oblador/keychain/PrefsStorage.java
+++ b/node_modules/react-native-keychain/android/src/main/java/com/oblador/keychain/PrefsStorage.java
@@ -7,7 +7,6 @@ import android.util.Base64;
import com.facebook.react.bridge.ReactApplicationContext;
import com.oblador.keychain.cipherStorage.CipherStorage.EncryptionResult;
-import com.oblador.keychain.cipherStorage.CipherStorageFacebookConceal;
public class PrefsStorage {
public static final String KEYCHAIN_DATA = "RN_KEYCHAIN";
@@ -35,10 +34,6 @@ public class PrefsStorage {
byte[] bytesForPassword = getBytesForPassword(service);
String cipherStorageName = getCipherStorageName(service);
if (bytesForUsername != null && bytesForPassword != null) {
- if (cipherStorageName == null) {
- // If the CipherStorage name is not found, we assume it is because the entry was written by an older version of this library. The older version used Facebook Conceal, so we default to that.
- cipherStorageName = CipherStorageFacebookConceal.CIPHER_STORAGE_NAME;
- }
return new ResultSet(cipherStorageName, bytesForUsername, bytesForPassword);
}
return null;
diff --git a/node_modules/react-native-keychain/android/src/main/java/com/oblador/keychain/cipherStorage/CipherStorageFacebookConceal.java b/node_modules/react-native-keychain/android/src/main/java/com/oblador/keychain/cipherStorage/CipherStorageFacebookConceal.java
deleted file mode 100644
index 3162f99..0000000
--- a/node_modules/react-native-keychain/android/src/main/java/com/oblador/keychain/cipherStorage/CipherStorageFacebookConceal.java
+++ /dev/null
@@ -1,110 +0,0 @@
-package com.oblador.keychain.cipherStorage;
-
-import android.os.Build;
-import androidx.annotation.NonNull;
-
-import com.facebook.android.crypto.keychain.AndroidConceal;
-import com.facebook.android.crypto.keychain.SharedPrefsBackedKeyChain;
-import com.facebook.crypto.Crypto;
-import com.facebook.crypto.CryptoConfig;
-import com.facebook.crypto.Entity;
-import com.facebook.crypto.keychain.KeyChain;
-import com.facebook.react.bridge.ReactApplicationContext;
-import com.oblador.keychain.SecurityLevel;
-import com.oblador.keychain.exceptions.CryptoFailedException;
-
-import java.nio.charset.Charset;
-
-public class CipherStorageFacebookConceal implements CipherStorage {
- public static final String CIPHER_STORAGE_NAME = "FacebookConceal";
- public static final String KEYCHAIN_DATA = "RN_KEYCHAIN";
- private final Crypto crypto;
-
- public CipherStorageFacebookConceal(ReactApplicationContext reactContext) {
- KeyChain keyChain = new SharedPrefsBackedKeyChain(reactContext, CryptoConfig.KEY_256);
- this.crypto = AndroidConceal.get().createDefaultCrypto(keyChain);
- }
-
- @Override
- public String getCipherStorageName() {
- return CIPHER_STORAGE_NAME;
- }
-
- @Override
- public int getMinSupportedApiLevel() {
- return Build.VERSION_CODES.JELLY_BEAN;
- }
-
- @Override
- public SecurityLevel securityLevel() {
- return SecurityLevel.ANY;
- }
-
- @Override
- public boolean supportsSecureHardware() {
- return false;
- }
-
- @Override
- public EncryptionResult encrypt(@NonNull String service, @NonNull String username, @NonNull String password, SecurityLevel level) throws CryptoFailedException {
-
- if (!this.securityLevel().satisfiesSafetyThreshold(level)) {
- throw new CryptoFailedException(String.format("Insufficient security level (wants %s; got %s)", level, this.securityLevel()));
- }
-
- if (!crypto.isAvailable()) {
- throw new CryptoFailedException("Crypto is missing");
- }
- Entity usernameEntity = createUsernameEntity(service);
- Entity passwordEntity = createPasswordEntity(service);
-
- try {
- byte[] encryptedUsername = crypto.encrypt(username.getBytes(Charset.forName("UTF-8")), usernameEntity);
- byte[] encryptedPassword = crypto.encrypt(password.getBytes(Charset.forName("UTF-8")), passwordEntity);
-
- return new EncryptionResult(encryptedUsername, encryptedPassword, this);
- } catch (Exception e) {
- throw new CryptoFailedException("Encryption failed for service " + service, e);
- }
- }
-
- @Override
- public DecryptionResult decrypt(@NonNull String service, @NonNull byte[] username, @NonNull byte[] password) throws CryptoFailedException {
- if (!crypto.isAvailable()) {
- throw new CryptoFailedException("Crypto is missing");
- }
- Entity usernameEntity = createUsernameEntity(service);
- Entity passwordEntity = createPasswordEntity(service);
-
- try {
- byte[] decryptedUsername = crypto.decrypt(username, usernameEntity);
- byte[] decryptedPassword = crypto.decrypt(password, passwordEntity);
-
- return new DecryptionResult(
- new String(decryptedUsername, Charset.forName("UTF-8")),
- new String(decryptedPassword, Charset.forName("UTF-8")),
- SecurityLevel.ANY);
- } catch (Exception e) {
- throw new CryptoFailedException("Decryption failed for service " + service, e);
- }
- }
-
- @Override
- public void removeKey(@NonNull String service) {
- // Facebook Conceal stores only one key across all services, so we cannot delete the key (otherwise decryption will fail for encrypted data of other services).
- }
-
- private Entity createUsernameEntity(String service) {
- String prefix = getEntityPrefix(service);
- return Entity.create(prefix + "user");
- }
-
- private Entity createPasswordEntity(String service) {
- String prefix = getEntityPrefix(service);
- return Entity.create(prefix + "pass");
- }
-
- private String getEntityPrefix(String service) {
- return KEYCHAIN_DATA + ":" + service;
- }
-}

View File

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

View File

@@ -70,6 +70,7 @@ const EXTRA_ICON_NAMES = [
"chevron-down",
"calendar",
"minus-circle-outline",
"circle-outline",
"close-circle-outline",
"qrcode",
"text",

View File

@@ -28,7 +28,6 @@ import RNFetchBlob from "react-native-blob-util";
import WebView from "react-native-webview";
import { Config } from "./store";
import { db } from "../app/common/database";
import { SUBSCRIPTION_STATUS } from "../app/utils/constants";
export const fetchHandle = createRef();
export const HtmlLoadingWebViewAgent = React.memo(
@@ -40,6 +39,7 @@ export const HtmlLoadingWebViewAgent = React.memo(
const webview = useRef();
const premium = useRef(false);
const corsProxy = Config.corsProxy;
const [isLoggedIn, setIsLoggedIn] = useState();
useImperativeHandle(
fetchHandle,
@@ -72,11 +72,8 @@ export const HtmlLoadingWebViewAgent = React.memo(
useEffect(() => {
(async () => {
const user = await db.user.getUser();
const subscriptionStatus =
user?.subscription?.type || SUBSCRIPTION_STATUS.BASIC;
premium.current =
user && subscriptionStatus !== SUBSCRIPTION_STATUS.BASIC;
setIsLoggedIn(!!user);
console.log("USER", !!user);
const clipperPath =
Platform.OS === "ios"
? RNFetchBlob.fs.dirs.MainBundleDir +
@@ -91,6 +88,7 @@ export const HtmlLoadingWebViewAgent = React.memo(
.catch((e) => console.log(e));
})();
}, []);
console.log(isLoggedIn);
return !source || !clipper ? null : (
<WebView
@@ -103,7 +101,8 @@ export const HtmlLoadingWebViewAgent = React.memo(
height: 100,
position: "absolute",
opacity: 0,
zIndex: -1
zIndex: -1,
pointerEvents: "none"
}}
useSharedProcessPool={false}
pointerEvents="none"
@@ -123,7 +122,11 @@ export const HtmlLoadingWebViewAgent = React.memo(
console.log("Error handling webview message", e);
}
}}
injectedJavaScriptBeforeContentLoaded={script(clipper, premium.current)}
injectedJavaScriptBeforeContentLoaded={script(
clipper,
corsProxy,
isLoggedIn
)}
onError={() => {
console.log("Error loading page");
loadHandler.current?.();
@@ -137,9 +140,11 @@ export const HtmlLoadingWebViewAgent = React.memo(
() => true
);
const script = (clipper, pro) => `
const script = (clipper, corsProxy, loggedIn) => `
globalThis.module = {};
${clipper}
function postMessage(type, value) {
if (window.ReactNativeWebView) {
window.ReactNativeWebView.postMessage(
@@ -158,10 +163,10 @@ function postMessage(type, value) {
postMessage("error", globalThis.Clipper.clipPage);
} else {
globalThis.Clipper.clipPage(document,false, {
images: ${pro},
images: ${loggedIn ? "true" : "false"},
inlineImages: false,
styles: false,
corsProxy: undefined
corsProxy: ${corsProxy ? `"${corsProxy}"` : "undefined"}
}).then(result => {
postMessage("html", result);
}).catch(e => {

View File

@@ -19,7 +19,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import ShareExtension from "@ammarahmed/react-native-share-extension";
import { getPreviewData } from "@flyerhq/react-native-link-preview";
import { formatBytes } from "@notesnook/common";
import {
formatBytes,
isFeatureAvailable,
useIsFeatureAvailable
} from "@notesnook/common";
import { isImage } from "@notesnook/core";
import { useThemeColors } from "@notesnook/theme";
import React, { useCallback, useEffect, useRef, useState } from "react";
@@ -119,6 +123,7 @@ const ShareView = () => {
const noteTitle = useRef("");
const [loading, setLoading] = useState(false);
const [loadingExtension, setLoadingExtension] = useState(true);
const fullQualityImages = useIsFeatureAvailable("fullQualityImages");
const [rawData, setRawData] = useState({
type: null,
value: null
@@ -161,6 +166,12 @@ const ShareView = () => {
};
}, []);
useEffect(() => {
if (!fullQualityImages?.isAllowed) {
setCompress(true);
}
}, [fullQualityImages]);
const showLinkPreview = async (note, link) => {
let _note = note;
_note.content.data = makeHtmlFromUrl(link);
@@ -223,14 +234,14 @@ const ShareView = () => {
}
} else {
const user = await db.user.getUser();
if (user && user.subscription.type !== 0) {
if (
(isImage(item.type) && item.size > IMAGE_SIZE_LIMIT) ||
(!isImage(item.type) && item.size > FILE_SIZE_LIMIT)
) {
if (user) {
const feature = await isFeatureAvailable(
"fileSize",
item.size || 0
);
if (!feature.isAllowed) {
continue;
}
setRawFiles((files) => {
const index = files.findIndex(
(file) => file.name === item.name
@@ -256,7 +267,6 @@ const ShareView = () => {
);
const onLoad = useCallback(() => {
console.log(noteContent.current, "current...");
eSendEvent(eOnLoadNote + "shareEditor", {
id: null,
content: {
@@ -491,7 +501,7 @@ const ShareView = () => {
style={{
flexShrink: 1,
flexGrow: 1,
fontFamily: "OpenSans-SemiBold",
fontFamily: "Inter-SemiBold",
fontSize: AppFontSize.lg,
paddingBottom: 0,
paddingTop: 0
@@ -506,7 +516,7 @@ const ShareView = () => {
style={{
flexShrink: 1,
flexGrow: 1,
fontFamily: "OpenSans-SemiBold",
fontFamily: "Inter-SemiBold",
fontSize: AppFontSize.lg,
paddingBottom: 0,
paddingTop: 0,
@@ -632,7 +642,9 @@ const ShareView = () => {
marginTop: 6
}}
onPress={() => {
setCompress(!compress);
if (fullQualityImages?.isAllowed) {
setCompress(!compress);
}
}}
>
<Icon
@@ -643,7 +655,7 @@ const ShareView = () => {
: "checkbox-blank-outline"
}
color={
compress
compress && fullQualityImages?.isAllowed
? colors.primary.accent
: colors.primary.icon
}
@@ -734,7 +746,7 @@ const ShareView = () => {
</Paragraph>
{rawData.value && isURL(rawData.value) ? (
<Button
type={mode === 2 ? "inverted" : "transparent"}
type={mode === 2 ? "inverted" : "plain"}
icon={mode === 2 ? "radiobox-marked" : "radiobox-blank"}
onPress={() => changeMode(2)}
title={modes[2].title}
@@ -745,9 +757,9 @@ const ShareView = () => {
/>
) : null}
<Button
type={mode === 1 ? "inverted" : "transparent"}
type={mode === 1 ? "inverted" : "plain"}
icon={mode === 1 ? "radiobox-marked" : "radiobox-blank"}
onPress={() => changeMode(2)}
onPress={() => changeMode(1)}
title={modes[1].title}
height={30}
style={{

View File

@@ -68,11 +68,10 @@ export const useShareStore = create((set) => ({
let appendNote = MMKV.getString(StorageKeys.appendNote);
let selectedNotebooks = MMKV.getString(StorageKeys.selectedNotebooks);
let selectedTags = MMKV.getString(StorageKeys.selectedTag);
appendNote = JSON.parse(appendNote);
set({
appendNote: appendNote,
selectedNotebooks: selectedNotebooks ? JSON.parse(selectedNotebooks) : [],
selectedTag: selectedTags ? JSON.parse(selectedTags) : []
selectedTags: selectedTags ? JSON.parse(selectedTags) : []
});
},
selectedTags: [],

View File

@@ -15,10 +15,7 @@
"@notesnook/theme": ["../../packages/theme"],
"@types/react": ["./node_modules/@types/react"],
"react": ["./node_modules/react"]
},
"incremental": true,
"maxNodeModuleJsDepth": 5,
"downlevelIteration": true
}
},
"exclude": ["native", "e2e"]
}

File diff suppressed because one or more lines are too long

View File

@@ -208,6 +208,7 @@
"happy-dom": "16.0.1",
"isomorphic-fetch": "^3.0.0",
"nodemon": "^3.1.7",
"prismjs": "^1.30.0",
"prosemirror-test-builder": "^1.1.1",
"react": "18.3.1",
"react-dom": "18.3.1",

View File

@@ -987,7 +987,7 @@
},
"../web": {
"name": "@notesnook/web",
"version": "3.3.0-beta.1",
"version": "3.3.1",
"hasInstallScript": true,
"license": "GPL-3.0-or-later",
"dependencies": {

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
{
"name": "@notesnook/web",
"description": "Your private note taking space",
"version": "3.3.0",
"version": "3.3.3",
"private": true,
"main": "./src/app.js",
"homepage": "https://notesnook.com/",
@@ -18,7 +18,7 @@
"@lingui/react": "5.1.2",
"@mdi/js": "7.4.47",
"@mdi/react": "1.6.1",
"@notesnook-importer/core": "^2.2.2",
"@notesnook-importer/core": "^2.2.5",
"@notesnook/common": "file:../../packages/common",
"@notesnook/core": "file:../../packages/core",
"@notesnook/crypto": "file:../../packages/crypto",

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