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
94 changed files with 1030 additions and 260 deletions
+4
View File
@@ -3,6 +3,10 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.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
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/api",
"version": "1.8.1",
"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",
+64
View File
@@ -3,6 +3,70 @@
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
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@standardnotes/desktop",
"main": "./app/dist/index.js",
"version": "3.23.136",
"version": "3.23.152",
"license": "AGPL-3.0-or-later",
"author": "Standard Notes.",
"private": true,
+4
View File
@@ -3,6 +3,10 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.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 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/encryption",
"version": "1.15.3",
"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',
+4
View File
@@ -3,6 +3,10 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.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 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/filepicker",
"version": "1.23.3",
"version": "1.23.4",
"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.
## [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 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/files",
"version": "1.10.3",
"version": "1.10.4",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
+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.
## [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
@@ -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.4",
"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
}
+12 -1
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) {}
@@ -432,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"
@@ -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 />}
+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.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 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/models",
"version": "1.18.3",
"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)
+64
View File
@@ -3,6 +3,70 @@
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 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/releases",
"version": "1.3.59",
"version": "1.3.75",
"license": "AGPL-3.0-or-later",
"main": "dist/releases.json",
"types": "dist/index.d.ts",
+4
View File
@@ -3,6 +3,10 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.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
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/responses",
"version": "1.10.2",
"version": "1.10.3",
"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.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
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/services",
"version": "1.21.2",
"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
}
@@ -11,4 +11,5 @@ export interface MobileDeviceInterface extends DeviceInterface {
hideMobileInterfaceFromScreenshots(): void
stopHidingMobileInterfaceFromScreenshots(): void
consoleLog(...args: any[]): void
handleThemeSchemeChange(isDark: boolean): void
}
+34
View File
@@ -3,6 +3,40 @@
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
+20 -5
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
@@ -329,7 +335,7 @@ export class SNApplication
this.apiService.loadHost()
this.webSocketsService.loadWebSocketUrl()
this.sessionManager.initializeFromDisk()
await this.sessionManager.initializeFromDisk()
this.settingsService.initializeFromDisk()
@@ -954,10 +960,6 @@ export class SNApplication
| undefined
}
async loadMobileUnlockTiming() {
return this.protectionService.loadMobileUnlockTiming()
}
getBiometricsTimingOptions() {
return this.protectionService.getBiometricsTimingOptions()
}
@@ -1094,6 +1096,8 @@ export class SNApplication
this.createUserApiService()
this.createSubscriptionServer()
this.createSubscriptionApiService()
this.createWebSocketServer()
this.createWebSocketApiService()
this.createSubscriptionManager()
this.createWebSocketsService()
this.createSessionManager()
@@ -1135,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
@@ -1252,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)
@@ -1337,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()
}
@@ -284,11 +286,6 @@ export class SNProtectionService extends AbstractService<ProtectionEvent> implem
return this.storageService.getValue(StorageKey.MobileScreenshotPrivacyEnabled, StorageValueModes.Default, false)
}
loadMobileUnlockTiming(): void {
this.mobilePasscodeTiming = this.getPasscodeTiming()
this.mobileBiometricsTiming = this.getBiometricsTiming()
}
private async validateOrRenewSession(
reason: ChallengeReason,
{ fallBackToAccountPassword = true, requireAccountPassword = false } = {},
@@ -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 {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/snjs",
"version": "2.130.2",
"version": "2.132.4",
"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.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
+3 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/ui-services",
"version": "1.2.7",
"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() {
+100
View File
@@ -3,6 +3,106 @@
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
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/web",
"version": "3.50.4",
"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" />
@@ -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}>
@@ -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
@@ -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'}
/>
)
}
@@ -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 = 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])
@@ -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() ? (
@@ -1,18 +1,20 @@
import { NoteHistoryController } from '@/Controllers/NoteHistory/NoteHistoryController'
import { FeaturesClientInterface } from '@standardnotes/snjs'
import { observer } from 'mobx-react-lite'
import { FunctionComponent } from 'react'
import { FunctionComponent, useCallback } from 'react'
import LegacyHistoryList from './LegacyHistoryList'
import RemoteHistoryList from './RemoteHistoryList'
import { RevisionType } from './RevisionType'
import SessionHistoryList from './SessionHistoryList'
import { HistoryModalMobileTab } from './utils'
type Props = {
features: FeaturesClientInterface
noteHistoryController: NoteHistoryController
selectMobileModalTab: (tab: HistoryModalMobileTab) => void
}
const HistoryListContainer: FunctionComponent<Props> = ({ features, noteHistoryController }) => {
const HistoryListContainer: FunctionComponent<Props> = ({ features, noteHistoryController, selectMobileModalTab }) => {
const { legacyHistory, currentTab, selectTab } = noteHistoryController
const TabButton: FunctionComponent<{
@@ -34,14 +36,30 @@ const HistoryListContainer: FunctionComponent<Props> = ({ features, noteHistoryC
)
}
const onSelectRevision = useCallback(() => {
selectMobileModalTab('Content')
}, [selectMobileModalTab])
const CurrentTabList = () => {
switch (currentTab) {
case RevisionType.Remote:
return <RemoteHistoryList features={features} noteHistoryController={noteHistoryController} />
return (
<RemoteHistoryList
onSelectRevision={onSelectRevision}
features={features}
noteHistoryController={noteHistoryController}
/>
)
case RevisionType.Session:
return <SessionHistoryList noteHistoryController={noteHistoryController} />
return <SessionHistoryList onSelectRevision={onSelectRevision} noteHistoryController={noteHistoryController} />
case RevisionType.Legacy:
return <LegacyHistoryList legacyHistory={legacyHistory} noteHistoryController={noteHistoryController} />
return (
<LegacyHistoryList
onSelectRevision={onSelectRevision}
legacyHistory={legacyHistory}
noteHistoryController={noteHistoryController}
/>
)
}
}
@@ -16,7 +16,7 @@ const HistoryModalDialog = ({ children, onDismiss }: Props) => {
>
<DialogContent
aria-label="Note revision history"
className="my-0 flex h-full w-full flex-col rounded-md bg-[color:var(--modal-background-color)] p-0 shadow-lg md:max-h-[90%] md:w-[90%] md:max-w-[90%]"
className="my-0 flex h-screen w-full flex-col rounded-md bg-[color:var(--modal-background-color)] p-0 pt-safe-top pb-safe-bottom shadow-lg md:max-h-[90%] md:w-[90%] md:max-w-[90%]"
>
<div className="flex h-full flex-col overflow-hidden bg-default">{children}</div>
</DialogContent>
@@ -7,6 +7,7 @@ import HistoryModalContentPane from './HistoryModalContentPane'
import { NoteHistoryController } from '@/Controllers/NoteHistory/NoteHistoryController'
import Icon from '../Icon/Icon'
import { classNames } from '@/Utils/ConcatenateClassNames'
import { HistoryModalMobileTab } from './utils'
const HistoryModalDialogContent = ({
application,
@@ -18,7 +19,7 @@ const HistoryModalDialogContent = ({
}: RevisionHistoryModalContentProps) => {
const [noteHistoryController] = useState(() => new NoteHistoryController(application, note, selectionController))
const [selectedMobileTab, setSelectedMobileTab] = useState<'List' | 'Content'>('Content')
const [selectedMobileTab, setSelectedMobileTab] = useState<HistoryModalMobileTab>('Content')
return (
<>
@@ -56,7 +57,11 @@ const HistoryModalDialogContent = ({
selectedMobileTab === 'List' ? 'flex' : 'hidden',
)}
>
<HistoryListContainer features={application.features} noteHistoryController={noteHistoryController} />
<HistoryListContainer
features={application.features}
noteHistoryController={noteHistoryController}
selectMobileModalTab={setSelectedMobileTab}
/>
</div>
<div
className={classNames(
@@ -7,9 +7,10 @@ import { NoteHistoryController } from '@/Controllers/NoteHistory/NoteHistoryCont
type Props = {
legacyHistory: Action[] | undefined
noteHistoryController: NoteHistoryController
onSelectRevision: () => void
}
const LegacyHistoryList: FunctionComponent<Props> = ({ legacyHistory, noteHistoryController }) => {
const LegacyHistoryList: FunctionComponent<Props> = ({ legacyHistory, noteHistoryController, onSelectRevision }) => {
const { selectLegacyRevision, selectedEntry } = noteHistoryController
const legacyHistoryListRef = useRef<HTMLDivElement>(null)
@@ -33,6 +34,7 @@ const LegacyHistoryList: FunctionComponent<Props> = ({ legacyHistory, noteHistor
isSelected={selectedEntryUrl === url}
onClick={() => {
selectLegacyRevision(entry)
onSelectRevision()
}}
>
{entry.label}
@@ -12,9 +12,14 @@ import { PremiumFeatureIconClass, PremiumFeatureIconName } from '../Icon/Premium
type RemoteHistoryListProps = {
features: FeaturesClientInterface
noteHistoryController: NoteHistoryController
onSelectRevision: () => void
}
const RemoteHistoryList: FunctionComponent<RemoteHistoryListProps> = ({ features, noteHistoryController }) => {
const RemoteHistoryList: FunctionComponent<RemoteHistoryListProps> = ({
features,
noteHistoryController,
onSelectRevision,
}) => {
const { remoteHistory, isFetchingRemoteHistory, selectRemoteRevision, selectedEntry } = noteHistoryController
const remoteHistoryListRef = useRef<HTMLDivElement>(null)
@@ -44,6 +49,7 @@ const RemoteHistoryList: FunctionComponent<RemoteHistoryListProps> = ({ features
isSelected={(selectedEntry as RevisionListEntry)?.uuid === entry.uuid}
onClick={() => {
selectRemoteRevision(entry)
onSelectRevision()
}}
>
<div className="flex flex-grow items-center justify-between">
@@ -6,9 +6,10 @@ import { NoteHistoryController } from '@/Controllers/NoteHistory/NoteHistoryCont
type Props = {
noteHistoryController: NoteHistoryController
onSelectRevision: () => void
}
const SessionHistoryList: FunctionComponent<Props> = ({ noteHistoryController }) => {
const SessionHistoryList: FunctionComponent<Props> = ({ noteHistoryController, onSelectRevision }) => {
const { sessionHistory, selectedRevision, selectSessionRevision } = noteHistoryController
const sessionHistoryListRef = useRef<HTMLDivElement>(null)
@@ -40,6 +41,7 @@ const SessionHistoryList: FunctionComponent<Props> = ({ noteHistoryController })
isSelected={selectedRevision?.payload.updated_at === entry.payload.updated_at}
onClick={() => {
selectSessionRevision(entry)
onSelectRevision()
}}
>
{entry.previewTitle()}
@@ -2,6 +2,8 @@ import { DAYS_IN_A_WEEK, DAYS_IN_A_YEAR } from '@/Constants/Constants'
import { HistoryEntry, NoteHistoryEntry, RevisionListEntry } from '@standardnotes/snjs'
import { calculateDifferenceBetweenDatesInDays } from '../../Utils/CalculateDifferenceBetweenDatesInDays'
export type HistoryModalMobileTab = 'Content' | 'List'
export type LegacyHistoryEntry = {
payload: HistoryEntry['payload']
created_at: string
@@ -112,6 +112,8 @@ const SmartViewsListItem: FunctionComponent<Props> = ({ view, tagsState }) => {
return (
<>
<div
role="button"
tabIndex={0}
className={classNames('tag py-2 px-3.5 md:py-1', isSelected && 'selected', isFaded && 'opacity-50')}
onClick={selectCurrentTag}
style={{
@@ -202,7 +202,9 @@ export const TagsListItem: FunctionComponent<Props> = observer(({ tag, features,
return (
<>
<button
<div
role="button"
tabIndex={0}
className={classNames(
'tag py-2 px-3.5 focus:shadow-inner md:py-1',
isSelected && 'selected',
@@ -272,7 +274,7 @@ export const TagsListItem: FunctionComponent<Props> = observer(({ tag, features,
<div className={`meta ${hasAtLeastOneFolder ? 'with-folders' : ''}`}>
{tag.conflictOf && <div className="danger text-[0.625rem] font-bold">Conflicted Copy {tag.conflictOf}</div>}
</div>
</button>
</div>
{isAddingSubtag && (
<div
className="tag overflow-hidden"
@@ -116,7 +116,7 @@ export class NotesController extends AbstractViewController {
return this.application.items.trashedItems.length
}
setContextMenuOpen(open: boolean): void {
setContextMenuOpen = (open: boolean) => {
this.contextMenuOpen = open
}
@@ -29,9 +29,18 @@ export class PreferencesController {
closePreferences = (): void => {
this._open = false
this.currentPane = DEFAULT_PANE
this.removePreferencesToggleFromURLQueryParameters()
}
get isOpen(): boolean {
return this._open
}
private removePreferencesToggleFromURLQueryParameters() {
const urlSearchParams = new URLSearchParams(window.location.search)
urlSearchParams.delete('settings')
const newUrl = `${window.location.origin}${window.location.pathname}${urlSearchParams.toString()}`
window.history.replaceState(null, document.title, newUrl)
}
}
@@ -29,6 +29,8 @@ import { NavigationController } from './Navigation/NavigationController'
import { FilePreviewModalController } from './FilePreviewModalController'
import { SelectedItemsController } from './SelectedItemsController'
import { HistoryModalController } from './NoteHistory/HistoryModalController'
import { PreferenceId } from '@/Components/Preferences/PreferencesMenu'
import { AccountMenuPane } from '@/Components/AccountMenu/AccountMenuPane'
export class ViewControllerManager {
readonly enableUnfinishedFeatures: boolean = window?.enabledUnfinishedFeatures
@@ -209,11 +211,31 @@ export class ViewControllerManager {
addAppEventObserver() {
this.unsubAppEventObserver = this.application.addEventObserver(async (eventName) => {
const urlSearchParams = new URLSearchParams(window.location.search)
switch (eventName) {
case ApplicationEvent.Launched:
if (window.location.search.includes('purchase=true')) {
if (urlSearchParams.get('purchase')) {
this.purchaseFlowController.openPurchaseFlow()
}
if (urlSearchParams.get('settings')) {
const user = this.application.getUser()
if (user === undefined) {
this.accountMenuController.setShow(true)
this.accountMenuController.setCurrentPane(AccountMenuPane.SignIn)
break
}
this.preferencesController.openPreferences()
this.preferencesController.setCurrentPane(urlSearchParams.get('settings') as PreferenceId)
}
break
case ApplicationEvent.SignedIn:
if (urlSearchParams.get('settings')) {
this.preferencesController.openPreferences()
this.preferencesController.setCurrentPane(urlSearchParams.get('settings') as PreferenceId)
}
break
case ApplicationEvent.SyncStatusChanged:
this.syncStatusController.update(this.application.sync.getSyncStatus())
@@ -1,14 +1,18 @@
import { SNApplication } from '@standardnotes/snjs'
import { Environment, SNApplication } from '@standardnotes/snjs'
export async function openSubscriptionDashboard(application: SNApplication) {
const token = await application.getNewSubscriptionToken()
if (!token) {
return
}
const url = `${window.dashboardUrl}?subscription_token=${token}`
if (application.deviceInterface.environment === Environment.NativeMobileWeb) {
application.deviceInterface.openUrl(url)
return
}
export function openSubscriptionDashboard(application: SNApplication): void {
const windowProxy = window.open('', '_blank')
application
.getNewSubscriptionToken()
.then((token) => {
if (!token) {
return
}
;(windowProxy as WindowProxy).location = `${window.dashboardUrl}?subscription_token=${token}`
})
.catch(console.error)
;(windowProxy as WindowProxy).location = url
}
+11
View File
@@ -23,6 +23,11 @@
--sn-stylekit-editor-font-family: var(--sn-stylekit-sans-serif-font);
--reach-checkbox: 1;
--safe-area-inset-top: env(safe-area-inset-top, 0);
--safe-area-inset-bottom: env(safe-area-inset-bottom, 0);
--safe-area-inset-left: env(safe-area-inset-left, 0);
--safe-area-inset-right: env(safe-area-inset-right, 0);
}
html {
@@ -31,9 +36,15 @@ html {
body {
font-size: var(--sn-stylekit-base-font-size);
background-color: var(--sn-stylekit-background-color);
color: var(--sn-stylekit-foreground-color);
}
.safe-area-padding {
padding: var(--safe-area-inset-top) var(--safe-area-inset-right) var(--safe-area-inset-bottom)
var(--safe-area-inset-left);
}
html,
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans',
+10
View File
@@ -15,6 +15,10 @@ module.exports = {
87.5: '21.875rem',
125: '31.25rem',
160: '40rem',
'safe-top': 'var(--safe-area-inset-top)',
'safe-bottom': 'var(--safe-area-inset-bottom)',
'safe-left': 'var(--safe-area-inset-left)',
'safe-right': 'var(--safe-area-inset-right)',
},
minWidth: {
1: '0.25rem',
@@ -135,6 +139,12 @@ module.exports = {
'text-accessory-tint-4',
'text-accessory-tint-5',
'text-accessory-tint-6',
'border-accessory-tint-1',
'border-accessory-tint-2',
'border-accessory-tint-3',
'border-accessory-tint-4',
'border-accessory-tint-5',
'border-accessory-tint-6',
],
plugins: [
plugin(function ({ addVariant }) {
+1
View File
@@ -7650,6 +7650,7 @@ __metadata:
eslint-plugin-prettier: "*"
jest: ^28.1.2
ts-jest: ^28.0.5
typescript: "*"
languageName: unknown
linkType: soft