Compare commits

...
Author SHA1 Message Date
StandardNotes CI 29f2c18311 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
2023-11-11 20:24:20 +00:00
Aman Harwara e37cd1d299 chore: fix super note html export style [skip e2e] 2023-11-12 01:40:22 +05:30
Aman Harwara e0d48afbe2 fix: Fixed issue on Android where only one selected file would be uploaded instead of all 2023-11-12 00:00:28 +05:30
Aman Harwara 7d9dabb818 chore: dont show embedded file export options if no selected super note has them 2023-11-11 22:17:32 +05:30
StandardNotes CI 991a7a521f chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
2023-11-09 15:10:42 +00:00
Aman Harwara a49549177c chore: fix range selection logic on ios [skip e2e] 2023-11-09 20:31:46 +05:30
StandardNotes CI 6097cb50d9 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
2023-11-09 13:31:43 +00:00
Aman Harwara 9d532e83e1 chore: potential fix for unintentional multiple selection after editing on ios [skip e2e] 2023-11-09 18:49:55 +05:30
StandardNotes CI 1bf3a99911 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
2023-11-09 06:59:05 +00:00
Aman Harwara 67494b647e chore: trigger release [skip e2e] 2023-11-09 12:19:41 +05:30
StandardNotes CI 54ba30ea1d chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
2023-11-08 21:18:05 +00:00
Aman Harwara e2c04b3576 chore: android material you themed icon (#2629) [skip e2e] 2023-11-09 02:31:21 +05:30
StandardNotes CI 9c06b6ae71 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].3
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].2
 - @standardnotes/[email protected]
2023-11-08 20:11:40 +00:00
Aman Harwara 2d687d9786 chore: on android use notification to display file upload progress instead of toast (#2628) [skip e2e] 2023-11-09 01:31:34 +05:30
StandardNotes CI 6a7c5277f8 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].1
 - @standardnotes/[email protected]
2023-11-07 07:29:17 +00:00
Aman Harwara 894167520d fix: Fixed issue where non-image inlined files would not correctly be imported from a Markdown file 2023-11-07 12:11:21 +05:30
StandardNotes CI a1317b2bfd chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
2023-11-06 15:41:31 +00:00
Karol Sójko a6be2f0a9a chore: add test for breaching transfer limit (#2620) 2023-11-06 16:03:11 +01:00
StandardNotes CI 6295f179a1 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].0
 - @standardnotes/[email protected]
2023-11-06 11:46:38 +00:00
Aman Harwara 3bf670ece7 feat: Importing markdown files from the Import dialog will now automatically use Super notes 2023-11-06 16:25:22 +05:30
StandardNotes CI a3978f142b chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
2023-11-06 09:59:15 +00:00
Aman Harwara 7a24ea3c25 chore: fix converting empty plaintext note with only spaces to super 2023-11-06 14:52:03 +05:30
Aman Harwara 56c522b5c3 chore: fix scroll in mobile popovers [skip e2e] 2023-11-06 14:45:27 +05:30
Aman Harwara ade6c8bb1e chore: ios window color [skip e2e] 2023-11-06 14:38:05 +05:30
StandardNotes CI d55b2527d5 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].1
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].2
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].3
 - @standardnotes/[email protected]
2023-11-04 13:11:12 +00:00
Aman Harwara 20354a926a refactor: evernote imports (#2619) [skip e2e] 2023-11-04 18:26:22 +05:30
StandardNotes CI 3d794bb12e chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
2023-11-03 12:29:41 +00:00
Aman Harwara d9630c99c7 refactor: take velocity into account for mobile popover gesture [skip e2e] 2023-11-03 17:45:09 +05:30
StandardNotes CI 5ff795d636 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].1
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].2
 - @standardnotes/[email protected]
2023-11-03 11:32:50 +00:00
Aman Harwara 86e9c90c10 refactor: window background color on mobile, hide webview until ready (#2618) [skip e2e] 2023-11-03 16:50:11 +05:30
Karol Sójko 0902580b79 chore: enable vaults on free internal team user accounts (#2617) 2023-11-03 11:23:42 +01:00
StandardNotes CI 202a132482 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
2023-11-02 12:49:28 +00:00
Aman Harwara 23331788f6 chore: revert fastfile change [skip e2e] 2023-11-02 18:10:07 +05:30
Karol Sójko f95a4fe981 chore: establish websockets connection only on first party server hosts (#2616) 2023-11-02 13:33:42 +01:00
StandardNotes CI 4be9b51481 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
2023-11-02 10:55:29 +00:00
Aman Harwara 6fdd8b3729 chore: ios window background color [skip e2e] 2023-11-02 16:06:34 +05:30
StandardNotes CI 4260c1ec4a chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
2023-11-02 08:56:48 +00:00
Aman Harwara 63281b9998 chore: fix some enex imports [skip e2e] 2023-11-02 14:10:11 +05:30
StandardNotes CI b97ed403bf chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].9
2023-11-02 08:39:10 +00:00
Aman Harwara af6ac568f0 chore: adjust empty line placeholder contrast [skip e2e] 2023-11-02 13:55:34 +05:30
Aman Harwara de3836869d chore: trigger release [skip e2e] 2023-11-02 13:45:45 +05:30
Aman Harwara d28b20008c fix: Fixed white flash issue when starting app on iOS 2023-11-02 13:45:36 +05:30
StandardNotes CI 7bbe8d3842 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].8
2023-11-01 20:57:08 +00:00
Aman Harwara 8a40364c6c chore: change ios launchscreen storyboard background color [skip e2e] 2023-11-02 02:14:55 +05:30
StandardNotes CI 752448f9e6 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].7
2023-11-01 15:12:45 +00:00
Aman Harwara 79b47150d6 chore: fix mac release step [skip e2e] 2023-11-01 20:25:58 +05:30
StandardNotes CI ed30fec2ba chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
2023-11-01 08:07:07 +00:00
Aman Harwara 61cb95dc4a chore: update fastfile [skip e2e] 2023-11-01 13:22:31 +05:30
StandardNotes CI 00317fda88 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].6
2023-11-01 07:46:24 +00:00
Aman Harwara 83a731b076 chore: trigger release [skip e2e] 2023-11-01 13:03:08 +05:30
StandardNotes CI f4479feae7 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].5
2023-10-31 13:36:26 +00:00
Aman Harwara f37bd487a2 chore: toolbar color [skip e2e] 2023-10-31 18:50:45 +05:30
Aman Harwara 9c43c87f14 chore: update electron notarize dep [skip e2e] 2023-10-31 18:47:15 +05:30
StandardNotes CI 61cdfc6030 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].1
 - @standardnotes/[email protected].4
2023-10-31 11:52:43 +00:00
Aman Harwara f408950aa4 fix: Fixed issue where exporting multiple files with the same name would error 2023-10-31 16:43:02 +05:30
StandardNotes CI d1c295751d chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].3
2023-10-31 10:38:38 +00:00
Aman Harwara e42e2d6130 chore: new line placeholder classname [skip e2e] 2023-10-31 15:50:15 +05:30
Aman Harwara 572c9b7dfa fix: Fixed issue where a brief flash of white would appear when starting the app on mobile 2023-10-31 15:48:20 +05:30
StandardNotes CI 14ea00dc28 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
2023-10-31 10:03:56 +00:00
Aman Harwara daaee89639 chore: update ruby gems 2023-10-31 14:46:10 +05:30
StandardNotes CI da37c421db chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].2
2023-10-31 09:01:57 +00:00
Aman Harwara 85bd411d8f chore: super note new-line placeholder [skip e2e] 2023-10-31 14:19:18 +05:30
StandardNotes CI 63f14d318d chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].1
2023-10-30 21:24:10 +00:00
Aman Harwara 95cd682d49 chore: fix changelog [skip e2e] 2023-10-31 02:36:24 +05:30
StandardNotes CI 941eeea4e3 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].0
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].0
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].0
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].0
 - @standardnotes/[email protected].0
