Compare commits

...
Author SHA1 Message Date
StandardNotes CI 285df04a59 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].4
 - @standardnotes/[email protected].1
 - @standardnotes/[email protected].4
 - @standardnotes/[email protected].4
 - @standardnotes/[email protected].3
 - @standardnotes/[email protected].4
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].3
 - @standardnotes/[email protected].3
 - @standardnotes/[email protected].4
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].2
2022-09-23 19:29:51 +00:00
Mo 4d5429cc89 fix(mobile): adjust status bar color to match current theme (#1624)
* feat: sync page theme color metadata with active theme bg

* fix: lint

* refactor: extract to method

* feat: recieve theme scheme change on mobile

* fix: handle issue where status bar color changes when keyboard appears on iOS

* fix: disable bouncing on web view
2022-09-23 13:48:51 -05:00
StandardNotes CI da6622dc95 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected].2
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].1
2022-09-23 18:23:20 +00:00
Aman Harwara a548883863 fix: prefs view on desktop (#1628) 2022-09-23 23:22:01 +05:30
StandardNotes CI 1330201d2e chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected].1
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].0
2022-09-23 17:16:32 +00:00
Aman Harwara 0af720146c feat: add prefs button to navigation panel on mobile (#1625) 2022-09-23 22:17:50 +05:30
StandardNotes CI 4d6992cf83 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected].0
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].3
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].6
2022-09-23 15:54:05 +00:00
Aman Harwara 5de6f459c1 feat: sync page theme color metadata with active theme bg (#1623) 2022-09-23 20:53:00 +05:30
Mo 3c0d4fac76 fix: biometrics timing loading (#1622) 2022-09-23 09:59:16 -05:00
StandardNotes CI 4cdfcbfd95 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].5
2022-09-23 11:16:50 +00:00
Aman Harwara 51e50433d3 fix: protected overlay on mobile (#1621) 2022-09-23 16:16:04 +05:30
StandardNotes CI 696327ff03 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].4
2022-09-23 08:47:03 +00:00
Karol Sójko de64f1bfce fix(web): move email notification preferences to account pane (#1620) 2022-09-23 10:17:21 +02:00
StandardNotes CI 48d484675b chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].3
2022-09-22 20:08:00 +00:00
Aman Harwara 86251b49d3 fix: better safe area padding on iOS (#1618) 2022-09-23 01:03:36 +05:30
StandardNotes CI 5961bc491d chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].2
 - @standardnotes/[email protected].2
2022-09-22 18:54:43 +00:00
Karol Sójko e50f4eb92e Revert "Revert "feat(web): move emails notifications to one pane and enable opening settings via url (#1614)" (#1617)" (#1619)
This reverts commit 6824dd2d5f.
2022-09-22 20:18:19 +02:00
StandardNotes CI 4f8e75f36a chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].1
 - @standardnotes/[email protected].1
2022-09-22 17:21:08 +00:00
Karol Sójko 6824dd2d5f Revert "feat(web): move emails notifications to one pane and enable opening settings via url (#1614)" (#1617)
This reverts commit 1fe833bc24.
2022-09-22 18:50:41 +02:00
Mo 76ec8b0f90 refactor: new mobile experience opt in flow (#1616)
* refactor: new mobile experience opt in flow

* chore: lint
2022-09-22 11:20:26 -05:00
StandardNotes CI 3eebdbb77d chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].0
2022-09-22 15:22:42 +00:00
Aman Harwara ce252def33 feat: show selected editor icon in change editor button (#1615) 2022-09-22 20:22:49 +05:30
StandardNotes CI cb7af03ce8 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].0
 - @standardnotes/[email protected].0
2022-09-22 11:16:54 +00:00
Karol Sójko 1fe833bc24 feat(web): move emails notifications to one pane and enable opening settings via url (#1614)
* feat(web): move emails notifications to one pane and enable opening settings via url

* fix(web): rename notifications to email

* fix(snjs): add mute marketing emails to settings list options

* fix(web): linter issues
2022-09-22 12:40:08 +02:00
StandardNotes CI ac1f59cde7 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected].9
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].1
2022-09-22 08:08:31 +00:00
Aman Harwara db4ceca10e fix: manage subscription button on mobile webview (#1613) 2022-09-22 13:10:15 +05:30
StandardNotes CI 0176f47fe7 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected].8
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].0
2022-09-22 03:20:23 +00:00
Aman Harwara f281041221 feat: on mobile goto content tab after selecting revision (#1611) 2022-09-22 08:15:08 +05:30
StandardNotes CI ebd56cd5aa chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected].7
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].0
2022-09-21 19:32:23 +00:00
Aman Harwara 8fa566336c fix: iOS safe area using CSS (#1610) 2022-09-22 00:22:11 +05:30
Aman Harwara 9dfeac7489 fix: disable focus mode and dynamic panel switches on mobile (#1607) 2022-09-21 22:09:02 +05:30
Aman Harwara d1b71861ec feat: add lock button to navigation panel on mobile (#1609) 2022-09-21 21:40:32 +05:30
StandardNotes CI 766548f12d chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected].6
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].6
2022-09-21 15:42:20 +00:00
Aman Harwara 581a08cd09 fix: tag input auto-submitting when pressing space (#1608) 2022-09-21 20:39:29 +05:30
Aman Harwara ee0d44405d fix: revert webview alert changes (#1606) 2022-09-21 20:18:56 +05:30
Aman Harwara 1ae64dcac4 fix: iOS webview window size and padding (#1605) 2022-09-21 19:58:46 +05:30
StandardNotes CI 2be4fb4f83 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected].5
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].0
 - @standardnotes/[email protected].5
2022-09-21 13:19:58 +00:00
Mo 271a8d1d70 fix(web): subscription sharing copy 2022-09-21 07:50:17 -05:00
Karol Sójko e809328fa8 feat(snjs): add retrieving web sockets token for establishing connection (#1602)
* feat(snjs): add retrieving web sockets token for establishing connection

* fix(snjs): imports

* fix(snjs): use only web sockets connection token

* fix(snjs): linter issue
2022-09-21 14:39:43 +02:00
StandardNotes CI 784cefa26f chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].3
 - @standardnotes/[email protected].3
 - @standardnotes/[email protected].3
 - @standardnotes/[email protected].4
 - @standardnotes/[email protected].3
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].2
 - @standardnotes/[email protected].2
 - @standardnotes/[email protected].2
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].4
2022-09-20 17:45:27 +00:00
Mo c5e225d335 fix: move wrapped storage to unwrapped if not encrypted (#1603) 2022-09-20 12:18:00 -05:00
StandardNotes CI cb4c0f1b5c chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected].3
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].3
2022-09-20 14:32:24 +00:00
Aman Harwara 91d9364e95 fix: close menu & toggle notes list when note action occurs (#1601) 2022-09-20 19:33:14 +05:30
117 changed files with 1343 additions and 376 deletions
+18 -1
View File
@@ -1,2 +1,19 @@
node_modules
scripts
scripts
actions
.yarn
.vscode
.sass-cache
.husky
.github
.git
**/dist
**/coverage
**/node_modules
packages/components
packages/docs
packages/mobile/android
packages/mobile/ios
packages/mobile/html
packages/snjs/mocha
*.d.ts
+1 -1
View File
@@ -1,4 +1,4 @@
{
"extends": ["./node_modules/@standardnotes/config/src/.eslintrc"],
"ignorePatterns": [".eslintrc.js", "*.webpack.*.js", "webpack-defaults.js", "jest.config.js", "__mocks__"]
"ignorePatterns": [".eslintrc.js", "*.webpack.*.js", "webpack-defaults.js", "jest.config.js", "__mocks__", "**/**/coverage"]
}
+1
View File
@@ -1,2 +1,3 @@
node_modules
dist
coverage
+10
View File
@@ -3,6 +3,16 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.8.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-23)
**Note:** Version bump only for package @standardnotes/api
## [1.8.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-20)
### Bug Fixes
* move wrapped storage to unwrapped if not encrypted ([#1603](https://github.com/standardnotes/app/issues/1603)) ([c5e225d](https://github.com/standardnotes/app/commit/c5e225d335537257f44168b8ad05222afccb508a))
# [1.8.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-20)
### Features
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/api",
"version": "1.8.0",
"version": "1.8.2",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
+4
View File
@@ -3,6 +3,10 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [2.7.14](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-23)
**Note:** Version bump only for package @standardnotes/components-meta
## [2.7.13](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-16)
**Note:** Version bump only for package @standardnotes/components-meta
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/components-meta",
"version": "2.7.13",
"version": "2.7.14",
"private": true,
"author": "Standard Notes.",
"main": "dist",
+3
View File
@@ -0,0 +1,3 @@
node_modules
dist
jsign
+74
View File
@@ -3,6 +3,80 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [3.23.152](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-23)
**Note:** Version bump only for package @standardnotes/desktop
## [3.23.151](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-23)
**Note:** Version bump only for package @standardnotes/desktop
## [3.23.150](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-23)
**Note:** Version bump only for package @standardnotes/desktop
## [3.23.149](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-23)
**Note:** Version bump only for package @standardnotes/desktop
## [3.23.148](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-23)
**Note:** Version bump only for package @standardnotes/desktop
## [3.23.147](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-23)
**Note:** Version bump only for package @standardnotes/desktop
## [3.23.146](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-22)
**Note:** Version bump only for package @standardnotes/desktop
## [3.23.145](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-22)
**Note:** Version bump only for package @standardnotes/desktop
## [3.23.144](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-22)
**Note:** Version bump only for package @standardnotes/desktop
## [3.23.143](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-22)
**Note:** Version bump only for package @standardnotes/desktop
## [3.23.142](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-22)
**Note:** Version bump only for package @standardnotes/desktop
## [3.23.141](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-22)
**Note:** Version bump only for package @standardnotes/desktop
## [3.23.140](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-22)
**Note:** Version bump only for package @standardnotes/desktop
## [3.23.139](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-21)
**Note:** Version bump only for package @standardnotes/desktop
## [3.23.138](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-21)
**Note:** Version bump only for package @standardnotes/desktop
## [3.23.137](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-21)
**Note:** Version bump only for package @standardnotes/desktop
## [3.23.136](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-20)
### Bug Fixes
* move wrapped storage to unwrapped if not encrypted ([#1603](https://github.com/standardnotes/app/issues/1603)) ([c5e225d](https://github.com/standardnotes/app/commit/c5e225d335537257f44168b8ad05222afccb508a))
## [3.23.135](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-20)
**Note:** Version bump only for package @standardnotes/desktop
## [3.23.134](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-20)
**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.23.134",
"version": "3.23.152",
"license": "AGPL-3.0-or-later",
"author": "Standard Notes.",
"private": true,
+8
View File
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.15.4](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-23)
**Note:** Version bump only for package @standardnotes/encryption
## [1.15.3](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-20)
**Note:** Version bump only for package @standardnotes/encryption
## [1.15.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-15)
**Note:** Version bump only for package @standardnotes/encryption
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/encryption",
"version": "1.15.2",
"version": "1.15.4",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
+6
View File
@@ -3,6 +3,12 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.52.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-23)
### Bug Fixes
* **mobile:** adjust status bar color to match current theme ([#1624](https://github.com/standardnotes/app/issues/1624)) ([4d5429c](https://github.com/standardnotes/app/commit/4d5429cc89c15f870825f20e97844825102c6aec))
# [1.52.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-13)
### Features
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/features",
"version": "1.52.0",
"version": "1.52.1",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
@@ -72,6 +72,7 @@ export type ThemeFeatureDescription = ComponentFeatureDescription & {
/** Some themes can be layered on top of other themes */
layerable?: boolean
dock_icon?: ThemeDockIcon
isDark?: boolean
}
export type FeatureDescription = BaseFeatureDescription &
@@ -12,6 +12,7 @@ export function themes(): ThemeFeatureDescription[] {
permission_name: PermissionName.MidnightTheme,
description: 'Elegant utilitarianism.',
thumbnail_url: 'https://s3.amazonaws.com/standard-notes/screenshots/models/themes/midnight-with-mobile.jpg',
isDark: true,
dock_icon: {
type: 'circle',
background_color: '#086DD6',
@@ -27,6 +28,7 @@ export function themes(): ThemeFeatureDescription[] {
permission_name: PermissionName.FuturaTheme,
description: 'Calm and relaxed. Take some time off.',
thumbnail_url: 'https://s3.amazonaws.com/standard-notes/screenshots/models/themes/futura-with-mobile.jpg',
isDark: true,
dock_icon: {
type: 'circle',
background_color: '#fca429',
@@ -42,6 +44,7 @@ export function themes(): ThemeFeatureDescription[] {
permission_name: PermissionName.SolarizedDarkTheme,
description: 'The perfect theme for any time.',
thumbnail_url: 'https://s3.amazonaws.com/standard-notes/screenshots/models/themes/solarized-dark.jpg',
isDark: true,
dock_icon: {
type: 'circle',
background_color: '#2AA198',
@@ -72,6 +75,7 @@ export function themes(): ThemeFeatureDescription[] {
permission_name: PermissionName.FocusedTheme,
description: 'For when you need to go in.',
thumbnail_url: 'https://s3.amazonaws.com/standard-notes/screenshots/models/themes/focus-with-mobile.jpg',
isDark: true,
dock_icon: {
type: 'circle',
background_color: '#a464c2',
+8
View File
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.23.4](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-23)
**Note:** Version bump only for package @standardnotes/filepicker
## [1.23.3](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-20)
**Note:** Version bump only for package @standardnotes/filepicker
## [1.23.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-15)
**Note:** Version bump only for package @standardnotes/filepicker
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/filepicker",
"version": "1.23.2",
"version": "1.23.4",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
+8
View File
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.10.4](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-23)
**Note:** Version bump only for package @standardnotes/files
## [1.10.3](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-20)
**Note:** Version bump only for package @standardnotes/files
## [1.10.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-15)
**Note:** Version bump only for package @standardnotes/files
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/files",
"version": "1.10.2",
"version": "1.10.4",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
+2 -1
View File
@@ -5,4 +5,5 @@ ios
e2e
android
fastlane
WebFrame
WebFrame
__tests__
+82
View File
@@ -3,6 +3,88 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [3.36.3](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-23)
### Bug Fixes
* **mobile:** adjust status bar color to match current theme ([#1624](https://github.com/standardnotes/app/issues/1624)) ([4d5429c](https://github.com/standardnotes/app/commit/4d5429cc89c15f870825f20e97844825102c6aec))
## [3.36.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-23)
**Note:** Version bump only for package @standardnotes/mobile
## [3.36.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-23)
**Note:** Version bump only for package @standardnotes/mobile
# [3.36.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-23)
### Features
* sync page theme color metadata with active theme bg ([#1623](https://github.com/standardnotes/app/issues/1623)) ([5de6f45](https://github.com/standardnotes/app/commit/5de6f459c106127f294693389f62fa1c3ed57798))
## [3.35.16](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-23)
**Note:** Version bump only for package @standardnotes/mobile
## [3.35.15](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-23)
**Note:** Version bump only for package @standardnotes/mobile
## [3.35.14](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-22)
**Note:** Version bump only for package @standardnotes/mobile
## [3.35.13](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-22)
**Note:** Version bump only for package @standardnotes/mobile
## [3.35.12](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-22)
**Note:** Version bump only for package @standardnotes/mobile
## [3.35.11](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-22)
**Note:** Version bump only for package @standardnotes/mobile
## [3.35.10](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-22)
**Note:** Version bump only for package @standardnotes/mobile
## [3.35.9](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-22)
**Note:** Version bump only for package @standardnotes/mobile
## [3.35.8](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-22)
**Note:** Version bump only for package @standardnotes/mobile
## [3.35.7](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-21)
### Bug Fixes
* iOS safe area using CSS ([#1610](https://github.com/standardnotes/app/issues/1610)) ([8fa5663](https://github.com/standardnotes/app/commit/8fa566336ceef8a3d7b559b1aaf342f7c51f21cd))
## [3.35.6](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-21)
### Bug Fixes
* iOS webview window size and padding ([#1605](https://github.com/standardnotes/app/issues/1605)) ([1ae64dc](https://github.com/standardnotes/app/commit/1ae64dcac4cc714f8931b2301fce1cb802570862))
## [3.35.5](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-21)
**Note:** Version bump only for package @standardnotes/mobile
## [3.35.4](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-20)
### Bug Fixes
* move wrapped storage to unwrapped if not encrypted ([#1603](https://github.com/standardnotes/app/issues/1603)) ([c5e225d](https://github.com/standardnotes/app/commit/c5e225d335537257f44168b8ad05222afccb508a))
## [3.35.3](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-20)
**Note:** Version bump only for package @standardnotes/mobile
## [3.35.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-20)
**Note:** Version bump only for package @standardnotes/mobile
@@ -4,7 +4,8 @@
<head>
<meta charset="utf-8" />
<meta content="IE=edge" http-equiv="X-UA-Compatible" />
<meta content="width=device-width, initial-scale=1" name="viewport" />
<meta content="viewport-fit=cover, width=device-width, initial-scale=1" name="viewport" />
<meta content="#ffffff" name="theme-color" />
<link rel="stylesheet" href="web-src/app.css" />
<script>
window.defaultSyncServer = "https://api.standardnotes.com";
@@ -22,4 +23,4 @@
<body>
</body>
</html>
</html>
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/mobile",
"version": "3.35.2",
"version": "3.36.3",
"author": "Standard Notes.",
"private": true,
"license": "AGPL-3.0-or-later",
+1 -2
View File
@@ -18,7 +18,7 @@ import { ICON_MENU } from '@Style/Icons'
import { ThemeService } from '@Style/ThemeService'
import { getDefaultDrawerWidth } from '@Style/Utils'
import React, { useCallback, useContext, useEffect, useRef, useState } from 'react'
import { Dimensions, Keyboard, ScaledSize, StatusBar } from 'react-native'
import { Dimensions, Keyboard, ScaledSize } from 'react-native'
import DrawerLayout, { DrawerState } from 'react-native-gesture-handler/DrawerLayout'
import { HeaderButtons, Item } from 'react-navigation-header-buttons'
import { ThemeContext } from 'styled-components'
@@ -150,7 +150,6 @@ export const AppStackComponent = (props: ModalStackNavigationProp<'AppStack'>) =
onDrawerStateChanged={handleDrawerStateChange}
renderNavigationView={() => !isLocked && <MainSideMenu drawerRef={drawerRef.current} />}
>
<StatusBar translucent={!shouldOpenWebApp} />
<DrawerLayout
ref={noteDrawerRef}
drawerWidth={getDefaultDrawerWidth(dimensions)}
+4 -1
View File
@@ -13,6 +13,7 @@ import {
platformFromString,
SNApplication,
SNComponentManager,
StorageValueModes,
} from '@standardnotes/snjs'
import { Platform } from 'react-native'
@@ -21,6 +22,7 @@ import { MobileAlertService } from './AlertService'
import { ApplicationState } from './ApplicationState'
import { BackupsService } from './BackupsService'
import { ComponentManager } from './ComponentManager'
import { AlwaysOpenWebAppOnLaunchKey } from './constants'
import { FilesService } from './FilesService'
import { InstallationService } from './InstallationService'
import { MobileDevice } from './Interface'
@@ -135,7 +137,8 @@ export class MobileApplication extends SNApplication {
}
promptForChallenge(challenge: Challenge) {
if (IsMobileWeb) {
const optedIntoWebPreview = this.getValue(AlwaysOpenWebAppOnLaunchKey, StorageValueModes.Nonwrapped) as boolean
if (IsMobileWeb || optedIntoWebPreview) {
return
}
+1 -1
View File
@@ -570,7 +570,7 @@ export class ApplicationState extends ApplicationService {
).includes(state)
}
private async getScreenshotPrivacyEnabled(): Promise<boolean | undefined> {
private async getScreenshotPrivacyEnabled(): Promise<boolean> {
return this.application.getMobileScreenshotPrivacyEnabled()
}
+18 -2
View File
@@ -11,7 +11,7 @@ import {
removeFromArray,
TransferPayload,
} from '@standardnotes/snjs'
import { Alert, Linking, Platform } from 'react-native'
import { Alert, Linking, Platform, StatusBar } from 'react-native'
import FingerprintScanner from 'react-native-fingerprint-scanner'
import FlagSecure from 'react-native-flag-secure-android'
import { hide, show } from 'react-native-privacy-snapshot'
@@ -65,6 +65,7 @@ const showLoadFailForItemIds = (failedItemIds: string[]) => {
export class MobileDevice implements MobileDeviceInterface {
environment: Environment.Mobile = Environment.Mobile
private eventObservers: MobileDeviceEventHandler[] = []
public isDarkMode = false
constructor(private stateObserverService?: AppStateObserverService) {}
@@ -73,6 +74,11 @@ export class MobileDevice implements MobileDeviceInterface {
;(this.stateObserverService as unknown) = undefined
}
consoleLog(...args: any[]): void {
// eslint-disable-next-line no-console
console.log(args)
}
async setLegacyRawKeychainValue(value: LegacyRawKeychainValue): Promise<void> {
await Keychain.setKeys(value)
}
@@ -378,7 +384,7 @@ export class MobileDevice implements MobileDeviceInterface {
await Keychain.clearKeys()
}
async setAndroidScreenshotPrivacy(enable: boolean): Promise<void> {
setAndroidScreenshotPrivacy(enable: boolean): void {
if (Platform.OS === 'android') {
enable ? FlagSecure.activate() : FlagSecure.deactivate()
}
@@ -427,6 +433,16 @@ export class MobileDevice implements MobileDeviceInterface {
}
}
handleThemeSchemeChange(isDark: boolean): void {
this.isDarkMode = isDark
this.reloadStatusBarStyle()
}
reloadStatusBarStyle(animated = true) {
StatusBar.setBarStyle(this.isDarkMode ? 'light-content' : 'dark-content', animated)
}
private notifyEvent(event: MobileDeviceEvent): void {
for (const handler of this.eventObservers) {
handler(event)
+14 -3
View File
@@ -1,11 +1,12 @@
import { MobileDevice, MobileDeviceEvent } from '@Lib/Interface'
import { IsDev } from '@Lib/Utils'
import { ReactNativeToWebEvent } from '@standardnotes/snjs'
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { Platform } from 'react-native'
import { Keyboard, Platform } from 'react-native'
import { WebView, WebViewMessageEvent } from 'react-native-webview'
import { AppStateObserverService } from './AppStateObserverService'
const LoggingEnabled = false
const LoggingEnabled = IsDev
export const MobileWebAppContainer = () => {
const [identifier, setIdentifier] = useState(Math.random())
@@ -28,8 +29,18 @@ const MobileWebAppContents = ({ destroyAndReload }: { destroyAndReload: () => vo
webViewRef.current?.postMessage(JSON.stringify({ reactNativeEvent: event, messageType: 'event' }))
})
const keyboardShowListener = Keyboard.addListener('keyboardWillShow', () => {
device.reloadStatusBarStyle(false)
})
const keyboardHideListener = Keyboard.addListener('keyboardDidHide', () => {
device.reloadStatusBarStyle(false)
})
return () => {
removeListener()
keyboardShowListener.remove()
keyboardHideListener.remove()
}
}, [webViewRef, stateService])
@@ -175,7 +186,6 @@ const MobileWebAppContents = ({ destroyAndReload }: { destroyAndReload: () => vo
ref={webViewRef}
source={{ uri: sourceUri }}
originWhitelist={['*']}
contentInset={{ top: 30, bottom: 10 }}
onLoad={() => {}}
onError={(err) => console.error('An error has occurred', err)}
onHttpError={() => console.error('An HTTP error occurred')}
@@ -183,6 +193,7 @@ const MobileWebAppContents = ({ destroyAndReload }: { destroyAndReload: () => vo
allowFileAccess={true}
allowUniversalAccessFromFileURLs={true}
injectedJavaScriptBeforeContentLoaded={injectedJS}
bounces={false}
/>
)
/* eslint-enable @typescript-eslint/no-empty-function */
@@ -0,0 +1,69 @@
import { AlwaysOpenWebAppOnLaunchKey } from '@Lib/constants'
import { ApplicationContext } from '@Root/ApplicationContext'
import { ButtonCell } from '@Root/Components/ButtonCell'
import { SectionHeader } from '@Root/Components/SectionHeader'
import { TableSection } from '@Root/Components/TableSection'
import { ButtonType, StorageValueModes } from '@standardnotes/snjs'
import React, { useContext } from 'react'
import styled from 'styled-components/native'
import { Label } from './CompanySection.styled'
import { BaseView, StyledSectionedTableCell } from './EncryptionSection.styled'
const Title = styled.Text`
color: ${({ theme }) => theme.stylekitForegroundColor};
font-size: 16px;
font-weight: bold;
`
export const NewMobileSection = () => {
const application = useContext(ApplicationContext)
if (!application) {
return <></>
}
const optIn = async () => {
const confirmationText =
'This will close the app and switch to the new mobile experience next time you open it. You will be able to switch back to the soon-to-be removed classic experience from the settings.'
if (
await application.alertService.confirm(
confirmationText,
'Switch To New Mobile Experience?',
'Switch',
ButtonType.Info,
)
) {
application.setValue(AlwaysOpenWebAppOnLaunchKey, true, StorageValueModes.Nonwrapped)
setTimeout(() => application.deviceInterface.performSoftReset(), 1000)
}
}
return (
<TableSection>
<SectionHeader title={'New Mobile Experience'} />
<StyledSectionedTableCell last={true} first={true}>
<BaseView>
<Title>🎉 New Mobile Experience Preview</Title>
<Label>
The new mobile experience (MX) brings the desktop experience you've come to love right here on your mobile
device. This mode will replace the existing classic mobile experience soon. You can opt in below to begin
using the new MX now.
</Label>
</BaseView>
</StyledSectionedTableCell>
<ButtonCell leftAligned={true} title="Opt In to New Mobile Experience" onPress={optIn}></ButtonCell>
<ButtonCell
leftAligned={true}
title="Read Blog Post"
onPress={() => {
application?.deviceInterface!.openUrl(
'https://blog.standardnotes.com/38384/our-new-mobile-experience-is-launching-soon',
)
}}
></ButtonCell>
</TableSection>
)
}
@@ -1,4 +1,3 @@
import { AlwaysOpenWebAppOnLaunchKey } from '@Lib/constants'
import { useSignedIn } from '@Lib/SnjsHelperHooks'
import { useNavigation } from '@react-navigation/native'
import { ButtonCell } from '@Root/Components/ButtonCell'
@@ -9,7 +8,7 @@ import { TableSection } from '@Root/Components/TableSection'
import { useSafeApplicationContext } from '@Root/Hooks/useSafeApplicationContext'
import { ModalStackNavigationProp } from '@Root/ModalStack'
import { SCREEN_MANAGE_SESSIONS, SCREEN_SETTINGS } from '@Root/Screens/screens'
import { ButtonType, PrefKey, StorageValueModes } from '@standardnotes/snjs'
import { ButtonType, PrefKey } from '@standardnotes/snjs'
import moment from 'moment'
import React, { useCallback, useMemo, useState } from 'react'
import { Platform } from 'react-native'
@@ -222,21 +221,6 @@ export const OptionsSection = ({ title, encryptionAvailable }: Props) => {
onPress={onExportPress}
/>
<ButtonCell
onPress={async () => {
const confirmationText =
'This will close the app and fully switch to the web view next time you open it. You will be able to switch back from the settings.'
if (
await application.alertService.confirm(confirmationText, 'Switch To Web View?', 'Switch', ButtonType.Info)
) {
application.setValue(AlwaysOpenWebAppOnLaunchKey, true, StorageValueModes.Nonwrapped)
setTimeout(() => application.deviceInterface.performSoftReset(), 1000)
}
}}
title="Switch to Web View"
/>
{!signedIn && (
<SectionedAccessoryTableCell
testID="lastExportDate"
@@ -38,14 +38,14 @@ export const SecuritySection = (props: Props) => {
useEffect(() => {
let mounted = true
const getHasScreenshotPrivacy = async () => {
const hasScreenshotPrivacyEnabled = (await application?.getMobileScreenshotPrivacyEnabled()) ?? true
const hasScreenshotPrivacyEnabled = application?.getMobileScreenshotPrivacyEnabled()
if (mounted) {
setHasScreenshotPrivacy(hasScreenshotPrivacyEnabled)
}
}
void getHasScreenshotPrivacy()
const getHasBiometrics = async () => {
const appHasBiometrics = await application!.hasBiometrics()
const appHasBiometrics = application!.hasBiometrics()
if (mounted) {
setHasBiometrics(appHasBiometrics)
}
@@ -9,6 +9,7 @@ import React, { useCallback, useEffect, useState } from 'react'
import { AuthSection } from './Sections/AuthSection'
import { CompanySection } from './Sections/CompanySection'
import { EncryptionSection } from './Sections/EncryptionSection'
import { NewMobileSection } from './Sections/NewMobilePreview'
import { OptionsSection } from './Sections/OptionsSection'
import { PreferencesSection } from './Sections/PreferencesSection'
import { ProtectionsSection } from './Sections/ProtectionsSection'
@@ -54,6 +55,7 @@ export const Settings = (props: Props) => {
<Container keyboardShouldPersistTaps={'always'} keyboardDismissMode={'interactive'}>
<AuthSection title="Account" signedIn={signedIn} />
<OptionsSection encryptionAvailable={!!encryptionAvailable} title="Options" />
<NewMobileSection />
<WorkspacesSection />
<PreferencesSection />
{application.hasAccount() && isEntitledToFiles && <FilesSection />}
+10
View File
@@ -3,6 +3,16 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.18.4](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-23)
### Bug Fixes
* **mobile:** adjust status bar color to match current theme ([#1624](https://github.com/standardnotes/app/issues/1624)) ([4d5429c](https://github.com/standardnotes/app/commit/4d5429cc89c15f870825f20e97844825102c6aec))
## [1.18.3](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-20)
**Note:** Version bump only for package @standardnotes/models
## [1.18.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-15)
### Bug Fixes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/models",
"version": "1.18.2",
"version": "1.18.4",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
@@ -1,4 +1,4 @@
import { FeatureDescription } from '@standardnotes/features'
import { FeatureDescription, ThemeFeatureDescription } from '@standardnotes/features'
type ThirdPartyPackageInfo = {
version: string
@@ -6,3 +6,4 @@ type ThirdPartyPackageInfo = {
}
export type ComponentPackageInfo = FeatureDescription & Partial<ThirdPartyPackageInfo>
export type ThemePackageInfo = FeatureDescription & Partial<ThirdPartyPackageInfo> & ThemeFeatureDescription
@@ -6,11 +6,13 @@ import { HistoryEntryInterface } from '../../Runtime/History'
import { DecryptedItemInterface, ItemInterface } from '../../Abstract/Item'
import { ContentType } from '@standardnotes/common'
import { useBoolean } from '@standardnotes/utils'
import { ThemePackageInfo } from '../Component/PackageInfo'
export const isTheme = (x: ItemInterface): x is SNTheme => x.content_type === ContentType.Theme
export class SNTheme extends SNComponent {
public override area: ComponentArea = ComponentArea.Themes
public override readonly package_info!: ThemePackageInfo
isLayerable(): boolean {
return useBoolean(this.package_info && this.package_info.layerable, false)
+72
View File
@@ -3,6 +3,78 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.3.75](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-23)
**Note:** Version bump only for package @standardnotes/releases
## [1.3.74](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-23)
**Note:** Version bump only for package @standardnotes/releases
## [1.3.73](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-23)
**Note:** Version bump only for package @standardnotes/releases
## [1.3.72](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-23)
**Note:** Version bump only for package @standardnotes/releases
## [1.3.71](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-23)
**Note:** Version bump only for package @standardnotes/releases
## [1.3.70](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-23)
**Note:** Version bump only for package @standardnotes/releases
## [1.3.69](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-22)
**Note:** Version bump only for package @standardnotes/releases
## [1.3.68](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-22)
**Note:** Version bump only for package @standardnotes/releases
## [1.3.67](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-22)
**Note:** Version bump only for package @standardnotes/releases
## [1.3.66](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-22)
**Note:** Version bump only for package @standardnotes/releases
## [1.3.65](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-22)
**Note:** Version bump only for package @standardnotes/releases
## [1.3.64](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-22)
**Note:** Version bump only for package @standardnotes/releases
## [1.3.63](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-22)
**Note:** Version bump only for package @standardnotes/releases
## [1.3.62](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-21)
**Note:** Version bump only for package @standardnotes/releases
## [1.3.61](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-21)
**Note:** Version bump only for package @standardnotes/releases
## [1.3.60](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-21)
**Note:** Version bump only for package @standardnotes/releases
## [1.3.59](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-20)
**Note:** Version bump only for package @standardnotes/releases
## [1.3.58](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-20)
**Note:** Version bump only for package @standardnotes/releases
## [1.3.57](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-20)
**Note:** Version bump only for package @standardnotes/releases
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/releases",
"version": "1.3.57",
"version": "1.3.75",
"license": "AGPL-3.0-or-later",
"main": "dist/releases.json",
"types": "dist/index.d.ts",
+1
View File
@@ -1,2 +1,3 @@
node_modules
dist
coverage
+10
View File
@@ -3,6 +3,16 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.10.3](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-23)
**Note:** Version bump only for package @standardnotes/responses
## [1.10.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-20)
### Bug Fixes
* move wrapped storage to unwrapped if not encrypted ([#1603](https://github.com/standardnotes/app/issues/1603)) ([c5e225d](https://github.com/standardnotes/app/commit/c5e225d335537257f44168b8ad05222afccb508a))
## [1.10.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-13)
**Note:** Version bump only for package @standardnotes/responses
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/responses",
"version": "1.10.1",
"version": "1.10.3",
"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.21.3](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-23)
### Bug Fixes
* **mobile:** adjust status bar color to match current theme ([#1624](https://github.com/standardnotes/app/issues/1624)) ([4d5429c](https://github.com/standardnotes/app/commit/4d5429cc89c15f870825f20e97844825102c6aec))
## [1.21.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-20)
### Bug Fixes
* move wrapped storage to unwrapped if not encrypted ([#1603](https://github.com/standardnotes/app/issues/1603)) ([c5e225d](https://github.com/standardnotes/app/commit/c5e225d335537257f44168b8ad05222afccb508a))
## [1.21.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-20)
**Note:** Version bump only for package @standardnotes/services
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/services",
"version": "1.21.1",
"version": "1.21.3",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
@@ -1,3 +1,4 @@
import { MobileDeviceInterface } from './../Device/MobileDeviceInterface'
import { DesktopManagerInterface } from '../Device/DesktopManagerInterface'
import { WebAppEvent } from '../Event/WebAppEvent'
import { ApplicationInterface } from './ApplicationInterface'
@@ -9,4 +10,6 @@ export interface WebApplicationInterface extends ApplicationInterface {
handleMobileGainingFocusEvent(): Promise<void>
handleMobileLosingFocusEvent(): Promise<void>
handleMobileResumingFromBackgroundEvent(): Promise<void>
isNativeMobileWeb(): boolean
get mobileDevice(): MobileDeviceInterface
}
@@ -6,8 +6,10 @@ export interface MobileDeviceInterface extends DeviceInterface {
getRawKeychainValue(): Promise<RawKeychainValue | undefined>
getDeviceBiometricsAvailability(): Promise<boolean>
setAndroidScreenshotPrivacy(enable: boolean): Promise<void>
setAndroidScreenshotPrivacy(enable: boolean): void
authenticateWithBiometrics(): Promise<boolean>
hideMobileInterfaceFromScreenshots(): void
stopHidingMobileInterfaceFromScreenshots(): void
consoleLog(...args: any[]): void
handleThemeSchemeChange(isDark: boolean): void
}
+5 -1
View File
@@ -2,4 +2,8 @@ node_modules
dist
test
*.config.js
mocha/**/*
mocha/**/*
coverage
e2e-server.js
jest-global.ts
webpack.*.js
+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.
## [2.132.4](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-23)
**Note:** Version bump only for package @standardnotes/snjs
## [2.132.3](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-23)
### Bug Fixes
* biometrics timing loading ([#1622](https://github.com/standardnotes/app/issues/1622)) ([3c0d4fa](https://github.com/standardnotes/app/commit/3c0d4fac766c3a31bdbebe4f7e88f83ba1ea58da))
## [2.132.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-22)
### Reverts
* Revert "Revert "feat(web): move emails notifications to one pane and enable opening settings via url (#1614)" (#1617)" (#1619) ([e50f4eb](https://github.com/standardnotes/app/commit/e50f4eb92efd65b0b8fa3a5001b8dfb611f60180)), closes [#1614](https://github.com/standardnotes/app/issues/1614) [#1617](https://github.com/standardnotes/app/issues/1617) [#1619](https://github.com/standardnotes/app/issues/1619)
## [2.132.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-22)
### Reverts
* Revert "feat(web): move emails notifications to one pane and enable opening settings via url (#1614)" (#1617) ([6824dd2](https://github.com/standardnotes/app/commit/6824dd2d5fe4a6d427ff5465540f3b7865933e98)), closes [#1614](https://github.com/standardnotes/app/issues/1614) [#1617](https://github.com/standardnotes/app/issues/1617)
# [2.132.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-22)
### Features
* **web:** move emails notifications to one pane and enable opening settings via url ([#1614](https://github.com/standardnotes/app/issues/1614)) ([1fe833b](https://github.com/standardnotes/app/commit/1fe833bc24a3a426a7230381704d418624cc2b82))
# [2.131.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-21)
### Features
* **snjs:** add retrieving web sockets token for establishing connection ([#1602](https://github.com/standardnotes/app/issues/1602)) ([e809328](https://github.com/standardnotes/app/commit/e809328fa86d49f76d24bc0d95db010e483c1853))
## [2.130.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-20)
### Bug Fixes
* move wrapped storage to unwrapped if not encrypted ([#1603](https://github.com/standardnotes/app/issues/1603)) ([c5e225d](https://github.com/standardnotes/app/commit/c5e225d335537257f44168b8ad05222afccb508a))
## [2.130.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-20)
**Note:** Version bump only for package @standardnotes/snjs
+34 -18
View File
@@ -10,6 +10,10 @@ import {
UserRegistrationResponseBody,
UserServer,
UserServerInterface,
WebSocketApiService,
WebSocketApiServiceInterface,
WebSocketServer,
WebSocketServerInterface,
} from '@standardnotes/api'
import * as Common from '@standardnotes/common'
import * as ExternalServices from '@standardnotes/services'
@@ -108,6 +112,8 @@ export class SNApplication
private declare subscriptionApiService: SubscriptionApiServiceInterface
private declare subscriptionServer: SubscriptionServerInterface
private declare subscriptionManager: SubscriptionClientInterface
private declare webSocketApiService: WebSocketApiServiceInterface
private declare webSocketServer: WebSocketServerInterface
private sessionManager!: InternalServices.SNSessionManager
private syncService!: InternalServices.SNSyncService
private challengeService!: InternalServices.ChallengeService
@@ -324,11 +330,12 @@ export class SNApplication
)
}
}
await this.handleStage(ExternalServices.ApplicationStage.StorageDecrypted_09)
this.apiService.loadHost()
this.webSocketsService.loadWebSocketUrl()
this.sessionManager.initializeFromDisk()
await this.sessionManager.initializeFromDisk()
this.settingsService.initializeFromDisk()
@@ -929,32 +936,28 @@ export class SNApplication
return this.deinit(this.getDeinitMode(), DeinitSource.Lock)
}
async setBiometricsTiming(timing: MobileUnlockTiming) {
setBiometricsTiming(timing: MobileUnlockTiming) {
return this.protectionService.setBiometricsTiming(timing)
}
async getMobileScreenshotPrivacyEnabled(): Promise<boolean | undefined> {
getMobileScreenshotPrivacyEnabled(): boolean {
return this.protectionService.getMobileScreenshotPrivacyEnabled()
}
async getMobilePasscodeTiming(): Promise<MobileUnlockTiming | undefined> {
return this.getValue(StorageKey.MobilePasscodeTiming, StorageValueModes.Nonwrapped) as Promise<
MobileUnlockTiming | undefined
>
}
async getMobileBiometricsTiming(): Promise<MobileUnlockTiming | undefined> {
return this.getValue(StorageKey.MobileBiometricsTiming, StorageValueModes.Nonwrapped) as Promise<
MobileUnlockTiming | undefined
>
}
async setMobileScreenshotPrivacyEnabled(isEnabled: boolean) {
setMobileScreenshotPrivacyEnabled(isEnabled: boolean) {
return this.protectionService.setMobileScreenshotPrivacyEnabled(isEnabled)
}
async loadMobileUnlockTiming() {
return this.protectionService.loadMobileUnlockTiming()
getMobilePasscodeTiming(): MobileUnlockTiming | undefined {
return this.getValue(StorageKey.MobilePasscodeTiming, StorageValueModes.Nonwrapped) as
| MobileUnlockTiming
| undefined
}
getMobileBiometricsTiming(): MobileUnlockTiming | undefined {
return this.getValue(StorageKey.MobileBiometricsTiming, StorageValueModes.Nonwrapped) as
| MobileUnlockTiming
| undefined
}
getBiometricsTimingOptions() {
@@ -1093,6 +1096,8 @@ export class SNApplication
this.createUserApiService()
this.createSubscriptionServer()
this.createSubscriptionApiService()
this.createWebSocketServer()
this.createWebSocketApiService()
this.createSubscriptionManager()
this.createWebSocketsService()
this.createSessionManager()
@@ -1134,6 +1139,8 @@ export class SNApplication
;(this.userServer as unknown) = undefined
;(this.subscriptionApiService as unknown) = undefined
;(this.subscriptionServer as unknown) = undefined
;(this.webSocketApiService as unknown) = undefined
;(this.webSocketServer as unknown) = undefined
;(this.subscriptionManager as unknown) = undefined
;(this.sessionManager as unknown) = undefined
;(this.syncService as unknown) = undefined
@@ -1251,6 +1258,7 @@ export class SNApplication
this.webSocketsService = new InternalServices.SNWebSocketsService(
this.diskStorageService,
this.options.webSocketUrl,
this.webSocketApiService,
this.internalEventBus,
)
this.services.push(this.webSocketsService)
@@ -1336,6 +1344,14 @@ export class SNApplication
this.subscriptionServer = new SubscriptionServer(this.httpService)
}
private createWebSocketApiService() {
this.webSocketApiService = new WebSocketApiService(this.webSocketServer)
}
private createWebSocketServer() {
this.webSocketServer = new WebSocketServer(this.httpService)
}
private createSubscriptionManager() {
this.subscriptionManager = new SubscriptionManager(this.subscriptionApiService, this.internalEventBus)
}
@@ -1,4 +1,6 @@
import { InternalEventBusInterface } from '@standardnotes/services'
import { WebSocketApiServiceInterface } from '@standardnotes/api'
import { StorageKey, DiskStorageService } from '@Lib/index'
import { SNWebSocketsService } from './WebsocketsService'
@@ -6,10 +8,11 @@ describe('webSocketsService', () => {
const webSocketUrl = ''
let storageService: DiskStorageService
let webSocketApiService: WebSocketApiServiceInterface
let internalEventBus: InternalEventBusInterface
const createService = () => {
return new SNWebSocketsService(storageService, webSocketUrl, internalEventBus)
return new SNWebSocketsService(storageService, webSocketUrl, webSocketApiService, internalEventBus)
}
beforeEach(() => {
@@ -18,6 +21,9 @@ describe('webSocketsService', () => {
internalEventBus = {} as jest.Mocked<InternalEventBusInterface>
internalEventBus.publish = jest.fn()
webSocketApiService = {} as jest.Mocked<WebSocketApiServiceInterface>
webSocketApiService.createConnectionToken = jest.fn().mockReturnValue({ token: 'foobar' })
})
describe('setWebSocketUrl()', () => {
@@ -1,6 +1,8 @@
import { UserRolesChangedEvent } from '@standardnotes/domain-events'
import { DiskStorageService } from '../Storage/DiskStorageService'
import { AbstractService, InternalEventBusInterface, StorageKey } from '@standardnotes/services'
import { WebSocketApiServiceInterface } from '@standardnotes/api'
import { DiskStorageService } from '../Storage/DiskStorageService'
export enum WebSocketsServiceEvent {
UserRoleMessageReceived = 'WebSocketMessageReceived',
@@ -12,6 +14,7 @@ export class SNWebSocketsService extends AbstractService<WebSocketsServiceEvent,
constructor(
private storageService: DiskStorageService,
private webSocketUrl: string | undefined,
private webSocketApiService: WebSocketApiServiceInterface,
protected override internalEventBus: InternalEventBusInterface,
) {
super(internalEventBus)
@@ -34,10 +37,15 @@ export class SNWebSocketsService extends AbstractService<WebSocketsServiceEvent,
)._websocket_url
}
public startWebSocketConnection(authToken: string): void {
async startWebSocketConnection(): Promise<void> {
const webSocketConectionToken = await this.createWebSocketConnectionToken()
if (webSocketConectionToken === undefined) {
return
}
if (this.webSocketUrl) {
try {
this.webSocket = new WebSocket(`${this.webSocketUrl}?authToken=Bearer+${authToken}`)
this.webSocket = new WebSocket(`${this.webSocketUrl}?authToken=${webSocketConectionToken}`)
this.webSocket.onmessage = this.onWebSocketMessage.bind(this)
this.webSocket.onclose = this.onWebSocketClose.bind(this)
} catch (e) {
@@ -59,9 +67,22 @@ export class SNWebSocketsService extends AbstractService<WebSocketsServiceEvent,
this.webSocket = undefined
}
private async createWebSocketConnectionToken(): Promise<string | undefined> {
try {
const response = await this.webSocketApiService.createConnectionToken()
return response.data.token
} catch (error) {
console.error((error as Error).message)
return undefined
}
}
override deinit(): void {
super.deinit()
;(this.storageService as unknown) = undefined
;(this.webSocketApiService as unknown) = undefined
this.closeWebSocketConnection()
}
}
@@ -87,6 +87,8 @@ export class SNProtectionService extends AbstractService<ProtectionEvent> implem
override handleApplicationStage(stage: ApplicationStage): Promise<void> {
if (stage === ApplicationStage.LoadedDatabase_12) {
this.updateSessionExpiryTimer(this.getSessionExpiryDate())
this.mobilePasscodeTiming = this.getPasscodeTiming()
this.mobileBiometricsTiming = this.getBiometricsTiming()
}
return Promise.resolve()
}
@@ -257,36 +259,31 @@ export class SNProtectionService extends AbstractService<ProtectionEvent> implem
]
}
private async getBiometricsTiming(): Promise<MobileUnlockTiming | undefined> {
return this.storageService.getValue<Promise<MobileUnlockTiming | undefined>>(
private getBiometricsTiming(): MobileUnlockTiming | undefined {
return this.storageService.getValue<MobileUnlockTiming | undefined>(
StorageKey.MobileBiometricsTiming,
StorageValueModes.Nonwrapped,
)
}
private async getPasscodeTiming(): Promise<MobileUnlockTiming | undefined> {
return this.storageService.getValue<Promise<MobileUnlockTiming | undefined>>(
private getPasscodeTiming(): MobileUnlockTiming | undefined {
return this.storageService.getValue<MobileUnlockTiming | undefined>(
StorageKey.MobilePasscodeTiming,
StorageValueModes.Nonwrapped,
)
}
async setBiometricsTiming(timing: MobileUnlockTiming) {
await this.storageService.setValue(StorageKey.MobileBiometricsTiming, timing, StorageValueModes.Nonwrapped)
this.storageService.setValue(StorageKey.MobileBiometricsTiming, timing, StorageValueModes.Nonwrapped)
this.mobileBiometricsTiming = timing
}
async setMobileScreenshotPrivacyEnabled(isEnabled: boolean) {
setMobileScreenshotPrivacyEnabled(isEnabled: boolean) {
return this.storageService.setValue(StorageKey.MobileScreenshotPrivacyEnabled, isEnabled, StorageValueModes.Default)
}
async getMobileScreenshotPrivacyEnabled(): Promise<boolean | undefined> {
return this.storageService.getValue(StorageKey.MobileScreenshotPrivacyEnabled, StorageValueModes.Default)
}
async loadMobileUnlockTiming() {
this.mobilePasscodeTiming = await this.getPasscodeTiming()
this.mobileBiometricsTiming = await this.getBiometricsTiming()
getMobileScreenshotPrivacyEnabled(): boolean {
return this.storageService.getValue(StorageKey.MobileScreenshotPrivacyEnabled, StorageValueModes.Default, false)
}
private async validateOrRenewSession(
@@ -107,7 +107,7 @@ export class SNSessionManager extends AbstractService<SessionEvent> implements S
this.apiService.setUser(user)
}
public initializeFromDisk() {
async initializeFromDisk() {
this.setUser(this.diskStorageService.getValue(StorageKey.User))
if (!this.user) {
@@ -121,7 +121,7 @@ export class SNSessionManager extends AbstractService<SessionEvent> implements S
if (rawSession) {
const session = SessionFromRawStorageValue(rawSession)
this.setSession(session, false)
this.webSocketsService.startWebSocketConnection(session.authorizationValue)
await this.webSocketsService.startWebSocketConnection()
}
}
@@ -623,9 +623,9 @@ export class SNSessionManager extends AbstractService<SessionEvent> implements S
this.httpService.setHost(host)
await this.setSession(session)
this.setSession(session)
this.webSocketsService.startWebSocketConnection(session.authorizationValue)
await this.webSocketsService.startWebSocketConnection()
}
private async handleAuthResponse(body: UserRegistrationResponseBody, rootKey: SNRootKey, wrappingKey?: SNRootKey) {
@@ -11,6 +11,7 @@ import {
ListedAuthorSecretsData,
LogSessionUserAgentOption,
SettingName,
MuteMarketingEmailsOption,
} from '@standardnotes/settings'
type SettingType =
@@ -23,6 +24,7 @@ type SettingType =
| MuteFailedBackupsEmailsOption
| MuteFailedCloudBackupsEmailsOption
| MuteSignInEmailsOption
| MuteMarketingEmailsOption
| OneDriveBackupFrequency
export class SettingsList {
@@ -0,0 +1,33 @@
import { DiskStorageService } from './DiskStorageService'
import { InternalEventBus, DeviceInterface, InternalEventBusInterface } from '@standardnotes/services'
import { Environment } from '@standardnotes/models'
describe('diskStorageService', () => {
let storageService: DiskStorageService
let internalEventBus: InternalEventBusInterface
let device: DeviceInterface
beforeEach(() => {
internalEventBus = {} as jest.Mocked<InternalEventBus>
device = {} as jest.Mocked<DeviceInterface>
storageService = new DiskStorageService(device, 'test', Environment.Desktop, internalEventBus)
})
it('setInitialValues should set unwrapped values as wrapped value if wrapped value is not encrypted', async () => {
storageService.isStorageWrapped = jest.fn().mockReturnValue(false)
await storageService['setInitialValues']({
wrapped: { content: { foo: 'bar' } } as never,
nonwrapped: {},
unwrapped: { bar: 'zoo' },
})
expect(storageService['values']).toEqual({
wrapped: { content: { foo: 'bar' } } as never,
nonwrapped: {},
unwrapped: { bar: 'zoo', foo: 'bar' },
})
})
})
@@ -112,14 +112,10 @@ export class DiskStorageService extends Services.AbstractService implements Serv
const value = await this.deviceInterface.getRawStorageValue(this.getPersistenceKey())
const values = value ? JSON.parse(value as string) : undefined
this.setInitialValues(values)
await this.setInitialValues(values)
}
/**
* Called by platforms with the value they load from disk,
* after they handle initializeFromDisk
*/
private setInitialValues(values?: Services.StorageValuesObject) {
private async setInitialValues(values?: Services.StorageValuesObject) {
const sureValues = values || this.defaultValuesObject()
if (!sureValues[Services.ValueModesKeys.Unwrapped]) {
@@ -127,6 +123,13 @@ export class DiskStorageService extends Services.AbstractService implements Serv
}
this.values = sureValues
if (!this.isStorageWrapped()) {
this.values[Services.ValueModesKeys.Unwrapped] = {
...(this.values[Services.ValueModesKeys.Wrapped].content as object),
...this.values[Services.ValueModesKeys.Unwrapped],
}
}
}
public isStorageWrapped(): boolean {
@@ -370,7 +373,7 @@ export class DiskStorageService extends Services.AbstractService implements Serv
* Clears simple values from storage only. Does not affect payloads.
*/
async clearValues() {
this.setInitialValues()
await this.setInitialValues()
await this.immediatelyPersistValuesToDisk()
}
+1 -1
View File
@@ -1,5 +1,5 @@
module.exports = {
extends: ['../.eslintrc.js'],
extends: ['../.eslintrc'],
globals: {
chai: true,
chaiAsPromised: true,
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/snjs",
"version": "2.130.1",
"version": "2.132.4",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
+16
View File
@@ -3,6 +3,22 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.3.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-23)
### Bug Fixes
* **mobile:** adjust status bar color to match current theme ([#1624](https://github.com/standardnotes/app/issues/1624)) ([4d5429c](https://github.com/standardnotes/app/commit/4d5429cc89c15f870825f20e97844825102c6aec))
# [1.3.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-23)
### Features
* sync page theme color metadata with active theme bg ([#1623](https://github.com/standardnotes/app/issues/1623)) ([5de6f45](https://github.com/standardnotes/app/commit/5de6f459c106127f294693389f62fa1c3ed57798))
## [1.2.7](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-20)
**Note:** Version bump only for package @standardnotes/ui-services
## [1.2.6](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-20)
**Note:** Version bump only for package @standardnotes/ui-services
+3 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/ui-services",
"version": "1.2.6",
"version": "1.3.1",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
@@ -36,6 +36,7 @@
"@typescript-eslint/parser": "^5.12.1",
"eslint-plugin-prettier": "*",
"jest": "^28.1.2",
"ts-jest": "^28.0.5"
"ts-jest": "^28.0.5",
"typescript": "*"
}
}
+29 -1
View File
@@ -248,13 +248,14 @@ export class ThemeManager extends AbstractService {
this.deactivateTheme(theme.uuid)
}
}
if (source !== PayloadEmitSource.LocalRetrieved) {
this.cacheThemeState().catch(console.error)
}
})
}
public deactivateAllThemes() {
private deactivateAllThemes() {
const activeThemes = this.activeThemes.slice()
for (const uuid of activeThemes) {
@@ -287,10 +288,33 @@ export class ThemeManager extends AbstractService {
link.rel = 'stylesheet'
link.media = 'screen,print'
link.id = theme.uuid
link.onload = this.syncThemeColorMetadata
document.getElementsByTagName('head')[0].appendChild(link)
if (this.application.isNativeMobileWeb()) {
this.application.mobileDevice.handleThemeSchemeChange(theme.package_info.isDark ?? false)
}
}
/**
* Syncs the active theme's background color to the 'theme-color' meta tag
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta/name/theme-color
*/
private syncThemeColorMetadata() {
const themeColorMetaElement = document.querySelector('meta[name="theme-color"]')
if (!themeColorMetaElement) {
return
}
const bgColor = getComputedStyle(document.documentElement).getPropertyValue('--sn-stylekit-background-color')
themeColorMetaElement.setAttribute('content', bgColor ? bgColor.trim() : '#ffffff')
}
private deactivateTheme(uuid: string) {
if (!this.activeThemes.includes(uuid)) {
return
}
const element = document.getElementById(uuid) as HTMLLinkElement
if (element) {
element.disabled = true
@@ -298,6 +322,10 @@ export class ThemeManager extends AbstractService {
}
removeFromArray(this.activeThemes, uuid)
if (this.activeThemes.length === 0) {
this.application.mobileDevice.handleThemeSchemeChange(false)
}
}
private async cacheThemeState() {
+4
View File
@@ -0,0 +1,4 @@
dist
node_modules
web.webpack-defaults.js
coverage
+3 -1
View File
@@ -19,7 +19,9 @@
"__mocks__",
"src/components",
"src/favicon",
"src/vendor"
"src/vendor",
"coverage",
"*.config.js"
],
"rules": {
"standard/no-callback-literal": 0, // Disable this as we have too many callbacks relying on literals
+112
View File
@@ -3,6 +3,118 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [3.55.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-23)
**Note:** Version bump only for package @standardnotes/web
## [3.55.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-23)
### Bug Fixes
* prefs view on desktop ([#1628](https://github.com/standardnotes/app/issues/1628)) ([a548883](https://github.com/standardnotes/app/commit/a548883863b4e0ec949fa63a8581cc2984614993))
# [3.55.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-23)
### Features
* add prefs button to navigation panel on mobile ([#1625](https://github.com/standardnotes/app/issues/1625)) ([0af7201](https://github.com/standardnotes/app/commit/0af720146c412316fcb24999ff73c91337f19fb9))
## [3.54.6](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-23)
### Bug Fixes
* biometrics timing loading ([#1622](https://github.com/standardnotes/app/issues/1622)) ([3c0d4fa](https://github.com/standardnotes/app/commit/3c0d4fac766c3a31bdbebe4f7e88f83ba1ea58da))
## [3.54.5](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-23)
### Bug Fixes
* protected overlay on mobile ([#1621](https://github.com/standardnotes/app/issues/1621)) ([51e5043](https://github.com/standardnotes/app/commit/51e50433d3e1a3a682bcb7a774129a904a39b12e))
## [3.54.4](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-23)
### Bug Fixes
* **web:** move email notification preferences to account pane ([#1620](https://github.com/standardnotes/app/issues/1620)) ([de64f1b](https://github.com/standardnotes/app/commit/de64f1bfce6d343fe698c55d6eaf307d200df3ee))
## [3.54.3](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-22)
### Bug Fixes
* better safe area padding on iOS ([#1618](https://github.com/standardnotes/app/issues/1618)) ([86251b4](https://github.com/standardnotes/app/commit/86251b49d3b4965571da1a3c039ec4c6043f733c))
## [3.54.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-22)
### Reverts
* Revert "Revert "feat(web): move emails notifications to one pane and enable opening settings via url (#1614)" (#1617)" (#1619) ([e50f4eb](https://github.com/standardnotes/app/commit/e50f4eb92efd65b0b8fa3a5001b8dfb611f60180)), closes [#1614](https://github.com/standardnotes/app/issues/1614) [#1617](https://github.com/standardnotes/app/issues/1617) [#1619](https://github.com/standardnotes/app/issues/1619)
## [3.54.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-22)
### Reverts
* Revert "feat(web): move emails notifications to one pane and enable opening settings via url (#1614)" (#1617) ([6824dd2](https://github.com/standardnotes/app/commit/6824dd2d5fe4a6d427ff5465540f3b7865933e98)), closes [#1614](https://github.com/standardnotes/app/issues/1614) [#1617](https://github.com/standardnotes/app/issues/1617)
# [3.54.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-22)
### Features
* show selected editor icon in change editor button ([#1615](https://github.com/standardnotes/app/issues/1615)) ([ce252de](https://github.com/standardnotes/app/commit/ce252def332c99d8d8be6a3ce5d76b66e2ea325f))
# [3.53.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-22)
### Features
* **web:** move emails notifications to one pane and enable opening settings via url ([#1614](https://github.com/standardnotes/app/issues/1614)) ([1fe833b](https://github.com/standardnotes/app/commit/1fe833bc24a3a426a7230381704d418624cc2b82))
## [3.52.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-22)
### Bug Fixes
* manage subscription button on mobile webview ([#1613](https://github.com/standardnotes/app/issues/1613)) ([db4ceca](https://github.com/standardnotes/app/commit/db4ceca10e4b41707cae2a4daa9718646d808c19))
# [3.52.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-22)
### Features
* on mobile goto content tab after selecting revision ([#1611](https://github.com/standardnotes/app/issues/1611)) ([f281041](https://github.com/standardnotes/app/commit/f2810412217afdaa05d5012db37276c843d360b4))
# [3.51.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-21)
### Bug Fixes
* disable focus mode and dynamic panel switches on mobile ([#1607](https://github.com/standardnotes/app/issues/1607)) ([9dfeac7](https://github.com/standardnotes/app/commit/9dfeac74897594628c0bf657226f3e5e586267dc))
* iOS safe area using CSS ([#1610](https://github.com/standardnotes/app/issues/1610)) ([8fa5663](https://github.com/standardnotes/app/commit/8fa566336ceef8a3d7b559b1aaf342f7c51f21cd))
### Features
* add lock button to navigation panel on mobile ([#1609](https://github.com/standardnotes/app/issues/1609)) ([d1b7186](https://github.com/standardnotes/app/commit/d1b71861ecf5c8093cbf3d37813ad7ab514edc42))
## [3.50.6](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-21)
### Bug Fixes
* revert webview alert changes ([#1606](https://github.com/standardnotes/app/issues/1606)) ([ee0d444](https://github.com/standardnotes/app/commit/ee0d44405d14505e043aae2c63848bae1c14f1c3))
* tag input auto-submitting when pressing space ([#1608](https://github.com/standardnotes/app/issues/1608)) ([581a08c](https://github.com/standardnotes/app/commit/581a08cd09e02354676d9c14058475e71be05175))
## [3.50.5](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-21)
### Bug Fixes
* **web:** subscription sharing copy ([271a8d1](https://github.com/standardnotes/app/commit/271a8d1d70d25e4d5bdc7e3ad5cfffb2a5cb4f01))
## [3.50.4](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-20)
### Bug Fixes
* move wrapped storage to unwrapped if not encrypted ([#1603](https://github.com/standardnotes/app/issues/1603)) ([c5e225d](https://github.com/standardnotes/app/commit/c5e225d335537257f44168b8ad05222afccb508a))
## [3.50.3](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-20)
### Bug Fixes
* close menu & toggle notes list when note action occurs ([#1601](https://github.com/standardnotes/app/issues/1601)) ([91d9364](https://github.com/standardnotes/app/commit/91d9364e950bc5e613b449427fa32761feb30365))
## [3.50.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-09-20)
### Bug Fixes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/web",
"version": "3.50.2",
"version": "3.55.2",
"license": "AGPL-3.0-or-later",
"main": "dist/app.js",
"author": "Standard Notes.",
+1 -1
View File
@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8"/>
<meta content="IE=edge" http-equiv="X-UA-Compatible"/>
<meta content="width=device-width, initial-scale=1" name="viewport"/>
<meta content="viewport-fit=cover, width=device-width, initial-scale=1" name="viewport"/>
<link rel="canonical" href="https://app.standardnotes.com" />
@@ -76,6 +76,11 @@ export class WebApplication extends SNApplication implements WebApplicationInter
if (this.isNativeMobileWeb()) {
this.mobileWebReceiver = new MobileWebReceiver(this)
// eslint-disable-next-line no-console
console.log = (...args) => {
this.mobileDevice.consoleLog(...args)
}
}
this.onVisibilityChange = () => {
@@ -228,7 +233,7 @@ export class WebApplication extends SNApplication implements WebApplicationInter
async handleMobileGainingFocusEvent(): Promise<void> {}
async handleMobileLosingFocusEvent(): Promise<void> {
if (await this.getMobileScreenshotPrivacyEnabled()) {
if (this.getMobileScreenshotPrivacyEnabled()) {
this.mobileDevice.stopHidingMobileInterfaceFromScreenshots()
}
@@ -236,7 +241,7 @@ export class WebApplication extends SNApplication implements WebApplicationInter
}
async handleMobileResumingFromBackgroundEvent(): Promise<void> {
if (await this.getMobileScreenshotPrivacyEnabled()) {
if (this.getMobileScreenshotPrivacyEnabled()) {
this.mobileDevice.hideMobileInterfaceFromScreenshots()
}
}
@@ -45,9 +45,7 @@ const WorkspaceSwitcherMenu: FunctionComponent<Props> = ({
const signoutAll = useCallback(async () => {
const confirmed = await viewControllerManager.application.alertService.confirm(
`Are you sure you want to sign out of all workspaces on this device?${
viewControllerManager.application.isNativeMobileWeb() && '<b> Your app will quit after sign out completes.</b>'
}`,
'Are you sure you want to sign out of all workspaces on this device?',
undefined,
'Sign out all',
ButtonType.Danger,
@@ -64,44 +62,14 @@ const WorkspaceSwitcherMenu: FunctionComponent<Props> = ({
const activateWorkspace = useCallback(
async (descriptor: ApplicationDescriptor) => {
if (viewControllerManager.application.isNativeMobileWeb()) {
const confirmed = await viewControllerManager.application.alertService.confirm(
'<b>The app needs to be restarted to activate the workspace</b>',
undefined,
'Quit app and activate workspace',
ButtonType.Danger,
)
if (confirmed) {
void mainApplicationGroup.unloadCurrentAndActivateDescriptor(descriptor)
}
return
}
void mainApplicationGroup.unloadCurrentAndActivateDescriptor(descriptor)
},
[mainApplicationGroup, viewControllerManager.application],
[mainApplicationGroup],
)
const addAnotherWorkspace = useCallback(async () => {
if (viewControllerManager.application.isNativeMobileWeb()) {
const confirmed = await viewControllerManager.application.alertService.confirm(
'<b>The app needs to be restarted to add another workspace</b>',
undefined,
'Quit app and add new workspace',
ButtonType.Danger,
)
if (confirmed) {
void mainApplicationGroup.unloadCurrentAndCreateNewDescriptor()
}
return
}
void mainApplicationGroup.unloadCurrentAndCreateNewDescriptor()
}, [mainApplicationGroup, viewControllerManager.application])
}, [mainApplicationGroup])
return (
<Menu a11yLabel="Workspace switcher menu" className="px-0 focus:shadow-none" isOpen={isOpen}>
@@ -175,14 +175,14 @@ const ApplicationView: FunctionComponent<Props> = ({ application, mainApplicatio
return (
<PremiumModalProvider application={application} viewControllerManager={viewControllerManager}>
<div className={platformString + ' main-ui-view sn-component'}>
<div id="app" className={appClass + ' app app-column-container'}>
<FileDragNDropProvider
application={application}
featuresController={viewControllerManager.featuresController}
filesController={viewControllerManager.filesController}
>
<ResponsivePaneProvider>
<ResponsivePaneProvider>
<div className={platformString + ' main-ui-view sn-component'}>
<div id="app" className={appClass + ' app app-column-container'}>
<FileDragNDropProvider
application={application}
featuresController={viewControllerManager.featuresController}
filesController={viewControllerManager.filesController}
>
<Navigation application={application} />
<ContentListView
application={application}
@@ -197,52 +197,52 @@ const ApplicationView: FunctionComponent<Props> = ({ application, mainApplicatio
searchOptionsController={viewControllerManager.searchOptionsController}
/>
<NoteGroupView application={application} />
</ResponsivePaneProvider>
</FileDragNDropProvider>
</FileDragNDropProvider>
</div>
<>
<Footer application={application} applicationGroup={mainApplicationGroup} />
<SessionsModal application={application} viewControllerManager={viewControllerManager} />
<PreferencesViewWrapper viewControllerManager={viewControllerManager} application={application} />
<RevisionHistoryModal
application={application}
historyModalController={viewControllerManager.historyModalController}
notesController={viewControllerManager.notesController}
selectionController={viewControllerManager.selectionController}
subscriptionController={viewControllerManager.subscriptionController}
/>
</>
{renderChallenges()}
<>
<NotesContextMenu
application={application}
navigationController={viewControllerManager.navigationController}
notesController={viewControllerManager.notesController}
noteTagsController={viewControllerManager.noteTagsController}
historyModalController={viewControllerManager.historyModalController}
/>
<TagContextMenuWrapper
navigationController={viewControllerManager.navigationController}
featuresController={viewControllerManager.featuresController}
/>
<FileContextMenuWrapper
filesController={viewControllerManager.filesController}
selectionController={viewControllerManager.selectionController}
/>
<PurchaseFlowWrapper application={application} viewControllerManager={viewControllerManager} />
<ConfirmSignoutContainer
applicationGroup={mainApplicationGroup}
viewControllerManager={viewControllerManager}
application={application}
/>
<ToastContainer />
<FilePreviewModalWrapper application={application} viewControllerManager={viewControllerManager} />
<PermissionsModalWrapper application={application} />
</>
</div>
<>
<Footer application={application} applicationGroup={mainApplicationGroup} />
<SessionsModal application={application} viewControllerManager={viewControllerManager} />
<PreferencesViewWrapper viewControllerManager={viewControllerManager} application={application} />
<RevisionHistoryModal
application={application}
historyModalController={viewControllerManager.historyModalController}
notesController={viewControllerManager.notesController}
selectionController={viewControllerManager.selectionController}
subscriptionController={viewControllerManager.subscriptionController}
/>
</>
{renderChallenges()}
<>
<NotesContextMenu
application={application}
navigationController={viewControllerManager.navigationController}
notesController={viewControllerManager.notesController}
noteTagsController={viewControllerManager.noteTagsController}
historyModalController={viewControllerManager.historyModalController}
/>
<TagContextMenuWrapper
navigationController={viewControllerManager.navigationController}
featuresController={viewControllerManager.featuresController}
/>
<FileContextMenuWrapper
filesController={viewControllerManager.filesController}
selectionController={viewControllerManager.selectionController}
/>
<PurchaseFlowWrapper application={application} viewControllerManager={viewControllerManager} />
<ConfirmSignoutContainer
applicationGroup={mainApplicationGroup}
viewControllerManager={viewControllerManager}
application={application}
/>
<ToastContainer />
<FilePreviewModalWrapper application={application} viewControllerManager={viewControllerManager} />
<PermissionsModalWrapper application={application} />
</>
</div>
</ResponsivePaneProvider>
</PremiumModalProvider>
)
}
@@ -5,6 +5,7 @@ import { FunctionComponent, useCallback, useRef, useState } from 'react'
import Icon from '@/Components/Icon/Icon'
import ChangeEditorMenu from './ChangeEditorMenu'
import Popover from '../Popover/Popover'
import { classNames } from '@/Utils/ConcatenateClassNames'
type Props = {
application: WebApplication
@@ -21,6 +22,12 @@ const ChangeEditorButton: FunctionComponent<Props> = ({
const [isOpen, setIsOpen] = useState(false)
const buttonRef = useRef<HTMLButtonElement>(null)
const containerRef = useRef<HTMLDivElement>(null)
const [selectedEditor, setSelectedEditor] = useState(() => {
return note ? application.componentManager.editorForNote(note) : undefined
})
const [selectedEditorIcon, selectedEditorIconTint] = application.iconsController.getIconAndTintForNoteType(
selectedEditor?.package_info.note_type,
)
const toggleMenu = useCallback(async () => {
const willMenuOpen = !isOpen
@@ -33,13 +40,16 @@ const ChangeEditorButton: FunctionComponent<Props> = ({
return (
<div ref={containerRef}>
<button
className="bg-text-padding flex h-8 min-w-8 cursor-pointer items-center justify-center rounded-full border border-solid border-border text-neutral hover:bg-contrast focus:bg-contrast"
className={classNames(
'bg-text-padding flex h-8 min-w-8 cursor-pointer items-center justify-center rounded-full border border-solid text-neutral hover:bg-contrast focus:bg-contrast',
`border-accessory-tint-${selectedEditorIconTint}`,
)}
title="Change note type"
aria-label="Change note type"
onClick={toggleMenu}
ref={buttonRef}
>
<Icon type="dashboard" />
<Icon type={selectedEditorIcon} className={`text-accessory-tint-${selectedEditorIconTint}`} />
</button>
<Popover togglePopover={toggleMenu} anchorElement={buttonRef.current} open={isOpen} className="pt-2 md:pt-0">
<ChangeEditorMenu
@@ -49,6 +59,9 @@ const ChangeEditorButton: FunctionComponent<Props> = ({
closeMenu={() => {
setIsOpen(false)
}}
onSelect={(component) => {
setSelectedEditor(component)
}}
/>
</Popover>
</div>
@@ -31,11 +31,18 @@ type ChangeEditorMenuProps = {
closeMenu: () => void
isVisible: boolean
note: SNNote | undefined
onSelect?: (component: SNComponent | undefined) => void
}
const getGroupId = (group: EditorMenuGroup) => group.title.toLowerCase().replace(/\s/, '-')
const ChangeEditorMenu: FunctionComponent<ChangeEditorMenuProps> = ({ application, closeMenu, isVisible, note }) => {
const ChangeEditorMenu: FunctionComponent<ChangeEditorMenuProps> = ({
application,
closeMenu,
isVisible,
note,
onSelect,
}) => {
const editors = useMemo(
() =>
application.componentManager.componentsForArea(ComponentArea.Editor).sort((a, b) => {
@@ -162,8 +169,12 @@ const ChangeEditorMenu: FunctionComponent<ChangeEditorMenuProps> = ({ applicatio
}
closeMenu()
if (onSelect) {
onSelect(itemToBeSelected.component)
}
},
[application.componentManager, closeMenu, currentEditor, note, premiumModal, selectComponent],
[application.componentManager, closeMenu, currentEditor, note, onSelect, premiumModal, selectComponent],
)
return (
@@ -41,15 +41,7 @@ const ConfirmSignoutModal: FunctionComponent<Props> = ({ application, viewContro
<AlertDialogLabel className="sk-h3 sk-panel-section-title">Sign out workspace?</AlertDialogLabel>
<AlertDialogDescription className="sk-panel-row">
<div>
<p className="text-foreground">
{STRING_SIGN_OUT_CONFIRMATION}
{application.isNativeMobileWeb() && (
<div className="font-bold">
<br />
Your app will quit after sign out completes.
</div>
)}
</p>
<p className="text-foreground">{STRING_SIGN_OUT_CONFIRMATION}</p>
{showWorkspaceWarning && (
<>
<br />
@@ -185,13 +185,13 @@ const ContentListView: FunctionComponent<Props> = ({
<div
id="items-column"
className={classNames(
'sn-component section app-column flex h-screen flex-col md:h-full',
'sn-component section app-column flex h-screen flex-col pt-safe-top md:h-full',
'xl:w-87.5 xsm-only:!w-full sm-only:!w-full pointer-coarse:md-only:!w-52 pointer-coarse:lg-only:!w-52',
)}
aria-label={'Notes & Files'}
ref={itemsViewPanelRef}
>
<ResponsivePaneContent paneId={AppPaneId.Items} className="min-h-[85vh]">
<ResponsivePaneContent paneId={AppPaneId.Items}>
<div id="items-title-bar" className="section-title-bar border-b border-solid border-border">
<div id="items-title-bar-container">
<input
@@ -8,6 +8,8 @@ import { FilesController } from '@/Controllers/FilesController'
import { SelectedItemsController } from '@/Controllers/SelectedItemsController'
import HorizontalSeparator from '../Shared/HorizontalSeparator'
import { formatSizeToReadableString } from '@standardnotes/filepicker'
import { useResponsiveAppPane } from '../ResponsivePane/ResponsivePaneProvider'
import { AppPaneId } from '../ResponsivePane/AppPaneMetadata'
type Props = {
closeMenu: () => void
@@ -30,6 +32,7 @@ const FileMenuOptions: FunctionComponent<Props> = ({
}) => {
const { selectedFiles } = selectionController
const { handleFileAction } = filesController
const { toggleAppPane } = useResponsiveAppPane()
const hasProtectedFiles = useMemo(() => selectedFiles.some((file) => file.protected), [selectedFiles])
const hasSelectedMultipleFiles = useMemo(() => selectedFiles.length > 1, [selectedFiles.length])
@@ -68,6 +71,11 @@ const FileMenuOptions: FunctionComponent<Props> = ({
closeMenu()
}, [closeMenu, handleFileAction, selectedFiles])
const closeMenuAndToggleFilesList = useCallback(() => {
toggleAppPane(AppPaneId.Items)
closeMenu()
}, [closeMenu, toggleAppPane])
return (
<>
<button
@@ -139,6 +147,7 @@ const FileMenuOptions: FunctionComponent<Props> = ({
<button
className="flex w-full cursor-pointer items-center border-0 bg-transparent px-3 py-1.5 text-left text-sm text-text hover:bg-contrast hover:text-foreground focus:bg-info-backdrop focus:shadow-none"
onClick={() => {
closeMenuAndToggleFilesList()
void filesController.deleteFilesPermanently(selectionController.selectedFiles)
}}
>
@@ -28,16 +28,12 @@ const FileView = ({ application, viewControllerManager, file }: FileViewProps) =
}, [application, file])
return shouldShowProtectedOverlay ? (
<div aria-label="Note" className="section editor sn-component">
<div className="flex h-full items-center justify-center">
<ProtectedItemOverlay
viewControllerManager={viewControllerManager}
hasProtectionSources={application.hasProtectionSources()}
onViewItem={dismissProtectedOverlay}
itemType={'note'}
/>
</div>
</div>
<ProtectedItemOverlay
viewControllerManager={viewControllerManager}
hasProtectionSources={application.hasProtectionSources()}
onViewItem={dismissProtectedOverlay}
itemType={'file'}
/>
) : (
<FileViewWithoutProtection application={application} viewControllerManager={viewControllerManager} file={file} />
)
@@ -1,4 +1,4 @@
import { IconType } from '@standardnotes/snjs'
export const PremiumFeatureIconName: IconType = 'asterisk'
export const PremiumFeatureIconClass = 'text-info'
export const PremiumFeatureIconClass = 'text-info group-disabled:text-passive-2'
@@ -11,6 +11,7 @@ import { AppPaneId } from '@/Components/ResponsivePane/AppPaneMetadata'
import { classNames } from '@/Utils/ConcatenateClassNames'
import Icon from '../Icon/Icon'
import { useResponsiveAppPane } from '../ResponsivePane/ResponsivePaneProvider'
import { isIOS } from '@/Utils'
type Props = {
application: WebApplication
@@ -22,6 +23,15 @@ const Navigation: FunctionComponent<Props> = ({ application }) => {
const [panelWidth, setPanelWidth] = useState<number>(0)
const { toggleAppPane } = useResponsiveAppPane()
const [hasPasscode, setHasPasscode] = useState(() => application.hasPasscode())
useEffect(() => {
const removeObserver = application.addEventObserver(async () => {
setHasPasscode(application.hasPasscode())
}, ApplicationEvent.KeyStatusChanged)
return removeObserver
}, [application])
useEffect(() => {
const removeObserver = application.addEventObserver(async () => {
const width = application.getPreference(PrefKey.TagsPanelWidth)
@@ -51,7 +61,10 @@ const Navigation: FunctionComponent<Props> = ({ application }) => {
return (
<div
id="navigation"
className="sn-component section app-column h-screen max-h-screen w-[220px] overflow-hidden pb-8 md:h-full md:min-h-0 md:py-0 xsm-only:!w-full sm-only:!w-full"
className={classNames(
'sn-component section app-column h-screen max-h-screen w-[220px] overflow-hidden pt-safe-top md:h-full md:min-h-0 md:py-0 xsm-only:!w-full sm-only:!w-full',
isIOS() ? 'pb-safe-bottom' : 'pb-2.5',
)}
ref={ref}
>
<ResponsivePaneContent paneId={AppPaneId.Navigation} contentElementId="navigation-content">
@@ -87,20 +100,41 @@ const Navigation: FunctionComponent<Props> = ({ application }) => {
onClick={() => {
viewControllerManager.accountMenuController.toggleShow()
}}
title="Go to items list"
aria-label="Go to items list"
title="Go to account menu"
aria-label="Go to account menu"
>
<Icon type="account-circle" />
</button>
{hasPasscode && (
<button
id="lock-item"
onClick={() => application.lock()}
title="Locks application and wipes unencrypted data from memory."
aria-label="Locks application and wipes unencrypted data from memory."
className="ml-2.5 flex h-8 min-w-8 cursor-pointer items-center justify-center rounded-full border border-solid border-border bg-default text-neutral hover:bg-contrast focus:bg-contrast"
>
<Icon type="lock-filled" size="custom" className="h-4.5 w-4.5" />
</button>
)}
<button
className="ml-2.5 flex h-8 min-w-8 cursor-pointer items-center justify-center rounded-full border border-solid border-border bg-default text-neutral hover:bg-contrast focus:bg-contrast"
onClick={() => {
viewControllerManager.preferencesController.openPreferences()
}}
title="Go to preferences"
aria-label="Go to preferences"
>
<Icon type="tune" />
</button>
<button
className="ml-2.5 flex h-8 min-w-8 cursor-pointer items-center justify-center rounded-full border border-solid border-border bg-default text-neutral hover:bg-contrast focus:bg-contrast"
onClick={() => {
viewControllerManager.quickSettingsMenuController.toggle()
}}
title="Go to items list"
aria-label="Go to items list"
title="Go to quick settings menu"
aria-label="Go to quick settings menu"
>
<Icon type="tune" />
<Icon type="themes" />
</button>
</div>
</ResponsivePaneContent>
@@ -91,7 +91,7 @@ class NoteGroupView extends PureComponent<Props, State> {
return (
<div
id={ElementIds.EditorColumn}
className="app-column app-column-third flex min-h-screen flex-col md:h-full md:min-h-0"
className="app-column app-column-third flex min-h-screen flex-col pt-safe-top md:h-full md:min-h-0"
>
<ResponsivePaneContent paneId={AppPaneId.Editor} className="flex-grow">
{this.state.showMultipleSelectedNotes && (
@@ -874,18 +874,12 @@ class NoteView extends PureComponent<NoteViewProps, State> {
override render() {
if (this.state.showProtectedWarning) {
return (
<div aria-label="Note" className="section editor sn-component">
{this.state.showProtectedWarning && (
<div className="flex h-full items-center justify-center">
<ProtectedItemOverlay
viewControllerManager={this.viewControllerManager}
hasProtectionSources={this.application.hasProtectionSources()}
onViewItem={this.dismissProtectedWarning}
itemType={'note'}
/>
</div>
)}
</div>
<ProtectedItemOverlay
viewControllerManager={this.viewControllerManager}
hasProtectionSources={this.application.hasProtectionSources()}
onViewItem={this.dismissProtectedWarning}
itemType={'note'}
/>
)
}
@@ -23,10 +23,12 @@ const NotesContextMenu = ({
noteTagsController,
historyModalController,
}: Props) => {
const { contextMenuOpen, contextMenuClickLocation } = notesController
const { contextMenuOpen, contextMenuClickLocation, setContextMenuOpen } = notesController
const contextMenuRef = useRef<HTMLDivElement>(null)
const closeMenu = () => setContextMenuOpen(!contextMenuOpen)
return (
<Popover
align="start"
@@ -37,7 +39,7 @@ const NotesContextMenu = ({
className="py-2"
open={contextMenuOpen}
side="right"
togglePopover={() => notesController.setContextMenuOpen(!contextMenuOpen)}
togglePopover={closeMenu}
>
<div ref={contextMenuRef}>
<NotesOptions
@@ -46,6 +48,7 @@ const NotesContextMenu = ({
notesController={notesController}
noteTagsController={noteTagsController}
historyModalController={historyModalController}
closeMenu={closeMenu}
/>
</div>
</Popover>
@@ -13,6 +13,8 @@ import { NotesOptionsProps } from './NotesOptionsProps'
import { NotesController } from '@/Controllers/NotesController'
import HorizontalSeparator from '../Shared/HorizontalSeparator'
import { formatDateForContextMenu } from '@/Utils/DateUtils'
import { useResponsiveAppPane } from '../ResponsivePane/ResponsivePaneProvider'
import { AppPaneId } from '../ResponsivePane/AppPaneMetadata'
type DeletePermanentlyButtonProps = {
onClick: () => void
@@ -175,8 +177,10 @@ const NotesOptions = ({
notesController,
noteTagsController,
historyModalController,
closeMenu,
}: NotesOptionsProps) => {
const [altKeyDown, setAltKeyDown] = useState(false)
const { toggleAppPane } = useResponsiveAppPane()
const toggleOn = (condition: (note: SNNote) => boolean) => {
const notesMatchingAttribute = notes.filter(condition)
@@ -252,11 +256,15 @@ const NotesOptions = ({
}
}, [application, getNoteFileName, notes])
const duplicateSelectedItems = useCallback(() => {
notes.forEach((note) => {
application.mutator.duplicateItem(note).catch(console.error)
})
}, [application, notes])
const closeMenuAndToggleNotesList = useCallback(() => {
toggleAppPane(AppPaneId.Items)
closeMenu()
}, [closeMenu, toggleAppPane])
const duplicateSelectedItems = useCallback(async () => {
await Promise.all(notes.map((note) => application.mutator.duplicateItem(note).catch(console.error)))
closeMenuAndToggleNotesList()
}, [application.mutator, closeMenuAndToggleNotesList, notes])
const openRevisionHistoryModal = useCallback(() => {
historyModalController.openModal(notesController.firstSelectedNote)
@@ -365,8 +373,9 @@ const NotesOptions = ({
{unarchived && (
<button
className="flex w-full cursor-pointer items-center border-0 bg-transparent px-3 py-1.5 text-left text-menu-item text-text hover:bg-contrast hover:text-foreground focus:bg-info-backdrop focus:shadow-none"
onClick={() => {
notesController.setArchiveSelectedNotes(true).catch(console.error)
onClick={async () => {
await notesController.setArchiveSelectedNotes(true).catch(console.error)
closeMenuAndToggleNotesList()
}}
>
<Icon type="archive" className={iconClassWarning} />
@@ -376,8 +385,9 @@ const NotesOptions = ({
{archived && (
<button
className="flex w-full cursor-pointer items-center border-0 bg-transparent px-3 py-1.5 text-left text-menu-item text-text hover:bg-contrast hover:text-foreground focus:bg-info-backdrop focus:shadow-none"
onClick={() => {
notesController.setArchiveSelectedNotes(false).catch(console.error)
onClick={async () => {
await notesController.setArchiveSelectedNotes(false).catch(console.error)
closeMenuAndToggleNotesList()
}}
>
<Icon type="unarchive" className={iconClassWarning} />
@@ -389,6 +399,7 @@ const NotesOptions = ({
<DeletePermanentlyButton
onClick={async () => {
await notesController.deleteNotesPermanently()
closeMenuAndToggleNotesList()
}}
/>
) : (
@@ -396,6 +407,7 @@ const NotesOptions = ({
className="flex w-full cursor-pointer items-center border-0 bg-transparent px-3 py-1.5 text-left text-menu-item text-text hover:bg-contrast hover:text-foreground focus:bg-info-backdrop focus:shadow-none"
onClick={async () => {
await notesController.setTrashSelectedNotes(true)
closeMenuAndToggleNotesList()
}}
>
<Icon type="trash" className={iconClassDanger} />
@@ -408,6 +420,7 @@ const NotesOptions = ({
className="flex w-full cursor-pointer items-center border-0 bg-transparent px-3 py-1.5 text-left text-menu-item text-text hover:bg-contrast hover:text-foreground focus:bg-info-backdrop focus:shadow-none"
onClick={async () => {
await notesController.setTrashSelectedNotes(false)
closeMenuAndToggleNotesList()
}}
>
<Icon type="restore" className={iconClassSuccess} />
@@ -416,12 +429,14 @@ const NotesOptions = ({
<DeletePermanentlyButton
onClick={async () => {
await notesController.deleteNotesPermanently()
closeMenuAndToggleNotesList()
}}
/>
<button
className="flex w-full cursor-pointer items-center border-0 bg-transparent px-3 py-1.5 text-left text-menu-item text-text hover:bg-contrast hover:text-foreground focus:bg-info-backdrop focus:shadow-none"
onClick={async () => {
await notesController.emptyTrash()
closeMenuAndToggleNotesList()
}}
>
<div className="flex items-start">
@@ -55,6 +55,7 @@ const NotesOptionsPanel = ({
notesController={notesController}
noteTagsController={noteTagsController}
historyModalController={historyModalController}
closeMenu={toggleMenu}
/>
</Popover>
</>
@@ -10,4 +10,5 @@ export type NotesOptionsProps = {
notesController: NotesController
noteTagsController: NoteTagsController
historyModalController: HistoryModalController
closeMenu: () => void
}
@@ -57,9 +57,8 @@ const PositionedPopoverContent = ({
<Portal>
<div
className={classNames(
'absolute top-0 left-0 flex h-full w-full min-w-80 cursor-auto flex-col overflow-y-auto rounded bg-default shadow-main md:h-auto md:max-w-xs',
'safe-area-padding absolute top-0 left-0 flex h-full w-full min-w-80 cursor-auto flex-col overflow-y-auto rounded bg-default shadow-main md:h-auto md:max-w-xs',
overrideZIndex ? overrideZIndex : 'z-dropdown-menu',
className,
)}
style={{
...styles,
@@ -71,15 +70,17 @@ const PositionedPopoverContent = ({
}}
data-popover={id}
>
<div className="md:hidden">
<div className="flex items-center justify-end px-3">
<button className="rounded-full border border-border p-1" onClick={togglePopover}>
<Icon type="close" className="h-4 w-4" />
</button>
<div className={className}>
<div className="md:hidden">
<div className="flex items-center justify-end px-3">
<button className="rounded-full border border-border p-1" onClick={togglePopover}>
<Icon type="close" className="h-4 w-4" />
</button>
</div>
<HorizontalSeparator classes="my-2" />
</div>
<HorizontalSeparator classes="my-2" />
{children}
</div>
{children}
</div>
</Portal>
)
@@ -9,6 +9,7 @@ import SignOutWrapper from './SignOutView'
import FilesSection from './Files'
import PreferencesPane from '../../PreferencesComponents/PreferencesPane'
import SubscriptionSharing from './SubscriptionSharing/SubscriptionSharing'
import Email from './Email'
type Props = {
application: WebApplication
@@ -30,6 +31,7 @@ const AccountPreferences = ({ application, viewControllerManager }: Props) => (
{application.hasAccount() && viewControllerManager.featuresController.hasFiles && (
<FilesSection application={application} />
)}
<Email application={application} />
<SignOutWrapper application={application} viewControllerManager={viewControllerManager} />
</PreferencesPane>
)
@@ -0,0 +1,135 @@
import { MuteMarketingEmailsOption, MuteSignInEmailsOption, SettingName } from '@standardnotes/snjs'
import { observer } from 'mobx-react-lite'
import { FunctionComponent, useCallback, useEffect, useState } from 'react'
import HorizontalSeparator from '@/Components/Shared/HorizontalSeparator'
import Switch from '@/Components/Switch/Switch'
import { Subtitle, Text, Title } from '@/Components/Preferences/PreferencesComponents/Content'
import { WebApplication } from '@/Application/Application'
import { STRING_FAILED_TO_UPDATE_USER_SETTING } from '@/Constants/Strings'
import PreferencesGroup from '@/Components/Preferences/PreferencesComponents/PreferencesGroup'
import PreferencesSegment from '@/Components/Preferences/PreferencesComponents/PreferencesSegment'
import Spinner from '@/Components/Spinner/Spinner'
type Props = {
application: WebApplication
}
const Email: FunctionComponent<Props> = ({ application }: Props) => {
const [signInEmailsMutedValue, setSignInEmailsMutedValue] = useState(MuteSignInEmailsOption.NotMuted)
const [marketingEmailsMutedValue, setMarketingEmailsMutedValue] = useState(MuteMarketingEmailsOption.NotMuted)
const [isLoading, setIsLoading] = useState(true)
const updateSetting = async (settingName: SettingName, payload: string): Promise<boolean> => {
try {
await application.settings.updateSetting(settingName, payload, false)
return true
} catch (e) {
application.alertService.alert(STRING_FAILED_TO_UPDATE_USER_SETTING).catch(console.error)
return false
}
}
const loadSettings = useCallback(async () => {
if (!application.getUser()) {
return
}
setIsLoading(true)
try {
const userSettings = await application.settings.listSettings()
setSignInEmailsMutedValue(
userSettings.getSettingValue<MuteSignInEmailsOption>(
SettingName.MuteSignInEmails,
MuteSignInEmailsOption.NotMuted,
),
),
setMarketingEmailsMutedValue(
userSettings.getSettingValue<MuteMarketingEmailsOption>(
SettingName.MuteMarketingEmails,
MuteMarketingEmailsOption.NotMuted,
),
)
} catch (error) {
console.error(error)
} finally {
setIsLoading(false)
}
}, [application])
useEffect(() => {
loadSettings().catch(console.error)
}, [loadSettings])
const toggleMuteSignInEmails = async () => {
const previousValue = signInEmailsMutedValue
const newValue =
previousValue === MuteSignInEmailsOption.Muted ? MuteSignInEmailsOption.NotMuted : MuteSignInEmailsOption.Muted
setSignInEmailsMutedValue(newValue)
const updateResult = await updateSetting(SettingName.MuteSignInEmails, newValue)
if (!updateResult) {
setSignInEmailsMutedValue(previousValue)
}
}
const toggleMuteMarketingEmails = async () => {
const previousValue = marketingEmailsMutedValue
const newValue =
previousValue === MuteMarketingEmailsOption.Muted
? MuteMarketingEmailsOption.NotMuted
: MuteMarketingEmailsOption.Muted
setMarketingEmailsMutedValue(newValue)
const updateResult = await updateSetting(SettingName.MuteMarketingEmails, newValue)
if (!updateResult) {
setMarketingEmailsMutedValue(previousValue)
}
}
return (
<PreferencesGroup>
<PreferencesSegment>
<Title>Email</Title>
<div>
<div className="flex items-center justify-between">
<div className="flex flex-col">
<Subtitle>Disable sign-in notification emails</Subtitle>
<Text>
Disables email notifications when a new sign-in occurs on your account. (Email notifications are
available to paid subscribers).
</Text>
</div>
{isLoading ? (
<Spinner className="ml-2 flex-shrink-0" />
) : (
<Switch
onChange={toggleMuteSignInEmails}
checked={signInEmailsMutedValue === MuteSignInEmailsOption.Muted}
/>
)}
</div>
<HorizontalSeparator classes="my-4" />
<div className="flex items-center justify-between">
<div className="flex flex-col">
<Subtitle>Disable marketing notification emails</Subtitle>
<Text>Disables email notifications with special deals and promotions.</Text>
</div>
{isLoading ? (
<Spinner className="ml-2 flex-shrink-0" />
) : (
<Switch
onChange={toggleMuteMarketingEmails}
checked={marketingEmailsMutedValue === MuteMarketingEmailsOption.Muted}
/>
)}
</div>
</div>
</PreferencesSegment>
</PreferencesGroup>
)
}
export default observer(Email)
@@ -51,7 +51,7 @@ const InvitationsList = ({ subscriptionState, application }: Props) => {
return (
<div>
<SubtitleLight className="mb-2 text-info">Active Invitations:</SubtitleLight>
<SubtitleLight className="mb-2 text-info">Active Invites:</SubtitleLight>
{activeSubscriptions?.map((invitation) => (
<div key={invitation.uuid} className="mt-1 mb-4">
<Text>
@@ -64,7 +64,7 @@ const InvitationsList = ({ subscriptionState, application }: Props) => {
))}
{!!inActiveSubscriptions?.length && (
<>
<SubtitleLight className="mb-2 text-info">Inactive Invitations:</SubtitleLight>
<SubtitleLight className="mb-2 text-info">Inactive Invites:</SubtitleLight>
<div>
{inActiveSubscriptions?.map((invitation) => (
<div key={invitation.uuid} className="mb-3 first:mt-2">
@@ -13,7 +13,7 @@ import InviteForm from './InviteForm'
import InviteSuccess from './InviteSuccess'
enum SubmitButtonTitles {
Default = 'Send Invitation',
Default = 'Send Invite',
Sending = 'Sending...',
Finish = 'Finish',
}
@@ -96,7 +96,7 @@ const Invite: FunctionComponent<Props> = ({ onCloseDialog, application, subscrip
const success = await processInvite()
if (!success) {
application.alertService
.alert('We could not send the invitation. Please try again or contact support if the issue persists.')
.alert('An error occurred while sending the invite. Please try again or contact support if the issue persists.')
.catch(console.error)
resetProgressState()
@@ -112,7 +112,7 @@ const Invite: FunctionComponent<Props> = ({ onCloseDialog, application, subscrip
return (
<div>
<ModalDialog>
<ModalDialogLabel closeDialog={handleDialogClose}>Invite</ModalDialogLabel>
<ModalDialogLabel closeDialog={handleDialogClose}>Share your Subscription</ModalDialogLabel>
<ModalDialogDescription className="flex flex-row items-center px-4.5">
{currentStep === Steps.InitialStep && <InviteForm setInviteeEmail={setInviteeEmail} />}
{currentStep === Steps.FinishStep && <InviteSuccess />}
@@ -9,8 +9,8 @@ const SharingStatusText = ({ subscriptionState }: Props) => {
return (
<Text className="mt-1">
You have have used <span className="font-bold">{usedInvitationsCount}</span> out of {allowedInvitationsCount}{' '}
subscription invitations.
You've used <span className="font-bold">{usedInvitationsCount}</span> out of {allowedInvitationsCount}{' '}
subscription invites.
</Text>
)
}
@@ -126,10 +126,10 @@ const Defaults: FunctionComponent<Props> = ({ application }) => {
{application.isNativeMobileWeb() && (
<>
<div className="flex flex-col">
<Subtitle>Switch to Native View</Subtitle>
<Subtitle>Switch to Classic Mobile Experience</Subtitle>
<Text>
This will close the app and fully switch to the native view next time you open it. You will be able to
switch back from the settings.
This will close the app and switch back to the soon-to-be removed classic mobile experience. You can opt
back in to new experience from the app settings.
</Text>
<Button className="mt-3 min-w-20" label="Switch" onClick={switchToNativeView} />
</div>
@@ -19,10 +19,8 @@ const BiometricsLock = ({ application }: Props) => {
const [biometricsTimingOptions, setBiometricsTimingOptions] = useState(() => application.getBiometricsTimingOptions())
useEffect(() => {
const getHasBiometrics = async () => {
const appHasBiometrics = await application.hasBiometrics()
setHasBiometrics(appHasBiometrics)
}
const appHasBiometrics = application.hasBiometrics()
setHasBiometrics(appHasBiometrics)
const hasBiometricsSupport = async () => {
const hasBiometricsAvailable = await (
@@ -30,7 +28,6 @@ const BiometricsLock = ({ application }: Props) => {
).getDeviceBiometricsAvailability?.()
setSupportsBiometrics(hasBiometricsAvailable)
}
void getHasBiometrics()
void hasBiometricsSupport()
}, [application])
@@ -50,7 +47,7 @@ const BiometricsLock = ({ application }: Props) => {
await disableBiometrics()
} else {
setHasBiometrics(true)
await application.enableBiometrics()
application.enableBiometrics()
await setBiometricsTimingValue(MobileUnlockTiming.OnQuit)
}
}
@@ -13,22 +13,19 @@ type Props = {
}
const MultitaskingPrivacy = ({ application }: Props) => {
const [hasScreenshotPrivacy, setHasScreenshotPrivacy] = useState<boolean | undefined>(false)
const [hasScreenshotPrivacy, setHasScreenshotPrivacy] = useState<boolean>(false)
useEffect(() => {
const getHasScreenshotPrivacy = async () => {
const hasScreenshotPrivacyEnabled = (await application.getMobileScreenshotPrivacyEnabled()) ?? true
setHasScreenshotPrivacy(hasScreenshotPrivacyEnabled)
}
void getHasScreenshotPrivacy()
const hasScreenshotPrivacyEnabled = application.getMobileScreenshotPrivacyEnabled()
setHasScreenshotPrivacy(hasScreenshotPrivacyEnabled)
}, [application])
const onScreenshotPrivacyPress = async () => {
const enable = !hasScreenshotPrivacy
setHasScreenshotPrivacy(enable)
await application.setMobileScreenshotPrivacyEnabled(enable)
await (application.deviceInterface as MobileDeviceInterface).setAndroidScreenshotPrivacy(enable)
application.setMobileScreenshotPrivacyEnabled(enable)
;(application.deviceInterface as MobileDeviceInterface).setAndroidScreenshotPrivacy(enable)
}
const screenshotPrivacyFeatureText = isIOS() ? 'Multitasking Privacy' : 'Multitasking/Screenshot Privacy'
@@ -2,7 +2,7 @@ import HorizontalSeparator from '@/Components/Shared/HorizontalSeparator'
import Switch from '@/Components/Switch/Switch'
import { Subtitle, Text, Title } from '@/Components/Preferences/PreferencesComponents/Content'
import { WebApplication } from '@/Application/Application'
import { MuteSignInEmailsOption, LogSessionUserAgentOption, SettingName } from '@standardnotes/snjs'
import { LogSessionUserAgentOption, SettingName } from '@standardnotes/snjs'
import { observer } from 'mobx-react-lite'
import { FunctionComponent, useCallback, useEffect, useState } from 'react'
import { STRING_FAILED_TO_UPDATE_USER_SETTING } from '@/Constants/Strings'
@@ -15,9 +15,6 @@ type Props = {
}
const Privacy: FunctionComponent<Props> = ({ application }: Props) => {
const [signInEmailsMutedValue, setSignInEmailsMutedValue] = useState<MuteSignInEmailsOption>(
MuteSignInEmailsOption.NotMuted,
)
const [sessionUaLoggingValue, setSessionUaLoggingValue] = useState<LogSessionUserAgentOption>(
LogSessionUserAgentOption.Enabled,
)
@@ -41,12 +38,6 @@ const Privacy: FunctionComponent<Props> = ({ application }: Props) => {
try {
const userSettings = await application.settings.listSettings()
setSignInEmailsMutedValue(
userSettings.getSettingValue<MuteSignInEmailsOption>(
SettingName.MuteSignInEmails,
MuteSignInEmailsOption.NotMuted,
),
)
setSessionUaLoggingValue(
userSettings.getSettingValue<LogSessionUserAgentOption>(
SettingName.LogSessionUserAgent,
@@ -64,19 +55,6 @@ const Privacy: FunctionComponent<Props> = ({ application }: Props) => {
loadSettings().catch(console.error)
}, [loadSettings])
const toggleMuteSignInEmails = async () => {
const previousValue = signInEmailsMutedValue
const newValue =
previousValue === MuteSignInEmailsOption.Muted ? MuteSignInEmailsOption.NotMuted : MuteSignInEmailsOption.Muted
setSignInEmailsMutedValue(newValue)
const updateResult = await updateSetting(SettingName.MuteSignInEmails, newValue)
if (!updateResult) {
setSignInEmailsMutedValue(previousValue)
}
}
const toggleSessionLogging = async () => {
const previousValue = sessionUaLoggingValue
const newValue =
@@ -97,23 +75,6 @@ const Privacy: FunctionComponent<Props> = ({ application }: Props) => {
<PreferencesSegment>
<Title>Privacy</Title>
<div>
<div className="flex items-center justify-between">
<div className="flex flex-col">
<Subtitle>Disable sign-in notification emails</Subtitle>
<Text>
Disables email notifications when a new sign-in occurs on your account. (Email notifications are
available to paid subscribers).
</Text>
</div>
{isLoading ? (
<Spinner className="ml-2 flex-shrink-0" />
) : (
<Switch
onChange={toggleMuteSignInEmails}
checked={signInEmailsMutedValue === MuteSignInEmailsOption.Muted}
/>
)}
</div>
<HorizontalSeparator classes="my-4" />
<div className="flex items-center justify-between">
<div className="flex flex-col">
@@ -8,7 +8,9 @@ import { PreferencesProps } from './PreferencesProps'
const PreferencesCanvas: FunctionComponent<PreferencesProps & { menu: PreferencesMenu }> = (props) => (
<div className="flex min-h-0 flex-grow flex-col-reverse md:flex-row md:justify-between">
<PreferencesMenuView menu={props.menu} />
<PaneSelector {...props} />
<div className="min-h-0 flex-grow overflow-auto bg-contrast">
<PaneSelector {...props} />
</div>
</div>
)
@@ -7,7 +7,7 @@ const PreferencesPane: FunctionComponent<{ children?: ReactNode }> = ({ children
{children != undefined && Array.isArray(children) ? children.filter((child) => child != undefined) : children}
</div>
</div>
<div className="flex-shrink basis-[13.75rem]" />
<div className="hidden flex-shrink basis-[13.75rem] md:block" />
</div>
)
@@ -37,7 +37,7 @@ const PreferencesMenuView: FunctionComponent<Props> = ({ menu }) => {
)
return (
<div className="border-t border-border bg-default px-5 pt-2 pb-6 md:border-0 md:bg-transparent md:px-0 md:py-0">
<div className="border-t border-border bg-default px-5 pt-2 md:border-0 md:bg-contrast md:px-0 md:py-0">
<div className="hidden min-w-55 flex-col overflow-y-auto px-3 py-6 md:flex">
{menuItems.map((pref) => (
<PreferencesMenuItem
@@ -4,8 +4,9 @@ import { observer } from 'mobx-react-lite'
import { PreferencesMenu } from './PreferencesMenu'
import PreferencesCanvas from './PreferencesCanvas'
import { PreferencesProps } from './PreferencesProps'
import { fitNodeToMobileScreen } from '@/Utils'
import { fitNodeToMobileScreen, isIOS } from '@/Utils'
import { useDisableBodyScrollOnMobile } from '@/Hooks/useDisableBodyScrollOnMobile'
import { classNames } from '@/Utils/ConcatenateClassNames'
const PreferencesView: FunctionComponent<PreferencesProps> = (props) => {
const menu = useMemo(
@@ -31,7 +32,10 @@ const PreferencesView: FunctionComponent<PreferencesProps> = (props) => {
return (
<div
className="absolute top-0 left-0 z-preferences flex h-full max-h-screen w-full flex-col bg-contrast"
className={classNames(
'absolute top-0 left-0 z-preferences flex h-full max-h-screen w-full flex-col bg-default pt-safe-top',
isIOS() ? 'pb-safe-bottom' : 'pb-2 md:pb-0',
)}
ref={fitNodeToMobileScreen}
>
<div className="flex w-full flex-row items-center justify-between border-b border-solid border-border bg-default px-3 py-2 md:p-3">
@@ -1,5 +1,6 @@
import { ViewControllerManager } from '@/Controllers/ViewControllerManager'
import Button from '@/Components/Button/Button'
import MobileItemsListButton from '../NoteGroupView/MobileItemsListButton'
type Props = {
viewControllerManager: ViewControllerManager
@@ -14,24 +15,31 @@ const ProtectedItemOverlay = ({ viewControllerManager, onViewItem, hasProtection
: `Add a passcode or create an account to require authentication to view this ${itemType}.`
return (
<div className="flex max-w-md flex-col items-center justify-center text-center">
<h1 className="m-0 w-full text-2xl font-bold">This {itemType} is protected</h1>
<p className="mt-2 w-full text-lg">{instructionText}</p>
<div className="mt-4 flex gap-3">
{!hasProtectionSources && (
<Button
primary
small
onClick={() => {
viewControllerManager.accountMenuController.setShow(true)
}}
>
Open account menu
</Button>
)}
<Button small onClick={onViewItem}>
{hasProtectionSources ? 'Authenticate' : `View ${itemType}`}
</Button>
<div aria-label="Protected overlay" className="section editor sn-component">
<div className="flex h-full flex-grow flex-col justify-center md:flex-row md:items-center">
<div className="mb-auto p-4 md:hidden">
<MobileItemsListButton />
</div>
<div className="mb-auto flex max-w-md flex-col items-center justify-center text-center md:mb-0">
<h1 className="m-0 w-full text-2xl font-bold">This {itemType} is protected</h1>
<p className="mt-2 w-full text-lg">{instructionText}</p>
<div className="mt-4 flex gap-3">
{!hasProtectionSources && (
<Button
primary
small
onClick={() => {
viewControllerManager.accountMenuController.setShow(true)
}}
>
Open account menu
</Button>
)}
<Button small onClick={onViewItem}>
{hasProtectionSources ? 'Authenticate' : `View ${itemType}`}
</Button>
</div>
</div>
</div>
</div>
)
@@ -5,6 +5,7 @@ import Icon from '@/Components/Icon/Icon'
import { usePremiumModal } from '@/Hooks/usePremiumModal'
import Switch from '@/Components/Switch/Switch'
import { PremiumFeatureIconClass, PremiumFeatureIconName } from '../Icon/PremiumFeatureIcon'
import { isMobileScreen } from '@/Utils'
type Props = {
application: WebApplication
@@ -34,11 +35,12 @@ const FocusModeSwitch: FunctionComponent<Props> = ({ application, onToggle, onCl
return (
<>
<button
className="flex w-full cursor-pointer items-center justify-between border-0 bg-transparent px-3 py-1.5 text-left text-sm text-text hover:bg-contrast hover:text-foreground focus:bg-info-backdrop focus:shadow-none"
className="group flex w-full cursor-pointer items-center justify-between border-0 bg-transparent px-3 py-1.5 text-left text-sm text-text hover:bg-contrast hover:text-foreground focus:bg-info-backdrop focus:shadow-none disabled:bg-default disabled:text-passive-2"
onClick={toggle}
disabled={application.isNativeMobileWeb() || isMobileScreen()}
>
<div className="flex items-center">
<Icon type="menu-close" className="mr-2 text-neutral" />
<Icon type="menu-close" className="mr-2 text-neutral group-disabled:text-passive-2" />
Focused Writing
</div>
{isEntitled ? (
@@ -1,5 +1,5 @@
import { WebApplication } from '@/Application/Application'
import { FeatureStatus } from '@standardnotes/snjs'
import { FeatureIdentifier, FeatureStatus } from '@standardnotes/snjs'
import { FunctionComponent, MouseEventHandler, useCallback, useMemo } from 'react'
import Icon from '@/Components/Icon/Icon'
import { usePremiumModal } from '@/Hooks/usePremiumModal'
@@ -7,6 +7,7 @@ import Switch from '@/Components/Switch/Switch'
import { ThemeItem } from './ThemeItem'
import RadioIndicator from '../RadioIndicator/RadioIndicator'
import { PremiumFeatureIconClass, PremiumFeatureIconName } from '../Icon/PremiumFeatureIcon'
import { isMobileScreen } from '@/Utils'
type Props = {
item: ThemeItem
@@ -43,11 +44,14 @@ const ThemesMenuButton: FunctionComponent<Props> = ({ application, item }) => {
[application, canActivateTheme, item, premiumModal],
)
const isMobile = application.isNativeMobileWeb() || isMobileScreen()
return (
<button
className={
'flex w-full cursor-pointer items-center justify-between border-0 bg-transparent px-3 py-1.5 text-left text-sm text-text hover:bg-contrast hover:text-foreground focus:bg-info-backdrop focus:bg-info-backdrop focus:shadow-none focus:shadow-none'
'group flex w-full cursor-pointer items-center justify-between border-0 bg-transparent px-3 py-1.5 text-left text-sm text-text hover:bg-contrast hover:text-foreground focus:bg-info-backdrop focus:shadow-none disabled:bg-default disabled:text-passive-2'
}
disabled={item.identifier === FeatureIdentifier.DynamicTheme && isMobile}
onClick={toggleTheme}
>
{item.component?.isLayerable() ? (

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