Compare commits

...
Author SHA1 Message Date
StandardNotes CI 4620fe9f07 chore(release): publish
- @standardnotes/[email protected].8
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].8
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].9
 - @standardnotes/[email protected].9
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
2023-01-23 07:35:21 +00:00
Karol Sójko 981bf6ac92 fix(models): dependency level 2023-01-23 08:10:12 +01:00
StandardNotes CI 6e4a512371 chore(release): publish
- @standardnotes/[email protected].7
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].7
 - @standardnotes/[email protected].6
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].9
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].6
 - @standardnotes/[email protected].8
 - @standardnotes/[email protected].8
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].3
 - @standardnotes/[email protected].9
2023-01-21 10:54:24 +00:00
Aman Harwara 3a204cdcc8 Merge branch 'main' of github.com:standardnotes/app 2023-01-21 15:55:41 +05:30
Aman Harwara 98f6cbd7d0 chore: fix file reader input positioning 2023-01-21 15:55:32 +05:30
StandardNotes CI 607ac361d1 chore(release): publish
- @standardnotes/[email protected].6
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].6
 - @standardnotes/[email protected].5
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].8
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].5
 - @standardnotes/[email protected].7
 - @standardnotes/[email protected].7
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].8
2023-01-20 23:32:47 +00:00
moughxyz 545d2dbfa9 temp: skip history e2e 2023-01-20 17:06:52 -06:00
Mo e7214ea73a fix: fixed issue with third party editors not loading (#2174) 2023-01-20 16:32:33 -06:00
StandardNotes CI 67374ab49b chore(release): publish
- @standardnotes/[email protected].5
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].5
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].7
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].6
 - @standardnotes/[email protected].6
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].6
2023-01-20 15:22:48 +00:00
Karol Sójko e9a10123fe fix(models): dependency on utils declaration 2023-01-20 15:02:30 +01:00
Karol Sójko beccfb16b3 fix(models): dependency declaration 2023-01-20 15:02:30 +01:00
StandardNotes CI 6e7517650b chore(release): publish
- @standardnotes/[email protected].4
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].4
 - @standardnotes/[email protected].4
 - @standardnotes/[email protected].9
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].6
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].4
 - @standardnotes/[email protected].5
 - @standardnotes/[email protected].5
 - @standardnotes/[email protected].9
 - @standardnotes/[email protected].2
 - @standardnotes/[email protected].5
2023-01-20 12:48:06 +00:00
Karol Sójko 87b974bdd5 chore: upgrade @standardnotes/common 2023-01-20 12:37:38 +01:00
StandardNotes CI 16aaef00c3 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].4
 - @standardnotes/[email protected].4
 - @standardnotes/[email protected].8
 - @standardnotes/[email protected].4
2023-01-20 10:52:46 +00:00
Karol Sójko 21a4eb0cf0 fix(snjs): signed out fetching revisions test 2023-01-20 11:26:16 +01:00
Karol Sójko 6a7ff423ff fix(snjs): remove isFailed() checks during tests in order for getValue() to give a meaningful exception 2023-01-20 10:45:16 +01:00
Karol Sójko cb9c16047e fix(snjs): bring back history tests and fix handlinf of error with revisions 2023-01-20 10:02:48 +01:00
StandardNotes CI e61ac4c54a chore(release): publish
- @standardnotes/[email protected].3
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].3
 - @standardnotes/[email protected].3
 - @standardnotes/[email protected].8
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].5
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].3
 - @standardnotes/[email protected].3
 - @standardnotes/[email protected].3
 - @standardnotes/[email protected].7
 - @standardnotes/[email protected].3
2023-01-20 04:11:59 +00:00
Mo 544a28d450 refactor: offline roles (#2169) 2023-01-19 21:46:21 -06:00
moughxyz 391b2af4e1 temp: skip history e2e tests 2023-01-19 21:26:26 -06:00
StandardNotes CI 6c73885d1f chore(release): publish
- @standardnotes/[email protected].2
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].2
 - @standardnotes/[email protected].2
 - @standardnotes/[email protected].7
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].4
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].2
 - @standardnotes/[email protected].2
 - @standardnotes/[email protected].2
 - @standardnotes/[email protected].6
 - @standardnotes/[email protected].2
