Compare commits

...
Author SHA1 Message Date
StandardNotes CI 8c18feeffe chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].4
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].3
2023-04-18 16:50:07 +00:00
Aman Harwara 32c3b98293 chore: fix lockfile 2023-04-18 21:45:17 +05:30
Aman Harwara fe07c58e98 Merge branch 'main' of github.com:standardnotes/app 2023-04-18 21:41:10 +05:30
Aman Harwara 9e1bfc8c73 chore: update clipper when web changes 2023-04-18 21:41:02 +05:30
StandardNotes CI 3c563ae4c3 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected].3
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].2
2023-04-18 15:42:41 +00:00
Aman Harwara ac121265a9 Merge branch 'main' of github.com:standardnotes/app 2023-04-18 20:36:28 +05:30
Aman Harwara fc137a7e7b fix: Fixed issue where the Super note markdown preview modal could not be closed on mobile 2023-04-18 20:36:17 +05:30
StandardNotes CI 8f4ec469ba chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected].2
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].1
2023-04-18 11:39:42 +00:00
Aman Harwara 904d8fd1e9 Merge branch 'main' of github.com:standardnotes/app 2023-04-18 16:42:52 +05:30
Aman Harwara 877d46d8eb refactor: import modal 2023-04-18 16:42:42 +05:30
Karol Sójko 1bed27562a chore(web): reset Android app cert fingerprint to production value 2023-04-18 12:47:20 +02:00
StandardNotes CI 0203cf50ea chore(release): publish
- @standardnotes/[email protected].1
 - @standardnotes/[email protected]
2023-04-18 09:43:36 +00:00
Karol Sójko 4adabab256 fix(mobile): Android U2F authenticator response encoding (#2313) 2023-04-18 11:13:40 +02:00
StandardNotes CI 4182cebf6a chore(release): publish
- @standardnotes/[email protected].0
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].0
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].0
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].0
 - @standardnotes/[email protected].0
 - @standardnotes/[email protected].0
 - @standardnotes/[email protected].0