2023-10-30 20:34:09 +00:00
Aman Harwara 991de1ddf5 feat: When exporting a Super note, embedded files can be inlined in the note or exported along the note in a zip file. You can now also choose to include frontmatter when exporting to Markdown format.
(#2610)
2023-10-31 01:19:04 +05:30
StandardNotes CI 044776d937 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].8
2023-10-30 19:44:10 +00:00
Aman Harwara 83fa6adbeb chore: fix tag rename [skip e2e] 2023-10-31 01:00:36 +05:30
StandardNotes CI ce908c8ec4 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].7
2023-10-29 14:51:21 +00:00
Aman Harwara 98c61de501 refactor: move overrides into scss file [skip e2e] 2023-10-29 20:08:06 +05:30
Aman Harwara 198efdc41c fix: Fixed issue with checklist items in Super notes not being correctly exported to HTML 2023-10-29 20:05:47 +05:30
StandardNotes CI cace6522f6 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].6
2023-10-29 09:29:44 +00:00
Aman Harwara f3a9717883 chore: fix tag options menu opening notes list [skip e2e] 2023-10-29 14:41:44 +05:30
StandardNotes CI 00d30ca003 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].5
2023-10-29 08:46:12 +00:00
Aman Harwara 8574c42706 chore: fix positioning [skip e2e] 2023-10-29 14:03:25 +05:30
Aman Harwara 0f73ea8c4e chore: fix note options menu visibility in plain editor on mobile [skip e2e] 2023-10-29 14:00:45 +05:30
StandardNotes CI 12ccd22d78 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].4
2023-10-28 11:46:29 +00:00
Aman Harwara d891ac7578 chore: remove unused css [skip e2e] 2023-10-28 17:01:18 +05:30
Aman Harwara ce0db04646 fix: Fixed check list indentation in Super notes 2023-10-28 16:30:44 +05:30
113 changed files with 2870 additions and 1079 deletions
@@ -13,6 +13,7 @@ jobs:
env:
CSC_LINK: ${{ secrets.MAC_CI_KEYS }}
CSC_KEY_PASSWORD: ${{ secrets.MAC_CI_KEYS_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
NOTARIZE_APPLE_ID: ${{ secrets.NOTARIZE_APPLE_ID }}
NOTARIZE_APPLE_ID_PASSWORD: ${{ secrets.NOTARIZE_APPLE_ID_PASSWORD }}
defaults:
Binary file not shown.
+1
View File
@@ -26,6 +26,7 @@
"build:snjs": "yarn workspaces foreach -p --topological-dev --verbose -R --from @standardnotes/snjs run build",
"build:services": "yarn workspaces foreach -pt --topological-dev --verbose -R --from @standardnotes/services run build",
"build:api": "yarn workspaces foreach -pt --topological-dev --verbose -R --from @standardnotes/api run build",
"start:web": "yarn workspace @standardnotes/web start",
"e2e": "lerna run start:test-server --scope=@standardnotes/snjs",
"e2e:test": "yarn dlx mocha-headless-chrome --timeout 3600000 -f http://localhost:9001/mocha/test.html",
"reset": "find . -type dir -name node_modules | xargs rm -rf && rm -rf yarn.lock && yarn install",
+4
View File
@@ -3,6 +3,10 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.26.69](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
**Note:** Version bump only for package @standardnotes/api
## [1.26.68](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-26)
**Note:** Version bump only for package @standardnotes/api
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/api",
"version": "1.26.68",
"version": "1.26.69",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
+120
View File
@@ -3,6 +3,126 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.1.321](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-11)
**Note:** Version bump only for package @standardnotes/clipper
## [1.1.320](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-09)
**Note:** Version bump only for package @standardnotes/clipper
## [1.1.319](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-09)
**Note:** Version bump only for package @standardnotes/clipper
## [1.1.318](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-09)
**Note:** Version bump only for package @standardnotes/clipper
## [1.1.317](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-08)
**Note:** Version bump only for package @standardnotes/clipper
## [1.1.316](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-07)
**Note:** Version bump only for package @standardnotes/clipper
## [1.1.315](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-06)
**Note:** Version bump only for package @standardnotes/clipper
## [1.1.314](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-06)
**Note:** Version bump only for package @standardnotes/clipper
## [1.1.313](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-06)
**Note:** Version bump only for package @standardnotes/clipper
## [1.1.312](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-04)
**Note:** Version bump only for package @standardnotes/clipper
## [1.1.311](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-03)
**Note:** Version bump only for package @standardnotes/clipper
## [1.1.310](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-03)
**Note:** Version bump only for package @standardnotes/clipper
## [1.1.309](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-02)
**Note:** Version bump only for package @standardnotes/clipper
## [1.1.308](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-02)
**Note:** Version bump only for package @standardnotes/clipper
## [1.1.307](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-02)
**Note:** Version bump only for package @standardnotes/clipper
## [1.1.306](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-02)
**Note:** Version bump only for package @standardnotes/clipper
## [1.1.305](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-01)
**Note:** Version bump only for package @standardnotes/clipper
## [1.1.304](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-01)
**Note:** Version bump only for package @standardnotes/clipper
## [1.1.303](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-01)
**Note:** Version bump only for package @standardnotes/clipper
## [1.1.302](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)
**Note:** Version bump only for package @standardnotes/clipper
## [1.1.301](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)
**Note:** Version bump only for package @standardnotes/clipper
## [1.1.300](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)
**Note:** Version bump only for package @standardnotes/clipper
## [1.1.299](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)
**Note:** Version bump only for package @standardnotes/clipper
## [1.1.298](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
**Note:** Version bump only for package @standardnotes/clipper
## [1.1.297](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
**Note:** Version bump only for package @standardnotes/clipper
## [1.1.296](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
**Note:** Version bump only for package @standardnotes/clipper
## [1.1.295](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-29)
**Note:** Version bump only for package @standardnotes/clipper
## [1.1.294](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-29)
**Note:** Version bump only for package @standardnotes/clipper
## [1.1.293](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-29)
**Note:** Version bump only for package @standardnotes/clipper
## [1.1.292](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-28)
**Note:** Version bump only for package @standardnotes/clipper
## [1.1.291](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-27)
**Note:** Version bump only for package @standardnotes/clipper
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@standardnotes/clipper",
"description": "Web clipper browser extension for Standard Notes",
"version": "1.1.291",
"version": "1.1.321",
"private": true,
"scripts": {
"build-mv2": "yarn clean && webpack --config ./webpack.config.prod.js",
+120
View File
@@ -3,6 +3,126 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [3.108.255](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-11)
**Note:** Version bump only for package @standardnotes/desktop
## [3.108.254](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-09)
**Note:** Version bump only for package @standardnotes/desktop
## [3.108.253](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-09)
**Note:** Version bump only for package @standardnotes/desktop
## [3.108.252](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-09)
**Note:** Version bump only for package @standardnotes/desktop
## [3.108.251](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-08)
**Note:** Version bump only for package @standardnotes/desktop
## [3.108.250](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-07)
**Note:** Version bump only for package @standardnotes/desktop
## [3.108.249](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-06)
**Note:** Version bump only for package @standardnotes/desktop
## [3.108.248](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-06)
**Note:** Version bump only for package @standardnotes/desktop
## [3.108.247](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-06)
**Note:** Version bump only for package @standardnotes/desktop
## [3.108.246](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-04)
**Note:** Version bump only for package @standardnotes/desktop
## [3.108.245](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-03)
**Note:** Version bump only for package @standardnotes/desktop
## [3.108.244](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-03)
**Note:** Version bump only for package @standardnotes/desktop
## [3.108.243](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-02)
**Note:** Version bump only for package @standardnotes/desktop
## [3.108.242](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-02)
**Note:** Version bump only for package @standardnotes/desktop
## [3.108.241](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-02)
**Note:** Version bump only for package @standardnotes/desktop
## [3.108.240](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-02)
**Note:** Version bump only for package @standardnotes/desktop
## [3.108.239](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-01)
**Note:** Version bump only for package @standardnotes/desktop
## [3.108.238](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-01)
**Note:** Version bump only for package @standardnotes/desktop
## [3.108.237](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-01)
**Note:** Version bump only for package @standardnotes/desktop
## [3.108.236](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)
**Note:** Version bump only for package @standardnotes/desktop
## [3.108.235](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)
**Note:** Version bump only for package @standardnotes/desktop
## [3.108.234](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)
**Note:** Version bump only for package @standardnotes/desktop
## [3.108.233](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)
**Note:** Version bump only for package @standardnotes/desktop
## [3.108.232](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
**Note:** Version bump only for package @standardnotes/desktop
## [3.108.231](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
**Note:** Version bump only for package @standardnotes/desktop
## [3.108.230](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
**Note:** Version bump only for package @standardnotes/desktop
## [3.108.229](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-29)
**Note:** Version bump only for package @standardnotes/desktop
## [3.108.228](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-29)
**Note:** Version bump only for package @standardnotes/desktop
## [3.108.227](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-29)
**Note:** Version bump only for package @standardnotes/desktop
## [3.108.226](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-28)
**Note:** Version bump only for package @standardnotes/desktop
## [3.108.225](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-27)
**Note:** Version bump only for package @standardnotes/desktop
+2 -2
View File
@@ -1,7 +1,7 @@
{
"name": "@standardnotes/desktop",
"main": "./app/dist/index.js",
"version": "3.108.225",
"version": "3.108.255",
"license": "AGPL-3.0",
"author": "Standard Notes.",
"private": true,
@@ -53,6 +53,7 @@
"devDependencies": {
"@babel/core": "*",
"@babel/preset-env": "*",
"@electron/notarize": "^2.1.0",
"@types/fs-extra": "^11.0.1",
"@types/lodash": "^4.14.189",
"@types/mime-types": "^2.1.1",
@@ -63,7 +64,6 @@
"babel-loader": "^9.1.0",
"copy-webpack-plugin": "^11.0.0",
"electron-builder": "23.6.0",
"electron-notarize": "^1.2.1",
"eslint": "*",
"eslint-config-prettier": "^8.9.0",
"eslint-plugin-import": "^2.26.0",
+2 -1
View File
@@ -2,7 +2,7 @@
const fs = require('fs')
const path = require('path')
const electronNotarize = require('electron-notarize')
const electronNotarize = require('@electron/notarize')
module.exports = async function (params) {
const platformName = params.electronPlatformName
@@ -21,6 +21,7 @@ module.exports = async function (params) {
try {
electronNotarize
.notarize({
teamId: process.env.APPLE_TEAM_ID,
appBundleId: appId,
appPath: appPath,
appleId: process.env.NOTARIZE_APPLE_ID,
+4
View File
@@ -3,6 +3,10 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.21.91](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
**Note:** Version bump only for package @standardnotes/encryption
## [1.21.90](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-26)
**Note:** Version bump only for package @standardnotes/encryption
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/encryption",
"version": "1.21.90",
"version": "1.21.91",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
+8
View File
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.28.103](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-04)
**Note:** Version bump only for package @standardnotes/filepicker
## [1.28.102](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
**Note:** Version bump only for package @standardnotes/filepicker
## [1.28.101](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-26)
**Note:** Version bump only for package @standardnotes/filepicker
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/filepicker",
"version": "1.28.101",
"version": "1.28.103",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
+10
View File
@@ -3,6 +3,16 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.18.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-04)
**Note:** Version bump only for package @standardnotes/files
# [1.18.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
### Features
* When exporting a Super note, embedded files can be inlined in the note or exported along the note in a zip file. You can now also choose to include frontmatter when exporting to Markdown format. ([991de1d](https://github.com/standardnotes/app/commit/991de1ddf5dbb1016348d603d244699c676d9b5f)), closes [#2610](https://github.com/standardnotes/app/issues/2610)
## [1.17.20](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-26)
**Note:** Version bump only for package @standardnotes/files
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/files",
"version": "1.17.20",
"version": "1.18.1",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
@@ -1,5 +1,15 @@
import { FileItem } from '@standardnotes/models'
import { GenerateUuid } from '@standardnotes/services'
export interface SuperConverterServiceInterface {
isValidSuperString(superString: string): boolean
convertSuperStringToOtherFormat: (superString: string, toFormat: 'txt' | 'md' | 'html' | 'json') => string
convertSuperStringToOtherFormat: (superString: string, toFormat: 'txt' | 'md' | 'html' | 'json') => Promise<string>
convertOtherFormatToSuperString: (otherFormatString: string, fromFormat: 'txt' | 'md' | 'html' | 'json') => string
getEmbeddedFileIDsFromSuperString(superString: string): string[]
uploadAndReplaceInlineFilesInSuperString(
superString: string,
uploadFile: (file: File) => Promise<FileItem | undefined>,
linkFile: (file: FileItem) => Promise<void>,
generateUuid: GenerateUuid,
): Promise<string>
}
+138
View File
@@ -3,6 +3,144 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [3.56.237](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-11)
### Bug Fixes
* Fixed issue on Android where only one selected file would be uploaded instead of all ([e0d48af](https://github.com/standardnotes/app/commit/e0d48afbe22987624214b18ed613b0c31e6eb901))
## [3.56.236](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-09)
**Note:** Version bump only for package @standardnotes/mobile
## [3.56.235](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-09)
**Note:** Version bump only for package @standardnotes/mobile
## [3.56.234](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-09)
**Note:** Version bump only for package @standardnotes/mobile
## [3.56.233](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-08)
**Note:** Version bump only for package @standardnotes/mobile
## [3.56.232](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-08)
**Note:** Version bump only for package @standardnotes/mobile
## [3.56.231](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-07)
**Note:** Version bump only for package @standardnotes/mobile
## [3.56.230](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-06)
**Note:** Version bump only for package @standardnotes/mobile
## [3.56.229](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-06)
**Note:** Version bump only for package @standardnotes/mobile
## [3.56.228](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-06)
**Note:** Version bump only for package @standardnotes/mobile
## [3.56.227](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-04)
**Note:** Version bump only for package @standardnotes/mobile
## [3.56.226](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-03)
**Note:** Version bump only for package @standardnotes/mobile
## [3.56.225](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-03)
**Note:** Version bump only for package @standardnotes/mobile
## [3.56.224](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-02)
**Note:** Version bump only for package @standardnotes/mobile
## [3.56.223](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-02)
**Note:** Version bump only for package @standardnotes/mobile
## [3.56.222](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-02)
**Note:** Version bump only for package @standardnotes/mobile
## [3.56.221](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-02)
### Bug Fixes
* Fixed white flash issue when starting app on iOS ([d28b200](https://github.com/standardnotes/app/commit/d28b20008c6c1dcf8876ca4613e468fa5511ae3e))
## [3.56.220](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-01)
**Note:** Version bump only for package @standardnotes/mobile
## [3.56.219](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-01)
**Note:** Version bump only for package @standardnotes/mobile
## [3.56.218](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-01)
**Note:** Version bump only for package @standardnotes/mobile
## [3.56.217](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-01)
**Note:** Version bump only for package @standardnotes/mobile
## [3.56.216](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)
**Note:** Version bump only for package @standardnotes/mobile
## [3.56.215](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)
**Note:** Version bump only for package @standardnotes/mobile
## [3.56.214](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)
### Bug Fixes
* Fixed issue where a brief flash of white would appear when starting the app on mobile ([572c9b7](https://github.com/standardnotes/app/commit/572c9b7dfaa42773c050772940e383df2940a79f))
## [3.56.213](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)
**Note:** Version bump only for package @standardnotes/mobile
## [3.56.212](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)
**Note:** Version bump only for package @standardnotes/mobile
## [3.56.211](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
**Note:** Version bump only for package @standardnotes/mobile
## [3.56.210](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
**Note:** Version bump only for package @standardnotes/mobile
## [3.56.209](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
**Note:** Version bump only for package @standardnotes/mobile
## [3.56.208](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-29)
**Note:** Version bump only for package @standardnotes/mobile
## [3.56.207](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-29)
**Note:** Version bump only for package @standardnotes/mobile
## [3.56.206](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-29)
**Note:** Version bump only for package @standardnotes/mobile
## [3.56.205](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-28)
**Note:** Version bump only for package @standardnotes/mobile
## [3.56.204](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-27)
**Note:** Version bump only for package @standardnotes/mobile
+61 -53
View File
@@ -3,13 +3,17 @@ GEM
specs:
CFPropertyList (3.0.6)
rexml
activesupport (6.1.5)
activesupport (7.1.1)
base64
bigdecimal
concurrent-ruby (~> 1.0, >= 1.0.2)
connection_pool (>= 2.2.5)
drb
i18n (>= 1.6, < 2)
minitest (>= 5.1)
mutex_m
tzinfo (~> 2.0)
zeitwerk (~> 2.3)
addressable (2.8.4)
addressable (2.8.5)
public_suffix (>= 2.0.2, < 6.0)
algoliasearch (1.27.5)
httpclient (~> 2.8, >= 2.8.3)
@@ -17,32 +21,34 @@ GEM
artifactory (3.0.15)
atomos (0.1.3)
aws-eventstream (1.2.0)
aws-partitions (1.755.0)
aws-sdk-core (3.171.0)
aws-partitions (1.843.0)
aws-sdk-core (3.185.1)
aws-eventstream (~> 1, >= 1.0.2)
aws-partitions (~> 1, >= 1.651.0)
aws-sigv4 (~> 1.5)
jmespath (~> 1, >= 1.6.1)
aws-sdk-kms (1.63.0)
aws-sdk-core (~> 3, >= 3.165.0)
aws-sdk-kms (1.72.0)
aws-sdk-core (~> 3, >= 3.184.0)
aws-sigv4 (~> 1.1)
aws-sdk-s3 (1.121.0)
aws-sdk-core (~> 3, >= 3.165.0)
aws-sdk-s3 (1.136.0)
aws-sdk-core (~> 3, >= 3.181.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.4)
aws-sigv4 (1.5.2)
aws-sigv4 (~> 1.6)
aws-sigv4 (1.6.1)
aws-eventstream (~> 1, >= 1.0.2)
babosa (1.0.4)
claide (1.0.3)
cocoapods (1.11.3)
base64 (0.1.1)
bigdecimal (3.1.4)
claide (1.1.0)
cocoapods (1.14.2)
addressable (~> 2.8)
claide (>= 1.0.2, < 2.0)
cocoapods-core (= 1.11.3)
cocoapods-core (= 1.14.2)
cocoapods-deintegrate (>= 1.0.3, < 2.0)
cocoapods-downloader (>= 1.4.0, < 2.0)
cocoapods-downloader (>= 2.0)
cocoapods-plugins (>= 1.0.0, < 2.0)
cocoapods-search (>= 1.0.0, < 2.0)
cocoapods-trunk (>= 1.4.0, < 2.0)
cocoapods-trunk (>= 1.6.0, < 2.0)
cocoapods-try (>= 1.1.0, < 2.0)
colored2 (~> 3.1)
escape (~> 0.0.4)
@@ -50,10 +56,10 @@ GEM
gh_inspector (~> 1.0)
molinillo (~> 0.8.0)
nap (~> 1.0)
ruby-macho (>= 1.0, < 3.0)
xcodeproj (>= 1.21.0, < 2.0)
cocoapods-core (1.11.3)
activesupport (>= 5.0, < 7)
ruby-macho (>= 2.3.0, < 3.0)
xcodeproj (>= 1.23.0, < 2.0)
cocoapods-core (1.14.2)
activesupport (>= 5.0, < 8)
addressable (~> 2.8)
algoliasearch (~> 1.0)
concurrent-ruby (~> 1.1)
@@ -63,7 +69,7 @@ GEM
public_suffix (~> 4.0)
typhoeus (~> 1.0)
cocoapods-deintegrate (1.0.5)
cocoapods-downloader (1.5.1)
cocoapods-downloader (2.0)
cocoapods-plugins (1.0.0)
nap
cocoapods-search (1.0.1)
@@ -75,18 +81,21 @@ GEM
colored2 (3.1.2)
commander (4.6.0)
highline (~> 2.0.0)
concurrent-ruby (1.1.9)
concurrent-ruby (1.2.2)
connection_pool (2.4.1)
declarative (0.0.20)
digest-crc (0.6.4)
digest-crc (0.6.5)
rake (>= 12.0.0, < 14.0.0)
domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0)
dotenv (2.8.1)
drb (2.1.1)
ruby2_keywords
emoji_regex (3.2.3)
escape (0.0.4)
ethon (0.15.0)
ethon (0.16.0)
ffi (>= 1.15.0)
excon (0.99.0)
excon (0.104.0)
faraday (1.10.3)
faraday-em_http (~> 1.0)
faraday-em_synchrony (~> 1.0)
@@ -115,8 +124,8 @@ GEM
faraday-retry (1.0.3)
faraday_middleware (1.2.0)
faraday (~> 1.0)
fastimage (2.2.6)
fastlane (2.212.2)
fastimage (2.2.7)
fastlane (2.216.0)
CFPropertyList (>= 2.3, < 4.0.0)
addressable (>= 2.8, < 3.0.0)
artifactory (~> 3.0)
@@ -137,10 +146,11 @@ GEM
google-apis-playcustomapp_v1 (~> 0.1)
google-cloud-storage (~> 1.31)
highline (~> 2.0)
http-cookie (~> 1.0.5)
json (< 3.0.0)
jwt (>= 2.1.0, < 3)
mini_magick (>= 4.9.4, < 5.0.0)
multipart-post (~> 2.0.0)
multipart-post (>= 2.0.0, < 3.0.0)
naturally (~> 2.2)
optparse (~> 0.1.1)
plist (>= 3.1.0, < 4.0.0)
@@ -148,21 +158,21 @@ GEM
security (= 0.1.3)
simctl (~> 1.6.3)
terminal-notifier (>= 2.0.0, < 3.0.0)
terminal-table (>= 1.4.5, < 2.0.0)
terminal-table (~> 3)
tty-screen (>= 0.6.3, < 1.0.0)
tty-spinner (>= 0.8.0, < 1.0.0)
word_wrap (~> 1.0.0)
xcodeproj (>= 1.13.0, < 2.0.0)
xcpretty (~> 0.3.0)
xcpretty-travis-formatter (>= 0.0.3)
fastlane-plugin-bundletool (1.0.5)
ffi (1.15.5)
fastlane-plugin-bundletool (1.0.9)
ffi (1.16.3)
fourflusher (2.3.1)
fuzzy_match (2.0.4)
gh_inspector (1.1.3)
google-apis-androidpublisher_v3 (0.40.0)
google-apis-androidpublisher_v3 (0.51.0)
google-apis-core (>= 0.11.0, < 2.a)
google-apis-core (0.11.0)
google-apis-core (0.11.2)
addressable (~> 2.5, >= 2.5.1)
googleauth (>= 0.16.2, < 2.a)
httpclient (>= 2.8.1, < 3.a)
@@ -191,10 +201,9 @@ GEM
google-cloud-core (~> 1.6)
googleauth (>= 0.16.2, < 2.a)
mini_mime (~> 1.0)
googleauth (1.5.2)
googleauth (1.8.1)
faraday (>= 0.17.3, < 3.a)
jwt (>= 1.4, < 3.0)
memoist (~> 0.16)
multi_json (~> 1.11)
os (>= 0.9, < 2.0)
signet (>= 0.16, < 2.a)
@@ -202,18 +211,18 @@ GEM
http-cookie (1.0.5)
domain_name (~> 0.5)
httpclient (2.8.3)
i18n (1.10.0)
i18n (1.14.1)
concurrent-ruby (~> 1.0)
jmespath (1.6.2)
json (2.6.3)
jwt (2.7.0)
memoist (0.16.2)
jwt (2.7.1)
mini_magick (4.12.0)
mini_mime (1.1.2)
minitest (5.15.0)
mini_mime (1.1.5)
minitest (5.20.0)
molinillo (0.8.0)
multi_json (1.15.0)
multipart-post (2.0.0)
multipart-post (2.3.0)
mutex_m (0.1.2)
nanaimo (0.3.0)
nap (1.1.0)
naturally (2.2.1)
@@ -222,19 +231,19 @@ GEM
os (1.1.4)
plist (3.7.0)
public_suffix (4.0.7)
rake (13.0.6)
rake (13.1.0)
representable (3.2.0)
declarative (< 0.1.0)
trailblazer-option (>= 0.1.1, < 0.2.0)
uber (< 0.2.0)
retriable (3.1.2)
rexml (3.2.5)
rexml (3.2.6)
rouge (2.0.7)
ruby-macho (2.5.1)
ruby2_keywords (0.0.5)
rubyzip (2.3.2)
security (0.1.3)
signet (0.17.0)
signet (0.18.0)
addressable (~> 2.8)
faraday (>= 0.17.5, < 3.a)
jwt (>= 1.5, < 3.0)
@@ -243,8 +252,8 @@ GEM
CFPropertyList
naturally
terminal-notifier (2.0.0)
terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1)
terminal-table (3.0.2)
unicode-display_width (>= 1.1.1, < 3)
trailblazer-option (0.1.2)
tty-cursor (0.7.1)
tty-screen (0.8.1)
@@ -252,19 +261,19 @@ GEM
tty-cursor (~> 0.7)
typhoeus (1.4.0)
ethon (>= 0.9.0)
tzinfo (2.0.4)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
uber (0.1.0)
unf (0.1.4)
unf_ext
unf_ext (0.0.8.2)
unicode-display_width (1.8.0)
unicode-display_width (2.5.0)
webrick (1.8.1)
word_wrap (1.0.0)
xcode-install (2.8.0)
claide (>= 0.9.1, < 1.1.0)
xcode-install (2.8.1)
claide (>= 0.9.1)
fastlane (>= 2.1.0, < 3.0.0)
xcodeproj (1.22.0)
xcodeproj (1.23.0)
CFPropertyList (>= 2.3.3, < 4.0)
atomos (~> 0.1.3)
claide (>= 1.0.2, < 2.0)
@@ -275,14 +284,13 @@ GEM
rouge (~> 2.0.7)
xcpretty-travis-formatter (1.0.1)
xcpretty (~> 0.2, >= 0.0.7)
zeitwerk (2.5.4)
PLATFORMS
arm64-darwin-21
ruby
DEPENDENCIES
cocoapods (~> 1.11, >= 1.11.3)
cocoapods (~> 1.12)
fastlane
fastlane-plugin-bundletool
xcode-install
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@mipmap/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>
<background android:drawable="@mipmap/ic_launcher_background" />
<foreground android:drawable="@mipmap/ic_launcher_foreground" />
<monochrome android:drawable="@drawable/ic_launcher_monochrome" />
</adaptive-icon>
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="background">#2E2E2E</color>
<color name="background">#000000</color>
</resources>
@@ -25,6 +25,12 @@
};
</script>
<script src="web-src/app.js"></script>
<style>
html,
body {
background-color: black;
}
</style>
</head>
<body>
+3 -9
View File
@@ -1,11 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17156" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="22155" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17125"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22131"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
@@ -17,7 +16,7 @@
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<viewLayoutGuide key="safeArea" id="Bcu-3y-fUS"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
@@ -25,9 +24,4 @@
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
<resources>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
</resources>
</document>
+10 -1
View File
@@ -507,6 +507,11 @@ PODS:
- React-Core
- RNKeychain (8.1.2):
- React-Core
- RNNotifee (7.8.0):
- React-Core
- RNNotifee/NotifeeCore (= 7.8.0)
- RNNotifee/NotifeeCore (7.8.0):
- React-Core
- RNPrivacySnapshot (1.0.0):
- React-Core
- RNShare (9.4.1):
@@ -593,6 +598,7 @@ DEPENDENCIES:
- RNFS (from `../node_modules/react-native-fs`)
- RNIap (from `../node_modules/react-native-iap`)
- RNKeychain (from `../node_modules/react-native-keychain`)
- "RNNotifee (from `../node_modules/@notifee/react-native`)"
- RNPrivacySnapshot (from `../node_modules/react-native-privacy-snapshot`)
- RNShare (from `../node_modules/react-native-share`)
- RNStoreReview (from `../node_modules/react-native-store-review`)
@@ -716,6 +722,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native-iap"
RNKeychain:
:path: "../node_modules/react-native-keychain"
RNNotifee:
:path: "../node_modules/@notifee/react-native"
RNPrivacySnapshot:
:path: "../node_modules/react-native-privacy-snapshot"
RNShare:
@@ -789,6 +797,7 @@ SPEC CHECKSUMS:
RNFS: 4ac0f0ea233904cb798630b3c077808c06931688
RNIap: c397f49db45af3b10dca64b2325f21bb8078ad21
RNKeychain: a65256b6ca6ba6976132cc4124b238a5b13b3d9c
RNNotifee: f3c01b391dd8e98e67f539f9a35a9cbcd3bae744
RNPrivacySnapshot: 8eaf571478a353f2e5184f5c803164f22428b023
RNShare: 32e97adc8d8c97d4a26bcdd3c45516882184f8b6
RNStoreReview: 923b1c888c13469925bf0256dc2c046eab557ce5
@@ -800,4 +809,4 @@ SPEC CHECKSUMS:
PODFILE CHECKSUM: c3b827e3c92cdf3199eddc52083480826e717b88
COCOAPODS: 1.11.3
COCOAPODS: 1.14.2
@@ -991,6 +991,7 @@
OTHER_LDFLAGS = (
"$(inherited)",
" ",
"-Wl -ld_classic ",
);
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos;
@@ -1059,6 +1060,7 @@
OTHER_LDFLAGS = (
"$(inherited)",
" ",
"-Wl -ld_classic ",
);
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos;
@@ -24,14 +24,15 @@
[self clearWebEditorCache];
NSString *CFBundleIdentifier = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIdentifier"];
NSDictionary * initialProperties = @{@"env" : [CFBundleIdentifier isEqualToString:@"com.standardnotes.standardnotes.dev"] ? @"dev" : @"prod"};
self.moduleName = @"StandardNotes";
self.initialProps = @{};
return [super application:application didFinishLaunchingWithOptions:launchOptions];
BOOL success = [super application:application didFinishLaunchingWithOptions:launchOptions];
if (success) {
self.window.rootViewController.view.backgroundColor = [UIColor colorWithWhite:0.0 alpha:1.0];
self.window.backgroundColor = [UIColor colorWithWhite:0.0 alpha:1.0];
}
return success;
}
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
+2 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/mobile",
"version": "3.56.204",
"version": "3.56.237",
"author": "Standard Notes.",
"private": true,
"license": "AGPL-3.0",
@@ -72,6 +72,7 @@
"node": ">=16"
},
"dependencies": {
"@notifee/react-native": "^7.8.0",
"react-native-store-review": "^0.4.1"
}
}
+48 -1
View File
@@ -50,6 +50,7 @@ import { Database } from './Database/Database'
import { isLegacyIdentifier } from './Database/LegacyIdentifier'
import { LegacyKeyValueStore } from './Database/LegacyKeyValueStore'
import Keychain from './Keychain'
import notifee, { AuthorizationStatus, Notification, NotificationSettings } from '@notifee/react-native'
export type BiometricsType = 'Fingerprint' | 'Face ID' | 'Biometrics' | 'Touch ID'
@@ -71,11 +72,57 @@ export class MobileDevice implements MobileDeviceInterface {
private keyValueStore = new LegacyKeyValueStore()
private databases = new Map<string, Database>()
private notificationSettings: NotificationSettings | undefined
constructor(
private stateObserverService?: AppStateObserverService,
private androidBackHandlerService?: AndroidBackHandlerService,
private colorSchemeService?: ColorSchemeObserverService,
) {}
) {
this.initializeNotifications().catch(console.error)
}
async initializeNotifications() {
if (Platform.OS !== 'android') {
return
}
await notifee.createChannel({
id: 'files',
name: 'File Upload/Download',
})
const didAskForPermission = await this.keyValueStore.getValue<boolean>('didAskForNotificationPermission')
if (!didAskForPermission) {
this.notificationSettings = await notifee.requestPermission()
await this.keyValueStore.set('didAskForNotificationPermission', 'true')
}
this.notificationSettings = await notifee.getNotificationSettings()
}
async canDisplayNotifications(): Promise<boolean> {
if (!this.notificationSettings) {
return false
}
return this.notificationSettings.authorizationStatus >= AuthorizationStatus.AUTHORIZED
}
async displayNotification(options: Notification): Promise<string> {
return await notifee.displayNotification({
...options,
android: {
...options.android,
channelId: 'files',
},
})
}
async cancelNotification(notificationId: string): Promise<void> {
await notifee.cancelNotification(notificationId)
}
async removeRawStorageValuesForIdentifier(identifier: string): Promise<void> {
await this.removeRawStorageValue(namespacedKey(identifier, RawStorageKey.SnjsVersion))
+81 -35
View File
@@ -14,6 +14,7 @@ import { MobileDevice, MobileDeviceEvent } from './Lib/MobileDevice'
import { IsDev } from './Lib/Utils'
import { ReceivedSharedItemsHandler } from './ReceivedSharedItemsHandler'
import { ReviewService } from './ReviewService'
import notifee, { EventType } from '@notifee/react-native'
const LoggingEnabled = IsDev
@@ -117,6 +118,34 @@ const MobileWebAppContents = ({ destroyAndReload }: { destroyAndReload: () => vo
}
}, [webViewRef, stateService, device, androidBackHandlerService, colorSchemeService])
useEffect(() => {
return notifee.onForegroundEvent(({ type, detail }) => {
if (type !== EventType.ACTION_PRESS) {
return
}
const { notification, pressAction } = detail
if (!notification || !pressAction) {
return
}
if (pressAction.id !== 'open-file') {
return
}
webViewRef.current?.postMessage(
JSON.stringify({
reactNativeEvent: ReactNativeToWebEvent.OpenFilePreview,
messageType: 'event',
messageData: {
id: notification.id,
},
}),
)
})
}, [])
useEffect(() => {
const observer = device.addMobileDeviceEventReceiver((event) => {
if (event === MobileDeviceEvent.RequestsWebViewReload) {
@@ -242,6 +271,10 @@ const MobileWebAppContents = ({ destroyAndReload }: { destroyAndReload: () => vo
setShowAndroidWebviewUpdatePrompt(true)
return
}
if (message === 'appLoaded') {
setDidLoadEnd(true)
return
}
try {
const functionData = JSON.parse(message)
void onFunctionMessage(functionData.functionName, functionData.messageId, functionData.args)
@@ -308,6 +341,8 @@ const MobileWebAppContents = ({ destroyAndReload }: { destroyAndReload: () => vo
})
}, [device])
const [didLoadEnd, setDidLoadEnd] = useState(false)
if (showAndroidWebviewUpdatePrompt) {
return (
<View
@@ -350,41 +385,52 @@ const MobileWebAppContents = ({ destroyAndReload }: { destroyAndReload: () => vo
}
return (
<WebView
ref={webViewRef}
source={{ uri: sourceUri }}
style={{ backgroundColor: 'black' }}
originWhitelist={['*']}
onError={(err) => console.error('An error has occurred', err)}
onHttpError={() => console.error('An HTTP error occurred')}
onMessage={onMessage}
onContentProcessDidTerminate={() => {
webViewRef.current?.reload()
<View
style={{
flex: 1,
backgroundColor: '#000000',
}}
onRenderProcessGone={() => {
webViewRef.current?.reload()
}}
hideKeyboardAccessoryView={true}
onShouldStartLoadWithRequest={onShouldStartLoadWithRequest}
allowFileAccess={true}
allowUniversalAccessFromFileURLs={true}
injectedJavaScriptBeforeContentLoaded={injectedJS}
bounces={false}
keyboardDisplayRequiresUserAction={false}
allowsInlineMediaPlayback={requireInlineMediaPlaybackForMomentsFeature}
mediaPlaybackRequiresUserAction={requireMediaUserInteractionForMomentsFeature}
scalesPageToFit={true}
/**
* This disables the global window scroll but keeps scroll within div elements like lists and textareas.
* This is needed to prevent the keyboard from pushing the webview up and down when it appears and disappears.
*/
scrollEnabled={false}
overScrollMode="never"
nativeConfig={Platform.select({
android: {
component: CustomAndroidWebView,
} as WebViewNativeConfig,
})}
/>
>
<WebView
ref={webViewRef}
source={{ uri: sourceUri }}
style={{
backgroundColor: Platform.OS === 'ios' ? 'transparent' : '#000000',
opacity: didLoadEnd ? 1 : 0,
}}
originWhitelist={['*']}
onError={(err) => console.error('An error has occurred', err)}
onHttpError={() => console.error('An HTTP error occurred')}
onMessage={onMessage}
onContentProcessDidTerminate={() => {
webViewRef.current?.reload()
}}
onRenderProcessGone={() => {
webViewRef.current?.reload()
}}
hideKeyboardAccessoryView={true}
onShouldStartLoadWithRequest={onShouldStartLoadWithRequest}
allowFileAccess={true}
allowUniversalAccessFromFileURLs={true}
injectedJavaScriptBeforeContentLoaded={injectedJS}
bounces={false}
keyboardDisplayRequiresUserAction={false}
allowsInlineMediaPlayback={requireInlineMediaPlaybackForMomentsFeature}
mediaPlaybackRequiresUserAction={requireMediaUserInteractionForMomentsFeature}
scalesPageToFit={true}
/**
* This disables the global window scroll but keeps scroll within div elements like lists and textareas.
* This is needed to prevent the keyboard from pushing the webview up and down when it appears and disappears.
*/
scrollEnabled={false}
overScrollMode="never"
nativeConfig={Platform.select({
android: {
component: CustomAndroidWebView,
} as WebViewNativeConfig,
})}
webviewDebuggingEnabled
/>
</View>
)
}
+6
View File
@@ -3,6 +3,12 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [1.49.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
### Features
* When exporting a Super note, embedded files can be inlined in the note or exported along the note in a zip file. You can now also choose to include frontmatter when exporting to Markdown format. ([991de1d](https://github.com/standardnotes/app/commit/991de1ddf5dbb1016348d603d244699c676d9b5f)), closes [#2610](https://github.com/standardnotes/app/issues/2610)
## [1.48.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-26)
**Note:** Version bump only for package @standardnotes/models
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/models",
"version": "1.48.1",
"version": "1.49.0",
"publishConfig": {
"access": "public"
},
@@ -40,6 +40,8 @@ export const PrefDefaults = {
[PrefKey.ClipperDefaultTagUuid]: undefined,
[PrefKey.DefaultEditorIdentifier]: NativeFeatureIdentifier.TYPES.PlainEditor,
[PrefKey.SuperNoteExportFormat]: 'json',
[PrefKey.SuperNoteExportEmbedBehavior]: 'reference',
[PrefKey.SuperNoteExportUseMDFrontmatter]: true,
[PrefKey.SystemViewPreferences]: {},
[PrefKey.AuthenticatorNames]: '',
[PrefKey.ComponentPreferences]: {},
@@ -41,6 +41,8 @@ export enum PrefKey {
ClipperDefaultTagUuid = 'clipperDefaultTagUuid',
SystemViewPreferences = 'systemViewPreferences',
SuperNoteExportFormat = 'superNoteExportFormat',
SuperNoteExportEmbedBehavior = 'superNoteExportEmbedBehavior',
SuperNoteExportUseMDFrontmatter = 'superNoteExportUseMDFrontmatter',
AuthenticatorNames = 'authenticatorNames',
PaneGesturesEnabled = 'paneGesturesEnabled',
ComponentPreferences = 'componentPreferences',
@@ -83,6 +85,8 @@ export type PrefValue = {
[PrefKey.ClipperDefaultTagUuid]: string | undefined
[PrefKey.SystemViewPreferences]: Partial<Record<SystemViewId, TagPreferences>>
[PrefKey.SuperNoteExportFormat]: 'json' | 'md' | 'html'
[PrefKey.SuperNoteExportEmbedBehavior]: 'reference' | 'inline' | 'separate'
[PrefKey.SuperNoteExportUseMDFrontmatter]: boolean
[PrefKey.AuthenticatorNames]: string
[PrefKey.PaneGesturesEnabled]: boolean
[PrefKey.ComponentPreferences]: AllComponentPreferences
+132
View File
@@ -3,6 +3,138 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.4.612](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-11)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.611](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-09)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.610](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-09)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.609](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-09)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.608](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-08)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.607](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-08)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.606](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-07)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.605](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-06)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.604](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-06)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.603](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-06)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.602](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-04)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.601](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-03)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.600](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-03)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.599](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-02)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.598](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-02)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.597](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-02)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.596](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-02)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.595](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-01)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.594](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-01)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.593](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-01)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.592](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-01)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.591](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.590](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.589](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.588](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.587](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.586](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.585](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.584](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.583](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-29)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.582](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-29)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.581](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-29)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.580](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-28)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.579](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-27)
**Note:** Version bump only for package @standardnotes/releases
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/releases",
"version": "1.4.579",
"version": "1.4.612",
"license": "AGPL-3.0",
"main": "dist/releases.json",
"types": "dist/index.d.ts",
+18
View File
@@ -3,6 +3,24 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.65.3](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-08)
**Note:** Version bump only for package @standardnotes/services
## [1.65.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-04)
**Note:** Version bump only for package @standardnotes/services
## [1.65.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-03)
**Note:** Version bump only for package @standardnotes/services
# [1.65.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
### Features
* When exporting a Super note, embedded files can be inlined in the note or exported along the note in a zip file. You can now also choose to include frontmatter when exporting to Markdown format. ([991de1d](https://github.com/standardnotes/app/commit/991de1ddf5dbb1016348d603d244699c676d9b5f)), closes [#2610](https://github.com/standardnotes/app/issues/2610)
## [1.64.38](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-26)
**Note:** Version bump only for package @standardnotes/services
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/services",
"version": "1.64.38",
"version": "1.65.3",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
@@ -462,7 +462,7 @@ export class FilesBackupService
const tagNames = tags.map((tag) => this.items.getTagLongTitle(tag))
const text =
note.noteType === NoteType.Super
? this.markdownConverter.convertSuperStringToOtherFormat(note.text, 'md')
? await this.markdownConverter.convertSuperStringToOtherFormat(note.text, 'md')
: note.text
await this.device.savePlaintextNoteBackup(location, note.uuid, note.title, tagNames, text)
}
@@ -5,6 +5,8 @@ import { DeviceInterface } from './DeviceInterface'
import { AppleIAPReceipt } from '../Subscription/AppleIAPReceipt'
import { ApplicationEvent } from '../Event/ApplicationEvent'
import type { Notification } from '../../../../mobile/node_modules/@notifee/react-native/dist/index'
export interface MobileDeviceInterface extends DeviceInterface {
environment: Environment.Mobile
platform: Platform.Ios | Platform.Android
@@ -34,4 +36,8 @@ export interface MobileDeviceInterface extends DeviceInterface {
purchaseSubscriptionIAP(plan: AppleIAPProductId): Promise<AppleIAPReceipt | undefined>
authenticateWithU2F(authenticationOptionsJSONString: string): Promise<Record<string, unknown> | null>
notifyApplicationEvent(event: ApplicationEvent): void
canDisplayNotifications(): Promise<boolean>
displayNotification(options: Notification): Promise<string>
cancelNotification(notificationId: string): Promise<void>
}
@@ -3,7 +3,7 @@ import { ComponentInterface, DecryptedItemInterface } from '@standardnotes/model
import { FeatureStatus } from './FeatureStatus'
import { SetOfflineFeaturesFunctionResponse } from './SetOfflineFeaturesFunctionResponse'
import { NativeFeatureIdentifier } from '@standardnotes/features'
import { Uuid } from '@standardnotes/domain-core'
import { RoleName, Uuid } from '@standardnotes/domain-core'
export interface FeaturesClientInterface {
getFeatureStatus(
@@ -11,7 +11,7 @@ export interface FeaturesClientInterface {
options?: { inContextOfItem?: DecryptedItemInterface },
): FeatureStatus
hasMinimumRole(role: string): boolean
hasRole(roleName: RoleName): boolean
hasFirstPartyOfflineSubscription(): boolean
setOfflineFeaturesCode(code: string): Promise<SetOfflineFeaturesFunctionResponse>
hasOfflineRepo(): boolean
+24
View File
@@ -3,6 +3,30 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [2.202.109](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-08)
**Note:** Version bump only for package @standardnotes/snjs
## [2.202.108](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-06)
**Note:** Version bump only for package @standardnotes/snjs
## [2.202.107](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-04)
**Note:** Version bump only for package @standardnotes/snjs
## [2.202.106](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-03)
**Note:** Version bump only for package @standardnotes/snjs
## [2.202.105](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-02)
**Note:** Version bump only for package @standardnotes/snjs
## [2.202.104](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
**Note:** Version bump only for package @standardnotes/snjs
## [2.202.103](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-26)
**Note:** Version bump only for package @standardnotes/snjs
@@ -12,4 +12,5 @@ export enum ReactNativeToWebEvent {
ReceivedFile = 'ReceivedFile',
ReceivedLink = 'ReceivedLink',
ReceivedText = 'ReceivedText',
OpenFilePreview = 'OpenFilePreview',
}
@@ -412,6 +412,10 @@ export class FeaturesService
return Object.values(RoleName.NAMES).filter((role) => roles.includes(role))
}
hasRole(roleName: RoleName): boolean {
return this.onlineRoles.includes(roleName.value) || this.offlineRoles.includes(roleName.value)
}
public hasMinimumRole(role: string): boolean {
const sortedAllRoles = Object.values(RoleName.NAMES)
@@ -197,7 +197,9 @@ export class SessionManager
this.apiService.setSession(session, persist)
void this.webSocketsService.startWebSocketConnection()
if (this.isSignedIntoFirstPartyServer()) {
void this.webSocketsService.startWebSocketConnection()
}
}
public online() {
+3 -3
View File
@@ -112,7 +112,7 @@ describe('files', function () {
it('should encrypt and upload small file', async function () {
await setup({ fakeCrypto: false, subscription: true })
const response = await fetch('/packages/snjs/mocha/assets/small_file.md')
const response = await fetch('/mocha/assets/small_file.md')
const buffer = new Uint8Array(await response.arrayBuffer())
const file = await Files.uploadFile(fileService, buffer, 'my-file', 'md', 1000)
@@ -125,7 +125,7 @@ describe('files', function () {
it('should encrypt and upload big file', async function () {
await setup({ fakeCrypto: false, subscription: true })
const response = await fetch('/packages/snjs/mocha/assets/two_mb_file.md')
const response = await fetch('/mocha/assets/two_mb_file.md')
const buffer = new Uint8Array(await response.arrayBuffer())
const file = await Files.uploadFile(fileService, buffer, 'my-file', 'md', 100000)
@@ -138,7 +138,7 @@ describe('files', function () {
it('should delete file', async function () {
await setup({ fakeCrypto: false, subscription: true })
const response = await fetch('/packages/snjs/mocha/assets/small_file.md')
const response = await fetch('/mocha/assets/small_file.md')
const buffer = new Uint8Array(await response.arrayBuffer())
const file = await Files.uploadFile(fileService, buffer, 'my-file', 'md', 1000)
+4 -4
View File
@@ -147,7 +147,7 @@ describe('settings service', function () {
await context.activatePaidSubscriptionForUser()
const response = await fetch('/packages/snjs/mocha/assets/small_file.md')
const response = await fetch('/mocha/assets/small_file.md')
const buffer = new Uint8Array(await response.arrayBuffer())
await Files.uploadFile(application.files, buffer, 'my-file', 'md', 1000)
@@ -161,7 +161,7 @@ describe('settings service', function () {
const usedSettingBefore = await application.settings.getSubscriptionSetting(
SettingName.create(SettingName.NAMES.FileUploadBytesUsed).getValue(),
)
expect(usedSettingBefore).to.equal('196')
expect(usedSettingBefore).to.equal('1374')
await context.activatePaidSubscriptionForUser({
cancelPreviousSubscription: true,
@@ -181,7 +181,7 @@ describe('settings service', function () {
)
expect(usedSettingAfter).to.equal(usedSettingBefore)
const afterResponse = await fetch('/packages/snjs/mocha/assets/small_file.md')
const afterResponse = await fetch('/mocha/assets/small_file.md')
const afterBuffer = new Uint8Array(await afterResponse.arrayBuffer())
await Files.uploadFile(application.files, afterBuffer, 'my-file', 'md', 1000)
@@ -196,6 +196,6 @@ describe('settings service', function () {
const usedSettingAfterSecondUpload = await application.settings.getSubscriptionSetting(
SettingName.create(SettingName.NAMES.FileUploadBytesUsed).getValue(),
)
expect(usedSettingAfterSecondUpload).to.equal('392')
expect(usedSettingAfterSecondUpload).to.equal('2748')
})
})
@@ -572,6 +572,39 @@ describe('online syncing', function () {
expect(rawPayloads.length).to.equal(expectedItemCount)
}).timeout(Factory.SixtySecondTimeout)
it('should sync all items including ones that are breaching transfer limit', async function () {
const response = await fetch('/mocha/assets/small_file.md')
const buffer = new Uint8Array(await response.arrayBuffer())
const numberOfNotesToExceedThe1MBTransferLimit = 80
const testContext = await Factory.createAppContextWithFakeCrypto()
await testContext.launch()
await testContext.register()
const email = testContext.email
const password = testContext.password
for (let i = 0; i < numberOfNotesToExceedThe1MBTransferLimit; i++) {
await testContext.createSyncedNote(`note ${i}`, buffer.toString())
await testContext.sync()
}
await testContext.deinit()
const secondContext = await Factory.createAppContextWithFakeCrypto(Math.random(), email, password)
await secondContext.launch()
const firstSyncPromise = secondContext.awaitNextSyncEvent(SyncEvent.PaginatedSyncRequestCompleted)
await secondContext.signIn()
const firstSyncResult = await firstSyncPromise
expect(firstSyncResult.retrievedPayloads.length > 0).to.be.true
expect(firstSyncResult.retrievedPayloads.length < numberOfNotesToExceedThe1MBTransferLimit).to.be.true
expect(firstSyncResult.successResponseData.cursor_token).not.to.be.undefined
expect(secondContext.noteCount).to.equal(numberOfNotesToExceedThe1MBTransferLimit)
await secondContext.deinit()
}).timeout(Factory.SixtySecondTimeout)
it('syncing an item should storage it encrypted', async function () {
const note = await Factory.createMappedNote(application)
await application.mutator.setItemDirty(note)
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/snjs",
"version": "2.202.103",
"version": "2.202.109",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
+36
View File
@@ -3,6 +3,42 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.34.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-08)
**Note:** Version bump only for package @standardnotes/ui-services
## [1.34.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-07)
### Bug Fixes
* Fixed issue where non-image inlined files would not correctly be imported from a Markdown file ([8941675](https://github.com/standardnotes/app/commit/894167520dc829b72f721bdf63acc6038ff8816f))
# [1.34.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-06)
### Features
* Importing markdown files from the Import dialog will now automatically use Super notes ([3bf670e](https://github.com/standardnotes/app/commit/3bf670ece754df3f452a3ae305830c772687d36a))
## [1.33.3](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-04)
**Note:** Version bump only for package @standardnotes/ui-services
## [1.33.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-03)
**Note:** Version bump only for package @standardnotes/ui-services
## [1.33.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)
### Bug Fixes
* Fixed issue where exporting multiple files with the same name would error ([f408950](https://github.com/standardnotes/app/commit/f408950aa4e59389db81a4ca2b9db5ea49147aaf))
# [1.33.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
### Features
* When exporting a Super note, embedded files can be inlined in the note or exported along the note in a zip file. You can now also choose to include frontmatter when exporting to Markdown format. ([991de1d](https://github.com/standardnotes/app/commit/991de1ddf5dbb1016348d603d244699c676d9b5f)), closes [#2610](https://github.com/standardnotes/app/issues/2610)
## [1.32.7](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-26)
**Note:** Version bump only for package @standardnotes/ui-services
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/ui-services",
"version": "1.32.7",
"version": "1.34.2",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
@@ -19,6 +19,11 @@ function zippableFileName(name: string, suffix = '', format = 'txt'): string {
return sanitizedName.slice(0, maxFileNameLength - nameEnd.length) + nameEnd
}
export function parseAndCreateZippableFileName(name: string, suffix = '') {
const { name: parsedName, ext } = parseFileName(name)
return zippableFileName(parsedName, suffix, ext)
}
type ZippableData = {
name: string
content: Blob
@@ -3,7 +3,7 @@
*/
import { ContentType } from '@standardnotes/domain-core'
import { DecryptedTransferPayload, NoteContent, TagContent } from '@standardnotes/models'
import { DecryptedTransferPayload, FileItem, NoteContent, TagContent } from '@standardnotes/models'
import { EvernoteConverter, EvernoteResource } from './EvernoteConverter'
import { createTestResourceElement, enex, enexWithNoNoteOrTag } from './testData'
import { PureCryptoInterface } from '@standardnotes/sncrypto-common'
@@ -31,7 +31,14 @@ describe('EvernoteConverter', () => {
const superConverterService: SuperConverterServiceInterface = {
isValidSuperString: () => true,
convertOtherFormatToSuperString: (data: string) => data,
convertSuperStringToOtherFormat: (data: string) => data,
convertSuperStringToOtherFormat: async (data: string) => data,
getEmbeddedFileIDsFromSuperString: () => [],
uploadAndReplaceInlineFilesInSuperString: async (
superString: string,
_uploadFile: (file: File) => Promise<FileItem | undefined>,
_linkFile: (file: FileItem) => Promise<void>,
_generateUuid: GenerateUuid,
) => superString,
}
const generateUuid = new GenerateUuid(crypto)
@@ -6,7 +6,7 @@ import { jsonTextContentData, htmlTestData, jsonListContentData } from './testDa
import { GoogleKeepConverter } from './GoogleKeepConverter'
import { PureCryptoInterface } from '@standardnotes/sncrypto-common'
import { GenerateUuid } from '@standardnotes/services'
import { SuperConverterServiceInterface } from '@standardnotes/snjs'
import { FileItem, SuperConverterServiceInterface } from '@standardnotes/snjs'
describe('GoogleKeepConverter', () => {
const crypto = {
@@ -16,7 +16,14 @@ describe('GoogleKeepConverter', () => {
const superConverterService: SuperConverterServiceInterface = {
isValidSuperString: () => true,
convertOtherFormatToSuperString: (data: string) => data,
convertSuperStringToOtherFormat: (data: string) => data,
convertSuperStringToOtherFormat: async (data: string) => data,
getEmbeddedFileIDsFromSuperString: () => [],
uploadAndReplaceInlineFilesInSuperString: async (
superString: string,
_uploadFile: (file: File) => Promise<FileItem | undefined>,
_linkFile: (file: FileItem) => Promise<void>,
_generateUuid: GenerateUuid,
) => superString,
}
const generateUuid = new GenerateUuid(crypto)
+53 -5
View File
@@ -6,14 +6,23 @@ import {
ItemManagerInterface,
MutatorClientInterface,
} from '@standardnotes/services'
import { NativeFeatureIdentifier } from '@standardnotes/features'
import { NativeFeatureIdentifier, NoteType } from '@standardnotes/features'
import { AegisToAuthenticatorConverter } from './AegisConverter/AegisToAuthenticatorConverter'
import { EvernoteConverter } from './EvernoteConverter/EvernoteConverter'
import { GoogleKeepConverter } from './GoogleKeepConverter/GoogleKeepConverter'
import { PlaintextConverter } from './PlaintextConverter/PlaintextConverter'
import { SimplenoteConverter } from './SimplenoteConverter/SimplenoteConverter'
import { readFileAsText } from './Utils'
import { DecryptedTransferPayload, NoteContent } from '@standardnotes/models'
import {
DecryptedItemInterface,
DecryptedTransferPayload,
FileItem,
ItemContent,
NoteContent,
NoteMutator,
SNNote,
isNote,
} from '@standardnotes/models'
import { HTMLConverter } from './HTMLConverter/HTMLConverter'
import { SuperConverterServiceInterface } from '@standardnotes/snjs/dist/@types'
import { SuperConverter } from './SuperConverter/SuperConverter'
@@ -34,12 +43,27 @@ export class Importer {
private mutator: MutatorClientInterface,
private items: ItemManagerInterface,
private superConverterService: SuperConverterServiceInterface,
_generateUuid: GenerateUuid,
private filesController: {
uploadNewFile(
fileOrHandle: File | FileSystemFileHandle,
options?: {
showToast?: boolean
note?: SNNote
},
): Promise<FileItem | undefined>
},
private linkingController: {
linkItems(
item: DecryptedItemInterface<ItemContent>,
itemToLink: DecryptedItemInterface<ItemContent>,
): Promise<void>
},
private _generateUuid: GenerateUuid,
) {
this.aegisConverter = new AegisToAuthenticatorConverter(_generateUuid)
this.googleKeepConverter = new GoogleKeepConverter(this.superConverterService, _generateUuid)
this.simplenoteConverter = new SimplenoteConverter(_generateUuid)
this.plaintextConverter = new PlaintextConverter(_generateUuid)
this.plaintextConverter = new PlaintextConverter(this.superConverterService, _generateUuid)
this.evernoteConverter = new EvernoteConverter(this.superConverterService, _generateUuid)
this.htmlConverter = new HTMLConverter(this.superConverterService, _generateUuid)
this.superConverter = new SuperConverter(this.superConverterService, _generateUuid)
@@ -110,7 +134,7 @@ export class Importer {
} else if (type === 'evernote') {
return await this.evernoteConverter.convertENEXFileToNotesAndTags(file, isEntitledToSuper)
} else if (type === 'plaintext') {
return [await this.plaintextConverter.convertPlaintextFileToNote(file)]
return [await this.plaintextConverter.convertPlaintextFileToNote(file, isEntitledToSuper)]
} else if (type === 'html') {
return [await this.htmlConverter.convertHTMLFileToNote(file, isEntitledToSuper)]
}
@@ -142,4 +166,28 @@ export class Importer {
)
return insertedItems
}
async uploadAndReplaceInlineFilesInInsertedItems(insertedItems: DecryptedItemInterface<ItemContent>[]) {
for (const item of insertedItems) {
if (!isNote(item)) {
continue
}
if (item.noteType !== NoteType.Super) {
continue
}
try {
const text = await this.superConverterService.uploadAndReplaceInlineFilesInSuperString(
item.text,
async (file) => await this.filesController.uploadNewFile(file, { showToast: true, note: item }),
async (file) => await this.linkingController.linkItems(item, file),
this._generateUuid,
)
await this.mutator.changeItem<NoteMutator>(item, (mutator) => {
mutator.text = text
})
} catch (error) {
console.error(error)
}
}
}
}
@@ -3,15 +3,23 @@ import { parseFileName } from '@standardnotes/filepicker'
import { DecryptedTransferPayload, NoteContent } from '@standardnotes/models'
import { readFileAsText } from '../Utils'
import { GenerateUuid } from '@standardnotes/services'
import { SuperConverterServiceInterface } from '@standardnotes/files'
import { NativeFeatureIdentifier, NoteType } from '@standardnotes/features'
export class PlaintextConverter {
constructor(private _generateUuid: GenerateUuid) {}
constructor(
private superConverterService: SuperConverterServiceInterface,
private _generateUuid: GenerateUuid,
) {}
static isValidPlaintextFile(file: File): boolean {
return file.type === 'text/plain' || file.type === 'text/markdown'
}
async convertPlaintextFileToNote(file: File): Promise<DecryptedTransferPayload<NoteContent>> {
async convertPlaintextFileToNote(
file: File,
isEntitledToSuper: boolean,
): Promise<DecryptedTransferPayload<NoteContent>> {
const content = await readFileAsText(file)
const { name } = parseFileName(file.name)
@@ -19,6 +27,8 @@ export class PlaintextConverter {
const createdAtDate = file.lastModified ? new Date(file.lastModified) : new Date()
const updatedAtDate = file.lastModified ? new Date(file.lastModified) : new Date()
const shouldConvertToSuper = file.type === 'text/markdown' && isEntitledToSuper
return {
created_at: createdAtDate,
created_at_timestamp: createdAtDate.getTime(),
@@ -28,8 +38,16 @@ export class PlaintextConverter {
content_type: ContentType.TYPES.Note,
content: {
title: name,
text: content,
text: shouldConvertToSuper
? this.superConverterService.convertOtherFormatToSuperString(content, 'md')
: content,
references: [],
...(isEntitledToSuper
? {
noteType: NoteType.Super,
editorIdentifier: NativeFeatureIdentifier.TYPES.SuperEditor,
}
: {}),
},
}
}
@@ -36,7 +36,6 @@ export const SUPER_SHOW_MARKDOWN_PREVIEW = createKeyboardCommand('SUPER_SHOW_MAR
export const SUPER_EXPORT_JSON = createKeyboardCommand('SUPER_EXPORT_JSON')
export const SUPER_EXPORT_MARKDOWN = createKeyboardCommand('SUPER_EXPORT_MARKDOWN')
export const SUPER_EXPORT_HTML = createKeyboardCommand('SUPER_EXPORT_HTML')
export const OPEN_PREFERENCES_COMMAND = createKeyboardCommand('OPEN_PREFERENCES_COMMAND')
export const CHANGE_EDITOR_WIDTH_COMMAND = createKeyboardCommand('CHANGE_EDITOR_WIDTH_COMMAND')
@@ -24,6 +24,7 @@ export interface WebApplicationInterface extends ApplicationInterface {
handleReceivedFileEvent(file: { name: string; mimeType: string; data: string }): void
handleReceivedTextEvent(item: { text: string; title?: string }): Promise<void>
handleReceivedLinkEvent(item: { link: string; title: string }): Promise<void>
handleOpenFilePreviewEvent(item: { id: string }): void
isNativeMobileWeb(): boolean
handleAndroidBackButtonPressed(): void
addAndroidBackHandlerEventListener(listener: () => boolean): (() => void) | undefined
+132
View File
@@ -3,6 +3,138 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [3.181.24](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-11)
**Note:** Version bump only for package @standardnotes/web
## [3.181.23](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-09)
**Note:** Version bump only for package @standardnotes/web
## [3.181.22](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-09)
**Note:** Version bump only for package @standardnotes/web
## [3.181.21](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-09)
**Note:** Version bump only for package @standardnotes/web
## [3.181.20](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-08)
**Note:** Version bump only for package @standardnotes/web
## [3.181.19](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-07)
### Bug Fixes
* Fixed issue where non-image inlined files would not correctly be imported from a Markdown file ([8941675](https://github.com/standardnotes/app/commit/894167520dc829b72f721bdf63acc6038ff8816f))
## [3.181.18](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-06)
**Note:** Version bump only for package @standardnotes/web
## [3.181.17](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-06)
**Note:** Version bump only for package @standardnotes/web
## [3.181.16](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-06)
**Note:** Version bump only for package @standardnotes/web
## [3.181.15](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-04)
**Note:** Version bump only for package @standardnotes/web
## [3.181.14](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-03)
**Note:** Version bump only for package @standardnotes/web
## [3.181.13](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-03)
**Note:** Version bump only for package @standardnotes/web
## [3.181.12](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-02)
**Note:** Version bump only for package @standardnotes/web
## [3.181.11](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-02)
**Note:** Version bump only for package @standardnotes/web
## [3.181.10](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-02)
**Note:** Version bump only for package @standardnotes/web
## [3.181.9](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-02)
**Note:** Version bump only for package @standardnotes/web
## [3.181.8](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-01)
**Note:** Version bump only for package @standardnotes/web
## [3.181.7](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-01)
**Note:** Version bump only for package @standardnotes/web
## [3.181.6](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-01)
**Note:** Version bump only for package @standardnotes/web
## [3.181.5](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)
**Note:** Version bump only for package @standardnotes/web
## [3.181.4](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)
### Bug Fixes
* Fixed issue where exporting multiple files with the same name would error ([f408950](https://github.com/standardnotes/app/commit/f408950aa4e59389db81a4ca2b9db5ea49147aaf))
## [3.181.3](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)
### Bug Fixes
* Fixed issue where a brief flash of white would appear when starting the app on mobile ([572c9b7](https://github.com/standardnotes/app/commit/572c9b7dfaa42773c050772940e383df2940a79f))
## [3.181.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)
**Note:** Version bump only for package @standardnotes/web
## [3.181.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
**Note:** Version bump only for package @standardnotes/web
# [3.181.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
### Features
* When exporting a Super note, embedded files can be inlined in the note or exported along the note in a zip file. You can now also choose to include frontmatter when exporting to Markdown format.
## [3.180.8](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
**Note:** Version bump only for package @standardnotes/web
## [3.180.7](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-29)
### Bug Fixes
* Fixed issue with checklist items in Super notes not being correctly exported to HTML ([198efdc](https://github.com/standardnotes/app/commit/198efdc41c403ce10a40fc2f20345d5b44c83462))
## [3.180.6](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-29)
**Note:** Version bump only for package @standardnotes/web
## [3.180.5](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-29)
**Note:** Version bump only for package @standardnotes/web
## [3.180.4](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-28)
### Bug Fixes
* Fixed check list indentation in Super notes ([ce0db04](https://github.com/standardnotes/app/commit/ce0db04646737ec1dcb88ac989cd12927c46a156))
## [3.180.3](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-27)
**Note:** Version bump only for package @standardnotes/web
+348
View File
@@ -1,5 +1,353 @@
{
"versions": [
{
"version": "3.181.24",
"title": "[3.181.24](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-11)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.181.23",
"title": "[3.181.23](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-09)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.181.22",
"title": "[3.181.22](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-09)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.181.21",
"title": "[3.181.21](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-09)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.181.20",
"title": "[3.181.20](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-08)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.181.19",
"title": "[3.181.19](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-07)",
"date": null,
"body": "### Bug Fixes\n\n* Fixed issue where non-image inlined files would not correctly be imported from a Markdown file ([8941675](https://github.com/standardnotes/app/commit/894167520dc829b72f721bdf63acc6038ff8816f))",
"parsed": {
"_": [
"Fixed issue where non-image inlined files would not correctly be imported from a Markdown file (8941675)"
],
"Bug Fixes": [
"Fixed issue where non-image inlined files would not correctly be imported from a Markdown file (8941675)"
]
}
},
{
"version": "3.181.18",
"title": "[3.181.18](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-06)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.181.17",
"title": "[3.181.17](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-06)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.181.16",
"title": "[3.181.16](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-06)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.181.15",
"title": "[3.181.15](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-04)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.181.14",
"title": "[3.181.14](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-03)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.181.13",
"title": "[3.181.13](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-03)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.181.12",
"title": "[3.181.12](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-02)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.181.11",
"title": "[3.181.11](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-02)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.181.10",
"title": "[3.181.10](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-02)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.181.9",
"title": "[3.181.9](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-02)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.181.8",
"title": "[3.181.8](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-01)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.181.7",
"title": "[3.181.7](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-01)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.181.6",
"title": "[3.181.6](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-11-01)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.181.5",
"title": "[3.181.5](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.181.4",
"title": "[3.181.4](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)",
"date": null,
"body": "### Bug Fixes\n\n* Fixed issue where exporting multiple files with the same name would error ([f408950](https://github.com/standardnotes/app/commit/f408950aa4e59389db81a4ca2b9db5ea49147aaf))",
"parsed": {
"_": [
"Fixed issue where exporting multiple files with the same name would error (f408950)"
],
"Bug Fixes": [
"Fixed issue where exporting multiple files with the same name would error (f408950)"
]
}
},
{
"version": "3.181.3",
"title": "[3.181.3](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)",
"date": null,
"body": "### Bug Fixes\n\n* Fixed issue where a brief flash of white would appear when starting the app on mobile ([572c9b7](https://github.com/standardnotes/app/commit/572c9b7dfaa42773c050772940e383df2940a79f))",
"parsed": {
"_": [
"Fixed issue where a brief flash of white would appear when starting the app on mobile (572c9b7)"
],
"Bug Fixes": [
"Fixed issue where a brief flash of white would appear when starting the app on mobile (572c9b7)"
]
}
},
{
"version": "3.181.2",
"title": "[3.181.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.181.1",
"title": "[3.181.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.181.0",
"title": "[3.181.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)",
"date": null,
"body": "### Features\n\n* When exporting a Super note, embedded files can be inlined in the note or exported along the note in a zip file. You can now also choose to include frontmatter when exporting to Markdown format.",
"parsed": {
"_": [
"When exporting a Super note, embedded files can be inlined in the note or exported along the note in a zip file. You can now also choose to include frontmatter when exporting to Markdown format."
],
"Features": [
"When exporting a Super note, embedded files can be inlined in the note or exported along the note in a zip file. You can now also choose to include frontmatter when exporting to Markdown format."
]
}
},
{
"version": "3.180.8",
"title": "[3.180.8](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.180.7",
"title": "[3.180.7](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-29)",
"date": null,
"body": "### Bug Fixes\n\n* Fixed issue with checklist items in Super notes not being correctly exported to HTML ([198efdc](https://github.com/standardnotes/app/commit/198efdc41c403ce10a40fc2f20345d5b44c83462))",
"parsed": {
"_": [
"Fixed issue with checklist items in Super notes not being correctly exported to HTML (198efdc)"
],
"Bug Fixes": [
"Fixed issue with checklist items in Super notes not being correctly exported to HTML (198efdc)"
]
}
},
{
"version": "3.180.6",
"title": "[3.180.6](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-29)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.180.5",
"title": "[3.180.5](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-29)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.180.4",
"title": "[3.180.4](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-28)",
"date": null,
"body": "### Bug Fixes\n\n* Fixed check list indentation in Super notes ([ce0db04](https://github.com/standardnotes/app/commit/ce0db04646737ec1dcb88ac989cd12927c46a156))",
"parsed": {
"_": [
"Fixed check list indentation in Super notes (ce0db04)"
],
"Bug Fixes": [
"Fixed check list indentation in Super notes (ce0db04)"
]
}
},
{
"version": "3.180.3",
"title": "[3.180.3](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-27)",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/web",
"version": "3.180.3",
"version": "3.181.24",
"license": "AGPL-3.0",
"main": "dist/app.js",
"author": "Standard Notes.",
+7
View File
@@ -16,6 +16,9 @@ declare global {
webClient?: DesktopManagerInterface
electronRemoteBridge?: unknown
reactNativeDevice?: WebDevice
ReactNativeWebView?: {
postMessage: (message: string) => void
}
platform?: Platform
isClipper?: boolean
@@ -91,6 +94,10 @@ const startApplication: StartApplication = async function startApplication(
onDestroy={onDestroy}
/>,
)
if (window.ReactNativeWebView) {
window.ReactNativeWebView.postMessage('appLoaded')
}
}
const domReady = document.readyState === 'complete' || document.readyState === 'interactive'
@@ -34,7 +34,7 @@ import { SubscriptionController } from '@/Controllers/Subscription/SubscriptionC
import { PurchaseFlowController } from '@/Controllers/PurchaseFlow/PurchaseFlowController'
import { FilesController } from '@/Controllers/FilesController'
import { HistoryModalController } from '@/Controllers/NoteHistory/HistoryModalController'
import { ImportModalController } from '@/Controllers/ImportModalController'
import { ImportModalController } from '@/Components/ImportModal/ImportModalController'
import { ApplicationEventObserver } from '@/Event/ApplicationEventObserver'
import { SearchOptionsController } from '@/Controllers/SearchOptionsController'
import { LinkingController } from '@/Controllers/LinkingController'
@@ -64,6 +64,8 @@ export class WebDependencies extends DependencyContainer {
application.mutator,
application.items,
this.get<HeadlessSuperConverter>(Web_TYPES.SuperConverter),
this.get<FilesController>(Web_TYPES.FilesController),
this.get<LinkingController>(Web_TYPES.LinkingController),
application.generateUuid,
)
})
@@ -22,6 +22,7 @@ import {
NoteContent,
SNNote,
DesktopManagerInterface,
FileItem,
} from '@standardnotes/snjs'
import { action, computed, makeObservable, observable } from 'mobx'
import { startAuthentication, startRegistration } from '@simplewebauthn/browser'
@@ -65,7 +66,7 @@ import { PurchaseFlowController } from '@/Controllers/PurchaseFlow/PurchaseFlowC
import { AccountMenuController } from '@/Controllers/AccountMenu/AccountMenuController'
import { PreferencesController } from '@/Controllers/PreferencesController'
import { NotesController } from '@/Controllers/NotesController/NotesController'
import { ImportModalController } from '@/Controllers/ImportModalController'
import { ImportModalController } from '@/Components/ImportModal/ImportModalController'
import { SyncStatusController } from '@/Controllers/SyncStatusController'
import { HistoryModalController } from '@/Controllers/NoteHistory/HistoryModalController'
import { NavigationController } from '@/Controllers/Navigation/NavigationController'
@@ -76,6 +77,7 @@ import { NoAccountWarningController } from '@/Controllers/NoAccountWarningContro
import { SearchOptionsController } from '@/Controllers/SearchOptionsController'
import { PersistenceService } from '@/Controllers/Abstract/PersistenceService'
import { removeFromArray } from '@standardnotes/utils'
import { FileItemActionType } from '@/Components/AttachedFilesPopover/PopoverFileItemAction'
export type WebEventObserver = (event: WebAppEvent, data?: unknown) => void
@@ -353,6 +355,21 @@ export class WebApplication extends SNApplication implements WebApplicationInter
this.notifyWebEvent(WebAppEvent.MobileKeyboardDidChangeFrame, frame)
}
handleOpenFilePreviewEvent({ id }: { id: string }): void {
const file = this.items.findItem<FileItem>(id)
if (!file) {
return
}
this.filesController
.handleFileAction({
type: FileItemActionType.PreviewFile,
payload: {
file,
},
})
.catch(console.error)
}
handleReceivedFileEvent(file: { name: string; mimeType: string; data: string }): void {
const filesController = this.filesController
const blob = getBlobFromBase64(file.data, file.mimeType)
@@ -78,7 +78,8 @@ const NoteListItem: FunctionComponent<DisplayableListItemProps<SNNote>> = ({
const onClick = useCallback(
(event: MouseEvent) => {
if ((event.ctrlKey || event.metaKey) && !application.itemListController.isMultipleSelectionMode) {
const hasMultiSelectionModifierKey = !isMobileScreen && (event.ctrlKey || event.metaKey)
if (hasMultiSelectionModifierKey && !application.itemListController.isMultipleSelectionMode) {
application.itemListController.enableMultipleSelectionMode()
}
if (selected && !application.itemListController.isMultipleSelectionMode) {
@@ -87,7 +88,7 @@ const NoteListItem: FunctionComponent<DisplayableListItemProps<SNNote>> = ({
}
onSelect(item, true).catch(console.error)
},
[application.itemListController, item, onSelect, selected],
[application.itemListController, isMobileScreen, item, onSelect, selected],
)
useContextMenuEvent(listItemRef, handleContextMenuEvent)
@@ -4,7 +4,7 @@ import ImportModalFileItem from './ImportModalFileItem'
import ImportModalInitialPage from './InitialPage'
import Modal, { ModalAction } from '../Modal/Modal'
import ModalOverlay from '../Modal/ModalOverlay'
import { ImportModalController } from '@/Controllers/ImportModalController'
import { ImportModalController } from '@/Components/ImportModal/ImportModalController'
import { useApplication } from '../ApplicationProvider'
import Switch from '../Switch/Switch'
@@ -66,7 +66,7 @@ const ImportModal = ({ importModalController }: { importModalController: ImportM
)}
</div>
{files.length > 0 && (
<label className="py-2 px-4 flex items-center gap-2 border-t border-border">
<label className="flex items-center gap-2 border-t border-border px-4 py-2">
<Switch checked={shouldCreateTag} onChange={setShouldCreateTag} />
<span className="text-sm">Create tag with all imported notes</span>
</label>
@@ -8,7 +8,7 @@ import {
} from '@standardnotes/snjs'
import { Importer, NoteImportType } from '@standardnotes/ui-services'
import { action, makeObservable, observable } from 'mobx'
import { NavigationController } from './Navigation/NavigationController'
import { NavigationController } from '../../Controllers/Navigation/NavigationController'
type ImportModalFileCommon = {
id: string
@@ -21,6 +21,7 @@ export type ImportModalFile = (
| { status: 'ready'; payloads?: DecryptedTransferPayload[] }
| { status: 'parsing' }
| { status: 'importing' }
| { status: 'uploading-files' }
| { status: 'success'; successMessage: string }
| { status: 'error'; error: Error }
) &
@@ -105,7 +106,14 @@ export class ImportModalController {
})
try {
await this.importer.importFromTransferPayloads(payloads)
const insertedItems = await this.importer.importFromTransferPayloads(payloads)
this.updateFile({
...file,
status: 'uploading-files',
})
await this.importer.uploadAndReplaceInlineFilesInInsertedItems(insertedItems)
const notesImported = payloads.filter((payload) => payload.content_type === ContentType.TYPES.Note)
const tagsImported = payloads.filter((payload) => payload.content_type === ContentType.TYPES.Tag)
@@ -1,4 +1,4 @@
import { ImportModalController, ImportModalFile } from '@/Controllers/ImportModalController'
import { ImportModalController, ImportModalFile } from '@/Components/ImportModal/ImportModalController'
import { classNames, ContentType, DecryptedTransferPayload, pluralize } from '@standardnotes/snjs'
import { Importer, NoteImportType } from '@standardnotes/ui-services'
import { observer } from 'mobx-react-lite'
@@ -103,6 +103,7 @@ const ImportModalFileItem = ({
{file.status === 'pending' && 'Could not auto-detect service. Please select manually.'}
{file.status === 'parsing' && 'Parsing...'}
{file.status === 'importing' && 'Importing...'}
{file.status === 'uploading-files' && 'Uploading and embedding files...'}
{file.status === 'error' && JSON.stringify(file.error)}
{file.status === 'success' && file.successMessage}
</div>
@@ -1,4 +1,4 @@
import { ImportModalController } from '@/Controllers/ImportModalController'
import { ImportModalController } from '@/Components/ImportModal/ImportModalController'
import { ClassicFileReader } from '@standardnotes/filepicker'
import { NoteImportType } from '@standardnotes/ui-services'
import { observer } from 'mobx-react-lite'
@@ -41,30 +41,30 @@ const ImportModalInitialPage = ({ setFiles }: Props) => {
<div className="text-lg font-semibold">Drag and drop files to auto-detect and import</div>
<div className="text-sm">Or click to open file picker</div>
</button>
<div className="text-center my-4 w-full">or import from:</div>
<div className="my-4 w-full text-center">or import from:</div>
<div className="flex flex-wrap items-center justify-center gap-4">
<Button className="flex items-center !py-2" onClick={() => selectFiles('evernote')}>
<Icon type="evernote" className="text-[#14cc45] mr-2" />
<Icon type="evernote" className="mr-2 text-[#14cc45]" />
Evernote
</Button>
<Button className="flex items-center !py-2" onClick={() => selectFiles('google-keep')}>
<Icon type="gkeep" className="text-[#fbbd00] mr-2" />
<Icon type="gkeep" className="mr-2 text-[#fbbd00]" />
Google Keep
</Button>
<Button className="flex items-center !py-2" onClick={() => selectFiles('simplenote')}>
<Icon type="simplenote" className="text-[#3360cc] mr-2" />
<Icon type="simplenote" className="mr-2 text-[#3360cc]" />
Simplenote
</Button>
<Button className="flex items-center !py-2" onClick={() => selectFiles('aegis')}>
<Icon type="aegis" className="bg-[#0d47a1] text-[#fff] rounded mr-2 p-1" size="normal" />
<Icon type="aegis" className="mr-2 rounded bg-[#0d47a1] p-1 text-[#fff]" size="normal" />
Aegis
</Button>
<Button className="flex items-center !py-2" onClick={() => selectFiles('plaintext')}>
<Icon type="plain-text" className="text-info mr-2" />
<Icon type="plain-text" className="mr-2 text-info" />
Plaintext / Markdown
</Button>
<Button className="flex items-center !py-2" onClick={() => selectFiles('html')}>
<Icon type="rich-text" className="text-accessory-tint-2 mr-2" />
<Icon type="rich-text" className="mr-2 text-accessory-tint-2" />
HTML
</Button>
<Button
@@ -81,7 +81,7 @@ const ImportModalInitialPage = ({ setFiles }: Props) => {
selectFiles('super').catch(console.error)
}}
>
<Icon type="file-doc" className="text-accessory-tint-1 mr-2" />
<Icon type="file-doc" className="mr-2 text-accessory-tint-1" />
Super (JSON)
</Button>
</div>
@@ -27,25 +27,29 @@ export const DiffView = ({
const [textDiff, setTextDiff] = useState<fastdiff.Diff[]>([])
useEffect(() => {
const firstNote = selectedNotes[0]
const firstTitle = firstNote.title
const firstText =
firstNote.noteType === NoteType.Super && convertSuperToMarkdown
? new HeadlessSuperConverter().convertSuperStringToOtherFormat(firstNote.text, 'md')
: firstNote.text
const setDiffs = async () => {
const firstNote = selectedNotes[0]
const firstTitle = firstNote.title
const firstText =
firstNote.noteType === NoteType.Super && convertSuperToMarkdown
? await new HeadlessSuperConverter().convertSuperStringToOtherFormat(firstNote.text, 'md')
: firstNote.text
const secondNote = selectedNotes[1]
const secondTitle = secondNote.title
const secondText =
secondNote.noteType === NoteType.Super && convertSuperToMarkdown
? new HeadlessSuperConverter().convertSuperStringToOtherFormat(secondNote.text, 'md')
: secondNote.text
const secondNote = selectedNotes[1]
const secondTitle = secondNote.title
const secondText =
secondNote.noteType === NoteType.Super && convertSuperToMarkdown
? await new HeadlessSuperConverter().convertSuperStringToOtherFormat(secondNote.text, 'md')
: secondNote.text
const titleDiff = fastdiff(firstTitle, secondTitle, undefined, true)
const textDiff = fastdiff(firstText, secondText, undefined, true)
const titleDiff = fastdiff(firstTitle, secondTitle, undefined, true)
const textDiff = fastdiff(firstText, secondText, undefined, true)
setTitleDiff(titleDiff)
setTextDiff(textDiff)
setTitleDiff(titleDiff)
setTextDiff(textDiff)
}
setDiffs().catch(console.error)
}, [convertSuperToMarkdown, selectedNotes])
const [preElement, setPreElement] = useState<HTMLPreElement | null>(null)
@@ -29,7 +29,7 @@ import {
VaultUserServiceEvent,
} from '@standardnotes/snjs'
import { confirmDialog, DELETE_NOTE_KEYBOARD_COMMAND, KeyboardKey } from '@standardnotes/ui-services'
import { ChangeEventHandler, createRef, CSSProperties, KeyboardEventHandler, RefObject } from 'react'
import { ChangeEventHandler, createRef, CSSProperties, FocusEvent, KeyboardEventHandler, RefObject } from 'react'
import { SuperEditor } from '../SuperEditor/SuperEditor'
import IndicatorCircle from '../IndicatorCircle/IndicatorCircle'
import LinkedItemBubblesContainer from '../LinkedItems/LinkedItemBubblesContainer'
@@ -826,7 +826,10 @@ class NoteView extends AbstractComponent<NoteViewProps, State> {
this.setState({ plainEditorFocused: true })
}
onPlainBlur = () => {
onPlainBlur = (event: FocusEvent) => {
if (event.relatedTarget?.id === ElementIds.NoteOptionsButton) {
return
}
this.setState({ plainEditorFocused: false })
}
@@ -897,8 +900,9 @@ class NoteView extends AbstractComponent<NoteViewProps, State> {
>
<div
className={classNames(
'mb-2 flex flex-wrap justify-between gap-2 md:mb-0 md:flex-nowrap md:gap-4 xl:items-center',
'mb-2 flex justify-between md:mb-0 md:flex-nowrap md:gap-4 xl:items-center',
shouldShowConflictsButton ? 'items-center' : 'items-start',
!renderHeaderOptions ? 'flex-nowrap gap-4' : 'flex-wrap gap-2 ',
)}
>
<div className={classNames(this.state.noteLocked && 'locked', 'flex flex-grow items-center')}>
@@ -937,30 +941,33 @@ class NoteView extends AbstractComponent<NoteViewProps, State> {
{pluralize(this.state.conflictedNotes.length, 'conflict', 'conflicts')}
</Button>
)}
{renderHeaderOptions && (
<div className="note-view-options-buttons flex items-center gap-3">
{!this.state.readonly && (
<>
<LinkedItemsButton
linkingController={this.application.linkingController}
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
/>
<ChangeEditorButton
noteViewController={this.controller}
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
/>
<PinNoteButton
notesController={this.application.notesController}
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
/>
</>
)}
<NotesOptionsPanel
notesController={this.application.notesController}
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
/>
</div>
)}
<div className="note-view-options-buttons flex items-center gap-3">
{!this.state.readonly && renderHeaderOptions && (
<>
<LinkedItemsButton
linkingController={this.application.linkingController}
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
/>
<ChangeEditorButton
noteViewController={this.controller}
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
/>
<PinNoteButton
notesController={this.application.notesController}
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
/>
</>
)}
<NotesOptionsPanel
notesController={this.application.notesController}
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
onButtonBlur={() => {
this.setState({
plainEditorFocused: false,
})
}}
/>
</div>
</div>
<div className="mb-1 mt-2.5 md:hidden">
<CollaborationInfoHUD item={this.note} />
@@ -16,7 +16,16 @@ import {
PrefDefaults,
} from '@standardnotes/snjs'
import { TAB_COMMAND } from '@standardnotes/ui-services'
import { ChangeEventHandler, forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState } from 'react'
import {
ChangeEventHandler,
forwardRef,
useCallback,
useEffect,
useImperativeHandle,
useRef,
useState,
FocusEvent,
} from 'react'
import { NoteViewController } from '../Controller/NoteViewController'
type Props = {
@@ -25,7 +34,7 @@ type Props = {
controller: NoteViewController
locked: boolean
onFocus: () => void
onBlur: () => void
onBlur: (event: FocusEvent) => void
}
export type PlainEditorInterface = {
@@ -106,13 +115,16 @@ export const PlainEditor = forwardRef<PlainEditorInterface, Props>(
onFocus()
}, [application, isAdjustingMobileCursor, lastEditorFocusEventSource, onFocus])
const onContentBlur = useCallback(() => {
if (lastEditorFocusEventSource.current) {
application.notifyWebEvent(WebAppEvent.EditorFocused, { eventSource: lastEditorFocusEventSource })
}
lastEditorFocusEventSource.current = undefined
onBlur()
}, [application, lastEditorFocusEventSource, onBlur])
const onContentBlur = useCallback(
(event: FocusEvent) => {
if (lastEditorFocusEventSource.current) {
application.notifyWebEvent(WebAppEvent.EditorFocused, { eventSource: lastEditorFocusEventSource })
}
lastEditorFocusEventSource.current = undefined
onBlur(event)
},
[application, lastEditorFocusEventSource, onBlur],
)
const scrollMobileCursorIntoViewAfterWebviewResize = useCallback(() => {
if (needsAdjustMobileCursor.current) {
@@ -1,16 +1,13 @@
import Icon from '@/Components/Icon/Icon'
import { observer } from 'mobx-react-lite'
import { useState, useEffect, useMemo, useCallback, useRef } from 'react'
import { NoteType, Platform, SNNote } from '@standardnotes/snjs'
import { useState, useEffect, useMemo, useCallback } from 'react'
import { NoteType, Platform, SNNote, pluralize } from '@standardnotes/snjs'
import {
CHANGE_EDITOR_WIDTH_COMMAND,
OPEN_NOTE_HISTORY_COMMAND,
PIN_NOTE_COMMAND,
SHOW_HIDDEN_OPTIONS_KEYBOARD_COMMAND,
STAR_NOTE_COMMAND,
SUPER_EXPORT_HTML,
SUPER_EXPORT_JSON,
SUPER_EXPORT_MARKDOWN,
SUPER_SHOW_MARKDOWN_PREVIEW,
} from '@standardnotes/ui-services'
import ChangeEditorOption from './ChangeEditorOption'
@@ -20,9 +17,7 @@ import { addToast, dismissToast, ToastType } from '@standardnotes/toast'
import { NotesOptionsProps } from './NotesOptionsProps'
import { useResponsiveAppPane } from '../Panes/ResponsivePaneProvider'
import { AppPaneId } from '../Panes/AppPaneMetadata'
import { getNoteBlob, getNoteFileName } from '@/Utils/NoteExportUtils'
import { shareSelectedNotes } from '@/NativeMobileWeb/ShareSelectedNotes'
import { downloadSelectedNotesOnAndroid } from '@/NativeMobileWeb/DownloadSelectedNotesOnAndroid'
import { createNoteExport } from '@/Utils/NoteExportUtils'
import ProtectedUnauthorizedLabel from '../ProtectedItemOverlay/ProtectedUnauthorizedLabel'
import { MenuItemIconSize } from '@/Constants/TailwindClassNames'
import { KeyboardShortcutIndicator } from '../KeyboardShortcutIndicator/KeyboardShortcutIndicator'
@@ -39,9 +34,9 @@ import SuperExportModal from './SuperExportModal'
import { useApplication } from '../ApplicationProvider'
import { MutuallyExclusiveMediaQueryBreakpoints } from '@/Hooks/useMediaQuery'
import AddToVaultMenuOption from '../Vaults/AddToVaultMenuOption'
import Menu from '../Menu/Menu'
import Popover from '../Popover/Popover'
import MenuSection from '../Menu/MenuSection'
import { downloadOrShareBlobBasedOnPlatform } from '@/Utils/DownloadOrShareBasedOnPlatform'
import { shareBlobOnMobile } from '@/NativeMobileWeb/ShareBlobOnMobile'
const iconSize = MenuItemIconSize
const iconClassDanger = `text-danger mr-2 ${iconSize}`
@@ -104,33 +99,48 @@ const NotesOptions = ({ notes, closeMenu }: NotesOptionsProps) => {
}, [])
const downloadSelectedItems = useCallback(async () => {
if (notes.length === 1) {
const note = notes[0]
const blob = getNoteBlob(application, note)
application.archiveService.downloadData(blob, getNoteFileName(application, note))
if (notes.length === 0) {
return
}
const toast = addToast({
type: ToastType.Progress,
message: `Exporting ${notes.length} ${pluralize(notes.length, 'note', 'notes')}...`,
})
try {
const result = await createNoteExport(application, notes)
if (!result) {
return
}
const { blob, fileName } = result
void downloadOrShareBlobBasedOnPlatform({
archiveService: application.archiveService,
platform: application.platform,
mobileDevice: application.mobileDevice,
blob: blob,
filename: fileName,
isNativeMobileWeb: application.isNativeMobileWeb(),
})
dismissToast(toast)
} catch (error) {
console.error(error)
addToast({
type: ToastType.Error,
message: 'Could not export notes',
})
dismissToast(toast)
}
}, [application, notes])
const exportSelectedItems = useCallback(() => {
const hasSuperNote = notes.some((note) => note.noteType === NoteType.Super)
if (hasSuperNote) {
setShowExportSuperModal(true)
return
}
if (notes.length > 1) {
const loadingToastId = addToast({
type: ToastType.Loading,
message: `Exporting ${notes.length} notes...`,
})
await application.archiveService.downloadDataAsZip(
notes.map((note) => {
return {
name: getNoteFileName(application, note),
content: getNoteBlob(application, note),
}
}),
)
dismissToast(loadingToastId)
addToast({
type: ToastType.Success,
message: `Exported ${notes.length} notes`,
})
}
}, [application, notes])
downloadSelectedItems().catch(console.error)
}, [downloadSelectedItems, notes])
const closeMenuAndToggleNotesList = useCallback(() => {
const isMobileScreen = matchMedia(MutuallyExclusiveMediaQueryBreakpoints.sm).matches
@@ -199,9 +209,6 @@ const NotesOptions = ({ notes, closeMenu }: NotesOptionsProps) => {
[application],
)
const superExportButtonRef = useRef<HTMLButtonElement>(null)
const [isSuperExportMenuOpen, setIsSuperExportMenuOpen] = useState(false)
const unauthorized = notes.some((note) => !application.isAuthorizedToRenderItem(note))
if (unauthorized) {
return <ProtectedUnauthorizedLabel />
@@ -224,8 +231,6 @@ const NotesOptions = ({ notes, closeMenu }: NotesOptionsProps) => {
return null
}
const isOnlySuperNoteSelected = notes.length === 1 && notes[0].noteType === NoteType.Super
return (
<>
{notes.length === 1 && (
@@ -342,77 +347,35 @@ const NotesOptions = ({ notes, closeMenu }: NotesOptionsProps) => {
{pinShortcut && <KeyboardShortcutIndicator className="ml-auto" shortcut={pinShortcut} />}
</MenuItem>
)}
{isOnlySuperNoteSelected ? (
<>
<MenuItem
ref={superExportButtonRef}
onClick={() => {
setIsSuperExportMenuOpen((open) => !open)
}}
>
<div className="flex items-center">
<Icon type="download" className={iconClass} />
Export
</div>
<Icon type="chevron-right" className="ml-auto text-neutral" />
</MenuItem>
<Popover
title="Export note"
side="left"
align="start"
open={isSuperExportMenuOpen}
anchorElement={superExportButtonRef.current}
togglePopover={() => {
setIsSuperExportMenuOpen(!isSuperExportMenuOpen)
}}
className="md:py-1"
>
<Menu a11yLabel={'Super note export menu'}>
<MenuSection>
<MenuItem onClick={() => commandService.triggerCommand(SUPER_EXPORT_JSON, notes[0].title)}>
<Icon type="code" className={iconClass} />
Export as JSON
</MenuItem>
<MenuItem onClick={() => commandService.triggerCommand(SUPER_EXPORT_MARKDOWN, notes[0].title)}>
<Icon type="markdown" className={iconClass} />
Export as Markdown
</MenuItem>
<MenuItem onClick={() => commandService.triggerCommand(SUPER_EXPORT_HTML, notes[0].title)}>
<Icon type="rich-text" className={iconClass} />
Export as HTML
</MenuItem>
</MenuSection>
</Menu>
</Popover>
</>
) : (
<>
<MenuItem
onClick={() => {
if (application.isNativeMobileWeb()) {
void shareSelectedNotes(application, notes)
} else {
const hasSuperNote = notes.some((note) => note.noteType === NoteType.Super)
if (hasSuperNote) {
setShowExportSuperModal(true)
<MenuItem
onClick={() => {
if (application.isNativeMobileWeb()) {
createNoteExport(application, notes)
.then((result) => {
if (!result) {
return
}
void downloadSelectedItems()
}
}}
>
<Icon type={application.platform === Platform.Android ? 'share' : 'download'} className={iconClass} />
{application.platform === Platform.Android ? 'Share' : 'Export'}
</MenuItem>
{application.platform === Platform.Android && (
<MenuItem onClick={() => downloadSelectedNotesOnAndroid(application, notes)}>
<Icon type="download" className={iconClass} />
Export
</MenuItem>
)}
</>
const { blob, fileName } = result
shareBlobOnMobile(application.mobileDevice, application.isNativeMobileWeb(), blob, fileName).catch(
console.error,
)
})
.catch(console.error)
} else {
exportSelectedItems()
}
}}
>
<Icon type={application.platform === Platform.Android ? 'share' : 'download'} className={iconClass} />
{application.platform === Platform.Android ? 'Share' : 'Export'}
</MenuItem>
{application.platform === Platform.Android && (
<MenuItem onClick={exportSelectedItems}>
<Icon type="download" className={iconClass} />
Export
</MenuItem>
)}
<MenuItem onClick={duplicateSelectedItems} disabled={areSomeNotesInReadonlySharedVault}>
<Icon type="copy" className={iconClass} />
@@ -541,7 +504,7 @@ const NotesOptions = ({ notes, closeMenu }: NotesOptionsProps) => {
)}
<ModalOverlay isOpen={showExportSuperModal} close={closeSuperExportModal}>
<SuperExportModal exportNotes={downloadSelectedItems} close={closeSuperExportModal} />
<SuperExportModal notes={notes} exportNotes={downloadSelectedItems} close={closeSuperExportModal} />
</ModalOverlay>
</>
)
@@ -1,17 +1,19 @@
import { useCallback, useRef, useState } from 'react'
import { FocusEvent, useCallback, useRef, useState } from 'react'
import { observer } from 'mobx-react-lite'
import NotesOptions from './NotesOptions'
import { NotesController } from '@/Controllers/NotesController/NotesController'
import Popover from '../Popover/Popover'
import RoundIconButton from '../Button/RoundIconButton'
import Menu from '../Menu/Menu'
import { ElementIds } from '@/Constants/ElementIDs'
type Props = {
notesController: NotesController
onClickPreprocessing?: () => Promise<void>
onButtonBlur?: (event: FocusEvent) => void
}
const NotesOptionsPanel = ({ notesController, onClickPreprocessing }: Props) => {
const NotesOptionsPanel = ({ notesController, onClickPreprocessing, onButtonBlur }: Props) => {
const [isOpen, setIsOpen] = useState(false)
const buttonRef = useRef<HTMLButtonElement>(null)
@@ -30,7 +32,14 @@ const NotesOptionsPanel = ({ notesController, onClickPreprocessing }: Props) =>
return (
<>
<RoundIconButton label="Note options menu" onClick={toggleMenu} ref={buttonRef} icon="more" />
<RoundIconButton
id={ElementIds.NoteOptionsButton}
label="Note options menu"
onClick={toggleMenu}
onBlur={onButtonBlur}
ref={buttonRef}
icon="more"
/>
<Popover
title="Note options"
disableClickOutside={disableClickOutside}
@@ -1,17 +1,34 @@
import { PrefKey, PrefValue } from '@standardnotes/snjs'
import { PrefKey, PrefValue, SNNote } from '@standardnotes/snjs'
import { useApplication } from '../ApplicationProvider'
import Dropdown from '../Dropdown/Dropdown'
import Modal from '../Modal/Modal'
import usePreference from '@/Hooks/usePreference'
import RadioButtonGroup from '../RadioButtonGroup/RadioButtonGroup'
import { useEffect } from 'react'
import Switch from '../Switch/Switch'
import { noteHasEmbeddedFiles } from '@/Utils/NoteExportUtils'
type Props = {
notes: SNNote[]
exportNotes: () => void
close: () => void
}
const SuperExportModal = ({ exportNotes, close }: Props) => {
const SuperExportModal = ({ notes, exportNotes, close }: Props) => {
const application = useApplication()
const superNoteExportFormat = usePreference(PrefKey.SuperNoteExportFormat)
const superNoteExportEmbedBehavior = usePreference(PrefKey.SuperNoteExportEmbedBehavior)
const superNoteExportUseMDFrontmatter = usePreference(PrefKey.SuperNoteExportUseMDFrontmatter)
useEffect(() => {
if (superNoteExportFormat === 'json' && superNoteExportEmbedBehavior === 'separate') {
void application.setPreference(PrefKey.SuperNoteExportEmbedBehavior, 'reference')
}
if (superNoteExportFormat === 'md' && superNoteExportEmbedBehavior === 'reference') {
void application.setPreference(PrefKey.SuperNoteExportEmbedBehavior, 'separate')
}
}, [application, superNoteExportEmbedBehavior, superNoteExportFormat])
const someNotesHaveEmbeddedFiles = notes.some(noteHasEmbeddedFiles)
return (
<Modal
@@ -28,20 +45,21 @@ const SuperExportModal = ({ exportNotes, close }: Props) => {
{
label: 'Export',
type: 'primary',
onClick: exportNotes,
onClick: () => {
close()
exportNotes()
},
mobileSlot: 'right',
},
]}
>
<div className="mb-4">
<div className="mb-1 text-base">
We detected your selection includes Super notes. How do you want to export them?
</div>
<Dropdown
label="Super notes export format"
<div className="mb-2">
<div className="mb-3 text-base">We detected your selection includes Super notes.</div>
<div className="mb-1">What format do you want to export them in?</div>
<RadioButtonGroup
items={[
{ label: 'Keep as Super', value: 'json' },
{ label: 'Markdown', value: 'md' },
{ label: 'Super (.json)', value: 'json' },
{ label: 'Markdown (.md)', value: 'md' },
{ label: 'HTML', value: 'html' },
]}
value={superNoteExportFormat}
@@ -52,12 +70,47 @@ const SuperExportModal = ({ exportNotes, close }: Props) => {
)
}}
/>
{superNoteExportFormat === 'md' && (
<div className="mt-2 text-xs text-passive-0">
Note that conversion to Markdown is not lossless. Some features like collapsible blocks and formatting like
superscript/subscript may not be correctly converted.
</div>
)}
</div>
<div className="text-passive-0">
Note that if you convert Super notes to Markdown then import them back into Standard Notes in the future, you
will lose some formatting that the Markdown format is incapable of expressing, such as collapsible blocks and
embeds.
</div>
{superNoteExportFormat === 'md' && (
<div className="mt-4">
<Switch
checked={superNoteExportUseMDFrontmatter}
onChange={(checked) => {
void application.setPreference(
PrefKey.SuperNoteExportUseMDFrontmatter,
checked as PrefValue[PrefKey.SuperNoteExportUseMDFrontmatter],
)
}}
className="!flex items-center"
>
<span className="ml-2">Export with frontmatter</span>
</Switch>
</div>
)}
{superNoteExportFormat !== 'json' && someNotesHaveEmbeddedFiles && (
<div className="mb-2 mt-4">
<div className="mb-1">How do you want embedded files to be handled?</div>
<RadioButtonGroup
items={[
{ label: 'Inline', value: 'inline' },
{ label: 'Export separately', value: 'separate' },
].concat(superNoteExportFormat !== 'md' ? [{ label: 'Keep as reference', value: 'reference' }] : [])}
value={superNoteExportEmbedBehavior}
onChange={(value) => {
void application.setPreference(
PrefKey.SuperNoteExportEmbedBehavior,
value as PrefValue[PrefKey.SuperNoteExportEmbedBehavior],
)
}}
/>
</div>
)}
</Modal>
)
}
@@ -1,6 +1,6 @@
import { useDisableBodyScrollOnMobile } from '@/Hooks/useDisableBodyScrollOnMobile'
import { classNames } from '@standardnotes/snjs'
import { ReactNode, useCallback, useEffect, useRef } from 'react'
import { ReactNode, useCallback, useEffect } from 'react'
import Portal from '../Portal/Portal'
import MobileModalAction from '../Modal/MobileModalAction'
import { MobileModalAnimationOptions, useModalAnimation } from '../Modal/useModalAnimation'
@@ -10,6 +10,7 @@ import { DialogWithClose } from '@/Utils/CloseOpenModalsAndPopovers'
import { useMediaQuery, MutuallyExclusiveMediaQueryBreakpoints } from '@/Hooks/useMediaQuery'
import { SupportsPassiveListeners } from '@/Constants/Constants'
import { useLifecycleAnimation } from '@/Hooks/useLifecycleAnimation'
import { getScrollParent } from '@/Utils'
const DisableScroll = () => {
useDisableBodyScrollOnMobile()
@@ -61,17 +62,16 @@ const MobilePopoverContent = ({
options: MobileModalAnimationOptions,
},
})
const scrollContainerRef = useRef<HTMLDivElement | null>(null)
useEffect(() => {
const closestScrollContainer = scrollContainerRef.current
if (!element || !closestScrollContainer) {
if (!element) {
return
}
let closestScrollContainer: HTMLElement | null = null
let elementY = 0
let startY = 0
let startTimestamp = Date.now()
let closestScrollContainerScrollTop = 0
let isClosestScrollContainerScrolledAtStart = false
let containerScrollChangedAfterTouchStart = false
@@ -79,6 +79,8 @@ const MobilePopoverContent = ({
const touchStartHandler = (e: TouchEvent) => {
startY = e.touches[0].clientY
elementY = element.getBoundingClientRect().y
startTimestamp = Date.now()
closestScrollContainer = getScrollParent(e.target as HTMLElement)
closestScrollContainerScrollTop = closestScrollContainer?.scrollTop || 0
isClosestScrollContainerScrolledAtStart = !!closestScrollContainer && closestScrollContainerScrollTop > 0
containerScrollChangedAfterTouchStart = false
@@ -103,7 +105,7 @@ const MobilePopoverContent = ({
}
const y = element.getBoundingClientRect().y
if (y > elementY) {
if (y > elementY && closestScrollContainer) {
closestScrollContainer.style.overflowY = 'hidden'
}
@@ -117,11 +119,17 @@ const MobilePopoverContent = ({
},
)
}
const touchEndHandler = () => {
const touchEndHandler = (event: TouchEvent) => {
const y = element.getBoundingClientRect().y
const threshold = window.innerHeight * 0.75
if (y > threshold && !isClosestScrollContainerScrolledAtStart) {
const endTimestamp = Date.now()
const deltaY = event.changedTouches[0].clientY - startY
const velocity = deltaY / (endTimestamp - startTimestamp)
if (y < threshold && velocity > 2) {
requestClose()
} else if (y > threshold && !isClosestScrollContainerScrolledAtStart) {
requestClose()
} else {
element.animate(
@@ -136,7 +144,9 @@ const MobilePopoverContent = ({
}
startY = 0
closestScrollContainer.style.overflowY = ''
if (closestScrollContainer) {
closestScrollContainer.style.overflowY = ''
}
}
element.addEventListener('touchstart', touchStartHandler, SupportsPassiveListeners ? { passive: true } : false)
@@ -191,12 +201,7 @@ const MobilePopoverContent = ({
Done
</MobileModalAction>
</MobileModalHeader>
<div
className={classNames('h-full overflow-y-auto overscroll-none bg-passive-5', className)}
ref={scrollContainerRef}
>
{children}
</div>
<div className={classNames('h-full overflow-y-auto overscroll-none bg-passive-5', className)}>{children}</div>
</div>
</div>
</Portal>
@@ -2,7 +2,6 @@ import { FunctionComponent, UIEventHandler, useCallback, useState } from 'react'
import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin'
import { ContentEditable } from '@lexical/react/LexicalContentEditable'
import { OnChangePlugin } from '@lexical/react/LexicalOnChangePlugin'
import { CheckListPlugin } from '@lexical/react/LexicalCheckListPlugin'
import { ClearEditorPlugin } from '@lexical/react/LexicalClearEditorPlugin'
import { MarkdownShortcutPlugin } from '@lexical/react/LexicalMarkdownShortcutPlugin'
import { TablePlugin } from '@lexical/react/LexicalTablePlugin'
@@ -28,6 +27,8 @@ import { RemoveBrokenTablesPlugin } from './Plugins/TablePlugin'
import TableActionMenuPlugin from './Plugins/TableCellActionMenuPlugin'
import ToolbarPlugin from './Plugins/ToolbarPlugin/ToolbarPlugin'
import { useMediaQuery, MutuallyExclusiveMediaQueryBreakpoints } from '@/Hooks/useMediaQuery'
import { CheckListPlugin } from './Plugins/List/CheckListPlugin'
import { EmptyLinePlaceholderPlugin } from './Plugins/EmptyLinePlaceholderPlugin'
type BlocksEditorProps = {
onChange?: (value: string, preview: string) => void
@@ -113,6 +114,7 @@ export const BlocksEditor: FunctionComponent<BlocksEditorProps> = ({
<CollapsiblePlugin />
<TabIndentationPlugin />
<RemoveBrokenTablesPlugin />
<EmptyLinePlaceholderPlugin />
{!readonly && floatingAnchorElem && (
<>
<DraggableBlockPlugin anchorElem={floatingAnchorElem} />
@@ -16,8 +16,11 @@ import { FileNode } from '../../Plugins/EncryptedFilePlugin/Nodes/FileNode'
import { BubbleNode } from '../../Plugins/ItemBubblePlugin/Nodes/BubbleNode'
import { RemoteImageNode } from '../../Plugins/RemoteImagePlugin/RemoteImageNode'
import { InlineFileNode } from '../../Plugins/InlineFilePlugin/InlineFileNode'
import { CreateEditorArgs } from 'lexical'
import { ListHTMLExportNode } from '../../Plugins/List/ListHTMLExportNode'
import { FileExportNode } from './FileExportNode'
export const BlockEditorNodes = [
const CommonNodes = [
AutoLinkNode,
CodeHighlightNode,
CodeNode,
@@ -29,7 +32,6 @@ export const BlockEditorNodes = [
HorizontalRuleNode,
LinkNode,
ListItemNode,
ListNode,
MarkNode,
OverflowNode,
QuoteNode,
@@ -43,3 +45,17 @@ export const BlockEditorNodes = [
RemoteImageNode,
InlineFileNode,
]
export const BlockEditorNodes = [...CommonNodes, ListNode]
export const SuperExportNodes: CreateEditorArgs['nodes'] = [
...CommonNodes,
FileExportNode,
ListHTMLExportNode,
{
replace: ListNode,
with(node) {
return new ListHTMLExportNode(node.getListType(), node.getStart())
},
},
]
@@ -0,0 +1,93 @@
import { DecoratorBlockNode, SerializedDecoratorBlockNode } from '@lexical/react/LexicalDecoratorBlockNode'
import { parseAndCreateZippableFileName } from '@standardnotes/ui-services'
import { DOMExportOutput, Spread } from 'lexical'
type SerializedFileExportNode = Spread<
{
version: 1
type: 'file-export'
name: string
mimeType: string
},
SerializedDecoratorBlockNode
>
export class FileExportNode extends DecoratorBlockNode {
__name: string
__mimeType: string
static getType(): string {
return 'file-export'
}
constructor(name: string, mimeType: string) {
super()
this.__name = name
this.__mimeType = mimeType
}
static clone(node: FileExportNode): FileExportNode {
return new FileExportNode(node.__name, node.__mimeType)
}
static importJSON(serializedNode: SerializedFileExportNode): FileExportNode {
const node = new FileExportNode(serializedNode.name, serializedNode.mimeType)
return node
}
exportJSON(): SerializedFileExportNode {
return {
...super.exportJSON(),
name: this.__name,
mimeType: this.__mimeType,
version: 1,
type: 'file-export',
}
}
getZippableFileName(): string {
return parseAndCreateZippableFileName(this.__name)
}
getTextContent(): string {
return `${this.__mimeType.startsWith('image/') ? '!' : ''}[${this.__name}](./${this.getZippableFileName()})`
}
exportDOM(): DOMExportOutput {
const src = `./${this.getZippableFileName()}`
if (this.__mimeType.startsWith('image/')) {
const img = document.createElement('img')
img.setAttribute('src', src)
return { element: img }
} else if (this.__mimeType.startsWith('audio')) {
const audio = document.createElement('audio')
audio.setAttribute('controls', '')
const source = document.createElement('source')
source.setAttribute('src', src)
source.setAttribute('type', this.__mimeType)
audio.appendChild(source)
return { element: audio }
} else if (this.__mimeType.startsWith('video')) {
const video = document.createElement('video')
video.setAttribute('controls', '')
const source = document.createElement('source')
source.setAttribute('src', src)
source.setAttribute('type', this.__mimeType)
video.appendChild(source)
return { element: video }
}
const object = document.createElement('object')
object.setAttribute('data', src)
object.setAttribute('type', this.__mimeType)
return { element: object }
}
decorate(): JSX.Element {
// Doesn't need to actually render anything since this is only used for export
return <></>
}
}
export function $createFileExportNode(name: string, mimeType: string): FileExportNode {
return new FileExportNode(name, mimeType)
}
@@ -1,3 +1,5 @@
@import 'lists';
.Lexical__ltr {
text-align: left;
}
@@ -163,70 +165,6 @@
box-shadow: 0 0 5px rgba(0, 0, 0, 0.4);
border-radius: 3px;
}
.Lexical__tableAddColumns {
position: absolute;
top: 0;
width: 20px;
background-color: #eee;
height: 100%;
right: 0;
animation: table-controls 0.2s ease;
border: 0;
cursor: pointer;
}
.Lexical__tableAddColumns:after {
background-image: url(#{$blocks-editor-icons-path}/plus.svg);
background-size: contain;
background-position: center;
background-repeat: no-repeat;
display: block;
content: ' ';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0.4;
}
.Lexical__tableAddColumns:hover {
background-color: #c9dbf0;
}
.Lexical__tableAddRows {
position: absolute;
bottom: -25px;
width: calc(100% - 25px);
background-color: #eee;
height: 20px;
left: 0;
animation: table-controls 0.2s ease;
border: 0;
cursor: pointer;
}
.Lexical__tableAddRows:after {
background-image: url(#{$blocks-editor-icons-path}/plus.svg);
background-size: contain;
background-position: center;
background-repeat: no-repeat;
display: block;
content: ' ';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0.4;
}
.Lexical__tableAddRows:hover {
background-color: #c9dbf0;
}
@keyframes table-controls {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.Lexical__tableCellResizeRuler {
display: block;
position: absolute;
@@ -261,118 +199,6 @@
display: inline;
background-color: #ffbbbb !important;
}
:root {
--lexical-ordered-list-left-margin: 16px;
}
.monospace-font {
--lexical-ordered-list-left-margin: 42px;
}
@for $i from 1 through 5 {
.Lexical__ol#{$i} {
padding: 0;
margin: 0;
margin-left: var(--lexical-ordered-list-left-margin);
list-style-position: outside;
&.Lexical__rtl {
margin-left: 0;
margin-right: var(--lexical-ordered-list-left-margin);
}
}
}
.Lexical__ol2 {
list-style-type: upper-alpha;
}
.Lexical__ol3 {
list-style-type: lower-alpha;
}
.Lexical__ol4 {
list-style-type: upper-roman;
}
.Lexical__ol5 {
list-style-type: lower-roman;
}
.Lexical__ul {
padding: 0;
margin: 0;
margin-left: 16px;
list-style-position: outside;
&.Lexical__rtl {
margin-left: 0;
margin-right: 16px;
}
}
.Lexical__listItem {
margin: 0 0px;
}
.Lexical__listItemChecked,
.Lexical__listItemUnchecked {
position: relative;
margin-left: 8px;
margin-right: 8px;
padding-left: 24px;
padding-right: 24px;
list-style-type: none;
outline: none;
vertical-align: middle;
}
.Lexical__listItemChecked {
text-decoration: line-through;
opacity: 0.4;
}
.Lexical__listItemUnchecked:before,
.Lexical__listItemChecked:before {
content: '';
width: 16px;
height: 16px;
left: 0;
top: 5px;
cursor: pointer;
background-size: cover;
position: absolute;
}
.Lexical__listItemUnchecked[dir='rtl']:before,
.Lexical__listItemChecked[dir='rtl']:before {
left: auto;
right: 0;
}
.Lexical__listItemUnchecked:focus:before,
.Lexical__listItemChecked:focus:before {
box-shadow: 0 0 0 2px #a6cdfe;
border-radius: 2px;
}
.Lexical__listItemUnchecked:before {
border: 1px solid #999;
border-radius: 2px;
}
.Lexical__listItemChecked:before {
border: 1px solid var(--sn-stylekit-info-color);
border-radius: 2px;
background-color: var(--sn-stylekit-info-color);
background-repeat: no-repeat;
}
.Lexical__listItemChecked:after {
content: '';
cursor: pointer;
border-color: var(--sn-stylekit-info-contrast-color);
border-style: solid;
position: absolute;
display: block;
top: 7px;
width: 5px;
left: 6px;
height: 10px;
transform: rotate(45deg);
border-width: 0 2px 2px 0;
}
.Lexical__nestedListItem {
list-style-type: none;
}
.Lexical__nestedListItem:before,
.Lexical__nestedListItem:after {
display: none;
}
.Lexical__tokenComment {
color: slategray;
}
@@ -0,0 +1,15 @@
.Lexical__listItemUnchecked,
.Lexical__listItemChecked {
min-height: 18px;
margin-bottom: 4px;
}
.Lexical__listItemUnchecked:before,
.Lexical__listItemChecked:before {
top: 0px;
}
.Lexical__listItemChecked:after {
top: 1px;
}
.Lexical__table {
margin: 10px 0;
}
@@ -1,117 +0,0 @@
.icon.plus {
background-image: url(#{$blocks-editor-icons-path}/plus.svg);
}
/**
.icon.dropdown-more {
background-image: url(#{$blocks-editor-icons-path}/dropdown-more.svg);
}
.icon.font-color {
background-image: url(#{$blocks-editor-icons-path}/font-color.svg);
}
.icon.font-family {
background-image: url(#{$blocks-editor-icons-path}/font-family.svg);
}
.icon.bg-color {
background-image: url(#{$blocks-editor-icons-path}/bg-color.svg);
}
i.palette {
background-image: url(#{$blocks-editor-icons-path}/palette.svg);
}
i.bucket {
background-image: url(#{$blocks-editor-icons-path}/paint-bucket.svg);
}
i.clear {
background-image: url(#{$blocks-editor-icons-path}/trash.svg);
}
i.image {
background-image: url(#{$blocks-editor-icons-path}/file-image.svg);
}
i.close {
background-image: url(#{$blocks-editor-icons-path}/close.svg);
}
i.figma {
background-image: url(#{$blocks-editor-icons-path}/figma.svg);
}
i.poll {
background-image: url(#{$blocks-editor-icons-path}/card-checklist.svg);
}
i.indent {
background-image: url(#{$blocks-editor-icons-path}/indent.svg);
}
i.markdown {
background-image: url(#{$blocks-editor-icons-path}/markdown.svg);
}
i.outdent {
background-image: url(#{$blocks-editor-icons-path}/outdent.svg);
}
i.undo {
background-image: url(#{$blocks-editor-icons-path}/arrow-counterclockwise.svg);
}
i.redo {
background-image: url(#{$blocks-editor-icons-path}/arrow-clockwise.svg);
}
i.sticky {
background-image: url(#{$blocks-editor-icons-path}/sticky.svg);
}
i.mic {
background-image: url(#{$blocks-editor-icons-path}/mic.svg);
}
i.import {
background-image: url(#{$blocks-editor-icons-path}/upload.svg);
}
i.export {
background-image: url(#{$blocks-editor-icons-path}/download.svg);
}
i.diagram-2 {
background-image: url(#{$blocks-editor-icons-path}/diagram-2.svg);
}
i.user {
background-image: url(#{$blocks-editor-icons-path}/user.svg);
}
i.equation {
background-image: url(#{$blocks-editor-icons-path}/plus-slash-minus.svg);
}
i.gif {
background-image: url(#{$blocks-editor-icons-path}/filetype-gif.svg);
}
i.copy {
background-image: url(#{$blocks-editor-icons-path}/copy.svg);
}
i.success {
background-image: url(#{$blocks-editor-icons-path}/success.svg);
}
i.prettier {
background-image: url(#{$blocks-editor-icons-path}/prettier.svg);
}
i.prettier-error {
background-image: url(#{$blocks-editor-icons-path}/prettier-error.svg);
}
*/
@@ -1,5 +1,3 @@
@import 'base';
@import 'custom';
@import 'editor';
@import 'icons';
@import 'links';
@@ -1,110 +0,0 @@
.button.active,
.toolbar .button.active {
background-color: var(--sn-stylekit-contrast-background-color);
}
.link-editor {
background-color: var(--sn-stylekit-secondary-background-color);
border-radius: 8px;
border: 0;
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.3);
box-sizing: border-box;
display: absolute;
font-family: inherit;
font-size: 15px;
left: 0;
margin: 8px 12px;
max-width: 400px;
opacity: 0;
outline: 0;
padding: 8px 12px;
position: absolute;
top: 0;
transition: opacity 0.5s;
width: 100%;
will-change: transform;
z-index: 10;
}
.link-input {
background-color: var(--sn-stylekit-background-color);
border-radius: 15px;
border: 0;
box-sizing: border-box;
color: var(--sn-stylekit-contrast-color);
display: absolute;
font-family: inherit;
font-size: 15px;
margin: 8px 12px;
outline: 0;
padding: 8px 12px;
position: relative;
width: calc(100% - 24px);
}
.link-editor div.link-edit {
display: flex;
align-items: center;
background-size: 16px;
background-position: center;
background-repeat: no-repeat;
vertical-align: -0.25em;
position: absolute;
right: 12px;
top: 0;
bottom: 0;
cursor: pointer;
}
.link-editor .link-input a {
color: rgb(33, 111, 219);
text-decoration: none;
display: block;
white-space: nowrap;
overflow: hidden;
margin-right: 30px;
text-overflow: ellipsis;
}
.link-editor .link-input a:hover {
text-decoration: underline;
}
.link-editor .font-size-wrapper,
.link-editor .font-family-wrapper {
display: flex;
margin: 0 4px;
}
.link-editor select {
padding: 6px;
border: none;
background-color: rgba(0, 0, 0, 0.075);
border-radius: 4px;
}
.link-editor .button {
width: 20px;
height: 20px;
display: inline-block;
padding: 6px;
border-radius: 8px;
cursor: pointer;
margin: 0 2px;
}
.link-editor .button.hovered {
width: 20px;
height: 20px;
display: inline-block;
background-color: #eee;
}
.link-editor .button i,
.actions i {
background-size: contain;
display: inline-block;
height: 20px;
width: 20px;
vertical-align: -0.25em;
}
@@ -0,0 +1,119 @@
:root {
--lexical-ordered-list-left-margin: 16px;
}
.monospace-font {
--lexical-ordered-list-left-margin: 42px;
}
@for $i from 1 through 5 {
.Lexical__ol#{$i} {
padding: 0;
margin: 0;
margin-left: var(--lexical-ordered-list-left-margin);
list-style-position: outside;
&.Lexical__rtl {
margin-left: 0;
margin-right: var(--lexical-ordered-list-left-margin);
}
}
}
.Lexical__ol2 {
list-style-type: upper-alpha;
}
.Lexical__ol3 {
list-style-type: lower-alpha;
}
.Lexical__ol4 {
list-style-type: upper-roman;
}
.Lexical__ol5 {
list-style-type: lower-roman;
}
.Lexical__ul {
padding: 0;
margin: 0;
margin-left: 16px;
list-style-position: outside;
&.Lexical__rtl {
margin-left: 0;
margin-right: 16px;
}
}
.Lexical__checkList {
margin-left: 0;
.Lexical__nestedListItem & {
margin-left: 16px;
}
}
.Lexical__listItem {
margin: 0 0px;
}
.Lexical__listItemChecked,
.Lexical__listItemUnchecked {
position: relative;
padding-left: 24px;
padding-right: 24px;
list-style-type: none;
outline: none;
vertical-align: middle;
}
.Lexical__listItemChecked {
text-decoration: line-through;
opacity: 0.4;
}
.Lexical__listItemUnchecked:before,
.Lexical__listItemChecked:before {
content: '';
width: 16px;
height: 16px;
left: 0;
top: 7px;
cursor: pointer;
background-size: cover;
position: absolute;
}
.Lexical__listItemUnchecked[dir='rtl']:before,
.Lexical__listItemChecked[dir='rtl']:before {
left: auto;
right: 0;
}
.Lexical__listItemUnchecked:focus:before,
.Lexical__listItemChecked:focus:before {
box-shadow: 0 0 0 2px #a6cdfe;
border-radius: 2px;
}
.Lexical__listItemUnchecked:before {
border: 1px solid #999;
border-radius: 2px;
}
.Lexical__listItemChecked:before {
border: 1px solid var(--sn-stylekit-info-color);
border-radius: 2px;
background-color: var(--sn-stylekit-info-color);
background-repeat: no-repeat;
}
.Lexical__listItemChecked:after {
content: '';
cursor: pointer;
border-color: var(--sn-stylekit-info-contrast-color);
border-style: solid;
position: absolute;
display: block;
top: 9px;
width: 5px;
left: 6px;
height: 10px;
transform: rotate(45deg);
border-width: 0 2px 2px 0;
}
.Lexical__nestedListItem {
list-style-type: none;
&.Lexical__listItemUnchecked {
padding-left: 0;
}
}
.Lexical__nestedListItem:before,
.Lexical__nestedListItem:after {
display: none;
}
@@ -31,6 +31,7 @@ import {
$isRemoteImageNode,
RemoteImageNode,
} from './Plugins/RemoteImagePlugin/RemoteImageNode'
import { $createInlineFileNode, $isInlineFileNode, InlineFileNode } from './Plugins/InlineFilePlugin/InlineFileNode'
const HorizontalRule: ElementTransformer = {
dependencies: [HorizontalRuleNode],
@@ -72,6 +73,26 @@ const IMAGE: TextMatchTransformer = {
type: 'text-match',
}
const INLINE_FILE: TextMatchTransformer = {
dependencies: [InlineFileNode],
export: (node) => {
if (!$isInlineFileNode(node)) {
return null
}
return node.getTextContent()
},
importRegExp: /(?:\[([^[]*)\])(?:\((data:(.*);[^(]+)\))/,
regExp: /(?:\[([^[]*)\])(?:\((data:(.*);[^(]+)\))$/,
replace: (textNode, match) => {
const [, name, src, mimeType] = match
const inlineFileNode = $createInlineFileNode(src, mimeType, name)
textNode.replace(inlineFileNode)
},
trigger: ')',
type: 'text-match',
}
// Table transformer, taken from Lexical Playground
const TABLE_ROW_REG_EXP = /^(?:\|)(.+)(?:\|)\s?$/
const TABLE_ROW_DIVIDER_REG_EXP = /^(\| ?:?-*:? ?)+\|\s?$/
@@ -224,6 +245,7 @@ export const MarkdownTransformers = [
TABLE,
CHECK_LIST,
IMAGE,
INLINE_FILE,
...ELEMENT_TRANSFORMERS,
...TEXT_FORMAT_TRANSFORMERS,
...TEXT_MATCH_TRANSFORMERS,
@@ -0,0 +1,92 @@
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
import {
$getSelection,
$isRangeSelection,
$isParagraphNode,
$isTextNode,
SELECTION_CHANGE_COMMAND,
COMMAND_PRIORITY_LOW,
} from 'lexical'
import { useCallback, useEffect, useRef } from 'react'
import { getSelectedNode } from '../Lexical/Utils/getSelectedNode'
import { mergeRegister } from '@lexical/utils'
export const EmptyLinePlaceholderPlugin = () => {
const [editor] = useLexicalComposerContext()
const placeholderElementRef = useRef<HTMLDivElement>(null)
const cursorUpdate = useCallback((): boolean => {
const selection = $getSelection()
if (selection && $isRangeSelection(selection)) {
if (!placeholderElementRef.current) {
return false
}
const node = getSelectedNode(selection)
if (!node) {
return false
}
const isParagraph = $isParagraphNode(node) || $isTextNode(node)
const text = node.getTextContent()
if (!isParagraph) {
return false
}
const rootElement = editor.getRootElement()
const nodeElement = editor.getElementByKey(node.getKey())
const placeholder = placeholderElementRef.current
if (!nodeElement || !placeholder.parentElement || !rootElement) {
return false
}
const rect = nodeElement.getBoundingClientRect()
const parentRect = placeholder.parentElement.getBoundingClientRect()
const rootRect = rootElement.getBoundingClientRect()
if (!text && editor.isEditable()) {
placeholder.style.top = `${rect.y}px`
placeholder.style.left = `${rect.x - parentRect.x + rootRect.x}px`
placeholder.style.opacity = '0.65'
} else {
placeholder.style.opacity = '0'
}
}
return false
}, [editor])
useEffect(() => {
return mergeRegister(
editor.registerCommand(SELECTION_CHANGE_COMMAND, cursorUpdate, COMMAND_PRIORITY_LOW),
editor.registerEditableListener(cursorUpdate),
)
}, [cursorUpdate, editor])
useEffect(() => {
const scrollerElem = editor.getRootElement()
const update = () => {
editor.getEditorState().read(() => {
cursorUpdate()
})
}
window.addEventListener('resize', update)
if (scrollerElem) {
scrollerElem.addEventListener('scroll', update)
}
return () => {
window.removeEventListener('resize', update)
if (scrollerElem) {
scrollerElem.removeEventListener('scroll', update)
}
}
}, [cursorUpdate, editor])
return (
<div
className="super-empty-line-placeholder pointer-events-none fixed text-passive-1 opacity-0"
ref={placeholderElementRef}
>
Type <span className="rounded bg-passive-4-opacity-variant p-0.5">/</span> for commands...
</div>
)
}
@@ -1,111 +0,0 @@
import { useApplication } from '@/Components/ApplicationProvider'
import { downloadBlobOnAndroid } from '@/NativeMobileWeb/DownloadBlobOnAndroid'
import { shareBlobOnMobile } from '@/NativeMobileWeb/ShareBlobOnMobile'
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
import { Platform } from '@standardnotes/snjs'
import {
sanitizeFileName,
SUPER_EXPORT_HTML,
SUPER_EXPORT_JSON,
SUPER_EXPORT_MARKDOWN,
} from '@standardnotes/ui-services'
import { useCallback, useEffect, useRef } from 'react'
import { useCommandService } from '@/Components/CommandProvider'
import { HeadlessSuperConverter } from '../../Tools/HeadlessSuperConverter'
export const ExportPlugin = () => {
const application = useApplication()
const [editor] = useLexicalComposerContext()
const commandService = useCommandService()
const converter = useRef(new HeadlessSuperConverter())
const downloadData = useCallback(
(data: Blob, fileName: string) => {
if (!application.isNativeMobileWeb()) {
application.archiveService.downloadData(data, fileName)
return
}
if (application.platform === Platform.Android) {
downloadBlobOnAndroid(application.mobileDevice, data, fileName).catch(console.error)
} else {
shareBlobOnMobile(application.mobileDevice, application.isNativeMobileWeb(), data, fileName).catch(
console.error,
)
}
},
[application],
)
const exportJson = useCallback(
(title: string) => {
const content = converter.current.convertSuperStringToOtherFormat(JSON.stringify(editor.getEditorState()), 'json')
const blob = new Blob([content], { type: 'application/json' })
downloadData(blob, `${sanitizeFileName(title)}.json`)
},
[downloadData, editor],
)
const exportMarkdown = useCallback(
(title: string) => {
const content = converter.current.convertSuperStringToOtherFormat(JSON.stringify(editor.getEditorState()), 'md')
const blob = new Blob([content], { type: 'text/markdown' })
downloadData(blob, `${sanitizeFileName(title)}.md`)
},
[downloadData, editor],
)
const exportHtml = useCallback(
(title: string) => {
const content = converter.current.convertSuperStringToOtherFormat(JSON.stringify(editor.getEditorState()), 'html')
const blob = new Blob([content], { type: 'text/html' })
downloadData(blob, `${sanitizeFileName(title)}.html`)
},
[downloadData, editor],
)
useEffect(() => {
return commandService.addCommandHandler({
command: SUPER_EXPORT_JSON,
onKeyDown: (_, data) => {
if (!data) {
throw new Error('No data provided for export command')
}
const title = data as string
exportJson(title)
},
})
}, [commandService, exportJson])
useEffect(() => {
return commandService.addCommandHandler({
command: SUPER_EXPORT_MARKDOWN,
onKeyDown: (_, data) => {
if (!data) {
throw new Error('No data provided for export command')
}
const title = data as string
exportMarkdown(title)
},
})
}, [commandService, exportMarkdown])
useEffect(() => {
return commandService.addCommandHandler({
command: SUPER_EXPORT_HTML,
onKeyDown: (_, data) => {
if (!data) {
throw new Error('No data provided for export command')
}
const title = data as string
exportHtml(title)
},
})
}, [commandService, exportHtml])
return null
}
@@ -22,7 +22,7 @@ export default function ImportPlugin({
const [editor] = useLexicalComposerContext()
useEffect(() => {
const dontAllowConversionOfEmptyStringWhichWouldResultInError = text.length === 0
const dontAllowConversionOfEmptyStringWhichWouldResultInError = text.trim().length === 0
if (dontAllowConversionOfEmptyStringWhichWouldResultInError) {
return
}
@@ -148,6 +148,10 @@ export class InlineFileNode extends DecoratorBlockNode {
return { element: object }
}
getTextContent(): string {
return `${this.__mimeType.startsWith('image/') ? '!' : ''}[${this.__fileName}](${this.__src})`
}
decorate(_editor: LexicalEditor, config: EditorConfig): JSX.Element {
const embedBlockTheme = config.theme.embedBlock || {}
const className = {
@@ -0,0 +1,25 @@
import { CheckListPlugin as LexicalCheckListPlugin } from '@lexical/react/LexicalCheckListPlugin'
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
import { ListNode } from '@lexical/list'
import { useEffect } from 'react'
export function CheckListPlugin() {
const [editor] = useLexicalComposerContext()
useEffect(() => {
return editor.registerNodeTransform(ListNode, (node) => {
if (node.getListType() !== 'check') {
return
}
editor.getEditorState().read(() => {
const element = editor.getElementByKey(node.getKey())
if (!element) {
return
}
element.classList.add('Lexical__checkList')
})
})
}, [editor])
return <LexicalCheckListPlugin />
}
@@ -0,0 +1,38 @@
import { ListNode, SerializedListNode } from '@lexical/list'
import { DOMExportOutput, LexicalEditor, Spread } from 'lexical'
export type SerializedListHTMLExportNode = Spread<
{
type: 'list-html-export'
},
SerializedListNode
>
export class ListHTMLExportNode extends ListNode {
static getType(): string {
return 'list-html-export'
}
static clone(node: ListNode): ListHTMLExportNode {
return new ListHTMLExportNode(node.getListType(), node.getStart(), node.getKey())
}
static importJSON(serializedNode: SerializedListNode): ListNode {
return super.importJSON(serializedNode)
}
exportDOM(editor: LexicalEditor): DOMExportOutput {
const { element } = super.exportDOM(editor)
if (this.getListType() === 'check' && element instanceof HTMLElement) {
element.classList.add('Lexical__checkList')
}
return { element }
}
exportJSON(): SerializedListHTMLExportNode {
return {
...super.exportJSON(),
type: 'list-html-export',
}
}
}
@@ -580,11 +580,10 @@ const ToolbarPlugin = () => {
'bg-contrast',
!isEditable ? 'hidden opacity-0' : '',
isMobile && !canShowToolbarOnMobile ? 'hidden' : '',
!isMobile &&
'border-b border-border translucent-ui:border-[--popover-border-color] translucent-ui:bg-[--popover-background-color] translucent-ui:[backdrop-filter:var(--popover-backdrop-filter)]',
!isMobile && 'border-b border-border bg-default',
!isMobile
? !isToolbarFixedToTop
? 'fixed left-0 top-0 z-tooltip translate-x-[--translate-x] translate-y-[--translate-y] rounded border py-0.5 opacity-0'
? 'fixed left-0 top-0 z-tooltip translate-x-[--translate-x] translate-y-[--translate-y] rounded border py-0.5 opacity-0 translucent-ui:border-[--popover-border-color] translucent-ui:bg-[--popover-background-color] translucent-ui:[backdrop-filter:var(--popover-backdrop-filter)]'
: 'w-full px-1 py-1'
: '',
)}
@@ -37,7 +37,6 @@ import PasswordPlugin from './Plugins/PasswordPlugin/PasswordPlugin'
import { useCommandService } from '@/Components/CommandProvider'
import { SUPER_SHOW_MARKDOWN_PREVIEW } from '@standardnotes/ui-services'
import { SuperNoteMarkdownPreview } from './SuperNoteMarkdownPreview'
import { ExportPlugin } from './Plugins/ExportPlugin/ExportPlugin'
import GetMarkdownPlugin, { GetMarkdownPluginInterface } from './Plugins/GetMarkdownPlugin/GetMarkdownPlugin'
import { useResponsiveEditorFontSize } from '@/Utils/getPlaintextFontSize'
import ReadonlyPlugin from './Plugins/ReadonlyPlugin/ReadonlyPlugin'
@@ -211,7 +210,14 @@ export const SuperEditor: FunctionComponent<Props> = ({
}, [])
return (
<div className="font-editor relative flex h-full w-full flex-col" ref={ref}>
<div
className={classNames(
'font-editor relative flex h-full w-full flex-col',
lineHeight && `leading-${lineHeight.toLowerCase()}`,
responsiveFontSize,
)}
ref={ref}
>
{featureStatus !== FeatureStatus.Entitled && (
<NotEntitledBanner featureStatus={featureStatus} feature={GetSuperNoteFeature()} />
)}
@@ -243,7 +249,6 @@ export const SuperEditor: FunctionComponent<Props> = ({
/>
<NodeObserverPlugin nodeType={BubbleNode} onRemove={handleBubbleRemove} />
<NodeObserverPlugin nodeType={FileNode} onRemove={handleBubbleRemove} />
<ExportPlugin />
{readonly === undefined && <ReadonlyPlugin note={note.current} />}
<AutoFocusPlugin isEnabled={controller.isTemplateNote} />
<SuperSearchContextProvider>
@@ -6,7 +6,7 @@ import {
isUIFeatureAnIframeFeature,
spaceSeparatedStrings,
} from '@standardnotes/snjs'
import { useCallback, useEffect, useMemo } from 'react'
import { useCallback, useEffect, useMemo, useState } from 'react'
import { useApplication } from '../ApplicationProvider'
import IframeFeatureView from '../ComponentView/IframeFeatureView'
import Icon from '../Icon/Icon'
@@ -52,18 +52,23 @@ const SuperNoteConverter = ({
return 'json'
}, [uiFeature])
const convertedContent = useMemo(() => {
if (note.text.length === 0) {
const [convertedContent, setConvertedContent] = useState<string>('')
useEffect(() => {
const convertContent = async () => {
if (note.text.length === 0) {
return note.text
}
try {
return new HeadlessSuperConverter().convertSuperStringToOtherFormat(note.text, format)
} catch (error) {
console.error(error)
}
return note.text
}
try {
return new HeadlessSuperConverter().convertSuperStringToOtherFormat(note.text, format)
} catch (error) {
console.error(error)
}
return note.text
convertContent().then(setConvertedContent).catch(console.error)
}, [format, note])
const componentViewer = useMemo(() => {
@@ -1,6 +1,6 @@
import { createHeadlessEditor } from '@lexical/headless'
import { $convertToMarkdownString, $convertFromMarkdownString } from '@lexical/markdown'
import { SuperConverterServiceInterface } from '@standardnotes/snjs'
import { FileItem, GenerateUuid, PrefKey, PrefValue, SuperConverterServiceInterface } from '@standardnotes/snjs'
import {
$createParagraphNode,
$getRoot,
@@ -11,42 +11,119 @@ import {
ParagraphNode,
} from 'lexical'
import BlocksEditorTheme from '../Lexical/Theme/Theme'
import { BlockEditorNodes } from '../Lexical/Nodes/AllNodes'
import { BlockEditorNodes, SuperExportNodes } from '../Lexical/Nodes/AllNodes'
import { MarkdownTransformers } from '../MarkdownTransformers'
import { $generateHtmlFromNodes, $generateNodesFromDOM } from '@lexical/html'
import { FileNode } from '../Plugins/EncryptedFilePlugin/Nodes/FileNode'
import { $createFileExportNode } from '../Lexical/Nodes/FileExportNode'
import { $createInlineFileNode, $isInlineFileNode, InlineFileNode } from '../Plugins/InlineFilePlugin/InlineFileNode'
import { $createFileNode } from '../Plugins/EncryptedFilePlugin/Nodes/FileUtils'
import { RemoteImageNode } from '../Plugins/RemoteImagePlugin/RemoteImageNode'
export class HeadlessSuperConverter implements SuperConverterServiceInterface {
private editor: LexicalEditor
private importEditor: LexicalEditor
private exportEditor: LexicalEditor
constructor() {
this.editor = createHeadlessEditor({
this.importEditor = createHeadlessEditor({
namespace: 'BlocksEditor',
theme: BlocksEditorTheme,
editable: false,
onError: (error: Error) => console.error(error),
nodes: [...BlockEditorNodes],
nodes: BlockEditorNodes,
})
this.exportEditor = createHeadlessEditor({
namespace: 'BlocksEditor',
theme: BlocksEditorTheme,
editable: false,
onError: (error: Error) => console.error(error),
nodes: SuperExportNodes,
})
}
isValidSuperString(superString: string): boolean {
try {
this.editor.parseEditorState(superString)
this.importEditor.parseEditorState(superString)
return true
} catch (error) {
return false
}
}
convertSuperStringToOtherFormat(superString: string, toFormat: 'txt' | 'md' | 'html' | 'json'): string {
async convertSuperStringToOtherFormat(
superString: string,
toFormat: 'txt' | 'md' | 'html' | 'json',
config?: {
embedBehavior?: PrefValue[PrefKey.SuperNoteExportEmbedBehavior]
getFileItem?: (id: string) => FileItem | undefined
getFileBase64?: (id: string) => Promise<string | undefined>
},
): Promise<string> {
if (superString.length === 0) {
return superString
}
this.editor.setEditorState(this.editor.parseEditorState(superString))
const { embedBehavior, getFileItem, getFileBase64 } = config ?? { embedBehavior: 'reference' }
if (embedBehavior === 'separate' && !getFileItem) {
throw new Error('getFileItem must be provided when embedBehavior is "separate"')
}
if (embedBehavior === 'inline' && !getFileItem && !getFileBase64) {
throw new Error('getFileItem and getFileBase64 must be provided when embedBehavior is "inline"')
}
this.exportEditor.setEditorState(this.exportEditor.parseEditorState(superString))
let content: string | undefined
this.editor.update(
await new Promise<void>((resolve) => {
this.exportEditor.update(
() => {
if (embedBehavior === 'reference') {
resolve()
return
}
if (!getFileItem) {
resolve()
return
}
const fileNodes = $nodesOfType(FileNode)
Promise.all(
fileNodes.map(async (fileNode) => {
const fileItem = getFileItem(fileNode.getId())
if (!fileItem) {
return
}
if (embedBehavior === 'inline' && getFileBase64) {
const fileBase64 = await getFileBase64(fileNode.getId())
if (!fileBase64) {
return
}
this.exportEditor.update(
() => {
const inlineFileNode = $createInlineFileNode(fileBase64, fileItem.mimeType, fileItem.name)
fileNode.replace(inlineFileNode)
},
{ discrete: true },
)
} else {
this.exportEditor.update(
() => {
const fileExportNode = $createFileExportNode(fileItem.name, fileItem.mimeType)
fileNode.replace(fileExportNode)
},
{ discrete: true },
)
}
}),
)
.then(() => resolve())
.catch(console.error)
},
{ discrete: true },
)
})
this.exportEditor.update(
() => {
switch (toFormat) {
case 'txt':
@@ -61,7 +138,7 @@ export class HeadlessSuperConverter implements SuperConverterServiceInterface {
break
}
case 'html':
content = $generateHtmlFromNodes(this.editor)
content = $generateHtmlFromNodes(this.exportEditor)
break
case 'json':
default:
@@ -88,7 +165,7 @@ export class HeadlessSuperConverter implements SuperConverterServiceInterface {
return otherFormatString
}
this.editor.update(
this.importEditor.update(
() => {
$getRoot().clear()
},
@@ -99,12 +176,12 @@ export class HeadlessSuperConverter implements SuperConverterServiceInterface {
let didThrow = false
if (fromFormat === 'html') {
this.editor.update(
this.importEditor.update(
() => {
try {
const parser = new DOMParser()
const dom = parser.parseFromString(otherFormatString, 'text/html')
const generatedNodes = $generateNodesFromDOM(this.editor, dom)
const generatedNodes = $generateNodesFromDOM(this.importEditor, dom)
const nodesToInsert: LexicalNode[] = []
generatedNodes.forEach((node) => {
const type = node.getType()
@@ -114,9 +191,9 @@ export class HeadlessSuperConverter implements SuperConverterServiceInterface {
if (
type === 'text' ||
type === 'link' ||
type === 'linebreak' ||
type === 'unencrypted-image' ||
type === 'inline-file' ||
node.isParentRequired()
type === 'inline-file'
) {
const paragraphNode = $createParagraphNode()
paragraphNode.append(node)
@@ -138,7 +215,7 @@ export class HeadlessSuperConverter implements SuperConverterServiceInterface {
{ discrete: true },
)
} else {
this.editor.update(
this.importEditor.update(
() => {
try {
$convertFromMarkdownString(otherFormatString, MarkdownTransformers)
@@ -157,6 +234,83 @@ export class HeadlessSuperConverter implements SuperConverterServiceInterface {
throw new Error('Could not import note')
}
return JSON.stringify(this.editor.getEditorState())
return JSON.stringify(this.importEditor.getEditorState())
}
getEmbeddedFileIDsFromSuperString(superString: string): string[] {
if (superString.length === 0) {
return []
}
this.exportEditor.setEditorState(this.exportEditor.parseEditorState(superString))
const ids: string[] = []
this.exportEditor.getEditorState().read(() => {
const fileNodes = $nodesOfType(FileNode)
fileNodes.forEach((fileNode) => {
ids.push(fileNode.getId())
})
})
return ids
}
async uploadAndReplaceInlineFilesInSuperString(
superString: string,
uploadFile: (file: File) => Promise<FileItem | undefined>,
linkFile: (file: FileItem) => Promise<void>,
generateUuid: GenerateUuid,
): Promise<string> {
if (superString.length === 0) {
return superString
}
this.importEditor.setEditorState(this.importEditor.parseEditorState(superString))
await new Promise<void>((resolve) => {
this.importEditor.update(
() => {
const inlineFileNodes = $nodesOfType(InlineFileNode)
const remoteImageNodes = $nodesOfType(RemoteImageNode).filter((node) => node.__src.startsWith('data:'))
const concatenatedNodes = [...inlineFileNodes, ...remoteImageNodes]
if (concatenatedNodes.length === 0) {
resolve()
return
}
Promise.all(
concatenatedNodes.map(async (node) => {
const blob = await fetch(node.__src).then((response) => response.blob())
const name = $isInlineFileNode(node) ? node.__fileName : node.__alt
const mimeType = $isInlineFileNode(node) ? node.__mimeType : node.__src.split(';')[0].split(':')[1]
const file = new File([blob], name || generateUuid.execute().getValue(), {
type: mimeType,
})
const uploadedFile = await uploadFile(file)
if (!uploadedFile) {
return
}
this.importEditor.update(
() => {
const fileNode = $createFileNode(uploadedFile.uuid)
node.replace(fileNode)
},
{ discrete: true },
)
await linkFile(uploadedFile)
}),
)
.then(() => resolve())
.catch(console.error)
},
{ discrete: true },
)
})
return JSON.stringify(this.importEditor.getEditorState())
}
}
@@ -8,6 +8,7 @@ const Switch = ({
disabled = false,
tabIndex,
forceDesktopStyle,
children,
}: {
checked: boolean
onChange: (checked: boolean) => void
@@ -15,20 +16,12 @@ const Switch = ({
disabled?: boolean
tabIndex?: number
forceDesktopStyle?: boolean
children?: React.ReactNode
}) => {
const isActive = checked && !disabled
return (
<label
className={classNames(
'relative box-content inline-block flex-shrink-0 cursor-pointer rounded-full border-2 border-solid border-transparent bg-clip-padding transition-colors duration-150 ease-out',
'ring-2 ring-transparent focus-within:border-default focus-within:shadow-none focus-within:outline-none focus-within:ring-info',
disabled ? 'opacity-50' : '',
isActive ? 'bg-info' : 'bg-neutral',
forceDesktopStyle ? 'h-4.5 w-8' : 'h-7 w-12 md:h-4.5 md:w-8',
className,
)}
>
<label className={classNames(disabled ? 'opacity-50' : '', className)}>
<VisuallyHidden>
<Checkbox
checked={checked}
@@ -40,15 +33,25 @@ const Switch = ({
</VisuallyHidden>
<div
className={classNames(
'absolute top-1/2 block -translate-y-1/2 rounded-full bg-default transition-transform duration-150 ease-out',
forceDesktopStyle ? 'left-[2px] h-3.5 w-3.5' : 'left-[0.15rem] h-6 w-6 md:left-[2px] md:h-3.5 md:w-3.5',
checked
? forceDesktopStyle
? 'translate-x-[calc(2rem-1.125rem)]'
: 'translate-x-[calc(3.25rem-1.5rem-0.5rem)] md:translate-x-[calc(2rem-1.125rem)]'
: '',
'relative box-content inline-block flex-shrink-0 cursor-pointer rounded-full border-2 border-solid border-transparent bg-clip-padding transition-colors duration-150 ease-out',
'ring-2 ring-transparent focus-within:border-default focus-within:shadow-none focus-within:outline-none focus-within:ring-info',
isActive ? 'bg-info' : 'bg-neutral',
forceDesktopStyle ? 'h-4.5 w-8' : 'h-7 w-12 md:h-4.5 md:w-8',
)}
/>
>
<div
className={classNames(
'absolute top-1/2 block -translate-y-1/2 rounded-full bg-default transition-transform duration-150 ease-out',
forceDesktopStyle ? 'left-[2px] h-3.5 w-3.5' : 'left-[0.15rem] h-6 w-6 md:left-[2px] md:h-3.5 md:w-3.5',
checked
? forceDesktopStyle
? 'translate-x-[calc(2rem-1.125rem)]'
: 'translate-x-[calc(3.25rem-1.5rem-0.5rem)] md:translate-x-[calc(2rem-1.125rem)]'
: '',
)}
/>
</div>
{children}
</label>
)
}
@@ -115,7 +115,7 @@ const SmartViewsListItem: FunctionComponent<Props> = ({ view, tagsState, setEdit
<div
role="button"
tabIndex={FOCUSABLE_BUT_NOT_TABBABLE}
className={classNames('tag group px-3.5', isSelected && 'selected', isFaded && 'opacity-50')}
className={classNames('tag group px-3.5 py-1 md:py-0', isSelected && 'selected', isFaded && 'opacity-50')}
onClick={selectCurrentTag}
onContextMenu={(event) => {
event.preventDefault()

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