2023-01-19 23:32:24 +00:00
moughxyz 561d4da9bd chore: upgrade @standardnotes deps 2023-01-19 17:05:10 -06:00
85 changed files with 1002 additions and 438 deletions
Binary file not shown.
+28
View File
@@ -3,6 +3,34 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.24.8](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-23)
**Note:** Version bump only for package @standardnotes/api
## [1.24.7](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-21)
**Note:** Version bump only for package @standardnotes/api
## [1.24.6](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/api
## [1.24.5](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/api
## [1.24.4](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/api
## [1.24.3](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/api
## [1.24.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-19)
**Note:** Version bump only for package @standardnotes/api
## [1.24.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-19)
**Note:** Version bump only for package @standardnotes/api
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/api",
"version": "1.24.1",
"version": "1.24.8",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
@@ -36,12 +36,12 @@
"typescript": "*"
},
"dependencies": {
"@standardnotes/common": "^1.46.3",
"@standardnotes/common": "^1.46.4",
"@standardnotes/domain-core": "^1.11.1",
"@standardnotes/encryption": "workspace:*",
"@standardnotes/models": "workspace:*",
"@standardnotes/responses": "workspace:*",
"@standardnotes/security": "^1.7.0",
"@standardnotes/security": "^1.7.5",
"@standardnotes/utils": "workspace:*",
"reflect-metadata": "^0.1.13"
}
+32
View File
@@ -3,6 +3,38 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [3.104.102](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-23)
**Note:** Version bump only for package @standardnotes/desktop
## [3.104.101](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-21)
**Note:** Version bump only for package @standardnotes/desktop
## [3.104.100](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/desktop
## [3.104.99](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/desktop
## [3.104.98](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/desktop
## [3.104.97](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/desktop
## [3.104.96](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/desktop
## [3.104.95](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-19)
**Note:** Version bump only for package @standardnotes/desktop
## [3.104.94](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-19)
**Note:** Version bump only for package @standardnotes/desktop
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@standardnotes/desktop",
"main": "./app/dist/index.js",
"version": "3.104.94",
"version": "3.104.102",
"license": "AGPL-3.0-or-later",
"author": "Standard Notes.",
"private": true,
+28
View File
@@ -3,6 +3,34 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.21.8](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-23)
**Note:** Version bump only for package @standardnotes/encryption
## [1.21.7](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-21)
**Note:** Version bump only for package @standardnotes/encryption
## [1.21.6](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/encryption
## [1.21.5](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/encryption
## [1.21.4](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/encryption
## [1.21.3](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/encryption
## [1.21.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-19)
**Note:** Version bump only for package @standardnotes/encryption
## [1.21.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-19)
**Note:** Version bump only for package @standardnotes/encryption
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/encryption",
"version": "1.21.1",
"version": "1.21.8",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
@@ -35,7 +35,7 @@
"typescript": "*"
},
"dependencies": {
"@standardnotes/common": "^1.46.3",
"@standardnotes/common": "^1.46.4",
"@standardnotes/models": "workspace:*",
"@standardnotes/responses": "workspace:*",
"@standardnotes/sncrypto-common": "workspace:*",
+22
View File
@@ -3,6 +3,28 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.58.6](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-21)
**Note:** Version bump only for package @standardnotes/features
## [1.58.5](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
### Bug Fixes
* fixed issue with third party editors not loading ([#2174](https://github.com/standardnotes/app/issues/2174)) ([e7214ea](https://github.com/standardnotes/app/commit/e7214ea73ad5d3026d958c79022d2238a4d1cfdc))
## [1.58.4](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/features
## [1.58.3](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/features
## [1.58.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-19)
**Note:** Version bump only for package @standardnotes/features
## [1.58.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-19)
**Note:** Version bump only for package @standardnotes/features
+3 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/features",
"version": "1.58.1",
"version": "1.58.6",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
@@ -25,10 +25,9 @@
"test": "jest"
},
"dependencies": {
"@standardnotes/auth": "^3.19.4",
"@standardnotes/common": "^1.46.3",
"@standardnotes/common": "^1.46.4",
"@standardnotes/domain-core": "^1.11.1",
"@standardnotes/security": "^1.7.0",
"@standardnotes/security": "^1.7.5",
"reflect-metadata": "^0.1.13"
},
"devDependencies": {
@@ -5,7 +5,6 @@ describe('note type', () => {
it('should return the correct note type for editor identifier', () => {
expect(noteTypeForEditorIdentifier(FeatureIdentifier.PlainEditor)).toEqual(NoteType.Plain)
expect(noteTypeForEditorIdentifier(FeatureIdentifier.SuperEditor)).toEqual(NoteType.Super)
expect(noteTypeForEditorIdentifier(FeatureIdentifier.MarkdownVisualEditor)).toEqual(NoteType.Markdown)
expect(noteTypeForEditorIdentifier(FeatureIdentifier.MarkdownProEditor)).toEqual(NoteType.Markdown)
expect(noteTypeForEditorIdentifier(FeatureIdentifier.PlusEditor)).toEqual(NoteType.RichText)
expect(noteTypeForEditorIdentifier(FeatureIdentifier.CodeEditor)).toEqual(NoteType.Code)
@@ -1,5 +1,4 @@
export enum FeatureIdentifier {
AccountSwitcher = 'com.standardnotes.account-switcher',
CloudLink = 'org.standardnotes.cloudlink',
DailyDropboxBackup = 'org.standardnotes.daily-dropbox-backup',
DailyEmailBackup = 'org.standardnotes.daily-email-backup',
@@ -21,7 +20,6 @@ export enum FeatureIdentifier {
AutobiographyTheme = 'org.standardnotes.theme-autobiography',
DynamicTheme = 'org.standardnotes.theme-dynamic',
DarkTheme = 'org.standardnotes.theme-focus',
FocusMode = 'org.standardnotes.focus-mode',
FuturaTheme = 'org.standardnotes.theme-futura',
MidnightTheme = 'org.standardnotes.theme-midnight',
SolarizedDarkTheme = 'org.standardnotes.theme-solarized-dark',
@@ -32,12 +30,12 @@ export enum FeatureIdentifier {
CodeEditor = 'org.standardnotes.code-editor',
MarkdownProEditor = 'org.standardnotes.advanced-markdown-editor',
MarkdownVisualEditor = 'org.standardnotes.markdown-visual-editor',
PlusEditor = 'org.standardnotes.plus-editor',
SheetsEditor = 'org.standardnotes.standard-sheets',
TaskEditor = 'org.standardnotes.simple-task-editor',
TokenVaultEditor = 'org.standardnotes.token-vault',
DeprecatedMarkdownVisualEditor = 'org.standardnotes.markdown-visual-editor',
DeprecatedBoldEditor = 'org.standardnotes.bold-editor',
DeprecatedMarkdownBasicEditor = 'org.standardnotes.simple-markdown-editor',
DeprecatedMarkdownMathEditor = 'org.standardnotes.fancy-markdown-editor',
@@ -1,7 +1,5 @@
import { FeatureDescription } from './FeatureDescription'
import { FeatureIdentifier } from './FeatureIdentifier'
import { editors } from '../Lists/Editors'
import { themes } from '../Lists/Themes'
import { serverFeatures } from '../Lists/ServerFeatures'
import { clientFeatures } from '../Lists/ClientFeatures'
import { GetDeprecatedFeatures } from '../Lists/DeprecatedFeatures'
@@ -9,14 +7,7 @@ import { experimentalFeatures } from '../Lists/ExperimentalFeatures'
import { SubscriptionName } from '@standardnotes/common'
export function GetFeatures(): FeatureDescription[] {
return [
...themes(),
...editors(),
...serverFeatures(),
...clientFeatures(),
...experimentalFeatures(),
...GetDeprecatedFeatures(),
]
return [...serverFeatures(), ...clientFeatures(), ...experimentalFeatures(), ...GetDeprecatedFeatures()]
}
export function GetFeaturesForSubscription(subscription: SubscriptionName): FeatureDescription[] {
@@ -1,14 +1,19 @@
import { ClientFeatureDescription } from '../Feature/FeatureDescription'
import { FeatureDescription } from '../Feature/FeatureDescription'
import { PermissionName } from '../Permission/PermissionName'
import { FeatureIdentifier } from '../Feature/FeatureIdentifier'
import { SubscriptionName } from '@standardnotes/common'
import { RoleName } from '@standardnotes/domain-core'
import { themes } from './Themes'
import { editors } from './Editors'
export function clientFeatures(): ClientFeatureDescription[] {
export function clientFeatures(): FeatureDescription[] {
return [
...themes(),
...editors(),
{
availableInSubscriptions: [SubscriptionName.PlusPlan, SubscriptionName.ProPlan],
name: 'Tag Nesting',
availableInSubscriptions: [SubscriptionName.PlusPlan, SubscriptionName.ProPlan],
availableInRoles: [RoleName.NAMES.PlusUser, RoleName.NAMES.ProUser],
identifier: FeatureIdentifier.TagNesting,
permission_name: PermissionName.TagNesting,
description: 'Organize your tags into folders.',
@@ -17,45 +22,26 @@ export function clientFeatures(): ClientFeatureDescription[] {
name: 'Super Notes',
identifier: FeatureIdentifier.SuperEditor,
availableInSubscriptions: [SubscriptionName.PlusPlan, SubscriptionName.ProPlan],
availableInRoles: [RoleName.NAMES.PlusUser, RoleName.NAMES.ProUser],
permission_name: PermissionName.SuperEditor,
description:
'Type / to bring up the block selection menu, or @ to embed images or link other tags and notes. Type - then space to start a list, or [] then space to start a checklist. Drag and drop an image or file to embed it in your note.',
availableInRoles: [RoleName.NAMES.PlusUser, RoleName.NAMES.ProUser],
'A new way to edit notes. Type / to bring up the block selection menu, or @ to embed images or link other tags and notes. Type - then space to start a list, or [] then space to start a checklist. Drag and drop an image or file to embed it in your note. Cmd/Ctrl + F to bring up search and replace.',
},
{
availableInSubscriptions: [SubscriptionName.PlusPlan, SubscriptionName.ProPlan],
name: 'Smart Filters',
availableInSubscriptions: [SubscriptionName.PlusPlan, SubscriptionName.ProPlan],
availableInRoles: [RoleName.NAMES.PlusUser, RoleName.NAMES.ProUser],
identifier: FeatureIdentifier.SmartFilters,
permission_name: PermissionName.SmartFilters,
description: 'Create smart filters for viewing notes matching specific criteria.',
},
{
availableInSubscriptions: [SubscriptionName.PlusPlan, SubscriptionName.ProPlan],
name: 'Encrypted files',
availableInSubscriptions: [SubscriptionName.PlusPlan, SubscriptionName.ProPlan],
availableInRoles: [RoleName.NAMES.ProUser],
identifier: FeatureIdentifier.Files,
permission_name: PermissionName.Files,
description: '',
},
{
availableInSubscriptions: [SubscriptionName.PlusPlan, SubscriptionName.ProPlan],
name: 'Focus Mode',
identifier: FeatureIdentifier.FocusMode,
permission_name: PermissionName.FocusMode,
description: '',
},
{
availableInSubscriptions: [SubscriptionName.PlusPlan, SubscriptionName.ProPlan],
name: 'Listed Custom Domain',
identifier: FeatureIdentifier.ListedCustomDomain,
permission_name: PermissionName.ListedCustomDomain,
description: '',
},
{
availableInSubscriptions: [SubscriptionName.PlusPlan, SubscriptionName.ProPlan],
name: 'Multiple accounts',
identifier: FeatureIdentifier.AccountSwitcher,
permission_name: PermissionName.AccountSwitcher,
description: '',
},
]
}
@@ -10,6 +10,7 @@ import { NoteType } from '../Component/NoteType'
import { FillEditorComponentDefaults } from './Utilities/FillEditorComponentDefaults'
import { ComponentAction } from '../Component/ComponentAction'
import { ComponentArea } from '../Component/ComponentArea'
import { RoleName } from '@standardnotes/domain-core'
export function GetDeprecatedFeatures(): FeatureDescription[] {
const bold: EditorFeatureDescription = FillEditorComponentDefaults({
@@ -37,6 +38,7 @@ export function GetDeprecatedFeatures(): FeatureDescription[] {
permission_name: PermissionName.BoldEditor,
description: 'A simple and peaceful rich editor that helps you write and think clearly.',
thumbnail_url: 'https://s3.amazonaws.com/standard-notes/screenshots/models/editors/bold.jpg',
availableInRoles: [RoleName.NAMES.PlusUser, RoleName.NAMES.ProUser],
})
const markdownBasic: EditorFeatureDescription = FillEditorComponentDefaults({
@@ -50,6 +52,22 @@ export function GetDeprecatedFeatures(): FeatureDescription[] {
permission_name: PermissionName.MarkdownBasicEditor,
description: 'A Markdown editor with dynamic split-pane preview.',
thumbnail_url: 'https://s3.amazonaws.com/standard-notes/screenshots/models/editors/simple-markdown.jpg',
availableInRoles: [RoleName.NAMES.PlusUser, RoleName.NAMES.ProUser],
})
const markdownAlt: EditorFeatureDescription = FillEditorComponentDefaults({
availableInSubscriptions: [SubscriptionName.PlusPlan, SubscriptionName.ProPlan],
name: 'Markdown Alternative',
identifier: FeatureIdentifier.DeprecatedMarkdownVisualEditor,
note_type: NoteType.Markdown,
file_type: 'md',
deprecated: true,
permission_name: PermissionName.MarkdownVisualEditor,
spellcheckControl: true,
description:
'A WYSIWYG-style Markdown editor that renders Markdown in preview-mode while you type without displaying any syntax.',
index_path: 'build/index.html',
availableInRoles: [RoleName.NAMES.PlusUser, RoleName.NAMES.ProUser],
})
const markdownMinimist: EditorFeatureDescription = FillEditorComponentDefaults({
@@ -64,6 +82,7 @@ export function GetDeprecatedFeatures(): FeatureDescription[] {
deprecated: true,
description: 'A minimal Markdown editor with live rendering and in-text search via Ctrl/Cmd + F',
thumbnail_url: 'https://s3.amazonaws.com/standard-notes/screenshots/models/editors/min-markdown.jpg',
availableInRoles: [RoleName.NAMES.PlusUser, RoleName.NAMES.ProUser],
})
const markdownMath: EditorFeatureDescription = FillEditorComponentDefaults({
@@ -78,6 +97,7 @@ export function GetDeprecatedFeatures(): FeatureDescription[] {
index_path: 'index.html',
description: 'A beautiful split-pane Markdown editor with synced-scroll, LaTeX support, and colorful syntax.',
thumbnail_url: 'https://s3.amazonaws.com/standard-notes/screenshots/models/editors/fancy-markdown.jpg',
availableInRoles: [RoleName.NAMES.PlusUser, RoleName.NAMES.ProUser],
})
const filesafe: IframeComponentFeatureDescription = FillEditorComponentDefaults({
@@ -104,7 +124,8 @@ export function GetDeprecatedFeatures(): FeatureDescription[] {
description:
'Encrypted attachments for your notes using your Dropbox, Google Drive, or WebDAV server. Limited to 50MB per file.',
thumbnail_url: 'https://s3.amazonaws.com/standard-notes/screenshots/models/FileSafe-banner.png',
availableInRoles: [RoleName.NAMES.PlusUser, RoleName.NAMES.ProUser],
})
return [bold, markdownBasic, markdownMinimist, markdownMath, filesafe]
return [bold, markdownBasic, markdownMinimist, markdownMath, markdownAlt, filesafe]
}
+8 -14
View File
@@ -4,6 +4,7 @@ import { PermissionName } from '../Permission/PermissionName'
import { FeatureIdentifier } from '../Feature/FeatureIdentifier'
import { NoteType } from '../Component/NoteType'
import { FillEditorComponentDefaults } from './Utilities/FillEditorComponentDefaults'
import { RoleName } from '@standardnotes/domain-core'
export function editors(): EditorFeatureDescription[] {
const code: EditorFeatureDescription = FillEditorComponentDefaults({
@@ -20,6 +21,7 @@ export function editors(): EditorFeatureDescription[] {
'Syntax highlighting and convenient keyboard shortcuts for over 120 programming' +
' languages. Ideal for code snippets and procedures.',
thumbnail_url: 'https://s3.amazonaws.com/standard-notes/screenshots/models/editors/code.jpg',
availableInRoles: [RoleName.NAMES.PlusUser, RoleName.NAMES.ProUser],
})
const plus: EditorFeatureDescription = FillEditorComponentDefaults({
@@ -33,6 +35,7 @@ export function editors(): EditorFeatureDescription[] {
description:
'From highlighting to custom font sizes and colors, to tables and lists, this editor is perfect for crafting any document.',
thumbnail_url: 'https://s3.amazonaws.com/standard-notes/screenshots/models/editors/plus-editor.jpg',
availableInRoles: [RoleName.NAMES.PlusUser, RoleName.NAMES.ProUser],
})
const markdown: EditorFeatureDescription = FillEditorComponentDefaults({
@@ -46,19 +49,7 @@ export function editors(): EditorFeatureDescription[] {
description:
'A fully featured Markdown editor that supports live preview, a styling toolbar, and split pane support.',
thumbnail_url: 'https://s3.amazonaws.com/standard-notes/screenshots/models/editors/adv-markdown.jpg',
})
const markdownAlt: EditorFeatureDescription = FillEditorComponentDefaults({
availableInSubscriptions: [SubscriptionName.PlusPlan, SubscriptionName.ProPlan],
name: 'Markdown Alternative',
identifier: FeatureIdentifier.MarkdownVisualEditor,
note_type: NoteType.Markdown,
file_type: 'md',
permission_name: PermissionName.MarkdownVisualEditor,
spellcheckControl: true,
description:
'A WYSIWYG-style Markdown editor that renders Markdown in preview-mode while you type without displaying any syntax.',
index_path: 'build/index.html',
availableInRoles: [RoleName.NAMES.PlusUser, RoleName.NAMES.ProUser],
})
const task: EditorFeatureDescription = FillEditorComponentDefaults({
@@ -73,6 +64,7 @@ export function editors(): EditorFeatureDescription[] {
description:
'A great way to manage short-term and long-term to-do"s. You can mark tasks as completed, change their order, and edit the text naturally in place.',
thumbnail_url: 'https://s3.amazonaws.com/standard-notes/screenshots/models/editors/task-editor.jpg',
availableInRoles: [RoleName.NAMES.PlusUser, RoleName.NAMES.ProUser],
})
const tokenvault: EditorFeatureDescription = FillEditorComponentDefaults({
@@ -86,6 +78,7 @@ export function editors(): EditorFeatureDescription[] {
description:
'Encrypt and protect your 2FA secrets for all your internet accounts. Authenticator handles your 2FA secrets so that you never lose them again, or have to start over when you get a new device.',
thumbnail_url: 'https://standard-notes.s3.amazonaws.com/screenshots/models/editors/token-vault.png',
availableInRoles: [RoleName.NAMES.PlusUser, RoleName.NAMES.ProUser],
})
const spreadsheets: EditorFeatureDescription = FillEditorComponentDefaults({
@@ -99,7 +92,8 @@ export function editors(): EditorFeatureDescription[] {
description:
'A powerful spreadsheet editor with formatting and formula support. Not recommended for large data sets, as encryption of such data may decrease editor performance.',
thumbnail_url: 'https://s3.amazonaws.com/standard-notes/screenshots/models/editors/spreadsheets.png',
availableInRoles: [RoleName.NAMES.PlusUser, RoleName.NAMES.ProUser],
})
return [code, plus, markdown, markdownAlt, task, tokenvault, spreadsheets]
return [code, plus, markdown, task, tokenvault, spreadsheets]
}
@@ -65,5 +65,11 @@ export function serverFeatures(): ServerFeatureDescription[] {
identifier: FeatureIdentifier.SubscriptionSharing,
permission_name: PermissionName.SubscriptionSharing,
},
{
availableInSubscriptions: [SubscriptionName.PlusPlan, SubscriptionName.ProPlan],
name: 'Listed Custom Domain',
identifier: FeatureIdentifier.ListedCustomDomain,
permission_name: PermissionName.ListedCustomDomain,
},
]
}
@@ -3,6 +3,7 @@ import { PermissionName } from '../Permission/PermissionName'
import { FeatureIdentifier } from '../Feature/FeatureIdentifier'
import { FillThemeComponentDefaults } from './Utilities/FillThemeComponentDefaults'
import { SubscriptionName } from '@standardnotes/common'
import { RoleName } from '@standardnotes/domain-core'
export function themes(): ThemeFeatureDescription[] {
const midnight: ThemeFeatureDescription = FillThemeComponentDefaults({
@@ -17,10 +18,12 @@ export function themes(): ThemeFeatureDescription[] {
foreground_color: '#ffffff',
border_color: '#086DD6',
},
availableInRoles: [RoleName.NAMES.PlusUser, RoleName.NAMES.ProUser],
})
const futura: ThemeFeatureDescription = FillThemeComponentDefaults({
availableInSubscriptions: [SubscriptionName.PlusPlan, SubscriptionName.ProPlan],
availableInRoles: [RoleName.NAMES.PlusUser, RoleName.NAMES.ProUser],
name: 'Futura',
identifier: FeatureIdentifier.FuturaTheme,
permission_name: PermissionName.FuturaTheme,
@@ -35,6 +38,7 @@ export function themes(): ThemeFeatureDescription[] {
const solarizedDark: ThemeFeatureDescription = FillThemeComponentDefaults({
availableInSubscriptions: [SubscriptionName.PlusPlan, SubscriptionName.ProPlan],
availableInRoles: [RoleName.NAMES.PlusUser, RoleName.NAMES.ProUser],
name: 'Solarized Dark',
identifier: FeatureIdentifier.SolarizedDarkTheme,
permission_name: PermissionName.SolarizedDarkTheme,
@@ -49,6 +53,7 @@ export function themes(): ThemeFeatureDescription[] {
const autobiography: ThemeFeatureDescription = FillThemeComponentDefaults({
availableInSubscriptions: [SubscriptionName.PlusPlan, SubscriptionName.ProPlan],
availableInRoles: [RoleName.NAMES.PlusUser, RoleName.NAMES.ProUser],
name: 'Autobiography',
identifier: FeatureIdentifier.AutobiographyTheme,
permission_name: PermissionName.AutobiographyTheme,
@@ -77,6 +82,7 @@ export function themes(): ThemeFeatureDescription[] {
const titanium: ThemeFeatureDescription = FillThemeComponentDefaults({
availableInSubscriptions: [SubscriptionName.PlusPlan, SubscriptionName.ProPlan],
availableInRoles: [RoleName.NAMES.PlusUser, RoleName.NAMES.ProUser],
name: 'Titanium',
identifier: FeatureIdentifier.TitaniumTheme,
permission_name: PermissionName.TitaniumTheme,
@@ -90,6 +96,7 @@ export function themes(): ThemeFeatureDescription[] {
const dynamic: ThemeFeatureDescription = FillThemeComponentDefaults({
availableInSubscriptions: [SubscriptionName.PlusPlan, SubscriptionName.ProPlan],
availableInRoles: [RoleName.NAMES.PlusUser, RoleName.NAMES.ProUser],
name: 'Dynamic Panels',
identifier: FeatureIdentifier.DynamicTheme,
permission_name: PermissionName.ThemeDynamic,
+28
View File
@@ -3,6 +3,34 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.28.13](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-23)
**Note:** Version bump only for package @standardnotes/filepicker
## [1.28.12](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-21)
**Note:** Version bump only for package @standardnotes/filepicker
## [1.28.11](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/filepicker
## [1.28.10](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/filepicker
## [1.28.9](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/filepicker
## [1.28.8](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/filepicker
## [1.28.7](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-19)
**Note:** Version bump only for package @standardnotes/filepicker
## [1.28.6](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-19)
**Note:** Version bump only for package @standardnotes/filepicker
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/filepicker",
"version": "1.28.6",
"version": "1.28.13",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
@@ -26,7 +26,7 @@
"typescript": "*"
},
"dependencies": {
"@standardnotes/common": "^1.46.3",
"@standardnotes/common": "^1.46.4",
"@standardnotes/files": "workspace:*",
"@standardnotes/utils": "workspace:*",
"@types/wicg-file-system-access": "^2020.9.5",
@@ -28,7 +28,13 @@ function createFileInputOrReturnExisting(): HTMLInputElement {
fileInput = document.createElement('input')
fileInput.id = FileInputId
fileInput.type = 'file'
fileInput.className = 'absolute top-0 left-0 -z-50 h-px w-px opacity-0'
fileInput.style.position = 'absolute'
fileInput.style.top = '0'
fileInput.style.left = '0'
fileInput.style.height = '1px'
fileInput.style.width = '1px'
fileInput.style.opacity = '0'
fileInput.style.zIndex = '-50'
fileInput.multiple = true
document.body.appendChild(fileInput)
+28
View File
@@ -3,6 +3,34 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.14.23](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-23)
**Note:** Version bump only for package @standardnotes/files
## [1.14.22](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-21)
**Note:** Version bump only for package @standardnotes/files
## [1.14.21](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/files
## [1.14.20](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/files
## [1.14.19](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/files
## [1.14.18](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/files
## [1.14.17](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-19)
**Note:** Version bump only for package @standardnotes/files
## [1.14.16](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-19)
**Note:** Version bump only for package @standardnotes/files
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/files",
"version": "1.14.16",
"version": "1.14.23",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
@@ -28,7 +28,7 @@
"typescript": "*"
},
"dependencies": {
"@standardnotes/common": "^1.46.3",
"@standardnotes/common": "^1.46.4",
"@standardnotes/encryption": "workspace:*",
"@standardnotes/models": "workspace:*",
"@standardnotes/responses": "workspace:*",
+32
View File
@@ -3,6 +3,38 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [3.50.38](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-23)
**Note:** Version bump only for package @standardnotes/mobile
## [3.50.37](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-21)
**Note:** Version bump only for package @standardnotes/mobile
## [3.50.36](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/mobile
## [3.50.35](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/mobile
## [3.50.34](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/mobile
## [3.50.33](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/mobile
## [3.50.32](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/mobile
## [3.50.31](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-19)
**Note:** Version bump only for package @standardnotes/mobile
## [3.50.30](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-19)
**Note:** Version bump only for package @standardnotes/mobile
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/mobile",
"version": "3.50.30",
"version": "3.50.38",
"author": "Standard Notes.",
"private": true,
"license": "AGPL-3.0-or-later",
+35
View File
@@ -3,6 +3,41 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.42.10](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-23)
### Bug Fixes
* **models:** dependency level ([981bf6a](https://github.com/standardnotes/app/commit/981bf6ac928a8d6d84fb25bbf608f76a1dc6304b))
## [1.42.9](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-21)
**Note:** Version bump only for package @standardnotes/models
## [1.42.8](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
### Bug Fixes
* fixed issue with third party editors not loading ([#2174](https://github.com/standardnotes/app/issues/2174)) ([e7214ea](https://github.com/standardnotes/app/commit/e7214ea73ad5d3026d958c79022d2238a4d1cfdc))
## [1.42.7](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
### Bug Fixes
* **models:** dependency declaration ([beccfb1](https://github.com/standardnotes/app/commit/beccfb16b361ba70bd4f7c09d5840d73ed6e85da))
* **models:** dependency on utils declaration ([e9a1012](https://github.com/standardnotes/app/commit/e9a10123fed9e2883e3d2af38939b1608d7b2ffa))
## [1.42.6](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/models
## [1.42.5](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/models
## [1.42.4](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-19)
**Note:** Version bump only for package @standardnotes/models
## [1.42.3](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-19)
**Note:** Version bump only for package @standardnotes/models
+5 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/models",
"version": "1.42.3",
"version": "1.42.10",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
@@ -21,11 +21,13 @@
"lint": "eslint src --ext .ts",
"test": "jest"
},
"dependencies": {
"@standardnotes/common": "^1.46.4",
"@standardnotes/utils": "workspace:^"
},
"devDependencies": {
"@standardnotes/common": "^1.46.3",
"@standardnotes/features": "workspace:*",
"@standardnotes/responses": "workspace:*",
"@standardnotes/utils": "workspace:*",
"@types/jest": "^29.2.3",
"@types/lodash": "^4.14.189",
"@typescript-eslint/eslint-plugin": "*",
@@ -68,7 +68,7 @@ describe('component model', () => {
expect(component.noteType).toEqual(NoteType.Authentication)
})
it('should return plain as noteType if no note type defined in package_info', () => {
it('should return unknown as noteType if no note type defined in package_info', () => {
const component = new SNComponent(
new DecryptedPayload(
{
@@ -83,6 +83,6 @@ describe('component model', () => {
),
)
expect(component.noteType).toEqual(NoteType.Plain)
expect(component.noteType).toEqual(NoteType.Unknown)
})
})
@@ -180,7 +180,7 @@ export class SNComponent extends DecryptedItem<ComponentContent> implements Comp
}
public get noteType(): NoteType {
return this.package_info.note_type || NoteType.Plain
return this.package_info.note_type || NoteType.Unknown
}
public get isDeprecated(): boolean {
+32
View File
@@ -3,6 +3,38 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.4.125](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-23)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.124](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-21)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.123](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.122](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.121](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.120](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.119](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.118](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-19)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.117](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-19)
**Note:** Version bump only for package @standardnotes/releases
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/releases",
"version": "1.4.117",
"version": "1.4.125",
"license": "AGPL-3.0-or-later",
"main": "dist/releases.json",
"types": "dist/index.d.ts",
+20
View File
@@ -3,6 +3,26 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.13.6](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-21)
**Note:** Version bump only for package @standardnotes/responses
## [1.13.5](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/responses
## [1.13.4](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/responses
## [1.13.3](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/responses
## [1.13.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-19)
**Note:** Version bump only for package @standardnotes/responses
## [1.13.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-19)
**Note:** Version bump only for package @standardnotes/responses
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/responses",
"version": "1.13.1",
"version": "1.13.6",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
@@ -33,9 +33,9 @@
"typescript": "*"
},
"dependencies": {
"@standardnotes/common": "^1.46.3",
"@standardnotes/common": "^1.46.4",
"@standardnotes/features": "workspace:*",
"@standardnotes/security": "^1.7.0",
"@standardnotes/security": "^1.7.5",
"reflect-metadata": "^0.1.13"
}
}
@@ -4,5 +4,6 @@ import { MinimalHttpResponse } from '../Http/MinimalHttpResponses'
export type GetOfflineFeaturesResponse = MinimalHttpResponse & {
data?: {
features: FeatureDescription[]
roles: string[]
}
}
+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.
## [1.56.9](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-23)
**Note:** Version bump only for package @standardnotes/services
## [1.56.8](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-21)
**Note:** Version bump only for package @standardnotes/services
## [1.56.7](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/services
## [1.56.6](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/services
## [1.56.5](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/services
## [1.56.4](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
### Bug Fixes
* **snjs:** bring back history tests and fix handlinf of error with revisions ([cb9c160](https://github.com/standardnotes/app/commit/cb9c16047ebea7134c1aadaf89a8023497358a8e))
## [1.56.3](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/services
## [1.56.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-19)
**Note:** Version bump only for package @standardnotes/services
## [1.56.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-19)
**Note:** Version bump only for package @standardnotes/services
+3 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/services",
"version": "1.56.1",
"version": "1.56.9",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
@@ -17,14 +17,13 @@
},
"dependencies": {
"@standardnotes/api": "workspace:^",
"@standardnotes/auth": "^3.19.4",
"@standardnotes/common": "^1.46.3",
"@standardnotes/common": "^1.46.4",
"@standardnotes/domain-core": "^1.11.1",
"@standardnotes/encryption": "workspace:^",
"@standardnotes/files": "workspace:^",
"@standardnotes/models": "workspace:^",
"@standardnotes/responses": "workspace:*",
"@standardnotes/security": "^1.7.0",
"@standardnotes/security": "^1.7.5",
"@standardnotes/sncrypto-common": "workspace:^",
"@standardnotes/utils": "workspace:*",
"reflect-metadata": "^0.1.13"
@@ -1,7 +1,7 @@
import { Either } from '@standardnotes/common'
import { Role } from '@standardnotes/auth'
import { FilesApiInterface } from '@standardnotes/files'
import { Session } from '@standardnotes/domain-core'
import { Role } from '@standardnotes/security'
import { AbstractService } from '../Service/AbstractService'
@@ -1,4 +1,4 @@
import { FeatureDescription, FeatureIdentifier } from '@standardnotes/features'
import { FeatureIdentifier } from '@standardnotes/features'
import { SNComponent } from '@standardnotes/models'
import { FeatureStatus } from './FeatureStatus'
@@ -7,10 +7,10 @@ import { SetOfflineFeaturesFunctionResponse } from './SetOfflineFeaturesFunction
export interface FeaturesClientInterface {
downloadExternalFeature(urlOrCode: string): Promise<SNComponent | undefined>
getUserFeature(featureId: FeatureIdentifier): FeatureDescription | undefined
getFeatureStatus(featureId: FeatureIdentifier): FeatureStatus
hasFirstPartySubscription(): boolean
hasMinimumRole(role: string): boolean
setOfflineFeaturesCode(code: string): Promise<SetOfflineFeaturesFunctionResponse>
@@ -16,31 +16,23 @@ export class RevisionManager extends AbstractService implements RevisionClientIn
async listRevisions(
itemUuid: Uuid,
): Promise<{ uuid: string; content_type: string; created_at: string; updated_at: string; required_role: string }[]> {
try {
const result = await this.revisionApiService.listRevisions(itemUuid.value)
const result = await this.revisionApiService.listRevisions(itemUuid.value)
if (result.data.error) {
return []
}
return result.data.revisions
} catch (error) {
return []
if (result.data.error) {
throw new Error(result.data.error.message)
}
return result.data.revisions
}
async deleteRevision(itemUuid: Uuid, revisionUuid: Uuid): Promise<string> {
try {
const result = await this.revisionApiService.deleteRevision(itemUuid.value, revisionUuid.value)
const result = await this.revisionApiService.deleteRevision(itemUuid.value, revisionUuid.value)
if (result.data.error) {
return result.data.error.message
}
return result.data.message
} catch (error) {
return 'An error occurred while deleting the revision.'
if (result.data.error) {
throw new Error(result.data.error.message)
}
return result.data.message
}
async getRevision(
@@ -57,16 +49,12 @@ export class RevisionManager extends AbstractService implements RevisionClientIn
created_at: string
updated_at: string
} | null> {
try {
const result = await this.revisionApiService.getRevision(itemUuid.value, revisionUuid.value)
const result = await this.revisionApiService.getRevision(itemUuid.value, revisionUuid.value)
if (result.data.error) {
return null
}
return result.data.revision
} catch (error) {
return null
if (result.data.error) {
throw new Error(result.data.error.message)
}
return result.data.revision
}
}
@@ -34,6 +34,7 @@ export enum StorageKey {
StorageEncryptionPolicy = 'storage_policy',
WebSocketUrl = 'webSocket_url',
UserRoles = 'user_roles',
OfflineUserRoles = 'offline_user_roles',
UserFeatures = 'user_features',
ExperimentalFeatures = 'experimental_features',
DeinitMode = 'deinit_mode',
+38
View File
@@ -3,6 +3,44 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [2.164.9](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-23)
**Note:** Version bump only for package @standardnotes/snjs
## [2.164.8](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-21)
**Note:** Version bump only for package @standardnotes/snjs
## [2.164.7](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
### Bug Fixes
* fixed issue with third party editors not loading ([#2174](https://github.com/standardnotes/app/issues/2174)) ([e7214ea](https://github.com/standardnotes/app/commit/e7214ea73ad5d3026d958c79022d2238a4d1cfdc))
## [2.164.6](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/snjs
## [2.164.5](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/snjs
## [2.164.4](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
### Bug Fixes
* **snjs:** bring back history tests and fix handlinf of error with revisions ([cb9c160](https://github.com/standardnotes/app/commit/cb9c16047ebea7134c1aadaf89a8023497358a8e))
* **snjs:** remove isFailed() checks during tests in order for getValue() to give a meaningful exception ([6a7ff42](https://github.com/standardnotes/app/commit/6a7ff423ff82bd6eb7fbfbc95f4b1ebda36cc842))
* **snjs:** signed out fetching revisions test ([21a4eb0](https://github.com/standardnotes/app/commit/21a4eb0cf00add2c4cf2e69e55c55cb9fd50c239))
## [2.164.3](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/snjs
## [2.164.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-19)
**Note:** Version bump only for package @standardnotes/snjs
## [2.164.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-19)
**Note:** Version bump only for package @standardnotes/snjs
+2 -2
View File
@@ -1160,8 +1160,8 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli
return this.apiService.isThirdPartyHostUsed()
}
public getCloudProviderIntegrationUrl(cloudProviderName: Settings.CloudProvider, isDevEnvironment: boolean): string {
return this.settingsService.getCloudProviderIntegrationUrl(cloudProviderName, isDevEnvironment)
public getCloudProviderIntegrationUrl(cloudProviderName: Settings.CloudProvider): string {
return this.settingsService.getCloudProviderIntegrationUrl(cloudProviderName)
}
private constructServices() {
@@ -46,4 +46,18 @@ describe('DeleteRevision', () => {
expect(result.isFailed()).toBe(true)
expect(result.getError()).toEqual('Could not delete revision: Given value is not a valid uuid: invalid')
})
it('should fail if revision manager throws', async () => {
const useCase = createUseCase()
revisionManager.deleteRevision = jest.fn().mockRejectedValue(new Error('error'))
const result = await useCase.execute({
itemUuid: '00000000-0000-0000-0000-000000000000',
revisionUuid: '00000000-0000-0000-0000-000000000000',
})
expect(result.isFailed()).toBe(true)
expect(result.getError()).toEqual('Could not delete revision: error')
})
})
@@ -19,8 +19,12 @@ export class DeleteRevision implements UseCaseInterface<void> {
}
const revisionUuid = revisionUuidOrError.getValue()
await this.revisionManager.deleteRevision(itemUuid, revisionUuid)
try {
await this.revisionManager.deleteRevision(itemUuid, revisionUuid)
return Result.ok()
return Result.ok()
} catch (error) {
return Result.fail(`Could not delete revision: ${(error as Error).message}`)
}
}
}
@@ -155,4 +155,18 @@ describe('GetRevision', () => {
expect(result.isFailed()).toBe(true)
})
it('should fail if revision manager throws', async () => {
revisionManager.getRevision = jest.fn().mockRejectedValue(new Error('error'))
const useCase = createUseCase()
const result = await useCase.execute({
itemUuid: '00000000-0000-0000-0000-000000000000',
revisionUuid: '00000000-0000-0000-0000-000000000000',
})
expect(result.isFailed()).toBe(true)
expect(result.getError()).toEqual('Could not get revision: error')
})
})
@@ -29,8 +29,14 @@ export class GetRevision implements UseCaseInterface<HistoryEntry> {
}
const revisionUuid = revisionUuidOrError.getValue()
const revision = await this.revisionManager.getRevision(itemUuid, revisionUuid)
if (revision === null) {
let revision
try {
revision = await this.revisionManager.getRevision(itemUuid, revisionUuid)
} catch (error) {
return Result.fail(`Could not get revision: ${(error as Error).message}`)
}
if (!revision) {
return Result.fail('Could not get revision: Revision not found')
}
@@ -29,4 +29,15 @@ describe('ListRevisions', () => {
expect(result.isFailed()).toBe(true)
expect(result.getError()).toEqual('Could not list item revisions: Given value is not a valid uuid: invalid')
})
it('should fail if revision manager throws', async () => {
const useCase = createUseCase()
revisionManager.listRevisions = jest.fn().mockRejectedValue(new Error('error'))
const result = await useCase.execute({ itemUuid: '00000000-0000-0000-0000-000000000000' })
expect(result.isFailed()).toBe(true)
expect(result.getError()).toEqual('Could not list item revisions: error')
})
})
@@ -15,8 +15,12 @@ export class ListRevisions implements UseCaseInterface<Array<RevisionMetadata>>
}
const itemUuid = itemUuidOrError.getValue()
const revisions = await this.revisionManager.listRevisions(itemUuid)
try {
const revisions = await this.revisionManager.listRevisions(itemUuid)
return Result.ok(revisions)
return Result.ok(revisions)
} catch (error) {
return Result.fail(`Could not list item revisions: ${(error as Error).message}`)
}
}
}
+2 -11
View File
@@ -1,24 +1,15 @@
export const APPLICATION_DEFAULT_HOSTS = [
'api.standardnotes.com',
'api-dev.standardnotes.com',
'sync.standardnotes.org',
'syncing-server-demo.standardnotes.com',
]
export const APPLICATION_DEFAULT_HOSTS = ['api.standardnotes.com', 'sync.standardnotes.org']
export const FILES_DEFAULT_HOSTS = ['files.standardnotes.com', 'files-dev.standardnotes.com']
export const FILES_DEFAULT_HOSTS = ['files.standardnotes.com']
export const TRUSTED_FEATURE_HOSTS = [
'api-dev.standardnotes.com',
'api.standardnotes.com',
'extensions.standardnotes.com',
'extensions.standardnotes.org',
'extensions-server-dev.standardnotes.org',
'extensions-server-dev.standardnotes.com',
'features.standardnotes.com',
]
export enum ExtensionsServerURL {
Dev = 'https://extensions-server-dev.standardnotes.org',
Prod = 'https://extensions.standardnotes.org',
}
+4 -2
View File
@@ -654,7 +654,7 @@ export class SNApiService
public async downloadOfflineFeaturesFromRepo(
repo: SNFeatureRepo,
): Promise<{ features: FeatureDescription[] } | ClientDisplayableError> {
): Promise<{ features: FeatureDescription[]; roles: string[] } | ClientDisplayableError> {
try {
const featuresUrl = repo.offlineFeaturesUrl
const extensionKey = repo.offlineKey
@@ -678,8 +678,10 @@ export class SNApiService
if (response.error) {
return ClientDisplayableError.FromError(response.error)
}
const data = (response as Responses.GetOfflineFeaturesResponse).data
return {
features: (response as Responses.GetOfflineFeaturesResponse).data?.features || [],
features: data?.features || [],
roles: data?.roles || [],
}
} catch {
return new ClientDisplayableError(API_MESSAGE_FAILED_OFFLINE_ACTIVATION)
@@ -80,7 +80,7 @@ export class SNWebSocketsService extends AbstractService<WebSocketsServiceEvent,
return response.data.token
} catch (error) {
console.error((error as Error).message)
console.error('Caught error:', (error as Error).message)
return undefined
}
@@ -147,7 +147,7 @@ describe('featuresService', () => {
const manager = createManager(Environment.Desktop, Platform.MacDesktop)
expect(
manager.areRequestedPermissionsValid(nativeComponent(FeatureIdentifier.MarkdownVisualEditor), permissions),
manager.areRequestedPermissionsValid(nativeComponent(FeatureIdentifier.MarkdownProEditor), permissions),
).toEqual(true)
})
@@ -170,7 +170,7 @@ describe('featuresService', () => {
featuresService.getExperimentalFeatures = jest.fn().mockReturnValue([FeatureIdentifier.PlusEditor])
featuresService.initializeFromDisk()
await featuresService.updateRolesAndFetchFeatures('123', newRoles)
await featuresService.updateOnlineRolesAndFetchFeatures('123', newRoles)
expect(itemManager.createItem).not.toHaveBeenCalled()
})
@@ -191,7 +191,7 @@ describe('featuresService', () => {
featuresService.getEnabledExperimentalFeatures = jest.fn().mockReturnValue([FeatureIdentifier.PlusEditor])
featuresService.initializeFromDisk()
await featuresService.updateRolesAndFetchFeatures('123', newRoles)
await featuresService.updateOnlineRolesAndFetchFeatures('123', newRoles)
expect(itemManager.createItem).toHaveBeenCalled()
})
})
@@ -213,7 +213,7 @@ describe('featuresService', () => {
const mock = (featuresService['notifyEvent'] = jest.fn())
const newRoles = [...roles, RoleName.NAMES.PlusUser]
await featuresService.setRoles(newRoles)
await featuresService.setOnlineRoles(newRoles)
expect(mock.mock.calls[0][0]).toEqual(FeaturesEvent.UserRolesChanged)
})
@@ -226,7 +226,7 @@ describe('featuresService', () => {
const spy = jest.spyOn(featuresService, 'notifyEvent' as never)
const newRoles = [...roles, RoleName.NAMES.ProUser]
await featuresService.updateRolesAndFetchFeatures('123', newRoles)
await featuresService.updateOnlineRolesAndFetchFeatures('123', newRoles)
expect(spy.mock.calls[2][0]).toEqual(FeaturesEvent.DidPurchaseSubscription)
})
@@ -235,12 +235,12 @@ describe('featuresService', () => {
storageService.getValue = jest.fn().mockReturnValue(roles)
const featuresService = createService()
featuresService.initializeFromDisk()
featuresService['roles'] = []
featuresService['onlineRoles'] = []
const spy = jest.spyOn(featuresService, 'notifyEvent' as never)
const newRoles = [...roles, RoleName.NAMES.ProUser]
await featuresService.updateRolesAndFetchFeatures('123', newRoles)
await featuresService.updateOnlineRolesAndFetchFeatures('123', newRoles)
const triggeredEvents = spy.mock.calls.map((call) => call[0])
expect(triggeredEvents).not.toContain(FeaturesEvent.DidPurchaseSubscription)
@@ -252,7 +252,7 @@ describe('featuresService', () => {
storageService.getValue = jest.fn().mockReturnValue(roles)
const featuresService = createService()
featuresService.initializeFromDisk()
await featuresService.updateRolesAndFetchFeatures('123', newRoles)
await featuresService.updateOnlineRolesAndFetchFeatures('123', newRoles)
expect(storageService.setValue).toHaveBeenCalledWith(StorageKey.UserRoles, newRoles)
expect(apiService.getUserFeatures).toHaveBeenCalledWith('123')
})
@@ -263,7 +263,7 @@ describe('featuresService', () => {
storageService.getValue = jest.fn().mockReturnValue(roles)
const featuresService = createService()
featuresService.initializeFromDisk()
await featuresService.updateRolesAndFetchFeatures('123', newRoles)
await featuresService.updateOnlineRolesAndFetchFeatures('123', newRoles)
expect(storageService.setValue).toHaveBeenCalledWith(StorageKey.UserRoles, newRoles)
expect(apiService.getUserFeatures).toHaveBeenCalledWith('123')
})
@@ -274,7 +274,7 @@ describe('featuresService', () => {
storageService.getValue = jest.fn().mockReturnValue(roles)
const featuresService = createService()
featuresService.initializeFromDisk()
await featuresService.updateRolesAndFetchFeatures('123', newRoles)
await featuresService.updateOnlineRolesAndFetchFeatures('123', newRoles)
expect(storageService.setValue).toHaveBeenCalledWith(StorageKey.UserFeatures, features)
})
@@ -284,7 +284,7 @@ describe('featuresService', () => {
storageService.getValue = jest.fn().mockReturnValue(roles)
const featuresService = createService()
featuresService.initializeFromDisk()
await featuresService.updateRolesAndFetchFeatures('123', newRoles)
await featuresService.updateOnlineRolesAndFetchFeatures('123', newRoles)
expect(itemManager.createItem).toHaveBeenCalledTimes(2)
expect(itemManager.createItem).toHaveBeenCalledWith(
ContentType.Theme,
@@ -328,7 +328,7 @@ describe('featuresService', () => {
itemManager.getItems = jest.fn().mockReturnValue([existingItem])
const featuresService = createService()
featuresService.initializeFromDisk()
await featuresService.updateRolesAndFetchFeatures('123', newRoles)
await featuresService.updateOnlineRolesAndFetchFeatures('123', newRoles)
expect(itemManager.changeComponent).toHaveBeenCalledWith(existingItem, expect.any(Function))
})
@@ -354,7 +354,7 @@ describe('featuresService', () => {
const featuresService = createService()
featuresService.initializeFromDisk()
await featuresService.updateRolesAndFetchFeatures('123', newRoles)
await featuresService.updateOnlineRolesAndFetchFeatures('123', newRoles)
expect(itemManager.createItem).toHaveBeenCalledWith(
ContentType.Component,
expect.objectContaining({
@@ -401,7 +401,7 @@ describe('featuresService', () => {
const featuresService = createService()
featuresService.initializeFromDisk()
await featuresService.updateRolesAndFetchFeatures('123', newRoles)
await featuresService.updateOnlineRolesAndFetchFeatures('123', newRoles)
expect(itemManager.setItemsToBeDeleted).toHaveBeenCalledWith([existingItem])
})
@@ -424,7 +424,7 @@ describe('featuresService', () => {
storageService.getValue = jest.fn().mockReturnValue(roles)
const featuresService = createService()
featuresService.initializeFromDisk()
await featuresService.updateRolesAndFetchFeatures('123', newRoles)
await featuresService.updateOnlineRolesAndFetchFeatures('123', newRoles)
expect(itemManager.createItem).not.toHaveBeenCalled()
})
@@ -447,7 +447,7 @@ describe('featuresService', () => {
storageService.getValue = jest.fn().mockReturnValue(roles)
const featuresService = createService()
featuresService.initializeFromDisk()
await featuresService.updateRolesAndFetchFeatures('123', newRoles)
await featuresService.updateOnlineRolesAndFetchFeatures('123', newRoles)
expect(itemManager.createItem).not.toHaveBeenCalled()
})
@@ -455,10 +455,10 @@ describe('featuresService', () => {
storageService.getValue = jest.fn().mockReturnValue(roles)
const featuresService = createService()
featuresService.initializeFromDisk()
await featuresService.updateRolesAndFetchFeatures('123', roles)
await featuresService.updateRolesAndFetchFeatures('123', roles)
await featuresService.updateRolesAndFetchFeatures('123', roles)
await featuresService.updateRolesAndFetchFeatures('123', roles)
await featuresService.updateOnlineRolesAndFetchFeatures('123', roles)
await featuresService.updateOnlineRolesAndFetchFeatures('123', roles)
await featuresService.updateOnlineRolesAndFetchFeatures('123', roles)
await featuresService.updateOnlineRolesAndFetchFeatures('123', roles)
expect(storageService.setValue).toHaveBeenCalledTimes(2)
})
@@ -482,7 +482,7 @@ describe('featuresService', () => {
const nativeFeature = featuresService['mapRemoteNativeFeatureToStaticFeature'](remoteFeature)
featuresService['mapRemoteNativeFeatureToItem'] = jest.fn()
featuresService.initializeFromDisk()
await featuresService.updateRolesAndFetchFeatures('123', newRoles)
await featuresService.updateOnlineRolesAndFetchFeatures('123', newRoles)
expect(featuresService['mapRemoteNativeFeatureToItem']).toHaveBeenCalledWith(
nativeFeature,
expect.anything(),
@@ -509,7 +509,26 @@ describe('featuresService', () => {
await expect(() => featuresService['mapRemoteNativeFeatureToItem'](clientFeature, [], [])).rejects.toThrow()
})
it('feature status', async () => {
it('role-based feature status', async () => {
const featuresService = createService()
features = [] as jest.Mocked<FeatureDescription[]>
apiService.getUserFeatures = jest.fn().mockReturnValue({
data: {
features,
},
})
sessionManager.isSignedIntoFirstPartyServer = jest.fn().mockReturnValue(true)
await featuresService.updateOnlineRolesAndFetchFeatures('123', [RoleName.NAMES.CoreUser, RoleName.NAMES.PlusUser])
expect(featuresService.getFeatureStatus(FeatureIdentifier.MidnightTheme)).toBe(FeatureStatus.Entitled)
expect(featuresService.getFeatureStatus(FeatureIdentifier.SuperEditor)).toBe(FeatureStatus.Entitled)
})
it('feature status with no paid role but features listings', async () => {
const featuresService = createService()
features = [
@@ -535,54 +554,21 @@ describe('featuresService', () => {
sessionManager.isSignedIntoFirstPartyServer = jest.fn().mockReturnValue(true)
await featuresService.updateRolesAndFetchFeatures('123', [RoleName.NAMES.CoreUser, RoleName.NAMES.PlusUser])
expect(featuresService.getFeatureStatus(FeatureIdentifier.MidnightTheme)).toBe(FeatureStatus.Entitled)
expect(featuresService.getFeatureStatus(FeatureIdentifier.PlusEditor)).toBe(FeatureStatus.NotInCurrentPlan)
expect(featuresService.getFeatureStatus(FeatureIdentifier.SheetsEditor)).toBe(FeatureStatus.NotInCurrentPlan)
await featuresService.updateRolesAndFetchFeatures('123', [RoleName.NAMES.CoreUser])
await featuresService.updateOnlineRolesAndFetchFeatures('123', [RoleName.NAMES.CoreUser])
expect(featuresService.getFeatureStatus(FeatureIdentifier.MidnightTheme)).toBe(FeatureStatus.NoUserSubscription)
expect(featuresService.getFeatureStatus(FeatureIdentifier.PlusEditor)).toBe(FeatureStatus.NoUserSubscription)
expect(featuresService.getFeatureStatus(FeatureIdentifier.SheetsEditor)).toBe(FeatureStatus.NoUserSubscription)
features = [
{
identifier: FeatureIdentifier.MidnightTheme,
content_type: ContentType.Theme,
expires_at: expiredDate,
role_name: RoleName.NAMES.PlusUser,
},
{
identifier: FeatureIdentifier.PlusEditor,
content_type: ContentType.Component,
expires_at: expiredDate,
role_name: RoleName.NAMES.ProUser,
},
] as jest.Mocked<FeatureDescription[]>
apiService.getUserFeatures = jest.fn().mockReturnValue({
data: {
features,
},
})
await featuresService.updateRolesAndFetchFeatures('123', [RoleName.NAMES.PlusUser])
expect(featuresService.getFeatureStatus(FeatureIdentifier.MidnightTheme)).toBe(
FeatureStatus.InCurrentPlanButExpired,
)
expect(featuresService.getFeatureStatus(FeatureIdentifier.PlusEditor)).toBe(FeatureStatus.NotInCurrentPlan)
expect(featuresService.getFeatureStatus(FeatureIdentifier.SheetsEditor)).toBe(FeatureStatus.NotInCurrentPlan)
})
it('availableInRoles-based features', async () => {
it('role-based features while not signed into first party server', async () => {
const featuresService = createService()
await featuresService.updateRolesAndFetchFeatures('123', [RoleName.NAMES.ProUser])
sessionManager.isSignedIntoFirstPartyServer = jest.fn().mockReturnValue(false)
expect(featuresService.getFeatureStatus(FeatureIdentifier.SuperEditor)).toBe(FeatureStatus.Entitled)
await featuresService.updateOnlineRolesAndFetchFeatures('123', [RoleName.NAMES.ProUser])
expect(featuresService.getFeatureStatus(FeatureIdentifier.SuperEditor)).toBe(FeatureStatus.NotInCurrentPlan)
})
it('third party feature status', async () => {
@@ -629,7 +615,7 @@ describe('featuresService', () => {
} as never),
])
await featuresService.updateRolesAndFetchFeatures('123', [RoleName.NAMES.CoreUser])
await featuresService.updateOnlineRolesAndFetchFeatures('123', [RoleName.NAMES.CoreUser])
expect(featuresService.getFeatureStatus(themeFeature.identifier)).toBe(FeatureStatus.Entitled)
expect(featuresService.getFeatureStatus(editorFeature.identifier)).toBe(FeatureStatus.InCurrentPlanButExpired)
@@ -641,7 +627,7 @@ describe('featuresService', () => {
it('feature status should be not entitled if no account or offline repo', async () => {
const featuresService = createService()
await featuresService.updateRolesAndFetchFeatures('123', [RoleName.NAMES.CoreUser])
await featuresService.updateOnlineRolesAndFetchFeatures('123', [RoleName.NAMES.CoreUser])
sessionManager.isSignedIntoFirstPartyServer = jest.fn().mockReturnValue(false)
@@ -653,30 +639,6 @@ describe('featuresService', () => {
)
})
it('feature status should be entitled for subscriber until first successful features request made if no cached features', async () => {
const featuresService = createService()
apiService.getUserFeatures = jest.fn().mockReturnValue({
data: {
features: [],
},
})
await featuresService.updateRolesAndFetchFeatures('123', [RoleName.NAMES.CoreUser, RoleName.NAMES.PlusUser])
sessionManager.isSignedIntoFirstPartyServer = jest.fn().mockReturnValue(true)
featuresService['completedSuccessfulFeaturesRetrieval'] = false
expect(featuresService.getFeatureStatus(FeatureIdentifier.MidnightTheme)).toBe(FeatureStatus.Entitled)
expect(featuresService.getFeatureStatus(FeatureIdentifier.TokenVaultEditor)).toBe(FeatureStatus.Entitled)
await featuresService.didDownloadFeatures(features)
expect(featuresService.getFeatureStatus(FeatureIdentifier.MidnightTheme)).toBe(FeatureStatus.Entitled)
expect(featuresService.getFeatureStatus(FeatureIdentifier.TokenVaultEditor)).toBe(FeatureStatus.NotInCurrentPlan)
})
it('didDownloadFeatures should filter out client controlled features', async () => {
const featuresService = createService()
@@ -687,31 +649,13 @@ describe('featuresService', () => {
expect(featuresService['mapRemoteNativeFeaturesToItems']).toHaveBeenCalledWith([])
})
it('feature status should be dynamic for subscriber if cached features and no successful features request made yet', async () => {
const featuresService = createService()
await featuresService.updateRolesAndFetchFeatures('123', [RoleName.NAMES.CoreUser, RoleName.NAMES.PlusUser])
featuresService['completedSuccessfulFeaturesRetrieval'] = false
sessionManager.isSignedIntoFirstPartyServer = jest.fn().mockReturnValue(true)
expect(featuresService.getFeatureStatus(FeatureIdentifier.MidnightTheme)).toBe(FeatureStatus.Entitled)
expect(featuresService.getFeatureStatus(FeatureIdentifier.TokenVaultEditor)).toBe(FeatureStatus.NotInCurrentPlan)
featuresService['completedSuccessfulFeaturesRetrieval'] = false
expect(featuresService.getFeatureStatus(FeatureIdentifier.MidnightTheme)).toBe(FeatureStatus.Entitled)
expect(featuresService.getFeatureStatus(FeatureIdentifier.TokenVaultEditor)).toBe(FeatureStatus.NotInCurrentPlan)
})
it('feature status for offline subscription', async () => {
const featuresService = createService()
await featuresService.updateRolesAndFetchFeatures('123', [RoleName.NAMES.CoreUser, RoleName.NAMES.PlusUser])
await featuresService.updateOnlineRolesAndFetchFeatures('123', [RoleName.NAMES.CoreUser, RoleName.NAMES.PlusUser])
sessionManager.isSignedIntoFirstPartyServer = jest.fn().mockReturnValue(false)
featuresService.rolesIncludePaidSubscription = jest.fn().mockReturnValue(false)
featuresService.onlineRolesIncludePaidSubscription = jest.fn().mockReturnValue(false)
featuresService['completedSuccessfulFeaturesRetrieval'] = true
expect(featuresService.getFeatureStatus(FeatureIdentifier.MidnightTheme)).toBe(FeatureStatus.NoUserSubscription)
@@ -720,9 +664,11 @@ describe('featuresService', () => {
)
featuresService.hasOfflineRepo = jest.fn().mockReturnValue(true)
featuresService.hasFirstPartySubscription = jest.fn().mockReturnValue(true)
await featuresService.setOfflineRoles([RoleName.NAMES.CoreUser, RoleName.NAMES.PlusUser])
expect(featuresService.getFeatureStatus(FeatureIdentifier.MidnightTheme)).toBe(FeatureStatus.Entitled)
expect(featuresService.getFeatureStatus(FeatureIdentifier.TokenVaultEditor)).toBe(FeatureStatus.NotInCurrentPlan)
expect(featuresService.getFeatureStatus(FeatureIdentifier.TokenVaultEditor)).toBe(FeatureStatus.Entitled)
})
it('feature status for deprecated feature', async () => {
@@ -734,7 +680,7 @@ describe('featuresService', () => {
FeatureStatus.NoUserSubscription,
)
await featuresService.updateRolesAndFetchFeatures('123', [RoleName.NAMES.CoreUser, RoleName.NAMES.PlusUser])
await featuresService.updateOnlineRolesAndFetchFeatures('123', [RoleName.NAMES.CoreUser, RoleName.NAMES.PlusUser])
expect(featuresService.getFeatureStatus(FeatureIdentifier.DeprecatedFileSafe as FeatureIdentifier)).toBe(
FeatureStatus.Entitled,
@@ -744,25 +690,25 @@ describe('featuresService', () => {
it('has paid subscription', async () => {
const featuresService = createService()
await featuresService.updateRolesAndFetchFeatures('123', [RoleName.NAMES.CoreUser])
await featuresService.updateOnlineRolesAndFetchFeatures('123', [RoleName.NAMES.CoreUser])
sessionManager.isSignedIntoFirstPartyServer = jest.fn().mockReturnValue(true)
expect(featuresService.hasPaidOnlineOrOfflineSubscription()).toBeFalsy
expect(featuresService.hasPaidAnyPartyOnlineOrOfflineSubscription()).toBeFalsy
await featuresService.updateRolesAndFetchFeatures('123', [RoleName.NAMES.CoreUser, RoleName.NAMES.PlusUser])
await featuresService.updateOnlineRolesAndFetchFeatures('123', [RoleName.NAMES.CoreUser, RoleName.NAMES.PlusUser])
expect(featuresService.hasPaidOnlineOrOfflineSubscription()).toEqual(true)
expect(featuresService.hasPaidAnyPartyOnlineOrOfflineSubscription()).toEqual(true)
})
it('has paid subscription should be true if offline repo and signed into third party server', async () => {
const featuresService = createService()
await featuresService.updateRolesAndFetchFeatures('123', [RoleName.NAMES.CoreUser])
await featuresService.updateOnlineRolesAndFetchFeatures('123', [RoleName.NAMES.CoreUser])
featuresService.hasOfflineRepo = jest.fn().mockReturnValue(true)
sessionManager.isSignedIntoFirstPartyServer = jest.fn().mockReturnValue(false)
expect(featuresService.hasPaidOnlineOrOfflineSubscription()).toEqual(true)
expect(featuresService.hasPaidAnyPartyOnlineOrOfflineSubscription()).toEqual(true)
})
})
@@ -829,7 +775,11 @@ describe('featuresService', () => {
it('should sort given roles according to role hierarchy', () => {
const featuresService = createService()
const sortedRoles = featuresService.rolesBySorting([RoleName.NAMES.ProUser, RoleName.NAMES.CoreUser, RoleName.NAMES.PlusUser])
const sortedRoles = featuresService.rolesBySorting([
RoleName.NAMES.ProUser,
RoleName.NAMES.CoreUser,
RoleName.NAMES.PlusUser,
])
expect(sortedRoles).toStrictEqual([RoleName.NAMES.CoreUser, RoleName.NAMES.PlusUser, RoleName.NAMES.ProUser])
})
@@ -839,7 +789,7 @@ describe('featuresService', () => {
it('should be false if core user checks for plus role', async () => {
const featuresService = createService()
await featuresService.updateRolesAndFetchFeatures('123', [RoleName.NAMES.CoreUser])
await featuresService.updateOnlineRolesAndFetchFeatures('123', [RoleName.NAMES.CoreUser])
const hasPlusUserRole = featuresService.hasMinimumRole(RoleName.NAMES.PlusUser)
@@ -849,7 +799,9 @@ describe('featuresService', () => {
it('should be false if plus user checks for pro role', async () => {
const featuresService = createService()
await featuresService.updateRolesAndFetchFeatures('123', [RoleName.NAMES.PlusUser, RoleName.NAMES.CoreUser])
sessionManager.isSignedIntoFirstPartyServer = jest.fn().mockReturnValue(true)
await featuresService.updateOnlineRolesAndFetchFeatures('123', [RoleName.NAMES.PlusUser, RoleName.NAMES.CoreUser])
const hasProUserRole = featuresService.hasMinimumRole(RoleName.NAMES.ProUser)
@@ -859,7 +811,9 @@ describe('featuresService', () => {
it('should be true if pro user checks for core user', async () => {
const featuresService = createService()
await featuresService.updateRolesAndFetchFeatures('123', [RoleName.NAMES.ProUser, RoleName.NAMES.PlusUser])
sessionManager.isSignedIntoFirstPartyServer = jest.fn().mockReturnValue(true)
await featuresService.updateOnlineRolesAndFetchFeatures('123', [RoleName.NAMES.ProUser, RoleName.NAMES.PlusUser])
const hasCoreUserRole = featuresService.hasMinimumRole(RoleName.NAMES.CoreUser)
@@ -869,7 +823,9 @@ describe('featuresService', () => {
it('should be true if pro user checks for pro user', async () => {
const featuresService = createService()
await featuresService.updateRolesAndFetchFeatures('123', [RoleName.NAMES.ProUser, RoleName.NAMES.PlusUser])
sessionManager.isSignedIntoFirstPartyServer = jest.fn().mockReturnValue(true)
await featuresService.updateOnlineRolesAndFetchFeatures('123', [RoleName.NAMES.ProUser, RoleName.NAMES.PlusUser])
const hasProUserRole = featuresService.hasMinimumRole(RoleName.NAMES.ProUser)
@@ -58,7 +58,8 @@ export class SNFeaturesService
implements FeaturesClientInterface, InternalEventHandlerInterface
{
private deinited = false
private roles: string[] = []
private onlineRoles: string[] = []
private offlineRoles: string[] = []
private features: FeaturesImports.FeatureDescription[] = []
private enabledExperimentalFeatures: FeaturesImports.FeatureIdentifier[] = []
private removeWebSocketsServiceObserver: () => void
@@ -87,7 +88,7 @@ export class SNFeaturesService
const {
payload: { userUuid, currentRoles },
} = data as UserRolesChangedEvent
await this.updateRolesAndFetchFeatures(userUuid, currentRoles)
await this.updateOnlineRolesAndFetchFeatures(userUuid, currentRoles)
}
})
@@ -124,6 +125,16 @@ export class SNFeaturesService
})
}
public initializeFromDisk(): void {
this.onlineRoles = this.storageService.getValue<string[]>(StorageKey.UserRoles, undefined, [])
this.offlineRoles = this.storageService.getValue<string[]>(StorageKey.OfflineUserRoles, undefined, [])
this.features = this.storageService.getValue(StorageKey.UserFeatures, undefined, [])
this.enabledExperimentalFeatures = this.storageService.getValue(StorageKey.ExperimentalFeatures, undefined, [])
}
async handleEvent(event: InternalEventInterface): Promise<void> {
if (event.type === ApiServiceEvent.MetaReceived) {
if (!this.syncService) {
@@ -142,7 +153,7 @@ export class SNFeaturesService
}
const { userUuid, userRoles } = event.payload as MetaReceivedData
await this.updateRolesAndFetchFeatures(
await this.updateOnlineRolesAndFetchFeatures(
userUuid,
userRoles.map((role) => role.name),
)
@@ -155,7 +166,7 @@ export class SNFeaturesService
if (stage === ApplicationStage.FullSyncCompleted_13) {
void this.mapClientControlledFeaturesToItems()
if (!this.rolesIncludePaidSubscription()) {
if (!this.hasFirstPartyOnlineSubscription()) {
const offlineRepo = this.getOfflineRepo()
if (offlineRepo) {
void this.downloadOfflineFeatures(offlineRepo)
@@ -194,7 +205,7 @@ export class SNFeaturesService
}
public enableExperimentalFeature(identifier: FeaturesImports.FeatureIdentifier): void {
const feature = this.getUserFeature(identifier)
const feature = this.getFeatureThatOriginallyCameFromServer(identifier)
this.enabledExperimentalFeatures.push(identifier)
@@ -309,10 +320,14 @@ export class SNFeaturesService
repo: Models.SNFeatureRepo,
): Promise<SetOfflineFeaturesFunctionResponse | ClientDisplayableError> {
const result = await this.apiService.downloadOfflineFeaturesFromRepo(repo)
if (result instanceof ClientDisplayableError) {
return result
}
await this.didDownloadFeatures(result.features)
await this.setOfflineRoles(result.roles)
return undefined
}
@@ -363,18 +378,29 @@ export class SNFeaturesService
}
}
public initializeFromDisk(): void {
this.roles = this.storageService.getValue<string[]>(StorageKey.UserRoles, undefined, [])
this.features = this.storageService.getValue(StorageKey.UserFeatures, undefined, [])
this.enabledExperimentalFeatures = this.storageService.getValue(StorageKey.ExperimentalFeatures, undefined, [])
hasFirstPartyOnlineSubscription(): boolean {
return this.sessionManager.isSignedIntoFirstPartyServer() && this.onlineRolesIncludePaidSubscription()
}
public async updateRolesAndFetchFeatures(userUuid: UuidString, roles: string[]): Promise<void> {
const previousRoles = this.roles
hasFirstPartySubscription(): boolean {
if (this.hasFirstPartyOnlineSubscription()) {
return true
}
const userRolesChanged = this.haveRolesChanged(roles)
const offlineRepo = this.getOfflineRepo()
if (!offlineRepo) {
return false
}
const hasFirstPartyOfflineSubscription = offlineRepo.content.offlineFeaturesUrl === PROD_OFFLINE_FEATURES_URL
return hasFirstPartyOfflineSubscription
}
async updateOnlineRolesAndFetchFeatures(userUuid: UuidString, roles: string[]): Promise<void> {
const previousRoles = this.onlineRoles
const userRolesChanged =
roles.some((role) => !this.onlineRoles.includes(role)) || this.onlineRoles.some((role) => !roles.includes(role))
const isInitialLoadRolesChange = previousRoles.length === 0 && userRolesChanged
@@ -384,7 +410,7 @@ export class SNFeaturesService
this.needsInitialFeaturesUpdate = false
await this.setRoles(roles)
await this.setOnlineRoles(roles)
const shouldDownloadRoleBasedFeatures = !this.hasOfflineRepo()
@@ -398,22 +424,34 @@ export class SNFeaturesService
}
if (userRolesChanged && !isInitialLoadRolesChange) {
if (this.rolesIncludePaidSubscription()) {
if (this.onlineRolesIncludePaidSubscription()) {
await this.notifyEvent(FeaturesEvent.DidPurchaseSubscription)
}
}
}
async setRoles(roles: string[]): Promise<void> {
const rolesChanged = !arraysEqual(this.roles, roles)
async setOnlineRoles(roles: string[]): Promise<void> {
const rolesChanged = !arraysEqual(this.onlineRoles, roles)
this.roles = roles
this.onlineRoles = roles
if (rolesChanged) {
void this.notifyEvent(FeaturesEvent.UserRolesChanged)
}
this.storageService.setValue(StorageKey.UserRoles, this.roles)
this.storageService.setValue(StorageKey.UserRoles, this.onlineRoles)
}
async setOfflineRoles(roles: string[]): Promise<void> {
const rolesChanged = !arraysEqual(this.offlineRoles, roles)
this.offlineRoles = roles
if (rolesChanged) {
void this.notifyEvent(FeaturesEvent.UserRolesChanged)
}
this.storageService.setValue(StorageKey.OfflineUserRoles, this.offlineRoles)
}
public async didDownloadFeatures(features: FeaturesImports.FeatureDescription[]): Promise<void> {
@@ -465,17 +503,19 @@ export class SNFeaturesService
return nativeFeatureCopy
}
public getUserFeature(featureId: FeaturesImports.FeatureIdentifier): FeaturesImports.FeatureDescription | undefined {
public getFeatureThatOriginallyCameFromServer(
featureId: FeaturesImports.FeatureIdentifier,
): FeaturesImports.FeatureDescription | undefined {
return this.features.find((feature) => feature.identifier === featureId)
}
rolesIncludePaidSubscription(): boolean {
onlineRolesIncludePaidSubscription(): boolean {
const unpaidRoles = [RoleName.NAMES.CoreUser]
return this.roles.some((role) => !unpaidRoles.includes(role))
return this.onlineRoles.some((role) => !unpaidRoles.includes(role))
}
public hasPaidOnlineOrOfflineSubscription(): boolean {
return this.rolesIncludePaidSubscription() || this.hasOfflineRepo()
hasPaidAnyPartyOnlineOrOfflineSubscription(): boolean {
return this.onlineRolesIncludePaidSubscription() || this.hasOfflineRepo()
}
public rolesBySorting(roles: string[]): string[] {
@@ -485,7 +525,7 @@ export class SNFeaturesService
public hasMinimumRole(role: string): boolean {
const sortedAllRoles = Object.values(RoleName.NAMES)
const sortedUserRoles = this.rolesBySorting(this.roles)
const sortedUserRoles = this.rolesBySorting(this.rolesToUseForFeatureCheck())
const highestUserRoleIndex = sortedAllRoles.indexOf(lastElement(sortedUserRoles) as string)
@@ -508,16 +548,10 @@ export class SNFeaturesService
}
const nativeFeature = FeaturesImports.FindNativeFeature(featureId)
if (nativeFeature && nativeFeature.availableInRoles) {
const hasRole = this.roles.some((role) => nativeFeature.availableInRoles?.includes(role))
if (hasRole) {
return FeatureStatus.Entitled
}
}
const isDeprecated = this.isFeatureDeprecated(featureId)
if (isDeprecated) {
if (this.hasPaidOnlineOrOfflineSubscription()) {
if (this.hasPaidAnyPartyOnlineOrOfflineSubscription()) {
return FeatureStatus.Entitled
} else {
return FeatureStatus.NoUserSubscription
@@ -538,7 +572,7 @@ export class SNFeaturesService
return FeatureStatus.Entitled
}
if (this.hasPaidOnlineOrOfflineSubscription()) {
if (this.hasPaidAnyPartyOnlineOrOfflineSubscription()) {
if (!this.completedSuccessfulFeaturesRetrieval) {
const hasCachedFeatures = this.features.length > 0
const temporarilyAllowUntilServerUpdates = !hasCachedFeatures
@@ -550,25 +584,27 @@ export class SNFeaturesService
return FeatureStatus.NoUserSubscription
}
const feature = this.getUserFeature(featureId)
if (!feature) {
return FeatureStatus.NotInCurrentPlan
}
const expired = feature.expires_at && new Date(feature.expires_at).getTime() < new Date().getTime()
if (expired) {
if (!this.roles.includes(feature.role_name as string)) {
if (nativeFeature) {
if (!this.hasFirstPartySubscription()) {
return FeatureStatus.NotInCurrentPlan
} else {
return FeatureStatus.InCurrentPlanButExpired
}
const roles = this.rolesToUseForFeatureCheck()
if (nativeFeature.availableInRoles) {
const hasRole = roles.some((role) => {
return nativeFeature.availableInRoles?.includes(role)
})
if (!hasRole) {
return FeatureStatus.NotInCurrentPlan
}
}
}
return FeatureStatus.Entitled
}
private haveRolesChanged(roles: string[]): boolean {
return roles.some((role) => !this.roles.includes(role)) || this.roles.some((role) => !roles.includes(role))
private rolesToUseForFeatureCheck(): string[] {
return this.hasFirstPartyOnlineSubscription() ? this.onlineRoles : this.offlineRoles
}
private componentContentForNativeFeatureDescription(feature: FeaturesImports.FeatureDescription): Models.ItemContent {
@@ -776,7 +812,8 @@ export class SNFeaturesService
;(this.removeWebSocketsServiceObserver as unknown) = undefined
this.removefeatureReposObserver()
;(this.removefeatureReposObserver as unknown) = undefined
;(this.roles as unknown) = undefined
;(this.onlineRoles as unknown) = undefined
;(this.offlineRoles as unknown) = undefined
;(this.storageService as unknown) = undefined
;(this.apiService as unknown) = undefined
;(this.itemManager as unknown) = undefined
@@ -793,7 +830,7 @@ export class SNFeaturesService
override getDiagnostics(): Promise<DiagnosticInfo | undefined> {
return Promise.resolve({
features: {
roles: this.roles,
roles: this.onlineRoles,
features: this.features,
enabledExperimentalFeatures: this.enabledExperimentalFeatures,
needsInitialFeaturesUpdate: this.needsInitialFeaturesUpdate,
@@ -66,10 +66,9 @@ export class SNSettingsService extends AbstractService implements SettingsClient
return this.frequencyOptionsLabels[frequency]
}
getCloudProviderIntegrationUrl(cloudProviderName: CloudProvider, isDevEnvironment: boolean): string {
const { Dev, Prod } = ExtensionsServerURL
const extServerUrl = isDevEnvironment ? Dev : Prod
return `${extServerUrl}/${this.cloudProviderIntegrationUrlEndpoints[cloudProviderName]}?redirect_url=${extServerUrl}/components/cloudlink?`
getCloudProviderIntegrationUrl(cloudProviderName: CloudProvider): string {
const { Prod } = ExtensionsServerURL
return `${Prod}/${this.cloudProviderIntegrationUrlEndpoints[cloudProviderName]}?redirect_url=${Prod}/components/cloudlink?`
}
override deinit(): void {
+5 -5
View File
@@ -60,8 +60,8 @@ describe('features', () => {
describe('new user roles received on api response meta', () => {
it('should save roles and features', async () => {
expect(application.featuresService.roles).to.have.lengthOf(1)
expect(application.featuresService.roles[0]).to.equal('CORE_USER')
expect(application.featuresService.onlineRoles).to.have.lengthOf(1)
expect(application.featuresService.onlineRoles[0]).to.equal('CORE_USER')
expect(application.featuresService.features).to.have.lengthOf(3)
expect(application.featuresService.features[0]).to.containSubset(midnightThemeFeature)
@@ -115,7 +115,7 @@ describe('features', () => {
// Wipe items from initial sync
await application.itemManager.removeAllItemsFromMemory()
// Wipe roles from initial sync
await application.featuresService.setRoles([])
await application.featuresService.setOnlineRoles([])
// Create pre-existing item for theme without all the info
await application.itemManager.createItem(
ContentType.Theme,
@@ -165,7 +165,7 @@ describe('features', () => {
.find((theme) => theme.identifier === midnightThemeFeature.identifier)
// Wipe roles from initial sync
await application.featuresService.setRoles([])
await application.featuresService.setOnlineRoles([])
// Call sync intentionally to get roles again in meta
await application.sync.sync()
@@ -184,7 +184,7 @@ describe('features', () => {
})
it('should provide feature', async () => {
const feature = application.features.getUserFeature(FeatureIdentifier.PlusEditor)
const feature = application.features.getFeatureThatOriginallyCameFromServer(FeatureIdentifier.PlusEditor)
expect(feature).to.containSubset(plusEditorFeature)
})
+3 -23
View File
@@ -5,7 +5,7 @@ import { createNoteParams } from './lib/Items.js'
chai.use(chaiAsPromised)
const expect = chai.expect
describe('history manager', () => {
describe.skip('history manager', () => {
const largeCharacterChange = 25
const syncOptions = {
@@ -277,7 +277,7 @@ describe('history manager', () => {
await Factory.safeDeinit(this.application)
})
it('response from server should be empty if not signed in', async function () {
it('response from server should be failed if not signed in', async function () {
await this.application.user.signOut()
this.application = await Factory.createInitAppWithFakeCrypto()
this.historyManager = this.application.historyManager
@@ -286,8 +286,7 @@ describe('history manager', () => {
await this.application.syncService.sync(syncOptions)
const itemHistoryOrError = await this.application.listRevisions.execute({ itemUuid: item.uuid })
expect(itemHistoryOrError.isFailed()).to.equal(false)
expect(itemHistoryOrError.getValue().length).to.equal(0)
expect(itemHistoryOrError.isFailed()).to.equal(true)
})
it('create basic history entries 2', async function () {
@@ -295,8 +294,6 @@ describe('history manager', () => {
await Factory.sleep(Factory.ServerRevisionCreationDelay)
let itemHistoryOrError = await this.application.listRevisions.execute({ itemUuid: item.uuid })
expect(itemHistoryOrError.isFailed()).to.equal(false)
let itemHistory = itemHistoryOrError.getValue()
/** Server history should save initial revision */
@@ -305,8 +302,6 @@ describe('history manager', () => {
/** Sync within 5 seconds (ENV VAR dependend on self-hosted setup), should not create a new entry */
await Factory.markDirtyAndSyncItem(this.application, item)
itemHistoryOrError = await this.application.listRevisions.execute({ itemUuid: item.uuid })
expect(itemHistoryOrError.isFailed()).to.equal(false)
itemHistory = itemHistoryOrError.getValue()
expect(itemHistory.length).to.equal(1)
@@ -322,8 +317,6 @@ describe('history manager', () => {
)
await Factory.sleep(Factory.ServerRevisionCreationDelay)
itemHistoryOrError = await this.application.listRevisions.execute({ itemUuid: item.uuid })
expect(itemHistoryOrError.isFailed()).to.equal(false)
itemHistory = itemHistoryOrError.getValue()
expect(itemHistory.length).to.equal(1)
})
@@ -346,15 +339,11 @@ describe('history manager', () => {
await Factory.sleep(Factory.ServerRevisionCreationDelay)
const itemHistoryOrError = await this.application.listRevisions.execute({ itemUuid: item.uuid })
expect(itemHistoryOrError.isFailed()).to.equal(false)
const itemHistory = itemHistoryOrError.getValue()
expect(itemHistory.length).to.equal(2)
const oldestEntry = lastElement(itemHistory)
let revisionFromServerOrError = await this.application.getRevision.execute({ itemUuid: item.uuid, revisionUuid: oldestEntry.uuid })
expect(revisionFromServerOrError.isFailed()).to.equal(false)
const revisionFromServer = revisionFromServerOrError.getValue()
expect(revisionFromServer).to.be.ok
@@ -376,12 +365,9 @@ describe('history manager', () => {
await Factory.sleep(Factory.ServerRevisionCreationDelay)
const dupeHistoryOrError = await this.application.listRevisions.execute({ itemUuid: dupe.uuid })
expect(dupeHistoryOrError.isFailed()).to.equal(false)
const dupeHistory = dupeHistoryOrError.getValue()
const dupeRevisionOrError = await this.application.getRevision.execute({ itemUuid: dupe.uuid, revisionUuid: dupeHistory[0].uuid })
expect(dupeRevisionOrError.isFailed()).to.equal(false)
const dupeRevision = dupeRevisionOrError.getValue()
expect(dupeRevision.payload.uuid).to.equal(dupe.uuid)
})
@@ -405,11 +391,9 @@ describe('history manager', () => {
const expectedRevisions = 4
const noteHistoryOrError = await this.application.listRevisions.execute({ itemUuid: note.uuid })
expect(noteHistoryOrError.isFailed()).to.equal(false)
const noteHistory = noteHistoryOrError.getValue()
const dupeHistoryOrError = await this.application.listRevisions.execute({ itemUuid: dupe.uuid })
expect(dupeHistoryOrError.isFailed()).to.equal(false)
const dupeHistory = dupeHistoryOrError.getValue()
expect(noteHistory.length).to.equal(expectedRevisions)
@@ -432,15 +416,11 @@ describe('history manager', () => {
await Factory.sleep(Factory.ServerRevisionCreationDelay)
const itemHistoryOrError = await this.application.listRevisions.execute({ itemUuid: dupe.uuid })
expect(itemHistoryOrError.isFailed()).to.equal(false)
const itemHistory = itemHistoryOrError.getValue()
expect(itemHistory.length).to.be.above(1)
const newestRevision = itemHistory[0]
const fetchedOrError = await this.application.getRevision.execute({ itemUuid: dupe.uuid, revisionUuid: newestRevision.uuid })
expect(fetchedOrError.isFailed()).to.equal(false)
const fetched = fetchedOrError.getValue()
expect(fetched.payload.errorDecrypting).to.not.be.ok
expect(fetched.payload.content.title).to.equal(changedText)
+2
View File
@@ -645,6 +645,8 @@ describe('keys', function () {
expect(Object.keys(clientBUndecryptables).length).to.equal(1)
expect(Object.keys(clientAUndecryptables).length).to.equal(0)
await contextB.deinit()
})
describe('changing password on 003 client while signed into 004 client should', function () {
@@ -40,7 +40,7 @@ describe('online conflict handling', function () {
afterEach(async function () {
if (!this.application.dealloced) {
await Factory.safeDeinit(this.application)
await this.context.deinit()
}
localStorage.clear()
})
@@ -950,6 +950,7 @@ describe('online conflict handling', function () {
expect(contextA.findNoteByTitle('title-B').payload.updated_at_timestamp).to.equal(noteBExpectedTimestamp)
await this.sharedFinalAssertions()
await contextB.deinit()
}).timeout(20000)
it('editing original note many times after conflict on other client should only result in 2 cumulative notes', async function () {
@@ -979,5 +980,6 @@ describe('online conflict handling', function () {
expect(contextB.noteCount).to.equal(2)
await this.sharedFinalAssertions()
await contextB.deinit()
}).timeout(20000)
})
@@ -1052,5 +1052,7 @@ describe('online syncing', function () {
await contextB.sync()
expect(contextB.application.items.allCountableNotesCount()).to.equal(0)
await contextB.deinit()
})
})
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/snjs",
"version": "2.164.1",
"version": "2.164.9",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
@@ -36,14 +36,14 @@
"@babel/core": "*",
"@babel/preset-env": "*",
"@standardnotes/api": "workspace:*",
"@standardnotes/common": "^1.46.3",
"@standardnotes/domain-events": "^2.88.0",
"@standardnotes/common": "^1.46.4",
"@standardnotes/domain-events": "^2.106.0",
"@standardnotes/encryption": "workspace:*",
"@standardnotes/features": "workspace:*",
"@standardnotes/files": "workspace:*",
"@standardnotes/models": "workspace:*",
"@standardnotes/responses": "workspace:*",
"@standardnotes/security": "^1.7.0",
"@standardnotes/security": "^1.7.5",
"@standardnotes/services": "workspace:*",
"@standardnotes/settings": "^1.19.0",
"@standardnotes/sncrypto-common": "workspace:*",
+32
View File
@@ -3,6 +3,38 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.24.13](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-23)
**Note:** Version bump only for package @standardnotes/ui-services
## [1.24.12](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-21)
**Note:** Version bump only for package @standardnotes/ui-services
## [1.24.11](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/ui-services
## [1.24.10](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/ui-services
## [1.24.9](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/ui-services
## [1.24.8](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/ui-services
## [1.24.7](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/ui-services
## [1.24.6](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-19)
**Note:** Version bump only for package @standardnotes/ui-services
## [1.24.5](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-19)
**Note:** Version bump only for package @standardnotes/ui-services
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/ui-services",
"version": "1.24.5",
"version": "1.24.13",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
@@ -15,7 +15,7 @@
"test": "jest spec"
},
"dependencies": {
"@standardnotes/common": "^1.46.3",
"@standardnotes/common": "^1.46.4",
"@standardnotes/features": "workspace:^",
"@standardnotes/filepicker": "workspace:^",
"@standardnotes/services": "workspace:^",
+8
View File
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.16.3](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-21)
**Note:** Version bump only for package @standardnotes/utils
## [1.16.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/utils
## [1.16.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-19)
**Note:** Version bump only for package @standardnotes/utils
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/utils",
"version": "1.16.1",
"version": "1.16.3",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
@@ -25,7 +25,7 @@
"test": "jest spec"
},
"dependencies": {
"@standardnotes/common": "^1.46.3",
"@standardnotes/common": "^1.46.4",
"dompurify": "^2.4.1",
"lodash": "^4.17.21",
"reflect-metadata": "^0.1.13"
+34 -1
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.
## [3.140.10](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-23)
**Note:** Version bump only for package @standardnotes/web
## [3.140.9](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-21)
**Note:** Version bump only for package @standardnotes/web
## [3.140.8](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
### Bug Fixes
* fixed issue with third party editors not loading ([#2174](https://github.com/standardnotes/app/issues/2174)) ([e7214ea](https://github.com/standardnotes/app/commit/e7214ea73ad5d3026d958c79022d2238a4d1cfdc))
## [3.140.6](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/web
## [3.140.5](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/web
## [3.140.4](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/web
## [3.140.3](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)
**Note:** Version bump only for package @standardnotes/web
## [3.140.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-19)
**Note:** Version bump only for package @standardnotes/web
## [3.140.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-19)
### Bug Fixes
@@ -24,7 +58,6 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
### Features
* Added rename option to file preview modal ([aa88966](https://github.com/standardnotes/app/commit/aa8896678315de67551c786e64aec7dfd10479e3))
* **snjs:** add revisions api v2 ([#2154](https://github.com/standardnotes/app/issues/2154)) ([880a537](https://github.com/standardnotes/app/commit/880a537774ddcefaedb0d4e5dc50b363f4b93e01))
## [3.138.6](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-17)
+94 -5
View File
@@ -1,5 +1,96 @@
{
"versions": [
{
"version": "3.140.10",
"title": "[3.140.10](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-23)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.140.9",
"title": "[3.140.9](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-21)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.140.8",
"title": "[3.140.8](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)",
"date": null,
"body": "### Bug Fixes\n\n* fixed issue with third party editors not loading ([#2174](https://github.com/standardnotes/app/issues/2174)) ([e7214ea](https://github.com/standardnotes/app/commit/e7214ea73ad5d3026d958c79022d2238a4d1cfdc))",
"parsed": {
"_": [
"fixed issue with third party editors not loading (#2174) (e7214ea)"
],
"Bug Fixes": [
"fixed issue with third party editors not loading (#2174) (e7214ea)"
]
}
},
{
"version": "3.140.6",
"title": "[3.140.6](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.140.5",
"title": "[3.140.5](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.140.4",
"title": "[3.140.4](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.140.3",
"title": "[3.140.3](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-20)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.140.2",
"title": "[3.140.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-19)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.140.1",
"title": "[3.140.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-19)",
@@ -36,15 +127,13 @@
"version": "3.139.0",
"title": "[3.139.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-01-18)",
"date": null,
"body": "### Features\n\n* Added rename option to file preview modal ([aa88966](https://github.com/standardnotes/app/commit/aa8896678315de67551c786e64aec7dfd10479e3))\n* **snjs:** add revisions api v2 ([#2154](https://github.com/standardnotes/app/issues/2154)) ([880a537](https://github.com/standardnotes/app/commit/880a537774ddcefaedb0d4e5dc50b363f4b93e01))",
"body": "### Features\n\n* Added rename option to file preview modal ([aa88966](https://github.com/standardnotes/app/commit/aa8896678315de67551c786e64aec7dfd10479e3))",
"parsed": {
"_": [
"Added rename option to file preview modal (aa88966)",
"snjs: add revisions api v2 (#2154) (880a537)"
"Added rename option to file preview modal (aa88966)"
],
"Features": [
"Added rename option to file preview modal (aa88966)",
"snjs: add revisions api v2 (#2154) (880a537)"
"Added rename option to file preview modal (aa88966)"
]
}
},
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/web",
"version": "3.140.1",
"version": "3.140.10",
"license": "AGPL-3.0-or-later",
"main": "dist/app.js",
"author": "Standard Notes.",
@@ -13,6 +13,7 @@ type Props = {
const UpgradeNow = ({ application, featuresController, subscriptionContoller }: Props) => {
const shouldShowCTA = !featuresController.hasFolders
const hasAccount = subscriptionContoller.hasAccount
const hasAccessToFeatures = subscriptionContoller.hasFirstPartySubscription
const onClick = useCallback(() => {
if (hasAccount && application.isNativeIOS()) {
@@ -22,16 +23,20 @@ const UpgradeNow = ({ application, featuresController, subscriptionContoller }:
}
}, [application, hasAccount])
return shouldShowCTA ? (
if (!shouldShowCTA || hasAccessToFeatures) {
return null
}
return (
<div className="flex h-full items-center px-2">
<button
className="rounded bg-info py-0.5 px-1.5 text-sm font-bold uppercase text-info-contrast hover:brightness-125 lg:text-xs"
onClick={onClick}
>
{hasAccount ? 'Unlock features' : 'Sign up to sync'}
{!hasAccount ? 'Sign up to sync' : 'Unlock features'}
</button>
</div>
) : null
)
}
export default observer(UpgradeNow)
@@ -99,7 +99,7 @@ const Email: FunctionComponent<Props> = ({ application }: Props) => {
<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).
available only to paid subscribers).
</Text>
</div>
{isLoading ? (
@@ -15,7 +15,7 @@ type Props = {
const Subscription: FunctionComponent<Props> = ({ application, viewControllerManager }: Props) => {
const subscriptionState = viewControllerManager.subscriptionController
const { userSubscription } = subscriptionState
const { onlineSubscription } = subscriptionState
const now = new Date().getTime()
@@ -25,7 +25,7 @@ const Subscription: FunctionComponent<Props> = ({ application, viewControllerMan
<div className="flex flex-row items-center">
<div className="flex flex-grow flex-col">
<Title>Subscription</Title>
{userSubscription && userSubscription.endsAt > now ? (
{onlineSubscription && onlineSubscription.endsAt > now ? (
<SubscriptionInformation subscriptionState={subscriptionState} application={application} />
) : (
<NoSubscription application={application} />
@@ -17,7 +17,7 @@ import {
} from '@standardnotes/snjs'
import { WebApplication } from '@/Application/Application'
import Button from '@/Components/Button/Button'
import { isDev, openInNewTab } from '@/Utils'
import { openInNewTab } from '@/Utils'
import { Subtitle } from '@/Components/Preferences/PreferencesComponents/Content'
import { KeyboardKey } from '@standardnotes/ui-services'
@@ -61,7 +61,7 @@ const CloudBackupProvider: FunctionComponent<Props> = ({ application, providerNa
}
event.stopPropagation()
const authUrl = application.getCloudProviderIntegrationUrl(providerName, isDev)
const authUrl = application.getCloudProviderIntegrationUrl(providerName)
openInNewTab(authUrl)
setAuthBegan(true)
}
@@ -7,7 +7,7 @@ export class PackageProvider {
static async load(application: WebApplication): Promise<PackageProvider | undefined> {
const response = await application.getAvailableSubscriptions()
if (response instanceof ClientDisplayableError) {
if (!response || response instanceof ClientDisplayableError) {
return undefined
}
@@ -64,7 +64,10 @@ export const UpgradePrompt = ({
<div className="mb-2 font-bold">The Professional Plan costs $119.99/year and includes benefits like</div>
<ul className="list-inside list-[circle]">
<li>100GB encrypted file storage</li>
<li>Access to all note types, including markdown, rich text, authenticator, tasks, and spreadsheets</li>
<li>
Access to all note types, including Super, markdown, rich text, authenticator, tasks, and spreadsheets
</li>
<li>Access to Daily Notebooks and Moments journals</li>
<li>Note history going back indefinitely</li>
<li>Nested folders for your tags</li>
<li>Premium support</li>
@@ -79,7 +82,7 @@ export const UpgradePrompt = ({
className="no-border w-full cursor-pointer rounded bg-info py-2 font-bold text-info-contrast hover:brightness-125 focus:brightness-125"
ref={ctaRef}
>
Upgrade
{application.isNativeIOS() ? 'Start Free Trial' : 'Upgrade'}
</button>
</div>
</>
@@ -65,6 +65,7 @@ export class FeaturesController extends AbstractViewController {
break
case ApplicationEvent.FeaturesUpdated:
case ApplicationEvent.Launched:
case ApplicationEvent.LocalDataLoaded:
runInAction(() => {
this.hasFolders = this.isEntitledToFolders()
this.hasSmartViews = this.isEntitledToSmartViews()
@@ -75,7 +75,7 @@ export class LinkingController extends AbstractViewController {
}
get isEntitledToNoteLinking() {
return !!this.subscriptionController.userSubscription
return !!this.subscriptionController.onlineSubscription
}
setIsLinkingPanelOpen = (open: boolean) => {
@@ -17,14 +17,15 @@ import { Subscription } from './SubscriptionType'
export class SubscriptionController extends AbstractViewController {
private readonly ALLOWED_SUBSCRIPTION_INVITATIONS = 5
userSubscription: Subscription | undefined = undefined
onlineSubscription: Subscription | undefined = undefined
availableSubscriptions: AvailableSubscriptions | undefined = undefined
subscriptionInvitations: Invitation[] | undefined = undefined
hasAccount: boolean
hasFirstPartySubscription: boolean
override deinit() {
super.deinit()
;(this.userSubscription as unknown) = undefined
;(this.onlineSubscription as unknown) = undefined
;(this.availableSubscriptions as unknown) = undefined
;(this.subscriptionInvitations as unknown) = undefined
@@ -38,12 +39,14 @@ export class SubscriptionController extends AbstractViewController {
) {
super(application, eventBus)
this.hasAccount = application.hasAccount()
this.hasFirstPartySubscription = application.features.hasFirstPartySubscription()
makeObservable(this, {
userSubscription: observable,
onlineSubscription: observable,
availableSubscriptions: observable,
subscriptionInvitations: observable,
hasAccount: observable,
hasFirstPartySubscription: observable,
userSubscriptionName: computed,
userSubscriptionExpirationDate: computed,
@@ -64,11 +67,20 @@ export class SubscriptionController extends AbstractViewController {
this.reloadSubscriptionInvitations().catch(console.error)
}
runInAction(() => {
this.hasFirstPartySubscription = application.features.hasFirstPartySubscription()
this.hasAccount = application.hasAccount()
})
}, ApplicationEvent.Launched),
)
this.disposers.push(
application.addEventObserver(async () => {
runInAction(() => {
this.hasFirstPartySubscription = application.features.hasFirstPartySubscription()
})
}, ApplicationEvent.LocalDataLoaded),
)
this.disposers.push(
application.addEventObserver(async () => {
this.getSubscriptionInfo().catch(console.error)
@@ -83,6 +95,9 @@ export class SubscriptionController extends AbstractViewController {
application.addEventObserver(async () => {
this.getSubscriptionInfo().catch(console.error)
this.reloadSubscriptionInvitations().catch(console.error)
runInAction(() => {
this.hasFirstPartySubscription = application.features.hasFirstPartySubscription()
})
}, ApplicationEvent.UserRolesChanged),
)
}
@@ -90,20 +105,20 @@ export class SubscriptionController extends AbstractViewController {
get userSubscriptionName(): string {
if (
this.availableSubscriptions &&
this.userSubscription &&
this.availableSubscriptions[this.userSubscription.planName]
this.onlineSubscription &&
this.availableSubscriptions[this.onlineSubscription.planName]
) {
return this.availableSubscriptions[this.userSubscription.planName].name
return this.availableSubscriptions[this.onlineSubscription.planName].name
}
return ''
}
get userSubscriptionExpirationDate(): Date | undefined {
if (!this.userSubscription) {
if (!this.onlineSubscription) {
return undefined
}
return new Date(convertTimestampToMilliseconds(this.userSubscription.endsAt))
return new Date(convertTimestampToMilliseconds(this.onlineSubscription.endsAt))
}
get isUserSubscriptionExpired(): boolean {
@@ -115,11 +130,11 @@ export class SubscriptionController extends AbstractViewController {
}
get isUserSubscriptionCanceled(): boolean {
return Boolean(this.userSubscription?.cancelled)
return Boolean(this.onlineSubscription?.cancelled)
}
hasValidSubscription(): boolean {
return this.userSubscription != undefined && !this.isUserSubscriptionExpired && !this.isUserSubscriptionCanceled
return this.onlineSubscription != undefined && !this.isUserSubscriptionExpired && !this.isUserSubscriptionCanceled
}
get usedInvitationsCount(): number {
@@ -139,7 +154,7 @@ export class SubscriptionController extends AbstractViewController {
}
public setUserSubscription(subscription: Subscription): void {
this.userSubscription = subscription
this.onlineSubscription = subscription
}
public setAvailableSubscriptions(subscriptions: AvailableSubscriptions): void {
@@ -4,6 +4,9 @@ import { IconType } from '@standardnotes/models'
export function getIconAndTintForNoteType(noteType?: NoteType, subtle?: boolean): [IconType, number] {
switch (noteType) {
case undefined:
case NoteType.Plain:
return [PlainEditorMetadata.icon, PlainEditorMetadata.iconTintNumber]
case NoteType.RichText:
return ['rich-text', 1]
case NoteType.Markdown:
@@ -21,7 +24,8 @@ export function getIconAndTintForNoteType(noteType?: NoteType, subtle?: boolean)
subtle ? (SuperEditorMetadata.subtleIcon as IconType) : SuperEditorMetadata.icon,
SuperEditorMetadata.iconTintNumber,
]
case NoteType.Unknown:
default:
return [PlainEditorMetadata.icon, PlainEditorMetadata.iconTintNumber]
return ['editor', PlainEditorMetadata.iconTintNumber]
}
}
@@ -6,6 +6,7 @@ import {
ComponentArea,
FeatureDescription,
GetFeatures,
FindNativeFeature,
NoteType,
FeatureIdentifier,
} from '@standardnotes/snjs'
@@ -149,8 +150,7 @@ const createBaselineMap = (application: WebApplication): NoteTypeToEditorRowsMap
isEntitled: application.features.getFeatureStatus(FeatureIdentifier.SuperEditor) === FeatureStatus.Entitled,
noteType: NoteType.Super,
isLabs: true,
description:
'A new way to edit notes. Type / to bring up the block selection menu, or @ to embed images or link other tags and notes. Type - then space to start a list, or [] then space to start a checklist. Drag and drop an image or file to embed it in your note.',
description: FindNativeFeature(FeatureIdentifier.SuperEditor)?.description,
},
],
[NoteType.RichText]: [],
+51 -56
View File
@@ -4372,12 +4372,12 @@ __metadata:
version: 0.0.0-use.local
resolution: "@standardnotes/api@workspace:packages/api"
dependencies:
"@standardnotes/common": ^1.46.3
"@standardnotes/common": ^1.46.4
"@standardnotes/domain-core": ^1.11.1
"@standardnotes/encryption": "workspace:*"
"@standardnotes/models": "workspace:*"
"@standardnotes/responses": "workspace:*"
"@standardnotes/security": ^1.7.0
"@standardnotes/security": ^1.7.5
"@standardnotes/utils": "workspace:*"
"@types/jest": ^29.2.3
"@types/lodash": ^4.14.189
@@ -4494,15 +4494,6 @@ __metadata:
languageName: node
linkType: hard
"@standardnotes/common@npm:1.45.0":
version: 1.45.0
resolution: "@standardnotes/common@npm:1.45.0"
dependencies:
reflect-metadata: ^0.1.13
checksum: 3bf1dd805ba7a864caebd25d5390bdbf4fb6b7cd06b3c064ad19cda6e5a709b7eb8f22314a5f393fa5c21a50722056f6c4e40308c43ca8c112db3260cd17b45f
languageName: node
linkType: hard
"@standardnotes/common@npm:^1.43.0":
version: 1.43.0
resolution: "@standardnotes/common@npm:1.43.0"
@@ -4512,12 +4503,12 @@ __metadata:
languageName: node
linkType: hard
"@standardnotes/common@npm:^1.46.3":
version: 1.46.3
resolution: "@standardnotes/common@npm:1.46.3"
"@standardnotes/common@npm:^1.46.4":
version: 1.46.4
resolution: "@standardnotes/common@npm:1.46.4"
dependencies:
reflect-metadata: ^0.1.13
checksum: 0fa509e30431a740ed142274c4f21ae03d74b6e05bcd4f028d89a3f1a6566de792bbd7c37b1b92587138dd6ea10459eead5a8cad2150f9f2268481615d390dee
checksum: 6d21999a1df420040a8dfa5eb3157744320cd0a610f2a1b911a86b44a66bf23d07235dd543fe5849e853ac6e8e944bd14f5cc0f6ef2ad4f264b5cea55066ebcb
languageName: node
linkType: hard
@@ -4606,16 +4597,14 @@ __metadata:
languageName: node
linkType: hard
"@standardnotes/domain-events@npm:^2.88.0":
version: 2.88.0
resolution: "@standardnotes/domain-events@npm:2.88.0"
"@standardnotes/domain-events@npm:^2.106.0":
version: 2.106.0
resolution: "@standardnotes/domain-events@npm:2.106.0"
dependencies:
"@standardnotes/common": 1.45.0
"@standardnotes/features": ^1.52.1
"@standardnotes/predicates": 1.6.0
"@standardnotes/security": 1.7.0
reflect-metadata: ^0.1.13
checksum: 8574ba4c7efe96ff7bb98612d4b5f0ceef3e81d5e9c401396bd5b3a8bc1d6382d059958261b88a117fe6eaf5c96fed3dd5969efe67fe3669d7badd2113ed47fb
"@standardnotes/features": ^1.58.1
"@standardnotes/predicates": 1.6.4
"@standardnotes/security": 1.7.5
checksum: db98a6b4ef5181a02862a3989df2d8f0a4929044456583c9ffda767c31c5dec676a4da82d1fe581ffc6e35a977a05b071a2a8646fee2a4bdbdf1b265ccbb70d8
languageName: node
linkType: hard
@@ -4650,7 +4639,7 @@ __metadata:
version: 0.0.0-use.local
resolution: "@standardnotes/encryption@workspace:packages/encryption"
dependencies:
"@standardnotes/common": ^1.46.3
"@standardnotes/common": ^1.46.4
"@standardnotes/config": 2.4.3
"@standardnotes/models": "workspace:*"
"@standardnotes/responses": "workspace:*"
@@ -4669,14 +4658,13 @@ __metadata:
languageName: unknown
linkType: soft
"@standardnotes/features@^1.52.1, @standardnotes/features@workspace:*, @standardnotes/features@workspace:^, @standardnotes/features@workspace:packages/features":
"@standardnotes/features@^1.58.1, @standardnotes/features@workspace:*, @standardnotes/features@workspace:^, @standardnotes/features@workspace:packages/features":
version: 0.0.0-use.local
resolution: "@standardnotes/features@workspace:packages/features"
dependencies:
"@standardnotes/auth": ^3.19.4
"@standardnotes/common": ^1.46.3
"@standardnotes/common": ^1.46.4
"@standardnotes/domain-core": ^1.11.1
"@standardnotes/security": ^1.7.0
"@standardnotes/security": ^1.7.5
"@types/jest": ^29.2.3
"@typescript-eslint/eslint-plugin": "*"
eslint: "*"
@@ -4704,7 +4692,7 @@ __metadata:
version: 0.0.0-use.local
resolution: "@standardnotes/filepicker@workspace:packages/filepicker"
dependencies:
"@standardnotes/common": ^1.46.3
"@standardnotes/common": ^1.46.4
"@standardnotes/files": "workspace:*"
"@standardnotes/utils": "workspace:*"
"@types/jest": ^29.2.3
@@ -4724,7 +4712,7 @@ __metadata:
version: 0.0.0-use.local
resolution: "@standardnotes/files@workspace:packages/files"
dependencies:
"@standardnotes/common": ^1.46.3
"@standardnotes/common": ^1.46.4
"@standardnotes/encryption": "workspace:*"
"@standardnotes/models": "workspace:*"
"@standardnotes/responses": "workspace:*"
@@ -4888,10 +4876,10 @@ __metadata:
version: 0.0.0-use.local
resolution: "@standardnotes/models@workspace:packages/models"
dependencies:
"@standardnotes/common": ^1.46.3
"@standardnotes/common": ^1.46.4
"@standardnotes/features": "workspace:*"
"@standardnotes/responses": "workspace:*"
"@standardnotes/utils": "workspace:*"
"@standardnotes/utils": "workspace:^"
"@types/jest": ^29.2.3
"@types/lodash": ^4.14.189
"@typescript-eslint/eslint-plugin": "*"
@@ -4905,13 +4893,10 @@ __metadata:
languageName: unknown
linkType: soft
"@standardnotes/predicates@npm:1.6.0":
version: 1.6.0
resolution: "@standardnotes/predicates@npm:1.6.0"
dependencies:
"@standardnotes/common": 1.45.0
reflect-metadata: ^0.1.13
checksum: 020e2206c75e6b964bf400314a116b29ece5f9e662a5dd6704de8864aaec1689256b008334db5f2983addc039d3b7f4a8108c87789e61d37a8ba9161ea93cfa0
"@standardnotes/predicates@npm:1.6.4":
version: 1.6.4
resolution: "@standardnotes/predicates@npm:1.6.4"
checksum: 6d7235896a6d591f6e33d2d0b89c58850d357095d26e1d74264db1d77164a8f1f6673f4095c660719992f2aa8411cfbfe79781f004c3eb2aa82a761e34827f60
languageName: node
linkType: hard
@@ -4938,9 +4923,9 @@ __metadata:
version: 0.0.0-use.local
resolution: "@standardnotes/responses@workspace:packages/responses"
dependencies:
"@standardnotes/common": ^1.46.3
"@standardnotes/common": ^1.46.4
"@standardnotes/features": "workspace:*"
"@standardnotes/security": ^1.7.0
"@standardnotes/security": ^1.7.5
"@types/jest": ^29.2.3
"@typescript-eslint/eslint-plugin": "*"
eslint: "*"
@@ -4961,14 +4946,13 @@ __metadata:
languageName: node
linkType: hard
"@standardnotes/security@npm:1.7.0, @standardnotes/security@npm:^1.7.0":
version: 1.7.0
resolution: "@standardnotes/security@npm:1.7.0"
"@standardnotes/security@npm:1.7.5, @standardnotes/security@npm:^1.7.5":
version: 1.7.5
resolution: "@standardnotes/security@npm:1.7.5"
dependencies:
"@standardnotes/common": 1.45.0
jsonwebtoken: ^8.5.1
jsonwebtoken: ^9.0.0
reflect-metadata: ^0.1.13
checksum: c053af16e620c29e8b9233212e5b220cebc7e71c195b5c63cd6fb68b617465c935ae1c926ebc6a4c9aff32487e538e949a3fe4a9e281d082c2fddcc9d17fa3a7
checksum: 69d180d25936cad64ee19d8932aedff60b91f4a25f96084e0a686b228773aba856f50c3da265d426d64160dff28f20d9d7980a625bce00fc6a47416caa4e130e
languageName: node
linkType: hard
@@ -4988,14 +4972,13 @@ __metadata:
resolution: "@standardnotes/services@workspace:packages/services"
dependencies:
"@standardnotes/api": "workspace:^"
"@standardnotes/auth": ^3.19.4
"@standardnotes/common": ^1.46.3
"@standardnotes/common": ^1.46.4
"@standardnotes/domain-core": ^1.11.1
"@standardnotes/encryption": "workspace:^"
"@standardnotes/files": "workspace:^"
"@standardnotes/models": "workspace:^"
"@standardnotes/responses": "workspace:*"
"@standardnotes/security": ^1.7.0
"@standardnotes/security": ^1.7.5
"@standardnotes/sncrypto-common": "workspace:^"
"@standardnotes/utils": "workspace:*"
"@types/jest": ^29.2.3
@@ -5086,15 +5069,15 @@ __metadata:
"@babel/core": "*"
"@babel/preset-env": "*"
"@standardnotes/api": "workspace:*"
"@standardnotes/common": ^1.46.3
"@standardnotes/common": ^1.46.4
"@standardnotes/domain-core": ^1.11.1
"@standardnotes/domain-events": ^2.88.0
"@standardnotes/domain-events": ^2.106.0
"@standardnotes/encryption": "workspace:*"
"@standardnotes/features": "workspace:*"
"@standardnotes/files": "workspace:*"
"@standardnotes/models": "workspace:*"
"@standardnotes/responses": "workspace:*"
"@standardnotes/security": ^1.7.0
"@standardnotes/security": ^1.7.5
"@standardnotes/services": "workspace:*"
"@standardnotes/settings": ^1.19.0
"@standardnotes/sncrypto-common": "workspace:*"
@@ -5214,7 +5197,7 @@ __metadata:
version: 0.0.0-use.local
resolution: "@standardnotes/ui-services@workspace:packages/ui-services"
dependencies:
"@standardnotes/common": ^1.46.3
"@standardnotes/common": ^1.46.4
"@standardnotes/features": "workspace:^"
"@standardnotes/filepicker": "workspace:^"
"@standardnotes/services": "workspace:^"
@@ -5236,7 +5219,7 @@ __metadata:
version: 0.0.0-use.local
resolution: "@standardnotes/utils@workspace:packages/utils"
dependencies:
"@standardnotes/common": ^1.46.3
"@standardnotes/common": ^1.46.4
"@types/dompurify": ^2.4.0
"@types/jest": ^29.2.3
"@types/jsdom": ^20.0.1
@@ -14999,6 +14982,18 @@ __metadata:
languageName: node
linkType: hard
"jsonwebtoken@npm:^9.0.0":
version: 9.0.0
resolution: "jsonwebtoken@npm:9.0.0"
dependencies:
jws: ^3.2.2
lodash: ^4.17.21
ms: ^2.1.1
semver: ^7.3.8
checksum: b9181cecf9df99f1dc0253f91ba000a1aa4d91f5816d1608c0dba61a5623726a0bfe200b51df25de18c1a6000825d231ad7ce2788aa54fd48dcb760ad9eb9514
languageName: node
linkType: hard
"jsx-ast-utils@npm:^2.4.1 || ^3.0.0":
version: 3.3.3
resolution: "jsx-ast-utils@npm:3.3.3"