2023-04-17 13:26:13 +00:00
Karol Sójko 725f55fca7 feat(mobile): add U2F support for Android devices (#2311)
* feat(mobile): add U2F support for Android devices

* chore: fix specs
2023-04-17 14:57:41 +02:00
StandardNotes CI c0c9a4ff91 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
2023-04-15 06:51:22 +00:00
Aman Harwara 5f1a1bb2e8 Merge branch 'main' of github.com:standardnotes/app 2023-04-15 11:53:03 +05:30
Aman Harwara 83e7809b6e chore: update lexical 2023-04-15 11:52:52 +05:30
StandardNotes CI 46462ab2f2 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
2023-04-14 07:55:00 +00:00
Karol Sójko afdbdfa0f1 chore: fix assets url 2023-04-14 09:27:04 +02:00
StandardNotes CI dd9ba740ec chore(release): publish
- @standardnotes/[email protected]
2023-04-13 18:23:06 +00:00
Aman Harwara b9614a9ee1 chore: trigger clipper version bump 2023-04-13 23:21:55 +05:30
Aman Harwara 402471ffae chore: modify firefox ci 2023-04-13 23:18:20 +05:30
StandardNotes CI 91b5f1e88e chore(release): publish
- @standardnotes/[email protected]
2023-04-13 16:04:56 +00:00
Aman Harwara 12aa423f03 Merge branch 'main' of github.com:standardnotes/app 2023-04-13 21:05:46 +05:30
Aman Harwara 7c3df1bb10 chore: fix ci 2023-04-13 21:05:39 +05:30
StandardNotes CI f560ab029b chore(release): publish
- @standardnotes/[email protected]
2023-04-13 14:59:41 +00:00
Aman Harwara 3d69056f6a chore: add signed firefox web ext ci 2023-04-13 19:53:41 +05:30
StandardNotes CI 33d70ffe22 chore(release): publish
- @standardnotes/[email protected]
2023-04-13 10:58:01 +00:00
Aman Harwara 52f5640b3a chore: bump clipper version 2023-04-13 15:58:16 +05:30
Aman Harwara eeb673787d chore: fix clipper ci 2023-04-13 15:22:33 +05:30
Aman Harwara da1fd0d8f5 chore: fix clipper ci 2023-04-13 15:20:24 +05:30
StandardNotes CI a7bc65b172 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
2023-04-12 20:26:59 +00:00
Aman Harwara 42329533dc Merge branch 'main' of github.com:standardnotes/app 2023-04-13 01:30:23 +05:30
Aman Harwara 26a89dc332 chore: fix clipper ci workflow 2023-04-13 01:24:47 +05:30
StandardNotes CI 86d92a03bd chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
2023-04-12 19:37:20 +00:00
Aman Harwara 8c121d7352 chore: conditionally run clipper ci action 2023-04-13 00:39:09 +05:30
Aman Harwara fdf2a50fd1 chore: fix clipper ci gh action 2023-04-13 00:37:43 +05:30
Aman Harwara 268fede088 chore: clipper gh release & chrome web store ci 2023-04-13 00:35:54 +05:30
Aman Harwara 9f824266ac fix: Fixed issue where a new note would not be correctly synced after making changes 2023-04-13 00:06:53 +05:30
StandardNotes CI 6971e4c028 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
2023-04-12 14:27:25 +00:00
Karol Sójko 81ea831370 chore: fix cert fingerprint for android 2023-04-12 15:57:35 +02:00
StandardNotes CI b9d357b53f chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
2023-04-12 13:46:45 +00:00
Karol Sójko 45f7ed96f1 chore: fix assetlinks for android app on production packages 2023-04-12 15:16:07 +02:00
Aman Harwara e04f09edca chore: fix footer overflow 2023-04-12 18:42:52 +05:30
102 changed files with 1444 additions and 539 deletions
+102
View File
@@ -0,0 +1,102 @@
name: Clipper Github Release
on:
push:
tags:
- '*standardnotes/web*'
workflow_dispatch:
jobs:
build:
defaults:
run:
working-directory: packages/clipper
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Set up Node
uses: actions/setup-node@v3
with:
registry-url: 'https://registry.npmjs.org'
node-version-file: '.nvmrc'
cache: 'yarn'
- name: Install dependencies
run: yarn install --immutable
- name: Export version from package.json
run:
echo "PACKAGE_VERSION=$(grep '"version"' ./package.json | cut -d '"' -f 4 | cut -d "-" -f 1)" >> $GITHUB_ENV
- name: Build web package for clipper
run: BUILD_TARGET=clipper yarn build:web
- name: Build for Chromium (MV3)
env:
PACKAGE_VERSION: ${{ env.PACKAGE_VERSION }}
run: |
EXT_TARGET=chromium yarn build-mv3
cd dist
zip -r standard-notes-clipper-$PACKAGE_VERSION.chromium.zip *
mv standard-notes-clipper-$PACKAGE_VERSION.chromium.zip ../
- name: Build for Firefox (MV2)
env:
PACKAGE_VERSION: ${{ env.PACKAGE_VERSION }}
WEB_EXT_API_KEY: ${{ secrets.AMO_WEB_EXT_API_KEY }}
WEB_EXT_API_SECRET: ${{ secrets.AMO_WEB_EXT_API_SECRET }}
run: |
EXT_TARGET=firefox yarn build-mv2
yarn web-ext sign --source-dir dist --api-key $WEB_EXT_API_KEY --api-secret $WEB_EXT_API_SECRET --channel=listed --use-submission-api
mv web-ext-artifacts/*.xpi standard-notes-clipper-$PACKAGE_VERSION.firefox.xpi
- name: Upload
uses: actions/[email protected]
with:
name: assets
path: |
packages/clipper/*.chromium.zip
packages/clipper/*.firefox.xpi
publish:
defaults:
run:
working-directory: packages/clipper
runs-on: ubuntu-latest
needs: [build]
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Set up Node
uses: actions/setup-node@v3
with:
registry-url: 'https://registry.npmjs.org'
node-version-file: '.nvmrc'
cache: 'yarn'
- name: Install dependencies
run: yarn install --immutable
- name: Export version from package.json
run:
echo "PACKAGE_VERSION=$(grep '"version"' ./package.json | cut -d '"' -f 4 | cut -d "-" -f 1)" >> $GITHUB_ENV
- uses: actions/download-artifact@v3
with:
name: assets
path: packages/clipper/artifacts
- name: Generate Release Notes
uses: ./actions/release-notes
with:
package: clipper
id: release-notes
continue-on-error: true
- name: Release
uses: softprops/action-gh-release@v1
with:
token: ${{ secrets.CI_PAT_TOKEN }}
tag_name: "@standardnotes/clipper@${{ env.PACKAGE_VERSION }}"
name: "Clipper ${{ env.PACKAGE_VERSION }}"
body: ${{ steps.release-notes.outputs.result }}
draft: false
files: packages/clipper/artifacts/*
- name: Publish to Chrome Web Store
uses: trmcnvn/chrome-addon@v2
with:
extension: heapafmadojoodklnkhjanbinemaagok
zip: packages/clipper/artifacts/standard-notes-clipper-${{ env.PACKAGE_VERSION }}.chromium.zip
client-id: ${{ secrets.CHROME_CLIENT_ID }}
client-secret: ${{ secrets.CHROME_CLIENT_SECRET }}
refresh-token: ${{ secrets.CHROME_REFRESH_TOKEN }}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+14
View File
@@ -3,6 +3,20 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [1.26.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-17)
### Features
* **mobile:** add U2F support for Android devices ([#2311](https://github.com/standardnotes/app/issues/2311)) ([725f55f](https://github.com/standardnotes/app/commit/725f55fca794b86c245742837af7e4370cebd68c))
## [1.25.14](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-15)
**Note:** Version bump only for package @standardnotes/api
## [1.25.13](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-14)
**Note:** Version bump only for package @standardnotes/api
## [1.25.12](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-11)
**Note:** Version bump only for package @standardnotes/api
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/api",
"version": "1.25.12",
"version": "1.26.0",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
@@ -37,7 +37,7 @@
},
"dependencies": {
"@standardnotes/common": "^1.46.6",
"@standardnotes/domain-core": "^1.11.3",
"@standardnotes/domain-core": "^1.12.0",
"@standardnotes/encryption": "workspace:*",
"@standardnotes/models": "workspace:*",
"@standardnotes/responses": "workspace:*",
+20
View File
@@ -3,6 +3,26 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.0.9](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-18)
**Note:** Version bump only for package @standardnotes/clipper
## [1.0.8](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-13)
**Note:** Version bump only for package @standardnotes/clipper
## [1.0.7](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-13)
**Note:** Version bump only for package @standardnotes/clipper
## [1.0.6](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-13)
**Note:** Version bump only for package @standardnotes/clipper
## [1.0.5](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-13)
**Note:** Version bump only for package @standardnotes/clipper
## [1.0.3](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-11)
**Note:** Version bump only for package @standardnotes/clipper
+2 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@standardnotes/clipper",
"description": "Web clipper browser extension for Standard Notes",
"version": "1.0.3",
"version": "1.0.9",
"private": true,
"scripts": {
"build-mv2": "yarn clean && webpack --config ./webpack.config.prod.js",
@@ -19,6 +19,7 @@
"clean": "rm -rf dist"
},
"devDependencies": {
"@standardnotes/web": "workspace:*",
"@types/webextension-polyfill": "^0.10.0",
"babel-loader": "^9.1.0",
"copy-webpack-plugin": "11.0.0",
+40
View File
@@ -3,6 +3,46 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [3.105.58](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-18)
**Note:** Version bump only for package @standardnotes/desktop
## [3.105.57](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-18)
**Note:** Version bump only for package @standardnotes/desktop
## [3.105.56](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-18)
**Note:** Version bump only for package @standardnotes/desktop
## [3.105.55](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-17)
**Note:** Version bump only for package @standardnotes/desktop
## [3.105.54](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-15)
**Note:** Version bump only for package @standardnotes/desktop
## [3.105.53](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-14)
**Note:** Version bump only for package @standardnotes/desktop
## [3.105.52](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-12)
**Note:** Version bump only for package @standardnotes/desktop
## [3.105.51](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-12)
**Note:** Version bump only for package @standardnotes/desktop
## [3.105.50](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-12)
**Note:** Version bump only for package @standardnotes/desktop
## [3.105.49](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-12)
**Note:** Version bump only for package @standardnotes/desktop
## [3.105.48](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-11)
**Note:** Version bump only for package @standardnotes/desktop
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@standardnotes/desktop",
"main": "./app/dist/index.js",
"version": "3.105.48",
"version": "3.105.58",
"license": "AGPL-3.0-or-later",
"author": "Standard Notes.",
"private": true,
+12
View File
@@ -3,6 +3,18 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.21.28](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-17)
**Note:** Version bump only for package @standardnotes/encryption
## [1.21.27](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-15)
**Note:** Version bump only for package @standardnotes/encryption
## [1.21.26](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-14)
**Note:** Version bump only for package @standardnotes/encryption
## [1.21.25](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-11)
**Note:** Version bump only for package @standardnotes/encryption
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/encryption",
"version": "1.21.25",
"version": "1.21.28",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
+14
View File
@@ -3,6 +3,20 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [1.59.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-17)
### Features
* **mobile:** add U2F support for Android devices ([#2311](https://github.com/standardnotes/app/issues/2311)) ([725f55f](https://github.com/standardnotes/app/commit/725f55fca794b86c245742837af7e4370cebd68c))
## [1.58.16](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-15)
**Note:** Version bump only for package @standardnotes/features
## [1.58.15](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-14)
**Note:** Version bump only for package @standardnotes/features
## [1.58.14](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-11)
**Note:** Version bump only for package @standardnotes/features
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/features",
"version": "1.58.14",
"version": "1.59.0",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
@@ -26,7 +26,7 @@
},
"dependencies": {
"@standardnotes/common": "^1.46.6",
"@standardnotes/domain-core": "^1.11.3",
"@standardnotes/domain-core": "^1.12.0",
"@standardnotes/security": "^1.7.6",
"reflect-metadata": "^0.1.13"
},
@@ -37,7 +37,7 @@ export function GetDeprecatedFeatures(): FeatureDescription[] {
deprecated: true,
permission_name: PermissionName.BoldEditor,
description: 'A simple and peaceful rich editor that helps you write and think clearly.',
thumbnail_url: 'https://s3.amazonaws.com/standard-notes/screenshots/models/editors/bold.jpg',
thumbnail_url: 'https://assets.standardnotes.com/screenshots/models/editors/bold.jpg',
availableInRoles: [RoleName.NAMES.PlusUser, RoleName.NAMES.ProUser],
})
@@ -51,7 +51,7 @@ export function GetDeprecatedFeatures(): FeatureDescription[] {
deprecated: true,
permission_name: PermissionName.MarkdownBasicEditor,
description: 'A Markdown editor with dynamic split-pane preview.',
thumbnail_url: 'https://s3.amazonaws.com/standard-notes/screenshots/models/editors/simple-markdown.jpg',
thumbnail_url: 'https://assets.standardnotes.com/screenshots/models/editors/simple-markdown.jpg',
availableInRoles: [RoleName.NAMES.PlusUser, RoleName.NAMES.ProUser],
})
@@ -81,7 +81,7 @@ export function GetDeprecatedFeatures(): FeatureDescription[] {
spellcheckControl: true,
deprecated: true,
description: 'A minimal Markdown editor with live rendering and in-text search via Ctrl/Cmd + F',
thumbnail_url: 'https://s3.amazonaws.com/standard-notes/screenshots/models/editors/min-markdown.jpg',
thumbnail_url: 'https://assets.standardnotes.com/screenshots/models/editors/min-markdown.jpg',
availableInRoles: [RoleName.NAMES.PlusUser, RoleName.NAMES.ProUser],
})
@@ -96,7 +96,7 @@ export function GetDeprecatedFeatures(): FeatureDescription[] {
deprecated: true,
index_path: 'index.html',
description: 'A beautiful split-pane Markdown editor with synced-scroll, LaTeX support, and colorful syntax.',
thumbnail_url: 'https://s3.amazonaws.com/standard-notes/screenshots/models/editors/fancy-markdown.jpg',
thumbnail_url: 'https://assets.standardnotes.com/screenshots/models/editors/fancy-markdown.jpg',
availableInRoles: [RoleName.NAMES.PlusUser, RoleName.NAMES.ProUser],
})
@@ -123,7 +123,7 @@ export function GetDeprecatedFeatures(): FeatureDescription[] {
deprecated: true,
description:
'Encrypted attachments for your notes using your Dropbox, Google Drive, or WebDAV server. Limited to 50MB per file.',
thumbnail_url: 'https://s3.amazonaws.com/standard-notes/screenshots/models/FileSafe-banner.png',
thumbnail_url: 'https://assets.standardnotes.com/screenshots/models/FileSafe-banner.png',
availableInRoles: [RoleName.NAMES.PlusUser, RoleName.NAMES.ProUser],
})
@@ -20,7 +20,7 @@ export function editors(): EditorFeatureDescription[] {
description:
'Syntax highlighting and convenient keyboard shortcuts for over 120 programming' +
' languages. Ideal for code snippets and procedures.',
thumbnail_url: 'https://s3.amazonaws.com/standard-notes/screenshots/models/editors/code.jpg',
thumbnail_url: 'https://assets.standardnotes.com/screenshots/models/editors/code.jpg',
availableInRoles: [RoleName.NAMES.PlusUser, RoleName.NAMES.ProUser],
})
@@ -34,7 +34,7 @@ export function editors(): EditorFeatureDescription[] {
spellcheckControl: true,
description:
'From highlighting to custom font sizes and colors, to tables and lists, this editor is perfect for crafting any document.',
thumbnail_url: 'https://s3.amazonaws.com/standard-notes/screenshots/models/editors/plus-editor.jpg',
thumbnail_url: 'https://assets.standardnotes.com/screenshots/models/editors/plus-editor.jpg',
availableInRoles: [RoleName.NAMES.PlusUser, RoleName.NAMES.ProUser],
})
@@ -48,7 +48,7 @@ export function editors(): EditorFeatureDescription[] {
spellcheckControl: true,
description:
'A fully featured Markdown editor that supports live preview, a styling toolbar, and split pane support.',
thumbnail_url: 'https://s3.amazonaws.com/standard-notes/screenshots/models/editors/adv-markdown.jpg',
thumbnail_url: 'https://assets.standardnotes.com/screenshots/models/editors/adv-markdown.jpg',
availableInRoles: [RoleName.NAMES.PlusUser, RoleName.NAMES.ProUser],
})
@@ -63,7 +63,7 @@ export function editors(): EditorFeatureDescription[] {
permission_name: PermissionName.TaskEditor,
description:
'A great way to manage short-term and long-term to-do"s. You can mark tasks as completed, change their order, and edit the text naturally in place.',
thumbnail_url: 'https://s3.amazonaws.com/standard-notes/screenshots/models/editors/task-editor.jpg',
thumbnail_url: 'https://assets.standardnotes.com/screenshots/models/editors/task-editor.jpg',
availableInRoles: [RoleName.NAMES.PlusUser, RoleName.NAMES.ProUser],
})
@@ -77,7 +77,7 @@ export function editors(): EditorFeatureDescription[] {
permission_name: PermissionName.TokenVaultEditor,
description:
'Encrypt and protect your 2FA secrets for all your internet accounts. Authenticator handles your 2FA secrets so that you never lose them again, or have to start over when you get a new device.',
thumbnail_url: 'https://standard-notes.s3.amazonaws.com/screenshots/models/editors/token-vault.png',
thumbnail_url: 'https://assets.standardnotes.com/screenshots/models/editors/token-vault.png',
availableInRoles: [RoleName.NAMES.PlusUser, RoleName.NAMES.ProUser],
})
@@ -91,7 +91,7 @@ export function editors(): EditorFeatureDescription[] {
permission_name: PermissionName.SheetsEditor,
description:
'A powerful spreadsheet editor with formatting and formula support. Not recommended for large data sets, as encryption of such data may decrease editor performance.',
thumbnail_url: 'https://s3.amazonaws.com/standard-notes/screenshots/models/editors/spreadsheets.png',
thumbnail_url: 'https://assets.standardnotes.com/screenshots/models/editors/spreadsheets.png',
availableInRoles: [RoleName.NAMES.PlusUser, RoleName.NAMES.ProUser],
})
+12
View File
@@ -3,6 +3,18 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.28.33](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-17)
**Note:** Version bump only for package @standardnotes/filepicker
## [1.28.32](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-15)
**Note:** Version bump only for package @standardnotes/filepicker
## [1.28.31](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-14)
**Note:** Version bump only for package @standardnotes/filepicker
## [1.28.30](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-11)
**Note:** Version bump only for package @standardnotes/filepicker
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/filepicker",
"version": "1.28.30",
"version": "1.28.33",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
+12
View File
@@ -3,6 +3,18 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.14.43](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-17)
**Note:** Version bump only for package @standardnotes/files
## [1.14.42](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-15)
**Note:** Version bump only for package @standardnotes/files
## [1.14.41](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-14)
**Note:** Version bump only for package @standardnotes/files
## [1.14.40](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-11)
**Note:** Version bump only for package @standardnotes/files
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/files",
"version": "1.14.40",
"version": "1.14.43",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
+48
View File
@@ -3,6 +3,54 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [3.52.4](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-18)
**Note:** Version bump only for package @standardnotes/mobile
## [3.52.3](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-18)
**Note:** Version bump only for package @standardnotes/mobile
## [3.52.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-18)
**Note:** Version bump only for package @standardnotes/mobile
## [3.52.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-18)
### Bug Fixes
* **mobile:** Android U2F authenticator response encoding ([#2313](https://github.com/standardnotes/app/issues/2313)) ([4adabab](https://github.com/standardnotes/app/commit/4adabab256dd2efde4209d2321564206f6719c69))
# [3.52.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-17)
### Features
* **mobile:** add U2F support for Android devices ([#2311](https://github.com/standardnotes/app/issues/2311)) ([725f55f](https://github.com/standardnotes/app/commit/725f55fca794b86c245742837af7e4370cebd68c))
## [3.51.87](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-15)
**Note:** Version bump only for package @standardnotes/mobile
## [3.51.86](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-14)
**Note:** Version bump only for package @standardnotes/mobile
## [3.51.85](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-12)
**Note:** Version bump only for package @standardnotes/mobile
## [3.51.84](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-12)
**Note:** Version bump only for package @standardnotes/mobile
## [3.51.83](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-12)
**Note:** Version bump only for package @standardnotes/mobile
## [3.51.82](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-12)
**Note:** Version bump only for package @standardnotes/mobile
## [3.51.81](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-11)
**Note:** Version bump only for package @standardnotes/mobile
+1
View File
@@ -178,6 +178,7 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.1.0-rc01'
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.0.0")
implementation 'de.undercouch:gradle-download-task:5.0.2'
implementation 'com.google.android.gms:play-services-fido:20.0.1'
debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}")
@@ -0,0 +1,204 @@
package com.standardnotes;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.IntentSender;
import android.util.Base64;
import android.util.Log;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ActivityEventListener;
import com.facebook.react.bridge.BaseActivityEventListener;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.WritableMap;
import java.util.Map;
import java.util.HashMap;
import java.util.ArrayList;
import org.json.JSONObject;
import org.json.JSONArray;
import org.json.JSONException;
import com.google.android.gms.fido.fido2.Fido2ApiClient;
import com.google.android.gms.fido.fido2.api.common.AuthenticatorErrorResponse;
import com.google.android.gms.fido.fido2.api.common.AuthenticatorAssertionResponse;
import com.google.android.gms.fido.fido2.api.common.AuthenticationExtensionsClientOutputs;
import com.google.android.gms.fido.fido2.api.common.PublicKeyCredential;
import com.google.android.gms.fido.fido2.api.common.PublicKeyCredentialType;
import com.google.android.gms.fido.fido2.api.common.PublicKeyCredentialDescriptor;
import com.google.android.gms.fido.fido2.api.common.PublicKeyCredentialRequestOptions;
import com.google.android.gms.fido.fido2.api.common.PublicKeyCredentialRequestOptions;
import com.google.android.gms.fido.Fido;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
public class Fido2ApiModule extends ReactContextBaseJavaModule {
private final Fido2ApiClient fido2ApiClient;
private final ReactApplicationContext reactContext;
private static final int SIGN_REQUEST_CODE = 111;
private static final String LOGS_TAG = "Fido2ApiModule";
private static final String RP_ID = "app.standardnotes.com";
private Promise signInPromise;
private final ActivityEventListener activityEventListener = new BaseActivityEventListener() {
@Override
public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent intent) {
super.onActivityResult(activity, requestCode, resultCode, intent);
if (requestCode == SIGN_REQUEST_CODE) {
if (signInPromise != null) {
if (resultCode == Activity.RESULT_CANCELED) {
Log.e(LOGS_TAG, "FIDO sign in cancelled");
signInPromise.reject("FIDO sign in cancelled");
} else if (resultCode == Activity.RESULT_OK) {
if (intent.hasExtra(Fido.FIDO2_KEY_ERROR_EXTRA)) {
AuthenticatorErrorResponse authenticatorErrorResponse =
AuthenticatorErrorResponse.deserializeFromBytes(intent.getByteArrayExtra(Fido.FIDO2_KEY_ERROR_EXTRA));
Log.e(LOGS_TAG, "Fido Error: " + authenticatorErrorResponse.getErrorMessage());
signInPromise.reject(authenticatorErrorResponse.getErrorMessage());
} else if (intent.hasExtra(Fido.FIDO2_KEY_CREDENTIAL_EXTRA)) {
PublicKeyCredential publicKeyCredential =
PublicKeyCredential.deserializeFromBytes(
intent.getByteArrayExtra(Fido.FIDO2_KEY_CREDENTIAL_EXTRA));
AuthenticatorAssertionResponse signedData =
(AuthenticatorAssertionResponse) publicKeyCredential.getResponse();
WritableMap signInResult = Arguments.createMap();
signInResult.putString("id", Base64.encodeToString(signedData.getKeyHandle(), Base64.URL_SAFE + Base64.NO_WRAP + Base64.NO_PADDING));
signInResult.putString("rawId", Base64.encodeToString(signedData.getKeyHandle(), Base64.URL_SAFE + Base64.NO_WRAP + Base64.NO_PADDING));
byte[] extensionOutputsBytes = null;
AuthenticationExtensionsClientOutputs extensionOutputs = publicKeyCredential.getClientExtensionResults();
if (extensionOutputs != null) {
extensionOutputsBytes = extensionOutputs.serializeToBytes();
if (extensionOutputsBytes != null) {
signInResult.putString("clientExtensionResults", Base64.encodeToString(extensionOutputsBytes, Base64.URL_SAFE + Base64.NO_WRAP + Base64.NO_PADDING));
}
}
WritableMap response = Arguments.createMap();
response.putString("clientDataJSON", Base64.encodeToString(signedData.getClientDataJSON(), Base64.URL_SAFE + Base64.NO_WRAP + Base64.NO_PADDING));
response.putString("authenticatorData", Base64.encodeToString(signedData.getAuthenticatorData(), Base64.URL_SAFE + Base64.NO_WRAP + Base64.NO_PADDING));
response.putString("signature", Base64.encodeToString(signedData.getSignature(), Base64.URL_SAFE + Base64.NO_WRAP + Base64.NO_PADDING));
byte[] userHandle = signedData.getUserHandle();
if (userHandle != null) {
response.putString("userHandle", Base64.encodeToString(userHandle, Base64.URL_SAFE + Base64.NO_WRAP + Base64.NO_PADDING));
}
signInResult.putMap("response", response);
signInResult.putString("type", PublicKeyCredentialType.PUBLIC_KEY.toString());
signInPromise.resolve(signInResult);
}
}
}
signInPromise = null;
}
}
};
Fido2ApiModule(ReactApplicationContext context) {
super(context);
fido2ApiClient = Fido.getFido2ApiClient(context);
context.addActivityEventListener(activityEventListener);
this.reactContext = context;
}
@Override
public String getName() {
return "Fido2ApiModule";
}
@ReactMethod
public void promptForU2FAuthentication(String authenticationOptionsJSONString, Promise promise) throws JSONException {
signInPromise = promise;
JSONObject authenticationOptions = new JSONObject(authenticationOptionsJSONString);
ArrayList<PublicKeyCredentialDescriptor> allowedKeys = new ArrayList<PublicKeyCredentialDescriptor>();
JSONArray allowedCredentials = authenticationOptions.getJSONArray("allowCredentials");
for (int i = 0, size = allowedCredentials.length(); i < size; i++) {
JSONObject allowedCredential = allowedCredentials.getJSONObject(i);
allowedKeys.add(
new PublicKeyCredentialDescriptor(
PublicKeyCredentialType.PUBLIC_KEY.toString(),
this.convertBase64URLStringToBytes(allowedCredential.getString("id")),
null
)
);
}
String challenge = authenticationOptions.getString("challenge");
Double timeout = authenticationOptions.getDouble("timeout") / 1000d;
PublicKeyCredentialRequestOptions.Builder optionsBuilder = new PublicKeyCredentialRequestOptions
.Builder()
.setRpId(RP_ID)
.setAllowList(allowedKeys)
.setChallenge(this.convertBase64URLStringToBytes(challenge))
.setTimeoutSeconds(timeout);
PublicKeyCredentialRequestOptions options = optionsBuilder.build();
Task result = this.fido2ApiClient.getSignPendingIntent(options);
final Activity activity = this.reactContext.getCurrentActivity();
result.addOnSuccessListener(
new OnSuccessListener<PendingIntent>() {
@Override
public void onSuccess(PendingIntent fido2PendingIntent) {
if (fido2PendingIntent == null) {
Log.e(LOGS_TAG, "No pending FIDO intent returned");
return;
}
try {
activity.startIntentSenderForResult(
fido2PendingIntent.getIntentSender(),
SIGN_REQUEST_CODE,
null,
0,
0,
0
);
} catch (IntentSender.SendIntentException exception) {
Log.e(LOGS_TAG, "Error starting FIDO intent: " + exception.getMessage());
}
}
}
);
result.addOnFailureListener(
new OnFailureListener() {
@Override
public void onFailure(Exception e) {
Log.e(LOGS_TAG, "Error getting FIDO intent: " + e.getMessage());
signInPromise.reject(e.getMessage());
}
}
);
}
private byte[] convertBase64URLStringToBytes(String base64URLString) {
String base64String = base64URLString.replace('-', '+').replace('_', '/');
int padding = (4 - (base64String.length() % 4)) % 4;
for (int i = 0; i < padding; i++) {
base64String += '=';
}
return Base64.decode(base64String, Base64.DEFAULT);
}
}
@@ -0,0 +1,26 @@
package com.standardnotes;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Fido2ApiPackage implements ReactPackage {
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();
modules.add(new Fido2ApiModule(reactContext));
return modules;
}
}
@@ -37,6 +37,8 @@ public class MainApplication extends Application implements ReactApplication {
@SuppressWarnings("UnnecessaryLocalVariable")
List<ReactPackage> packages = new PackageList(this).getPackages();
packages.add(new Fido2ApiPackage());
return packages;
}
+4 -1
View File
@@ -43,4 +43,7 @@ newArchEnabled=false
hermesEnabled=true
# Set AsyncStorage limit
AsyncStorage_db_size_in_MB=50
AsyncStorage_db_size_in_MB=50
# The URL of the server
host=https://app.standardnotes.com
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/mobile",
"version": "3.51.81",
"version": "3.52.4",
"author": "Standard Notes.",
"private": true,
"license": "AGPL-3.0-or-later",
+21
View File
@@ -22,6 +22,7 @@ import {
AppStateStatus,
ColorSchemeName,
Linking,
NativeModules,
PermissionsAndroid,
Platform,
StatusBar,
@@ -71,6 +72,26 @@ export class MobileDevice implements MobileDeviceInterface {
private colorSchemeService?: ColorSchemeObserverService,
) {}
async authenticateWithU2F(authenticationOptionsJSONString: string): Promise<Record<string, unknown> | null> {
const { Fido2ApiModule } = NativeModules
if (!Fido2ApiModule) {
this.consoleLog('Fido2ApiModule is not available')
return null
}
try {
const response = await Fido2ApiModule.promptForU2FAuthentication(authenticationOptionsJSONString)
return response
} catch (error) {
this.consoleLog(`Fido2ApiModule.authenticateWithU2F error: ${(error as Error).message}`)
return null
}
}
purchaseSubscriptionIAP(plan: AppleIAPProductId): Promise<AppleIAPReceipt | undefined> {
return PurchaseManager.getInstance().purchase(plan)
}
+12
View File
@@ -3,6 +3,18 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.43.16](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-17)
**Note:** Version bump only for package @standardnotes/models
## [1.43.15](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-15)
**Note:** Version bump only for package @standardnotes/models
## [1.43.14](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-14)
**Note:** Version bump only for package @standardnotes/models
## [1.43.13](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-11)
**Note:** Version bump only for package @standardnotes/models
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/models",
"version": "1.43.13",
"version": "1.43.16",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
+44
View File
@@ -3,6 +3,50 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.4.235](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-18)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.234](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-18)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.233](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-18)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.232](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-18)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.231](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-17)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.230](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-15)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.229](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-14)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.228](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-12)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.227](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-12)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.226](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-12)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.225](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-12)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.224](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-11)
**Note:** Version bump only for package @standardnotes/releases
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/releases",
"version": "1.4.224",
"version": "1.4.235",
"license": "AGPL-3.0-or-later",
"main": "dist/releases.json",
"types": "dist/index.d.ts",
+12
View File
@@ -3,6 +3,18 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.13.18](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-17)
**Note:** Version bump only for package @standardnotes/responses
## [1.13.17](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-15)
**Note:** Version bump only for package @standardnotes/responses
## [1.13.16](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-14)
**Note:** Version bump only for package @standardnotes/responses
## [1.13.15](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-11)
**Note:** Version bump only for package @standardnotes/responses
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/responses",
"version": "1.13.15",
"version": "1.13.18",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
+14
View File
@@ -3,6 +3,20 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [1.58.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-17)
### Features
* **mobile:** add U2F support for Android devices ([#2311](https://github.com/standardnotes/app/issues/2311)) ([725f55f](https://github.com/standardnotes/app/commit/725f55fca794b86c245742837af7e4370cebd68c))
## [1.57.15](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-15)
**Note:** Version bump only for package @standardnotes/services
## [1.57.14](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-14)
**Note:** Version bump only for package @standardnotes/services
## [1.57.13](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-11)
**Note:** Version bump only for package @standardnotes/services
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/services",
"version": "1.57.13",
"version": "1.58.0",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
@@ -18,7 +18,7 @@
"dependencies": {
"@standardnotes/api": "workspace:^",
"@standardnotes/common": "^1.46.4",
"@standardnotes/domain-core": "^1.11.3",
"@standardnotes/domain-core": "^1.12.0",
"@standardnotes/encryption": "workspace:^",
"@standardnotes/files": "workspace:^",
"@standardnotes/models": "workspace:^",
@@ -1,6 +1,7 @@
import { Environment, Platform, RawKeychainValue } from '@standardnotes/models'
import { AppleIAPProductId } from './../Subscription/AppleIAPProductId'
import { DeviceInterface } from './DeviceInterface'
import { Environment, Platform, RawKeychainValue } from '@standardnotes/models'
import { AppleIAPReceipt } from '../Subscription/AppleIAPReceipt'
export interface MobileDeviceInterface extends DeviceInterface {
@@ -25,4 +26,5 @@ export interface MobileDeviceInterface extends DeviceInterface {
getAppState(): Promise<'active' | 'background' | 'inactive' | 'unknown' | 'extension'>
getColorScheme(): Promise<'light' | 'dark' | null | undefined>
purchaseSubscriptionIAP(plan: AppleIAPProductId): Promise<AppleIAPReceipt | undefined>
authenticateWithU2F(authenticationOptionsJSONString: string): Promise<Record<string, unknown> | null>
}
+14
View File
@@ -3,6 +3,20 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [2.167.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-17)
### Features
* **mobile:** add U2F support for Android devices ([#2311](https://github.com/standardnotes/app/issues/2311)) ([725f55f](https://github.com/standardnotes/app/commit/725f55fca794b86c245742837af7e4370cebd68c))
## [2.166.22](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-15)
**Note:** Version bump only for package @standardnotes/snjs
## [2.166.21](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-14)
**Note:** Version bump only for package @standardnotes/snjs
## [2.166.20](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-11)
**Note:** Version bump only for package @standardnotes/snjs
+9 -1
View File
@@ -102,6 +102,7 @@ import { ListRevisions } from '@Lib/Domain/UseCase/ListRevisions/ListRevisions'
import { GetRevision } from '@Lib/Domain/UseCase/GetRevision/GetRevision'
import { DeleteRevision } from '@Lib/Domain/UseCase/DeleteRevision/DeleteRevision'
import { GetAuthenticatorAuthenticationResponse } from '@Lib/Domain/UseCase/GetAuthenticatorAuthenticationResponse/GetAuthenticatorAuthenticationResponse'
import { GetAuthenticatorAuthenticationOptions } from '@Lib/Domain/UseCase/GetAuthenticatorAuthenticationOptions/GetAuthenticatorAuthenticationOptions'
/** How often to automatically sync, in milliseconds */
const DEFAULT_AUTO_SYNC_INTERVAL = 30_000
@@ -182,6 +183,7 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli
private declare _addAuthenticator: AddAuthenticator
private declare _listAuthenticators: ListAuthenticators
private declare _deleteAuthenticator: DeleteAuthenticator
private declare _getAuthenticatorAuthenticationOptions: GetAuthenticatorAuthenticationOptions
private declare _getAuthenticatorAuthenticationResponse: GetAuthenticatorAuthenticationResponse
private declare _listRevisions: ListRevisions
private declare _getRevision: GetRevision
@@ -284,6 +286,10 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli
return this._deleteAuthenticator
}
get getAuthenticatorAuthenticationOptions(): GetAuthenticatorAuthenticationOptions {
return this._getAuthenticatorAuthenticationOptions
}
get getAuthenticatorAuthenticationResponse(): GetAuthenticatorAuthenticationResponse {
return this._getAuthenticatorAuthenticationResponse
}
@@ -1819,8 +1825,10 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli
this._deleteAuthenticator = new DeleteAuthenticator(this.authenticatorManager)
this._getAuthenticatorAuthenticationOptions = new GetAuthenticatorAuthenticationOptions(this.authenticatorManager)
this._getAuthenticatorAuthenticationResponse = new GetAuthenticatorAuthenticationResponse(
this.authenticatorManager,
this._getAuthenticatorAuthenticationOptions,
this.options.u2fAuthenticatorVerificationPromptFunction,
)
@@ -0,0 +1,42 @@
import { AuthenticatorClientInterface } from '@standardnotes/services'
import { GetAuthenticatorAuthenticationOptions } from './GetAuthenticatorAuthenticationOptions'
describe('GetAuthenticatorAuthenticationOptions', () => {
let authenticatorClient: AuthenticatorClientInterface
const createUseCase = () => new GetAuthenticatorAuthenticationOptions(authenticatorClient)
beforeEach(() => {
authenticatorClient = {} as jest.Mocked<AuthenticatorClientInterface>
authenticatorClient.generateAuthenticationOptions = jest.fn().mockResolvedValue({ foo: 'bar' })
})
it('should return an error if username is not provided', async () => {
const result = await createUseCase().execute({
username: '',
})
expect(result.isFailed()).toBe(true)
expect(result.getError()).toBe('Could not generate authenticator authentication options: Username cannot be empty')
})
it('should return an error if authenticator client fails to generate authentication options', async () => {
authenticatorClient.generateAuthenticationOptions = jest.fn().mockResolvedValue(null)
const result = await createUseCase().execute({
username: '[email protected]',
})
expect(result.isFailed()).toBe(true)
expect(result.getError()).toBe('Could not generate authenticator authentication options')
})
it('should return ok if authenticator client succeeds to generate authenticator response', async () => {
const result = await createUseCase().execute({
username: '[email protected]',
})
expect(result.isFailed()).toBe(false)
})
})
@@ -0,0 +1,23 @@
import { AuthenticatorClientInterface } from '@standardnotes/services'
import { Result, UseCaseInterface, Username } from '@standardnotes/domain-core'
import { GetAuthenticatorAuthenticationOptionsDTO } from './GetAuthenticatorAuthenticationOptionsDTO'
export class GetAuthenticatorAuthenticationOptions implements UseCaseInterface<Record<string, unknown>> {
constructor(private authenticatorClient: AuthenticatorClientInterface) {}
async execute(dto: GetAuthenticatorAuthenticationOptionsDTO): Promise<Result<Record<string, unknown>>> {
const usernameOrError = Username.create(dto.username)
if (usernameOrError.isFailed()) {
return Result.fail(`Could not generate authenticator authentication options: ${usernameOrError.getError()}`)
}
const username = usernameOrError.getValue()
const authenticationOptions = await this.authenticatorClient.generateAuthenticationOptions(username)
if (authenticationOptions === null) {
return Result.fail('Could not generate authenticator authentication options')
}
return Result.ok(authenticationOptions)
}
}
@@ -0,0 +1,3 @@
export interface GetAuthenticatorAuthenticationOptionsDTO {
username: string
}
@@ -1,40 +1,31 @@
import { AuthenticatorClientInterface } from '@standardnotes/services'
import { GetAuthenticatorAuthenticationResponse } from './GetAuthenticatorAuthenticationResponse'
import { GetAuthenticatorAuthenticationOptions } from '../GetAuthenticatorAuthenticationOptions/GetAuthenticatorAuthenticationOptions'
import { Result } from '@standardnotes/domain-core'
describe('GetAuthenticatorAuthenticationResponse', () => {
let authenticatorClient: AuthenticatorClientInterface
let getAuthenticatorAuthenticationOptions: GetAuthenticatorAuthenticationOptions
let authenticatorVerificationPromptFunction: (
authenticationOptions: Record<string, unknown>,
) => Promise<Record<string, unknown>>
const createUseCase = () => new GetAuthenticatorAuthenticationResponse(authenticatorClient, authenticatorVerificationPromptFunction)
const createUseCase = () => new GetAuthenticatorAuthenticationResponse(getAuthenticatorAuthenticationOptions, authenticatorVerificationPromptFunction)
beforeEach(() => {
authenticatorClient = {} as jest.Mocked<AuthenticatorClientInterface>
authenticatorClient.generateAuthenticationOptions = jest.fn().mockResolvedValue({ foo: 'bar' })
getAuthenticatorAuthenticationOptions = {} as jest.Mocked<GetAuthenticatorAuthenticationOptions>
getAuthenticatorAuthenticationOptions.execute = jest.fn().mockResolvedValue(Result.ok({ foo: 'bar' }))
authenticatorVerificationPromptFunction = jest.fn()
})
it('should return an error if username is not provided', async () => {
const result = await createUseCase().execute({
username: '',
})
expect(result.isFailed()).toBe(true)
expect(result.getError()).toBe('Could not generate authenticator authentication options: Username cannot be empty')
})
it('should return an error if authenticator client fails to generate authentication options', async () => {
authenticatorClient.generateAuthenticationOptions = jest.fn().mockResolvedValue(null)
it('should return an error if it fails to generate authentication options', async () => {
getAuthenticatorAuthenticationOptions.execute = jest.fn().mockReturnValue(Result.fail('error'))
const result = await createUseCase().execute({
username: '[email protected]',
})
expect(result.isFailed()).toBe(true)
expect(result.getError()).toBe('Could not generate authenticator authentication options')
expect(result.getError()).toBe('error')
})
it('should return an error if authenticator verification prompt function fails', async () => {
@@ -57,7 +48,7 @@ describe('GetAuthenticatorAuthenticationResponse', () => {
})
it('should return error if authenticatorVerificationPromptFunction is not provided', async () => {
const result = await new GetAuthenticatorAuthenticationResponse(authenticatorClient).execute({
const result = await new GetAuthenticatorAuthenticationResponse(getAuthenticatorAuthenticationOptions).execute({
username: '[email protected]',
})
@@ -1,10 +1,10 @@
import { AuthenticatorClientInterface } from '@standardnotes/services'
import { Result, UseCaseInterface, Username } from '@standardnotes/domain-core'
import { Result, UseCaseInterface } from '@standardnotes/domain-core'
import { GetAuthenticatorAuthenticationResponseDTO } from './GetAuthenticatorAuthenticationResponseDTO'
import { GetAuthenticatorAuthenticationOptions } from '../GetAuthenticatorAuthenticationOptions/GetAuthenticatorAuthenticationOptions'
export class GetAuthenticatorAuthenticationResponse implements UseCaseInterface<Record<string, unknown>> {
constructor(
private authenticatorClient: AuthenticatorClientInterface,
private getAuthenticatorAuthenticationOptions: GetAuthenticatorAuthenticationOptions,
private authenticatorVerificationPromptFunction?: (
authenticationOptions: Record<string, unknown>,
) => Promise<Record<string, unknown>>,
@@ -17,16 +17,13 @@ export class GetAuthenticatorAuthenticationResponse implements UseCaseInterface<
)
}
const usernameOrError = Username.create(dto.username)
if (usernameOrError.isFailed()) {
return Result.fail(`Could not generate authenticator authentication options: ${usernameOrError.getError()}`)
}
const username = usernameOrError.getValue()
const authenticationOptions = await this.authenticatorClient.generateAuthenticationOptions(username)
if (authenticationOptions === null) {
return Result.fail('Could not generate authenticator authentication options')
const authenticationOptionsOrError = await this.getAuthenticatorAuthenticationOptions.execute({
username: dto.username,
})
if (authenticationOptionsOrError.isFailed()) {
return Result.fail(authenticationOptionsOrError.getError())
}
const authenticationOptions = authenticationOptionsOrError.getValue()
let authenticatorResponse
try {
@@ -7,6 +7,7 @@ import { GetAuthenticatorAuthenticationResponse } from './GetAuthenticatorAuthen
import { ListRevisions } from './ListRevisions/ListRevisions'
import { GetRevision } from './GetRevision/GetRevision'
import { DeleteRevision } from './DeleteRevision/DeleteRevision'
import { GetAuthenticatorAuthenticationOptions } from './GetAuthenticatorAuthenticationOptions/GetAuthenticatorAuthenticationOptions'
export interface UseCaseContainerInterface {
get signInWithRecoveryCodes(): SignInWithRecoveryCodes
@@ -15,6 +16,7 @@ export interface UseCaseContainerInterface {
get listAuthenticators(): ListAuthenticators
get deleteAuthenticator(): DeleteAuthenticator
get getAuthenticatorAuthenticationResponse(): GetAuthenticatorAuthenticationResponse
get getAuthenticatorAuthenticationOptions(): GetAuthenticatorAuthenticationOptions
get listRevisions(): ListRevisions
get getRevision(): GetRevision
get deleteRevision(): DeleteRevision
+2
View File
@@ -6,6 +6,8 @@ export * from './UseCase/DeleteAuthenticator/DeleteAuthenticator'
export * from './UseCase/DeleteAuthenticator/DeleteAuthenticatorDTO'
export * from './UseCase/DeleteRevision/DeleteRevision'
export * from './UseCase/DeleteRevision/DeleteRevisionDTO'
export * from './UseCase/GetAuthenticatorAuthenticationOptions/GetAuthenticatorAuthenticationOptions'
export * from './UseCase/GetAuthenticatorAuthenticationOptions/GetAuthenticatorAuthenticationOptionsDTO'
export * from './UseCase/GetAuthenticatorAuthenticationResponse/GetAuthenticatorAuthenticationResponse'
export * from './UseCase/GetAuthenticatorAuthenticationResponse/GetAuthenticatorAuthenticationResponseDTO'
export * from './UseCase/GetRecoveryCodes/GetRecoveryCodes'
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/snjs",
"version": "2.166.20",
"version": "2.167.0",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
@@ -37,7 +37,7 @@
"@babel/preset-env": "*",
"@standardnotes/api": "workspace:*",
"@standardnotes/common": "^1.46.6",
"@standardnotes/domain-core": "^1.11.3",
"@standardnotes/domain-core": "^1.12.0",
"@standardnotes/domain-events": "^2.108.1",
"@standardnotes/encryption": "workspace:*",
"@standardnotes/features": "workspace:*",
+14
View File
@@ -3,6 +3,20 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [1.25.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-17)
### Features
* **mobile:** add U2F support for Android devices ([#2311](https://github.com/standardnotes/app/issues/2311)) ([725f55f](https://github.com/standardnotes/app/commit/725f55fca794b86c245742837af7e4370cebd68c))
## [1.24.45](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-15)
**Note:** Version bump only for package @standardnotes/ui-services
## [1.24.44](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-14)
**Note:** Version bump only for package @standardnotes/ui-services
## [1.24.43](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-11)
**Note:** Version bump only for package @standardnotes/ui-services
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/ui-services",
"version": "1.24.43",
"version": "1.25.0",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
@@ -2,7 +2,7 @@
* @jest-environment jsdom
*/
import { WebApplicationInterface } from '@standardnotes/snjs/dist/@types'
import { WebApplicationInterface } from '@standardnotes/snjs'
import { jsonTestData, htmlTestData } from './testData'
import { GoogleKeepConverter } from './GoogleKeepConverter'
+46
View File
@@ -3,6 +3,52 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [3.151.3](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-18)
**Note:** Version bump only for package @standardnotes/web
## [3.151.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-18)
### Bug Fixes
* Fixed issue where the Super note markdown preview modal could not be closed on mobile ([fc137a7](https://github.com/standardnotes/app/commit/fc137a7e7ba5bd9329b97c8197f9cf65a0bbad17))
## [3.151.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-18)
**Note:** Version bump only for package @standardnotes/web
# [3.151.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-17)
### Features
* **mobile:** add U2F support for Android devices ([#2311](https://github.com/standardnotes/app/issues/2311)) ([725f55f](https://github.com/standardnotes/app/commit/725f55fca794b86c245742837af7e4370cebd68c))
## [3.150.54](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-15)
**Note:** Version bump only for package @standardnotes/web
## [3.150.53](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-14)
**Note:** Version bump only for package @standardnotes/web
## [3.150.52](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-12)
**Note:** Version bump only for package @standardnotes/web
## [3.150.51](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-12)
### Bug Fixes
* Fixed issue where a new note would not be correctly synced after making changes ([9f82426](https://github.com/standardnotes/app/commit/9f824266ac47280c982da3900c107cc8bb239233))
## [3.150.50](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-12)
**Note:** Version bump only for package @standardnotes/web
## [3.150.49](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-12)
**Note:** Version bump only for package @standardnotes/web
## [3.150.48](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-11)
**Note:** Version bump only for package @standardnotes/web
+119
View File
@@ -1,5 +1,124 @@
{
"versions": [
{
"version": "3.151.3",
"title": "[3.151.3](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-18)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.151.2",
"title": "[3.151.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-18)",
"date": null,
"body": "### Bug Fixes\n\n* Fixed issue where the Super note markdown preview modal could not be closed on mobile ([fc137a7](https://github.com/standardnotes/app/commit/fc137a7e7ba5bd9329b97c8197f9cf65a0bbad17))",
"parsed": {
"_": [
"Fixed issue where the Super note markdown preview modal could not be closed on mobile (fc137a7)"
],
"Bug Fixes": [
"Fixed issue where the Super note markdown preview modal could not be closed on mobile (fc137a7)"
]
}
},
{
"version": "3.151.1",
"title": "[3.151.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-18)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.151.0",
"title": "[3.151.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-17)",
"date": null,
"body": "### Features\n\n* **mobile:** add U2F support for Android devices ([#2311](https://github.com/standardnotes/app/issues/2311)) ([725f55f](https://github.com/standardnotes/app/commit/725f55fca794b86c245742837af7e4370cebd68c))",
"parsed": {
"_": [
"mobile: add U2F support for Android devices (#2311) (725f55f)"
],
"Features": [
"mobile: add U2F support for Android devices (#2311) (725f55f)"
]
}
},
{
"version": "3.150.54",
"title": "[3.150.54](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-15)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.150.53",
"title": "[3.150.53](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-14)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.150.52",
"title": "[3.150.52](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-12)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.150.51",
"title": "[3.150.51](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-12)",
"date": null,
"body": "### Bug Fixes\n\n* Fixed issue where a new note would not be correctly synced after making changes ([9f82426](https://github.com/standardnotes/app/commit/9f824266ac47280c982da3900c107cc8bb239233))",
"parsed": {
"_": [
"Fixed issue where a new note would not be correctly synced after making changes (9f82426)"
],
"Bug Fixes": [
"Fixed issue where a new note would not be correctly synced after making changes (9f82426)"
]
}
},
{
"version": "3.150.50",
"title": "[3.150.50](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-12)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.150.49",
"title": "[3.150.49](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-12)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.150.48",
"title": "[3.150.48](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-04-11)",
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/web",
"version": "3.150.48",
"version": "3.151.3",
"license": "AGPL-3.0-or-later",
"main": "dist/app.js",
"author": "Standard Notes.",
@@ -28,7 +28,7 @@
"@babel/plugin-transform-react-jsx": "^7.19.0",
"@babel/preset-env": "*",
"@babel/preset-typescript": "^7.18.6",
"@lexical/react": "0.9.1",
"@lexical/react": "0.9.2",
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.10",
"@reach/alert": "^0.18.0",
"@reach/alert-dialog": "^0.18.0",
@@ -84,7 +84,7 @@
"identity-obj-proxy": "^3.0.0",
"jest": "^29.3.1",
"jest-environment-jsdom": "^29.3.1",
"lexical": "0.9.1",
"lexical": "0.9.2",
"lint-staged": ">=13",
"mini-css-extract-plugin": "^2.7.2",
"minimatch": "^5.1.1",
@@ -117,7 +117,7 @@
"app/**/*.{js,ts,jsx,tsx,css,md}": "prettier --write"
},
"dependencies": {
"@lexical/headless": "0.9.1",
"@lexical/headless": "0.9.2",
"contactjs": "2.1.5"
}
}
+2 -2
View File
@@ -10,9 +10,9 @@
"relation": ["delegate_permission/common.handle_all_urls", "delegate_permission/common.get_login_creds"],
"target": {
"namespace": "android_app",
"package_name": "com.standardnotes.dev",
"package_name": "com.standardnotes",
"sha256_cert_fingerprints": [
"CC:33:62:8B:53:9A:1E:1E:99:F2:75:7C:FC:7C:01:5D:6D:5A:99:D9:DD:93:6A:75:42:4B:08:BD:93:43:10:99"
"58:3F:C4:1B:49:0C:38:0B:56:FB:E9:EE:47:38:1E:B4:EF:53:E0:37:19:A5:50:3F:C1:F2:9D:CD:8E:28:90:2A"
]
}
}
@@ -165,7 +165,12 @@ const GeneralAccountMenu: FunctionComponent<Props> = ({
</MenuItem>
</>
)}
<MenuItem onClick={() => viewControllerManager.isImportModalVisible.set(true)}>
<MenuItem
onClick={() => {
viewControllerManager.importModalController.setIsVisible(true)
viewControllerManager.accountMenuController.closeAccountMenu()
}}
>
<Icon type="archive" className={iconClassName} />
Import
</MenuItem>
@@ -272,7 +272,7 @@ const ApplicationView: FunctionComponent<Props> = ({ application, mainApplicatio
application={application}
viewControllerManager={viewControllerManager}
/>
<ImportModal viewControllerManager={viewControllerManager} />
<ImportModal importModalController={viewControllerManager.importModalController} />
</>
{application.routeService.isDotOrg && <DotOrgNotice />}
{isIOS() && <IosKeyboardClose />}
@@ -1,8 +1,13 @@
import { WebApplication } from '@/Application/Application'
import { Username } from '@standardnotes/snjs'
import { ChallengePrompt } from '@standardnotes/services'
import { RefObject, useState } from 'react'
import { WebApplication } from '@/Application/Application'
import { isAndroid } from '@/Utils'
import Button from '../Button/Button'
import Icon from '../Icon/Icon'
import { InputValue } from './InputValue'
import U2FPromptIframeContainer from './U2FPromptIframeContainer'
@@ -18,7 +23,7 @@ const U2FPrompt = ({ application, onValueChange, prompt, buttonRef, contextData
const [authenticatorResponse, setAuthenticatorResponse] = useState<Record<string, unknown> | null>(null)
const [error, setError] = useState('')
if (!application.isFullU2FClient) {
if (!application.isFullU2FClient && !isAndroid()) {
return (
<U2FPromptIframeContainer
contextData={contextData}
@@ -28,48 +33,71 @@ const U2FPrompt = ({ application, onValueChange, prompt, buttonRef, contextData
}}
/>
)
} else {
return (
<div className="min-w-76">
{error && <div className="text-red-500">{error}</div>}
<Button
primary
fullWidth
colorStyle={authenticatorResponse ? 'success' : 'info'}
onClick={async () => {
const usernameOrError = Username.create((contextData as { username: string }).username)
if (usernameOrError.isFailed()) {
setError(usernameOrError.getError())
return
}
const username = usernameOrError.getValue()
let authenticatorResponse: Record<string, unknown> | null = null
if (isAndroid()) {
const authenticatorOptionsOrError = await application.getAuthenticatorAuthenticationOptions.execute({
username: username.value,
})
if (authenticatorOptionsOrError.isFailed()) {
setError(authenticatorOptionsOrError.getError())
return
}
const authenticatorOptions = authenticatorOptionsOrError.getValue()
authenticatorResponse = await application
.mobileDevice()
.authenticateWithU2F(JSON.stringify(authenticatorOptions))
} else {
const authenticatorResponseOrError = await application.getAuthenticatorAuthenticationResponse.execute({
username: username.value,
})
if (authenticatorResponseOrError.isFailed()) {
setError(authenticatorResponseOrError.getError())
return
}
authenticatorResponse = authenticatorResponseOrError.getValue()
}
if (authenticatorResponse === null) {
setError('Failed to obtain device response')
return
}
setAuthenticatorResponse(authenticatorResponse)
onValueChange(authenticatorResponse, prompt)
}}
ref={buttonRef}
>
{authenticatorResponse ? (
<span className="flex items-center justify-center gap-3">
<Icon type="check-circle" />
Obtained Device Response
</span>
) : (
'Authenticate Device'
)}
</Button>
</div>
)
}
return (
<div className="min-w-76">
{error && <div className="text-red-500">{error}</div>}
<Button
primary
fullWidth
colorStyle={authenticatorResponse ? 'success' : 'info'}
onClick={async () => {
if (!contextData || contextData.username === undefined) {
setError('No username provided')
return
}
const authenticatorResponseOrError = await application.getAuthenticatorAuthenticationResponse.execute({
username: contextData.username as string,
})
if (authenticatorResponseOrError.isFailed()) {
setError(authenticatorResponseOrError.getError())
return
}
const authenticatorResponse = authenticatorResponseOrError.getValue()
setAuthenticatorResponse(authenticatorResponse)
onValueChange(authenticatorResponse, prompt)
}}
ref={buttonRef}
>
{authenticatorResponse ? (
<span className="flex items-center justify-center gap-3">
<Icon type="check-circle" />
Obtained Device Response
</span>
) : (
'Authenticate Device'
)}
</Button>
</div>
)
}
export default U2FPrompt
@@ -354,7 +354,7 @@ class Footer extends AbstractComponent<Props, State> {
id="footer-bar"
className="z-footer-bar hidden h-8 w-full select-none items-center justify-between border-t border-border bg-contrast px-3 text-text md:flex"
>
<div className="left flex h-full">
<div className="left flex h-full flex-shrink-0">
<div className="sk-app-bar-item relative z-footer-bar-item ml-0 select-none">
<AccountMenuButton
application={this.application}
@@ -393,14 +393,14 @@ class Footer extends AbstractComponent<Props, State> {
</Fragment>
)}
</div>
<div className="center">
<div className="center max-h-full overflow-hidden px-4">
{this.state.arbitraryStatusMessage && (
<div className="relative z-footer-bar-item flex select-none items-center text-xs font-bold text-neutral">
<div className="relative z-footer-bar-item max-h-full select-none items-center overflow-hidden text-ellipsis whitespace-nowrap text-xs font-bold text-neutral">
{this.state.arbitraryStatusMessage}
</div>
)}
</div>
<div className="right flex h-full">
<div className="right flex h-full flex-shrink-0">
{this.state.dataUpgradeAvailable && (
<div
onClick={this.securityUpdateClickHandler}
@@ -418,7 +418,7 @@ class Footer extends AbstractComponent<Props, State> {
</div>
)}
{(this.state.outOfSync || this.state.showSyncResolution) && (
<div className="relative z-footer-bar-item ml-3 flex select-none items-center">
<div className="relative z-footer-bar-item ml-3 flex flex-shrink-0 select-none items-center">
{this.state.outOfSync && (
<div onClick={this.syncResolutionClickHandler} className="text-xs font-bold text-warning">
Potentially Out of Sync
@@ -430,7 +430,7 @@ class Footer extends AbstractComponent<Props, State> {
</div>
)}
{this.state.offline && (
<div className="relative z-footer-bar-item ml-3 flex select-none items-center text-xs font-bold">
<div className="relative z-footer-bar-item ml-3 flex flex-shrink-0 select-none items-center text-xs font-bold">
Offline
</div>
)}
@@ -1,191 +1,13 @@
import { ViewControllerManager } from '@/Controllers/ViewControllerManager'
import { ContentType, DecryptedTransferPayload, pluralize, SNTag, TagContent, UuidGenerator } from '@standardnotes/snjs'
import { Importer } from '@standardnotes/ui-services'
import { observer } from 'mobx-react-lite'
import { useCallback, useMemo, useReducer, useState } from 'react'
import { useApplication } from '../ApplicationProvider'
import { useStateRef } from '@/Hooks/useStateRef'
import { ImportModalFileItem } from './ImportModalFileItem'
import { useMemo } from 'react'
import ImportModalFileItem from './ImportModalFileItem'
import ImportModalInitialPage from './InitialPage'
import { ImportModalAction, ImportModalFile, ImportModalState } from './Types'
import Modal, { ModalAction } from '../Modal/Modal'
import ModalOverlay from '../Modal/ModalOverlay'
import { ImportModalController } from '@/Controllers/ImportModalController'
const reducer = (state: ImportModalState, action: ImportModalAction): ImportModalState => {
switch (action.type) {
case 'setFiles':
return {
...state,
files: action.files.map((file) => ({
id: UuidGenerator.GenerateUuid(),
file,
status: action.service ? 'ready' : 'pending',
service: action.service,
})),
}
case 'updateFile':
return {
...state,
files: state.files.map((file) => {
if (file.file.name === action.file.file.name) {
return action.file
}
return file
}),
}
case 'removeFile':
return {
...state,
files: state.files.filter((file) => file.id !== action.id),
}
case 'setImportTag':
return {
...state,
importTag: action.tag,
}
case 'clearState':
return {
files: [],
}
}
}
const initialState: ImportModalState = {
files: [],
}
const ImportModal = ({ viewControllerManager }: { viewControllerManager: ViewControllerManager }) => {
const application = useApplication()
const [importer] = useState(() => new Importer(application))
const [state, dispatch] = useReducer(reducer, initialState)
const { files } = state
const filesRef = useStateRef(files)
const importFromPayloads = useCallback(
async (file: ImportModalFile, payloads: DecryptedTransferPayload[]) => {
dispatch({
type: 'updateFile',
file: {
...file,
status: 'importing',
},
})
try {
await importer.importFromTransferPayloads(payloads)
const notesImported = payloads.filter((payload) => payload.content_type === ContentType.Note)
const tagsImported = payloads.filter((payload) => payload.content_type === ContentType.Tag)
const successMessage =
`Successfully imported ${notesImported.length} ` +
pluralize(notesImported.length, 'note', 'notes') +
(tagsImported.length > 0
? ` and ${tagsImported.length} ${pluralize(tagsImported.length, 'tag', 'tags')}`
: '')
dispatch({
type: 'updateFile',
file: {
...file,
status: 'success',
successMessage,
},
})
} catch (error) {
dispatch({
type: 'updateFile',
file: {
...file,
status: 'error',
error: error instanceof Error ? error : new Error('Could not import file'),
},
})
}
},
[importer],
)
const parseAndImport = useCallback(async () => {
const files = filesRef.current
if (files.length === 0) {
return
}
const importedPayloads: DecryptedTransferPayload[] = []
for (const file of files) {
if (!file.service) {
return
}
if (file.status === 'ready' && file.payloads) {
await importFromPayloads(file, file.payloads)
importedPayloads.push(...file.payloads)
continue
}
dispatch({
type: 'updateFile',
file: {
...file,
status: 'parsing',
},
})
try {
const payloads = await importer.getPayloadsFromFile(file.file, file.service)
await importFromPayloads(file, payloads)
importedPayloads.push(...payloads)
} catch (error) {
dispatch({
type: 'updateFile',
file: {
...file,
status: 'error',
error: error instanceof Error ? error : new Error('Could not import file'),
},
})
}
}
const currentDate = new Date()
const importTagPayload: DecryptedTransferPayload<TagContent> = {
uuid: UuidGenerator.GenerateUuid(),
created_at: currentDate,
created_at_timestamp: currentDate.getTime(),
updated_at: currentDate,
updated_at_timestamp: currentDate.getTime(),
content_type: ContentType.Tag,
content: {
title: `Imported on ${currentDate.toLocaleString()}`,
expanded: false,
iconString: '',
references: importedPayloads
.filter((payload) => payload.content_type === ContentType.Note)
.map((payload) => ({
content_type: ContentType.Note,
uuid: payload.uuid,
})),
},
}
const [importTag] = await importer.importFromTransferPayloads([importTagPayload])
if (importTag) {
dispatch({
type: 'setImportTag',
tag: importTag as SNTag,
})
}
}, [filesRef, importFromPayloads, importer])
const closeDialog = useCallback(() => {
viewControllerManager.isImportModalVisible.set(false)
if (state.importTag) {
void viewControllerManager.navigationController.setSelectedTag(state.importTag, 'all', {
userTriggered: true,
})
}
dispatch({
type: 'clearState',
})
}, [state.importTag, viewControllerManager.isImportModalVisible, viewControllerManager.navigationController])
const ImportModal = ({ importModalController }: { importModalController: ImportModalController }) => {
const { files, setFiles, updateFile, removeFile, importer, parseAndImport, isVisible, close } = importModalController
const isReadyToImport = files.length > 0 && files.every((file) => file.status === 'ready')
const importSuccessOrError =
@@ -203,22 +25,28 @@ const ImportModal = ({ viewControllerManager }: { viewControllerManager: ViewCon
{
label: importSuccessOrError ? 'Close' : 'Cancel',
type: 'cancel',
onClick: closeDialog,
onClick: close,
mobileSlot: 'left',
},
],
[closeDialog, importSuccessOrError, isReadyToImport, parseAndImport],
[close, importSuccessOrError, isReadyToImport, parseAndImport],
)
return (
<ModalOverlay isOpen={viewControllerManager.isImportModalVisible.get()} onDismiss={closeDialog}>
<Modal title="Import" close={closeDialog} actions={modalActions}>
<ModalOverlay isOpen={isVisible} onDismiss={close}>
<Modal title="Import" close={close} actions={modalActions}>
<div className="px-4 py-4">
{!files.length && <ImportModalInitialPage dispatch={dispatch} />}
{!files.length && <ImportModalInitialPage setFiles={setFiles} />}
{files.length > 0 && (
<div className="divide-y divide-border">
{files.map((file) => (
<ImportModalFileItem file={file} key={file.id} dispatch={dispatch} importer={importer} />
<ImportModalFileItem
file={file}
key={file.id}
updateFile={updateFile}
removeFile={removeFile}
importer={importer}
/>
))}
</div>
)}
@@ -1,8 +1,9 @@
import { ImportModalController, ImportModalFile } from '@/Controllers/ImportModalController'
import { classNames, ContentType, DecryptedTransferPayload, pluralize } from '@standardnotes/snjs'
import { Importer, NoteImportType } from '@standardnotes/ui-services'
import { Dispatch, useCallback, useEffect } from 'react'
import { observer } from 'mobx-react-lite'
import { useCallback, useEffect } from 'react'
import Icon from '../Icon/Icon'
import { ImportModalAction, ImportModalFile } from './Types'
const NoteImportTypeColors: Record<NoteImportType, string> = {
evernote: 'bg-[#14cc45] text-[#000]',
@@ -20,13 +21,15 @@ const NoteImportTypeIcons: Record<NoteImportType, string> = {
plaintext: 'plain-text',
}
export const ImportModalFileItem = ({
const ImportModalFileItem = ({
file,
dispatch,
updateFile,
removeFile,
importer,
}: {
file: ImportModalFile
dispatch: Dispatch<ImportModalAction>
updateFile: ImportModalController['updateFile']
removeFile: ImportModalController['removeFile']
importer: Importer
}) => {
const setFileService = useCallback(
@@ -34,21 +37,18 @@ export const ImportModalFileItem = ({
let payloads: DecryptedTransferPayload[] | undefined
try {
payloads = service ? await importer.getPayloadsFromFile(file.file, service) : undefined
} catch {
//
} catch (error) {
console.error(error)
}
dispatch({
type: 'updateFile',
file: {
...file,
service,
status: service ? 'ready' : 'pending',
payloads,
},
updateFile({
...file,
service,
status: service ? 'ready' : 'pending',
payloads,
})
},
[dispatch, file, importer],
[file, importer, updateFile],
)
useEffect(() => {
@@ -59,7 +59,7 @@ export const ImportModalFileItem = ({
if (file.service === undefined) {
void detect()
}
}, [dispatch, file, setFileService])
}, [file, setFileService])
const notePayloads =
file.status === 'ready' && file.payloads
@@ -129,10 +129,7 @@ export const ImportModalFileItem = ({
<button
className="ml-2 rounded border border-border bg-default p-1.5 hover:bg-contrast"
onClick={() => {
dispatch({
type: 'removeFile',
id: file.id,
})
removeFile(file.id)
}}
>
<Icon type="close" size="medium" />
@@ -144,3 +141,5 @@ export const ImportModalFileItem = ({
</div>
)
}
export default observer(ImportModalFileItem)
@@ -1,26 +1,23 @@
import { ImportModalController } from '@/Controllers/ImportModalController'
import { ClassicFileReader } from '@standardnotes/filepicker'
import { NoteImportType } from '@standardnotes/ui-services'
import { observer } from 'mobx-react-lite'
import { useCallback } from 'react'
import Button from '../Button/Button'
import Icon from '../Icon/Icon'
import { ImportModalAction } from './Types'
type Props = {
dispatch: React.Dispatch<ImportModalAction>
setFiles: ImportModalController['setFiles']
}
const ImportModalInitialPage = ({ dispatch }: Props) => {
const ImportModalInitialPage = ({ setFiles }: Props) => {
const selectFiles = useCallback(
async (service?: NoteImportType) => {
const files = await ClassicFileReader.selectFiles()
dispatch({
type: 'setFiles',
files,
service,
})
setFiles(files, service)
},
[dispatch],
[setFiles],
)
return (
@@ -33,10 +30,7 @@ const ImportModalInitialPage = ({ dispatch }: Props) => {
onDrop={(e) => {
e.preventDefault()
const files = Array.from(e.dataTransfer.files)
dispatch({
type: 'setFiles',
files,
})
setFiles(files)
}}
>
<div className="text-lg font-semibold">Drag and drop files to auto-detect and import</div>
@@ -90,4 +84,4 @@ const ImportModalInitialPage = ({ dispatch }: Props) => {
)
}
export default ImportModalInitialPage
export default observer(ImportModalInitialPage)
@@ -1,30 +0,0 @@
import { DecryptedTransferPayload, SNTag } from '@standardnotes/models'
import { NoteImportType } from '@standardnotes/ui-services'
type ImportModalFileCommon = {
id: string
file: File
service: NoteImportType | null | undefined
}
export type ImportModalFile = (
| { status: 'pending' }
| { status: 'ready'; payloads?: DecryptedTransferPayload[] }
| { status: 'parsing' }
| { status: 'importing' }
| { status: 'success'; successMessage: string }
| { status: 'error'; error: Error }
) &
ImportModalFileCommon
export type ImportModalState = {
files: ImportModalFile[]
importTag?: SNTag
}
export type ImportModalAction =
| { type: 'setFiles'; files: File[]; service?: NoteImportType }
| { type: 'updateFile'; file: ImportModalFile }
| { type: 'removeFile'; id: ImportModalFile['id'] }
| { type: 'setImportTag'; tag: SNTag }
| { type: 'clearState' }
@@ -26,7 +26,7 @@ export class NoteViewController implements ItemViewControllerInterface {
private defaultTagUuid: UuidString | undefined
private defaultTag?: SNTag
private syncController: NoteSyncController
private syncController!: NoteSyncController
constructor(
private application: WebApplication,
@@ -106,6 +106,7 @@ export class NoteViewController implements ItemViewControllerInterface {
this.isTemplateNote = true
this.item = note
this.syncController.setItem(this.item)
if (this.defaultTagUuid) {
const tag = this.application.items.findItem(this.defaultTagUuid) as SNTag
@@ -6,6 +6,7 @@ import { copyTextToClipboard } from '../../Utils/copyTextToClipboard'
import Modal, { ModalAction } from '@/Components/Modal/Modal'
import { BlocksEditor } from './BlocksEditor'
import { BlocksEditorComposer } from './BlocksEditorComposer'
import { MutuallyExclusiveMediaQueryBreakpoints, useMediaQuery } from '@/Hooks/useMediaQuery'
type Props = {
note: SNNote
@@ -28,6 +29,8 @@ export const SuperNoteMarkdownPreview: FunctionComponent<Props> = ({ note, close
setMarkdown(markdown)
}, [])
const isMobileScreen = useMediaQuery(MutuallyExclusiveMediaQueryBreakpoints.sm)
const modalActions: ModalAction[] = useMemo(
() => [
{
@@ -36,8 +39,15 @@ export const SuperNoteMarkdownPreview: FunctionComponent<Props> = ({ note, close
onClick: copy,
mobileSlot: 'left',
},
{
label: 'Done',
type: 'cancel',
onClick: closeDialog,
mobileSlot: 'right',
hidden: !isMobileScreen,
},
],
[copy, didCopy],
[closeDialog, copy, didCopy, isMobileScreen],
)
return (
@@ -0,0 +1,176 @@
import { WebApplication } from '@/Application/Application'
import { DecryptedTransferPayload, SNTag, TagContent } from '@standardnotes/models'
import { ContentType, pluralize, UuidGenerator } from '@standardnotes/snjs'
import { Importer, NoteImportType } from '@standardnotes/ui-services'
import { action, makeObservable, observable } from 'mobx'
import { NavigationController } from './Navigation/NavigationController'
type ImportModalFileCommon = {
id: string
file: File
service: NoteImportType | null | undefined
}
export type ImportModalFile = (
| { status: 'pending' }
| { status: 'ready'; payloads?: DecryptedTransferPayload[] }
| { status: 'parsing' }
| { status: 'importing' }
| { status: 'success'; successMessage: string }
| { status: 'error'; error: Error }
) &
ImportModalFileCommon
export class ImportModalController {
isVisible = false
importer: Importer
files: ImportModalFile[] = []
importTag: SNTag | undefined = undefined
constructor(application: WebApplication, private navigationController: NavigationController) {
makeObservable(this, {
isVisible: observable,
setIsVisible: action,
files: observable,
setFiles: action,
updateFile: action,
removeFile: action,
importTag: observable,
setImportTag: action,
})
this.importer = new Importer(application)
}
setIsVisible = (isVisible: boolean) => {
this.isVisible = isVisible
}
setFiles = (files: File[], service?: NoteImportType) => {
this.files = files.map((file) => ({
id: UuidGenerator.GenerateUuid(),
file,
service,
status: service ? 'ready' : 'pending',
}))
}
updateFile = (file: ImportModalFile) => {
this.files = this.files.map((f) => (f.id === file.id ? file : f))
}
removeFile = (id: ImportModalFile['id']) => {
this.files = this.files.filter((f) => f.id !== id)
}
setImportTag = (tag: SNTag | undefined) => {
this.importTag = tag
}
close = () => {
this.setIsVisible(false)
if (this.importTag) {
this.navigationController
.setSelectedTag(this.importTag, 'all', {
userTriggered: true,
})
.catch(console.error)
}
this.setFiles([])
this.setImportTag(undefined)
}
importFromPayloads = async (file: ImportModalFile, payloads: DecryptedTransferPayload[]) => {
this.updateFile({
...file,
status: 'importing',
})
try {
await this.importer.importFromTransferPayloads(payloads)
const notesImported = payloads.filter((payload) => payload.content_type === ContentType.Note)
const tagsImported = payloads.filter((payload) => payload.content_type === ContentType.Tag)
const successMessage =
`Successfully imported ${notesImported.length} ` +
pluralize(notesImported.length, 'note', 'notes') +
(tagsImported.length > 0 ? ` and ${tagsImported.length} ${pluralize(tagsImported.length, 'tag', 'tags')}` : '')
this.updateFile({
...file,
status: 'success',
successMessage,
})
} catch (error) {
this.updateFile({
...file,
status: 'error',
error: error instanceof Error ? error : new Error('Could not import file'),
})
console.error(error)
}
}
parseAndImport = async () => {
if (this.files.length === 0) {
return
}
const importedPayloads: DecryptedTransferPayload[] = []
for (const file of this.files) {
if (!file.service) {
return
}
if (file.status === 'ready' && file.payloads) {
await this.importFromPayloads(file, file.payloads)
importedPayloads.push(...file.payloads)
continue
}
this.updateFile({
...file,
status: 'parsing',
})
try {
const payloads = await this.importer.getPayloadsFromFile(file.file, file.service)
await this.importFromPayloads(file, payloads)
importedPayloads.push(...payloads)
} catch (error) {
this.updateFile({
...file,
status: 'error',
error: error instanceof Error ? error : new Error('Could not import file'),
})
console.error(error)
}
}
const currentDate = new Date()
const importTagPayload: DecryptedTransferPayload<TagContent> = {
uuid: UuidGenerator.GenerateUuid(),
created_at: currentDate,
created_at_timestamp: currentDate.getTime(),
updated_at: currentDate,
updated_at_timestamp: currentDate.getTime(),
content_type: ContentType.Tag,
content: {
title: `Imported on ${currentDate.toLocaleString()}`,
expanded: false,
iconString: '',
references: importedPayloads
.filter((payload) => payload.content_type === ContentType.Note)
.map((payload) => ({
content_type: ContentType.Note,
uuid: payload.uuid,
})),
},
}
const [importTag] = await this.importer.importFromTransferPayloads([importTagPayload])
if (importTag) {
this.setImportTag(importTag as SNTag)
}
}
}
@@ -25,6 +25,10 @@ export class NoteSyncController {
constructor(private application: WebApplication, private item: SNNote) {}
setItem(item: SNNote) {
this.item = item
}
deinit() {
if (this.saveTimeout) {
clearTimeout(this.saveTimeout)

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