Compare commits

..
Author SHA1 Message Date
StandardNotes CI e54e442399 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].1
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].8
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].1
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].1
 - @standardnotes/[email protected].3
2023-08-21 13:53:50 +00:00
Karol Sójko a6029e3ef1 chore: send shared vault owner context when creating a shared vault file valet token (#2435)
* chore: send shared vault owner context when creating a shared vault file valet token

* chore: remove unused shared vault upload bytes limit
2023-08-21 14:57:54 +02:00
StandardNotes CI f2c92d24f3 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].2
2023-08-18 19:24:16 +00:00
Aman Harwara 8be872feee chore: fix issues blocking app store review [skip e2e] 2023-08-19 00:34:43 +05:30
StandardNotes CI 24f878ecef chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].1
2023-08-18 15:41:40 +00:00
Aman Harwara ca0a7fa8a7 chore: edit smart view modal style 2023-08-18 20:15:21 +05:30
Aman Harwara d79484739b fix: Fixed issue where dragging a list item with a link in Super would only re-order the link 2023-08-18 20:04:46 +05:30
StandardNotes CI 6559c66ecf chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].0
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].0
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].0
 - @standardnotes/[email protected].0
2023-08-18 12:26:53 +00:00
Aman Harwara b43f306d6b chore: fix json detection issue when importing 2023-08-18 17:07:34 +05:30
Karol Sójko 18fdc482a9 chore: fix role checking test to consider transitioning role (#2434) 2023-08-18 13:34:15 +02:00
Aman Harwara f26ad410e2 feat: Add toggle to disable creating a new tag on import 2023-08-18 16:58:01 +05:30
Aman Harwara ca9895cac1 feat: Added Super & HTML import options in Import modal. Google Keep notes will now also be imported as Super notes, with attachments if importing from HTML (#2433) 2023-08-18 16:41:25 +05:30
StandardNotes CI 18b7728145 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].4
2023-08-17 17:52:17 +00:00
Aman Harwara 21b34a5039 chore: fix issue where preferences modal is grayed out when translucent ui is disabled [skip e2e] 2023-08-17 23:00:43 +05:30
StandardNotes CI a683ca4b40 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].3
2023-08-17 10:44:23 +00:00
Karol Sójko 94361f0222 chore: fix parsing url search params in e2e test setup 2023-08-17 12:11:38 +02:00
Karol Sójko 24afeaed63 chore: allow enabling vaults e2e tests by url param 2023-08-17 12:04:55 +02:00
StandardNotes CI cddc5e101b chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].2
2023-08-16 18:07:32 +00:00
Aman Harwara 6a84f25301 chore: fix issue where scroll would get reset in popovers [skip e2e] 2023-08-16 23:23:26 +05:30
StandardNotes CI a3d1f7d663 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].1
2023-08-16 17:27:05 +00:00
Aman Harwara 3b1d63ee71 chore: fix issues blocking app store review 2023-08-16 22:24:35 +05:30
StandardNotes CI 317167adea chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].0
2023-08-16 16:53:46 +00:00
Aman Harwara 77f72ff7b6 feat: Super formatting toolbar on mobile now shows whether an option is active in the selection, and also shows hints when an option is long-pressed (#2432) 2023-08-16 21:52:41 +05:30
StandardNotes CI d508425b34 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
2023-08-15 14:52:11 +00:00
Aman Harwara d920ed52ad chore: downgraded spreadsheets version [skip e2e] 2023-08-15 20:00:12 +05:30
StandardNotes CI 5503e672be chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
2023-08-15 10:26:36 +00:00
Aman Harwara 779d935dba chore: release [skip e2e] 2023-08-15 15:41:07 +05:30
Aman Harwara 2936ef174c refactor: auto-detect if theme is a dark theme and apply correct status bar colors 2023-08-15 15:40:49 +05:30
StandardNotes CI 600b690249 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
2023-08-14 19:42:04 +00:00
Aman Harwara 4246c5181a chore: fix preferences view when using custom titlebar [skip e2e] 2023-08-15 00:54:19 +05:30
StandardNotes CI 2ba427602d chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
2023-08-14 10:59:25 +00:00
Aman Harwara b8cbd446b8 chore: fix popover initial scroll 2023-08-14 16:00:54 +05:30
Aman Harwara f95a942f6e chore: smart view / tag hover style 2023-08-14 15:45:35 +05:30
Aman Harwara 4865e3ba28 refactor: popover a11y aria attributes 2023-08-14 14:42:33 +05:30
Aman Harwara e1c5d52dbe refactor: menu keyboard navigation 2023-08-14 13:49:32 +05:30
StandardNotes CI cd0111d6b1 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
2023-08-14 07:07:09 +00:00
Aman Harwara 40a22a1403 chore: features modal animation 2023-08-14 12:00:50 +05:30
Aman Harwara 2775d5e161 chore: dont auto-close popover when closing modal 2023-08-14 11:52:57 +05:30
Aman Harwara ea8f9dba03 chore: make account menu close animation smoother when in sign-in or create account pane 2023-08-14 11:49:52 +05:30
StandardNotes CI 86bc242ba2 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
2023-08-12 17:18:27 +00:00
Aman Harwara 5af0ff8f2e fix: Fixed issue where note context menu would not open if right-clicking multiple times 2023-08-12 22:19:42 +05:30
128 changed files with 1675 additions and 804 deletions
+4
View File
@@ -3,6 +3,10 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.26.49](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-21)
**Note:** Version bump only for package @standardnotes/api
## [1.26.48](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-12)
**Note:** Version bump only for package @standardnotes/api
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/api",
"version": "1.26.48",
"version": "1.26.49",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
@@ -0,0 +1,4 @@
export interface HttpRequestOptions {
authentication?: string
headers?: Record<string, string>[]
}
+12 -10
View File
@@ -16,6 +16,7 @@ import { Paths } from '../Server/Auth/Paths'
import { SessionRefreshResponseBody } from '../Response/Auth/SessionRefreshResponseBody'
import { FetchRequestHandler } from './FetchRequestHandler'
import { RequestHandlerInterface } from './RequestHandlerInterface'
import { HttpRequestOptions } from './HttpRequestOptions'
export class HttpService implements HttpServiceInterface {
private session?: Session | LegacySession
@@ -76,7 +77,7 @@ export class HttpService implements HttpServiceInterface {
}
}
async get<T>(path: string, params?: HttpRequestParams, authentication?: string): Promise<HttpResponse<T>> {
async get<T>(path: string, params?: HttpRequestParams, options?: HttpRequestOptions): Promise<HttpResponse<T>> {
if (!this.host) {
throw new Error('Attempting to make network request before host is set')
}
@@ -85,7 +86,7 @@ export class HttpService implements HttpServiceInterface {
url: joinPaths(this.host, path),
params,
verb: HttpVerb.Get,
authentication: authentication ?? this.getSessionAccessToken(),
authentication: options?.authentication ?? this.getSessionAccessToken(),
})
}
@@ -98,7 +99,7 @@ export class HttpService implements HttpServiceInterface {
})
}
async post<T>(path: string, params?: HttpRequestParams, authentication?: string): Promise<HttpResponse<T>> {
async post<T>(path: string, params?: HttpRequestParams, options?: HttpRequestOptions): Promise<HttpResponse<T>> {
if (!this.host) {
throw new Error('Attempting to make network request before host is set')
}
@@ -107,34 +108,35 @@ export class HttpService implements HttpServiceInterface {
url: joinPaths(this.host, path),
params,
verb: HttpVerb.Post,
authentication: authentication ?? this.getSessionAccessToken(),
authentication: options?.authentication ?? this.getSessionAccessToken(),
customHeaders: options?.headers,
})
}
async put<T>(path: string, params?: HttpRequestParams, authentication?: string): Promise<HttpResponse<T>> {
async put<T>(path: string, params?: HttpRequestParams, options?: HttpRequestOptions): Promise<HttpResponse<T>> {
return this.runHttp({
url: joinPaths(this.host, path),
params,
verb: HttpVerb.Put,
authentication: authentication ?? this.getSessionAccessToken(),
authentication: options?.authentication ?? this.getSessionAccessToken(),
})
}
async patch<T>(path: string, params: HttpRequestParams, authentication?: string): Promise<HttpResponse<T>> {
async patch<T>(path: string, params: HttpRequestParams, options?: HttpRequestOptions): Promise<HttpResponse<T>> {
return this.runHttp({
url: joinPaths(this.host, path),
params,
verb: HttpVerb.Patch,
authentication: authentication ?? this.getSessionAccessToken(),
authentication: options?.authentication ?? this.getSessionAccessToken(),
})
}
async delete<T>(path: string, params?: HttpRequestParams, authentication?: string): Promise<HttpResponse<T>> {
async delete<T>(path: string, params?: HttpRequestParams, options?: HttpRequestOptions): Promise<HttpResponse<T>> {
return this.runHttp({
url: joinPaths(this.host, path),
params,
verb: HttpVerb.Delete,
authentication: authentication ?? this.getSessionAccessToken(),
authentication: options?.authentication ?? this.getSessionAccessToken(),
})
}
@@ -1,16 +1,18 @@
import { LegacySession, Session } from '@standardnotes/domain-core'
import { HttpRequest, HttpRequestParams, HttpResponse, HttpResponseMeta } from '@standardnotes/responses'
import { HttpRequestOptions } from './HttpRequestOptions'
export interface HttpServiceInterface {
setHost(host: string): void
getHost(): string
get<T>(path: string, params?: HttpRequestParams, authentication?: string): Promise<HttpResponse<T>>
get<T>(path: string, params?: HttpRequestParams, options?: HttpRequestOptions): Promise<HttpResponse<T>>
getExternal<T>(url: string, params?: HttpRequestParams): Promise<HttpResponse<T>>
post<T>(path: string, params?: HttpRequestParams, authentication?: string): Promise<HttpResponse<T>>
put<T>(path: string, params?: HttpRequestParams, authentication?: string): Promise<HttpResponse<T>>
patch<T>(path: string, params: HttpRequestParams, authentication?: string): Promise<HttpResponse<T>>
delete<T>(path: string, params?: HttpRequestParams, authentication?: string): Promise<HttpResponse<T>>
post<T>(path: string, params?: HttpRequestParams, options?: HttpRequestOptions): Promise<HttpResponse<T>>
put<T>(path: string, params?: HttpRequestParams, options?: HttpRequestOptions): Promise<HttpResponse<T>>
patch<T>(path: string, params: HttpRequestParams, options?: HttpRequestOptions): Promise<HttpResponse<T>>
delete<T>(path: string, params?: HttpRequestParams, options?: HttpRequestOptions): Promise<HttpResponse<T>>
runHttp<T>(httpRequest: HttpRequest): Promise<HttpResponse<T>>
setSession(session: Session | LegacySession): void
+1
View File
@@ -1,4 +1,5 @@
export * from './HttpService'
export * from './FetchRequestHandler'
export * from './HttpRequestOptions'
export * from './HttpServiceInterface'
export * from './XMLHttpRequestState'
@@ -8,4 +8,5 @@ export type CreateSharedVaultValetTokenParams = {
unencryptedFileSize?: number
moveOperationType?: SharedVaultMoveType
sharedVaultToSharedVaultMoveTargetUuid?: string
sharedVaultOwnerUuid?: string
}
@@ -25,13 +25,23 @@ export class SharedVaultServer implements SharedVaultServerInterface {
createSharedVaultFileValetToken(
params: CreateSharedVaultValetTokenParams,
): Promise<HttpResponse<CreateSharedVaultValetTokenResponse>> {
return this.httpService.post(SharedVaultsPaths.createSharedVaultFileValetToken(params.sharedVaultUuid), {
file_uuid: params.fileUuid,
remote_identifier: params.remoteIdentifier,
operation: params.operation,
unencrypted_file_size: params.unencryptedFileSize,
move_operation_type: params.moveOperationType,
shared_vault_to_shared_vault_move_target_uuid: params.sharedVaultToSharedVaultMoveTargetUuid,
})
let headers = undefined
if (params.sharedVaultOwnerUuid) {
headers = [{ 'x-shared-vault-owner-context': params.sharedVaultOwnerUuid }]
}
return this.httpService.post(
SharedVaultsPaths.createSharedVaultFileValetToken(params.sharedVaultUuid),
{
file_uuid: params.fileUuid,
remote_identifier: params.remoteIdentifier,
operation: params.operation,
unencrypted_file_size: params.unencryptedFileSize,
move_operation_type: params.moveOperationType,
shared_vault_to_shared_vault_move_target_uuid: params.sharedVaultToSharedVaultMoveTargetUuid,
},
{
headers,
},
)
}
}
+60
View File
@@ -3,6 +3,66 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.1.186](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-21)
**Note:** Version bump only for package @standardnotes/clipper
## [1.1.185](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-18)
**Note:** Version bump only for package @standardnotes/clipper
## [1.1.184](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-18)
**Note:** Version bump only for package @standardnotes/clipper
## [1.1.183](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-18)
**Note:** Version bump only for package @standardnotes/clipper
## [1.1.182](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-17)
**Note:** Version bump only for package @standardnotes/clipper
## [1.1.181](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-17)
**Note:** Version bump only for package @standardnotes/clipper
## [1.1.180](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-16)
**Note:** Version bump only for package @standardnotes/clipper
## [1.1.179](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-16)
**Note:** Version bump only for package @standardnotes/clipper
## [1.1.178](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-16)
**Note:** Version bump only for package @standardnotes/clipper
## [1.1.177](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-15)
**Note:** Version bump only for package @standardnotes/clipper
## [1.1.176](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-15)
**Note:** Version bump only for package @standardnotes/clipper
## [1.1.175](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-14)
**Note:** Version bump only for package @standardnotes/clipper
## [1.1.174](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-14)
**Note:** Version bump only for package @standardnotes/clipper
## [1.1.173](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-14)
**Note:** Version bump only for package @standardnotes/clipper
## [1.1.172](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-12)
**Note:** Version bump only for package @standardnotes/clipper
## [1.1.171](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-12)
**Note:** Version bump only for package @standardnotes/clipper
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@standardnotes/clipper",
"description": "Web clipper browser extension for Standard Notes",
"version": "1.1.171",
"version": "1.1.186",
"private": true,
"scripts": {
"build-mv2": "yarn clean && webpack --config ./webpack.config.prod.js",
+60
View File
@@ -3,6 +3,66 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [3.108.118](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-21)
**Note:** Version bump only for package @standardnotes/desktop
## [3.108.117](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-18)
**Note:** Version bump only for package @standardnotes/desktop
## [3.108.116](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-18)
**Note:** Version bump only for package @standardnotes/desktop
## [3.108.115](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-18)
**Note:** Version bump only for package @standardnotes/desktop
## [3.108.114](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-17)
**Note:** Version bump only for package @standardnotes/desktop
## [3.108.113](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-17)
**Note:** Version bump only for package @standardnotes/desktop
## [3.108.112](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-16)
**Note:** Version bump only for package @standardnotes/desktop
## [3.108.111](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-16)
**Note:** Version bump only for package @standardnotes/desktop
## [3.108.110](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-16)
**Note:** Version bump only for package @standardnotes/desktop
## [3.108.109](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-15)
**Note:** Version bump only for package @standardnotes/desktop
## [3.108.108](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-15)
**Note:** Version bump only for package @standardnotes/desktop
## [3.108.107](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-14)
**Note:** Version bump only for package @standardnotes/desktop
## [3.108.106](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-14)
**Note:** Version bump only for package @standardnotes/desktop
## [3.108.105](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-14)
**Note:** Version bump only for package @standardnotes/desktop
## [3.108.104](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-12)
**Note:** Version bump only for package @standardnotes/desktop
## [3.108.103](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-12)
**Note:** Version bump only for package @standardnotes/desktop
@@ -128,7 +128,7 @@ async function configureWindow(remoteBridge: CrossProcessBridge) {
/* Use custom title bar. Take the sn-titlebar-height off of
the app content height so its not overflowing */
sheet.insertRule(
'[role="dialog"] { height: calc(100vh - var(--sn-desktop-titlebar-height)) !important; top: var(--sn-desktop-titlebar-height); }',
'[role="dialog"] { height: calc(100vh - var(--sn-desktop-titlebar-height)) !important; margin-top: var(--sn-desktop-titlebar-height); }',
sheet.cssRules.length,
)
sheet.insertRule(
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@standardnotes/desktop",
"main": "./app/dist/index.js",
"version": "3.108.103",
"version": "3.108.118",
"license": "CC BY-NC-SA 4.0",
"author": "Standard Notes.",
"private": true,
+4
View File
@@ -3,6 +3,10 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.21.71](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-21)
**Note:** Version bump only for package @standardnotes/encryption
## [1.21.70](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-12)
**Note:** Version bump only for package @standardnotes/encryption
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/encryption",
"version": "1.21.70",
"version": "1.21.71",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
+8
View File
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.28.82](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-21)
**Note:** Version bump only for package @standardnotes/filepicker
## [1.28.81](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-18)
**Note:** Version bump only for package @standardnotes/filepicker
## [1.28.80](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-12)
**Note:** Version bump only for package @standardnotes/filepicker
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/filepicker",
"version": "1.28.80",
"version": "1.28.82",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
+10
View File
@@ -3,6 +3,16 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.17.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-21)
**Note:** Version bump only for package @standardnotes/files
# [1.17.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-18)
### Features
* Added Super & HTML import options in Import modal. Google Keep notes will now also be imported as Super notes, with attachments if importing from HTML ([#2433](https://github.com/standardnotes/app/issues/2433)) ([ca9895c](https://github.com/standardnotes/app/commit/ca9895cac117aad16cd2f89633d7613ed54b67bf))
## [1.16.26](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-12)
**Note:** Version bump only for package @standardnotes/files
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/files",
"version": "1.16.26",
"version": "1.17.1",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
@@ -1,3 +1,5 @@
export interface SuperConverterServiceInterface {
convertString: (superString: string, toFormat: 'txt' | 'md' | 'html' | 'json') => string
isValidSuperString(superString: string): boolean
convertSuperStringToOtherFormat: (superString: string, toFormat: 'txt' | 'md' | 'html' | 'json') => string
convertOtherFormatToSuperString: (otherFormatString: string, fromFormat: 'txt' | 'md' | 'html' | 'json') => string
}
+60
View File
@@ -3,6 +3,66 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [3.56.97](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-21)
**Note:** Version bump only for package @standardnotes/mobile
## [3.56.96](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-18)
**Note:** Version bump only for package @standardnotes/mobile
## [3.56.95](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-18)
**Note:** Version bump only for package @standardnotes/mobile
## [3.56.94](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-18)
**Note:** Version bump only for package @standardnotes/mobile
## [3.56.93](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-17)
**Note:** Version bump only for package @standardnotes/mobile
## [3.56.92](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-17)
**Note:** Version bump only for package @standardnotes/mobile
## [3.56.91](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-16)
**Note:** Version bump only for package @standardnotes/mobile
## [3.56.90](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-16)
**Note:** Version bump only for package @standardnotes/mobile
## [3.56.89](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-16)
**Note:** Version bump only for package @standardnotes/mobile
## [3.56.88](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-15)
**Note:** Version bump only for package @standardnotes/mobile
## [3.56.87](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-15)
**Note:** Version bump only for package @standardnotes/mobile
## [3.56.86](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-14)
**Note:** Version bump only for package @standardnotes/mobile
## [3.56.85](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-14)
**Note:** Version bump only for package @standardnotes/mobile
## [3.56.84](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-14)
**Note:** Version bump only for package @standardnotes/mobile
## [3.56.83](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-12)
**Note:** Version bump only for package @standardnotes/mobile
## [3.56.82](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-12)
**Note:** Version bump only for package @standardnotes/mobile
+2 -2
View File
@@ -723,7 +723,7 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon/yoga"
SPEC CHECKSUMS:
boost: a7c83b31436843459a1961bfd74b96033dc77234
boost: 57d2868c099736d80fcd648bf211b4431e51a558
CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99
DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54
FBLazyVector: 4cce221dd782d3ff7c4172167bba09d58af67ccb
@@ -743,7 +743,7 @@ SPEC CHECKSUMS:
MMKV: 9c4663aa7ca255d478ff10f2f5cb7d17c1651ccd
MMKVCore: 89f5c8a66bba2dcd551779dea4d412eeec8ff5bb
OpenSSL-Universal: ebc357f1e6bc71fa463ccb2fe676756aff50e88c
RCT-Folly: 0080d0a6ebf2577475bda044aa59e2ca1f909cda
RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1
RCTRequired: a2faf4bad4e438ca37b2040cb8f7799baa065c18
RCTTypeSafety: cb09f3e4747b6d18331a15eb05271de7441ca0b3
React: 13109005b5353095c052f26af37413340ccf7a5d
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/mobile",
"version": "3.56.82",
"version": "3.56.97",
"author": "Standard Notes.",
"private": true,
"license": "CC BY-NC-SA 4.0",
+4
View File
@@ -3,6 +3,10 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.47.8](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-21)
**Note:** Version bump only for package @standardnotes/models
## [1.47.7](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-12)
**Note:** Version bump only for package @standardnotes/models
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/models",
"version": "1.47.7",
"version": "1.47.8",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
+60
View File
@@ -3,6 +3,66 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.4.470](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-21)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.469](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-18)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.468](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-18)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.467](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-18)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.466](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-17)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.465](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-17)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.464](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-16)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.463](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-16)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.462](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-16)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.461](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-15)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.460](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-15)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.459](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-14)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.458](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-14)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.457](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-14)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.456](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-12)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.455](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-12)
**Note:** Version bump only for package @standardnotes/releases
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/releases",
"version": "1.4.455",
"version": "1.4.470",
"license": "CC BY-NC-SA 4.0",
"main": "dist/releases.json",
"types": "dist/index.d.ts",
+4
View File
@@ -3,6 +3,10 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.13.38](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-21)
**Note:** Version bump only for package @standardnotes/responses
## [1.13.37](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-11)
**Note:** Version bump only for package @standardnotes/responses
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/responses",
"version": "1.13.37",
"version": "1.13.38",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
@@ -2,7 +2,6 @@ export interface SharedVaultServerHash {
uuid: string
user_uuid: string
file_upload_bytes_used: number
file_upload_bytes_limit: number
created_at_timestamp: number
updated_at_timestamp: number
}
+10
View File
@@ -3,6 +3,16 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.64.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-21)
**Note:** Version bump only for package @standardnotes/services
# [1.64.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-18)
### Features
* Added Super & HTML import options in Import modal. Google Keep notes will now also be imported as Super notes, with attachments if importing from HTML ([#2433](https://github.com/standardnotes/app/issues/2433)) ([ca9895c](https://github.com/standardnotes/app/commit/ca9895cac117aad16cd2f89633d7613ed54b67bf))
## [1.63.38](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-12)
**Note:** Version bump only for package @standardnotes/services
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/services",
"version": "1.63.38",
"version": "1.64.1",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
@@ -460,7 +460,10 @@ export class FilesBackupService
for (const note of notes) {
const tags = this.items.getSortedTagsForItem(note)
const tagNames = tags.map((tag) => this.items.getTagLongTitle(tag))
const text = note.noteType === NoteType.Super ? this.markdownConverter.convertString(note.text, 'md') : note.text
const text =
note.noteType === NoteType.Super
? this.markdownConverter.convertSuperStringToOtherFormat(note.text, 'md')
: note.text
await this.device.savePlaintextNoteBackup(location, note.uuid, note.title, tagNames, text)
}
@@ -107,6 +107,7 @@ export class FileService extends AbstractService implements FilesClientInterface
unencryptedFileSizeForUpload?: number | undefined
moveOperationType?: SharedVaultMoveType
sharedVaultToSharedVaultMoveTargetUuid?: string
sharedVaultOwnerUuid?: string
}): Promise<string | ClientDisplayableError> {
if (params.operation !== ValetTokenOperation.Write && !params.fileUuidRequiredForExistingFiles) {
throw new Error('File UUID is required for for non-write operations')
@@ -114,6 +115,7 @@ export class FileService extends AbstractService implements FilesClientInterface
const valetTokenResponse = await this.sharedVault.createSharedVaultFileValetToken({
sharedVaultUuid: params.sharedVaultUuid,
sharedVaultOwnerUuid: params.sharedVaultUuid,
fileUuid: params.fileUuidRequiredForExistingFiles,
remoteIdentifier: params.remoteIdentifier,
operation: params.operation,
@@ -135,6 +137,7 @@ export class FileService extends AbstractService implements FilesClientInterface
): Promise<void | ClientDisplayableError> {
const valetTokenResult = await this.createSharedVaultValetToken({
sharedVaultUuid: file.shared_vault_uuid ? file.shared_vault_uuid : sharedVault.sharing.sharedVaultUuid,
sharedVaultOwnerUuid: sharedVault.sharing.ownerUserUuid,
remoteIdentifier: file.remoteIdentifier,
operation: ValetTokenOperation.Move,
fileUuidRequiredForExistingFiles: file.uuid,
@@ -186,6 +189,7 @@ export class FileService extends AbstractService implements FilesClientInterface
vault && vault.isSharedVaultListing()
? await this.createSharedVaultValetToken({
sharedVaultUuid: vault.sharing.sharedVaultUuid,
sharedVaultOwnerUuid: vault.sharing.ownerUserUuid,
remoteIdentifier,
operation: ValetTokenOperation.Write,
unencryptedFileSizeForUpload: sizeInBytes,
@@ -13,7 +13,6 @@ describe('SyncLocalVaultsWithRemoteSharedVaults', () => {
uuid: '1-2-3',
user_uuid: '2-3-4',
file_upload_bytes_used: 123,
file_upload_bytes_limit: 10000000,
created_at_timestamp: 123,
updated_at_timestamp: 123,
}] } })
+12
View File
@@ -3,6 +3,18 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [2.202.52](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-21)
**Note:** Version bump only for package @standardnotes/snjs
## [2.202.51](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-18)
**Note:** Version bump only for package @standardnotes/snjs
## [2.202.50](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-17)
**Note:** Version bump only for package @standardnotes/snjs
## [2.202.49](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-12)
**Note:** Version bump only for package @standardnotes/snjs
+12 -4
View File
@@ -318,7 +318,9 @@ export class LegacyApiService
}
signOut(): Promise<HttpResponse<SignOutResponse>> {
return this.httpService.post<SignOutResponse>(Paths.v1.signOut, undefined, this.getSessionAccessToken())
return this.httpService.post<SignOutResponse>(Paths.v1.signOut, undefined, {
authentication: this.getSessionAccessToken(),
})
}
async changeCredentials(parameters: {
@@ -344,7 +346,9 @@ export class LegacyApiService
...parameters.newKeyParams.getPortableValue(),
})
const response = await this.httpService.put<ChangeCredentialsResponse>(path, params, this.getSessionAccessToken())
const response = await this.httpService.put<ChangeCredentialsResponse>(path, params, {
authentication: this.getSessionAccessToken(),
})
this.changing = false
@@ -481,7 +485,11 @@ export class LegacyApiService
return preprocessingError
}
const path = Paths.v1.sessions
const response = await this.httpService.get<SessionListResponse>(path, {}, this.getSessionAccessToken())
const response = await this.httpService.get<SessionListResponse>(
path,
{},
{ authentication: this.getSessionAccessToken() },
)
if (isErrorResponse(response)) {
this.preprocessAuthenticatedErrorResponse(response)
@@ -502,7 +510,7 @@ export class LegacyApiService
const response = await this.httpService.delete<SessionListResponse>(
path,
{ uuid: sessionId },
this.getSessionAccessToken(),
{ authentication: this.getSessionAccessToken() },
)
if (isErrorResponse(response)) {
+2 -2
View File
@@ -35,12 +35,12 @@ describe('features', () => {
describe('new user roles received on api response meta', () => {
it('should save roles and features', async () => {
expect(application.features.onlineRoles).to.have.lengthOf(1)
expect(application.features.onlineRoles).to.have.lengthOf.above(0)
expect(application.features.onlineRoles[0]).to.equal('CORE_USER')
const storedRoles = await application.getValue(StorageKey.UserRoles)
expect(storedRoles).to.have.lengthOf(1)
expect(storedRoles).to.have.lengthOf.above(0)
expect(storedRoles[0]).to.equal('CORE_USER')
})
})
+4
View File
@@ -38,6 +38,10 @@
<script type="module">
import MainRegistry from './TestRegistry/MainRegistry.js'
const urlSearchParams = new URLSearchParams(window.location.search);
const vaultTestsEnabled = urlSearchParams.get('vaults') === 'enabled' ? true : false;
MainRegistry.VaultTests.enabled = MainRegistry.VaultTests.enabled || vaultTestsEnabled;
const loadTest = (fileName) => {
return new Promise((resolve) => {
const script = document.createElement('script');
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/snjs",
"version": "2.202.49",
"version": "2.202.52",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
+14
View File
@@ -3,6 +3,20 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.30.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-21)
**Note:** Version bump only for package @standardnotes/ui-services
# [1.30.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-18)
### Features
* Added Super & HTML import options in Import modal. Google Keep notes will now also be imported as Super notes, with attachments if importing from HTML ([#2433](https://github.com/standardnotes/app/issues/2433)) ([ca9895c](https://github.com/standardnotes/app/commit/ca9895cac117aad16cd2f89633d7613ed54b67bf))
## [1.29.17](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-15)
**Note:** Version bump only for package @standardnotes/ui-services
## [1.29.16](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-12)
**Note:** Version bump only for package @standardnotes/ui-services
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/ui-services",
"version": "1.29.16",
"version": "1.30.1",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
@@ -2,37 +2,56 @@
* @jest-environment jsdom
*/
import { jsonTestData, htmlTestData } from './testData'
import { jsonTextContentData, htmlTestData, jsonListContentData } from './testData'
import { GoogleKeepConverter } from './GoogleKeepConverter'
import { PureCryptoInterface } from '@standardnotes/sncrypto-common'
import { GenerateUuid } from '@standardnotes/services'
import { SuperConverterServiceInterface } from '@standardnotes/snjs'
describe('GoogleKeepConverter', () => {
const crypto = {
generateUUID: () => String(Math.random()),
} as unknown as PureCryptoInterface
const superConverterService: SuperConverterServiceInterface = {
isValidSuperString: () => true,
convertOtherFormatToSuperString: (data: string) => data,
convertSuperStringToOtherFormat: (data: string) => data,
}
const generateUuid = new GenerateUuid(crypto)
it('should parse json data', () => {
const converter = new GoogleKeepConverter(generateUuid)
const converter = new GoogleKeepConverter(superConverterService, generateUuid)
const result = converter.tryParseAsJson(jsonTestData)
const textContent = converter.tryParseAsJson(jsonTextContentData, false)
expect(result).not.toBeNull()
expect(result?.created_at).toBeInstanceOf(Date)
expect(result?.updated_at).toBeInstanceOf(Date)
expect(result?.uuid).not.toBeNull()
expect(result?.content_type).toBe('Note')
expect(result?.content.title).toBe('Testing 1')
expect(result?.content.text).toBe('This is a test.')
expect(result?.content.trashed).toBe(false)
expect(result?.content.archived).toBe(false)
expect(result?.content.pinned).toBe(false)
expect(textContent).not.toBeNull()
expect(textContent?.created_at).toBeInstanceOf(Date)
expect(textContent?.updated_at).toBeInstanceOf(Date)
expect(textContent?.uuid).not.toBeNull()
expect(textContent?.content_type).toBe('Note')
expect(textContent?.content.title).toBe('Testing 1')
expect(textContent?.content.text).toBe('This is a test.')
expect(textContent?.content.trashed).toBe(false)
expect(textContent?.content.archived).toBe(false)
expect(textContent?.content.pinned).toBe(false)
const listContent = converter.tryParseAsJson(jsonListContentData, false)
expect(listContent).not.toBeNull()
expect(listContent?.created_at).toBeInstanceOf(Date)
expect(listContent?.updated_at).toBeInstanceOf(Date)
expect(listContent?.uuid).not.toBeNull()
expect(listContent?.content_type).toBe('Note')
expect(listContent?.content.title).toBe('Testing 1')
expect(listContent?.content.text).toBe('- [ ] Test 1\n- [x] Test 2')
expect(textContent?.content.trashed).toBe(false)
expect(textContent?.content.archived).toBe(false)
expect(textContent?.content.pinned).toBe(false)
})
it('should parse html data', () => {
const converter = new GoogleKeepConverter(generateUuid)
const converter = new GoogleKeepConverter(superConverterService, generateUuid)
const result = converter.tryParseAsHtml(
htmlTestData,
@@ -2,33 +2,48 @@ import { ContentType } from '@standardnotes/domain-core'
import { DecryptedTransferPayload, NoteContent } from '@standardnotes/models'
import { readFileAsText } from '../Utils'
import { GenerateUuid } from '@standardnotes/services'
import { SuperConverterServiceInterface } from '@standardnotes/files'
import { NativeFeatureIdentifier, NoteType } from '@standardnotes/features'
type Content =
| {
textContent: string
}
| {
listContent: {
text: string
isChecked: boolean
}[]
}
type GoogleKeepJsonNote = {
color: string
isTrashed: boolean
isPinned: boolean
isArchived: boolean
textContent: string
title: string
userEditedTimestampUsec: number
}
} & Content
export class GoogleKeepConverter {
constructor(private _generateUuid: GenerateUuid) {}
constructor(
private superConverterService: SuperConverterServiceInterface,
private _generateUuid: GenerateUuid,
) {}
async convertGoogleKeepBackupFileToNote(
file: File,
stripHtml: boolean,
isEntitledToSuper: boolean,
): Promise<DecryptedTransferPayload<NoteContent>> {
const content = await readFileAsText(file)
const possiblePayloadFromJson = this.tryParseAsJson(content)
const possiblePayloadFromJson = this.tryParseAsJson(content, isEntitledToSuper)
if (possiblePayloadFromJson) {
return possiblePayloadFromJson
}
const possiblePayloadFromHtml = this.tryParseAsHtml(content, file, stripHtml)
const possiblePayloadFromHtml = this.tryParseAsHtml(content, file, isEntitledToSuper)
if (possiblePayloadFromHtml) {
return possiblePayloadFromHtml
@@ -37,20 +52,51 @@ export class GoogleKeepConverter {
throw new Error('Could not parse Google Keep backup file')
}
tryParseAsHtml(data: string, file: { name: string }, stripHtml: boolean): DecryptedTransferPayload<NoteContent> {
tryParseAsHtml(
data: string,
file: { name: string },
isEntitledToSuper: boolean,
): DecryptedTransferPayload<NoteContent> {
const rootElement = document.createElement('html')
rootElement.innerHTML = data
const headingElement = rootElement.getElementsByClassName('heading')[0]
const date = new Date(headingElement?.textContent || '')
headingElement?.remove()
const contentElement = rootElement.getElementsByClassName('content')[0]
if (!contentElement) {
throw new Error('Could not parse content. Content element not found.')
}
let content: string | null
// Replace <br> with \n so line breaks get recognised
contentElement.innerHTML = contentElement.innerHTML.replace(/<br>/g, '\n')
// Convert lists to readable plaintext format
// or Super-convertable format
const lists = contentElement.getElementsByTagName('ul')
Array.from(lists).forEach((list) => {
list.setAttribute('__lexicallisttype', 'check')
if (stripHtml) {
const items = list.getElementsByTagName('li')
Array.from(items).forEach((item) => {
const bulletSpan = item.getElementsByClassName('bullet')[0]
bulletSpan?.remove()
const checked = item.classList.contains('checked')
item.setAttribute('aria-checked', checked ? 'true' : 'false')
if (!isEntitledToSuper) {
item.textContent = `- ${checked ? '[x]' : '[ ]'} ${item.textContent?.trim()}\n`
}
})
})
if (!isEntitledToSuper) {
// Replace <br> with \n so line breaks get recognised
contentElement.innerHTML = contentElement.innerHTML.replace(/<br>/g, '\n')
content = contentElement.textContent
} else {
content = contentElement.innerHTML
content = this.superConverterService.convertOtherFormatToSuperString(rootElement.innerHTML, 'html')
}
if (!content) {
@@ -59,8 +105,6 @@ export class GoogleKeepConverter {
const title = rootElement.getElementsByClassName('title')[0]?.textContent || file.name
const date = this.getDateFromGKeepNote(data) || new Date()
return {
created_at: date,
created_at_timestamp: date.getTime(),
@@ -72,35 +116,30 @@ export class GoogleKeepConverter {
title: title,
text: content,
references: [],
...(isEntitledToSuper
? {
noteType: NoteType.Super,
editorIdentifier: NativeFeatureIdentifier.TYPES.SuperEditor,
}
: {}),
},
}
}
getDateFromGKeepNote(note: string) {
const regexWithTitle = /.*(?=<\/div>\n<div class="title">)/
const regexWithoutTitle = /.*(?=<\/div>\n\n<div class="content">)/
const possibleDateStringWithTitle = regexWithTitle.exec(note)?.[0]
const possibleDateStringWithoutTitle = regexWithoutTitle.exec(note)?.[0]
if (possibleDateStringWithTitle) {
const date = new Date(possibleDateStringWithTitle)
if (date.toString() !== 'Invalid Date' && date.toString() !== 'NaN') {
return date
}
}
if (possibleDateStringWithoutTitle) {
const date = new Date(possibleDateStringWithoutTitle)
if (date.toString() !== 'Invalid Date' && date.toString() !== 'NaN') {
return date
}
}
return
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
static isValidGoogleKeepJson(json: any): boolean {
if (typeof json.textContent !== 'string') {
if (typeof json.listContent === 'object' && Array.isArray(json.listContent)) {
return json.listContent.every(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(item: any) => typeof item.text === 'string' && typeof item.isChecked === 'boolean',
)
}
return false
}
return (
typeof json.title === 'string' &&
typeof json.textContent === 'string' &&
typeof json.userEditedTimestampUsec === 'number' &&
typeof json.isArchived === 'boolean' &&
typeof json.isTrashed === 'boolean' &&
@@ -109,13 +148,26 @@ export class GoogleKeepConverter {
)
}
tryParseAsJson(data: string): DecryptedTransferPayload<NoteContent> | null {
tryParseAsJson(data: string, isEntitledToSuper: boolean): DecryptedTransferPayload<NoteContent> | null {
try {
const parsed = JSON.parse(data) as GoogleKeepJsonNote
if (!GoogleKeepConverter.isValidGoogleKeepJson(parsed)) {
return null
}
const date = new Date(parsed.userEditedTimestampUsec / 1000)
let text: string
if ('textContent' in parsed) {
text = parsed.textContent
} else {
text = parsed.listContent
.map((item) => {
return item.isChecked ? `- [x] ${item.text}` : `- [ ] ${item.text}`
})
.join('\n')
}
if (isEntitledToSuper) {
text = this.superConverterService.convertOtherFormatToSuperString(text, 'md')
}
return {
created_at: date,
created_at_timestamp: date.getTime(),
@@ -125,14 +177,21 @@ export class GoogleKeepConverter {
content_type: ContentType.TYPES.Note,
content: {
title: parsed.title,
text: parsed.textContent,
text,
references: [],
archived: Boolean(parsed.isArchived),
trashed: Boolean(parsed.isTrashed),
pinned: Boolean(parsed.isPinned),
...(isEntitledToSuper
? {
noteType: NoteType.Super,
editorIdentifier: NativeFeatureIdentifier.TYPES.SuperEditor,
}
: {}),
},
}
} catch (e) {
console.error(e)
return null
}
}
@@ -1,4 +1,4 @@
const json = {
const jsonWithTextContent = {
color: 'DEFAULT',
isTrashed: false,
isPinned: false,
@@ -8,7 +8,28 @@ const json = {
userEditedTimestampUsec: 1618528050144000,
}
export const jsonTestData = JSON.stringify(json)
export const jsonTextContentData = JSON.stringify(jsonWithTextContent)
const jsonWithListContent = {
color: 'DEFAULT',
isTrashed: false,
isPinned: false,
isArchived: false,
listContent: [
{
text: 'Test 1',
isChecked: false,
},
{
text: 'Test 2',
isChecked: true,
},
],
title: 'Testing 1',
userEditedTimestampUsec: 1618528050144000,
}
export const jsonListContentData = JSON.stringify(jsonWithListContent)
export const htmlTestData = `<?xml version="1.0" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
@@ -0,0 +1,51 @@
import { ContentType } from '@standardnotes/domain-core'
import { NativeFeatureIdentifier, NoteType } from '@standardnotes/features'
import { parseFileName } from '@standardnotes/filepicker'
import { SuperConverterServiceInterface } from '@standardnotes/files'
import { DecryptedTransferPayload, NoteContent } from '@standardnotes/models'
import { GenerateUuid } from '@standardnotes/services'
import { readFileAsText } from '../Utils'
export class HTMLConverter {
constructor(
private superConverterService: SuperConverterServiceInterface,
private _generateUuid: GenerateUuid,
) {}
static isHTMLFile(file: File): boolean {
return file.type === 'text/html'
}
async convertHTMLFileToNote(file: File, isEntitledToSuper: boolean): Promise<DecryptedTransferPayload<NoteContent>> {
const content = await readFileAsText(file)
const { name } = parseFileName(file.name)
const createdAtDate = file.lastModified ? new Date(file.lastModified) : new Date()
const updatedAtDate = file.lastModified ? new Date(file.lastModified) : new Date()
const text = isEntitledToSuper
? this.superConverterService.convertOtherFormatToSuperString(content, 'html')
: content
return {
created_at: createdAtDate,
created_at_timestamp: createdAtDate.getTime(),
updated_at: updatedAtDate,
updated_at_timestamp: updatedAtDate.getTime(),
uuid: this._generateUuid.execute().getValue(),
content_type: ContentType.TYPES.Note,
content: {
title: name,
text,
references: [],
...(isEntitledToSuper
? {
noteType: NoteType.Super,
editorIdentifier: NativeFeatureIdentifier.TYPES.SuperEditor,
}
: {}),
},
}
}
}
+32 -5
View File
@@ -14,8 +14,11 @@ import { PlaintextConverter } from './PlaintextConverter/PlaintextConverter'
import { SimplenoteConverter } from './SimplenoteConverter/SimplenoteConverter'
import { readFileAsText } from './Utils'
import { DecryptedTransferPayload, NoteContent } from '@standardnotes/models'
import { HTMLConverter } from './HTMLConverter/HTMLConverter'
import { SuperConverterServiceInterface } from '@standardnotes/snjs/dist/@types'
import { SuperConverter } from './SuperConverter/SuperConverter'
export type NoteImportType = 'plaintext' | 'evernote' | 'google-keep' | 'simplenote' | 'aegis'
export type NoteImportType = 'plaintext' | 'evernote' | 'google-keep' | 'simplenote' | 'aegis' | 'html' | 'super'
export class Importer {
aegisConverter: AegisToAuthenticatorConverter
@@ -23,21 +26,26 @@ export class Importer {
simplenoteConverter: SimplenoteConverter
plaintextConverter: PlaintextConverter
evernoteConverter: EvernoteConverter
htmlConverter: HTMLConverter
superConverter: SuperConverter
constructor(
private features: FeaturesClientInterface,
private mutator: MutatorClientInterface,
private items: ItemManagerInterface,
private superConverterService: SuperConverterServiceInterface,
_generateUuid: GenerateUuid,
) {
this.aegisConverter = new AegisToAuthenticatorConverter(_generateUuid)
this.googleKeepConverter = new GoogleKeepConverter(_generateUuid)
this.googleKeepConverter = new GoogleKeepConverter(this.superConverterService, _generateUuid)
this.simplenoteConverter = new SimplenoteConverter(_generateUuid)
this.plaintextConverter = new PlaintextConverter(_generateUuid)
this.evernoteConverter = new EvernoteConverter(_generateUuid)
this.htmlConverter = new HTMLConverter(this.superConverterService, _generateUuid)
this.superConverter = new SuperConverter(this.superConverterService, _generateUuid)
}
static detectService = async (file: File): Promise<NoteImportType | null> => {
detectService = async (file: File): Promise<NoteImportType | null> => {
const content = await readFileAsText(file)
const { ext } = parseFileName(file.name)
@@ -64,28 +72,47 @@ export class Importer {
/* empty */
}
if (file.type === 'application/json' && this.superConverterService.isValidSuperString(content)) {
return 'super'
}
if (PlaintextConverter.isValidPlaintextFile(file)) {
return 'plaintext'
}
if (HTMLConverter.isHTMLFile(file)) {
return 'html'
}
return null
}
async getPayloadsFromFile(file: File, type: NoteImportType): Promise<DecryptedTransferPayload[]> {
if (type === 'aegis') {
const isEntitledToSuper =
this.features.getFeatureStatus(
NativeFeatureIdentifier.create(NativeFeatureIdentifier.TYPES.SuperEditor).getValue(),
) === FeatureStatus.Entitled
if (type === 'super') {
if (!isEntitledToSuper) {
throw new Error('Importing Super notes requires a subscription.')
}
return [await this.superConverter.convertSuperFileToNote(file)]
} else if (type === 'aegis') {
const isEntitledToAuthenticator =
this.features.getFeatureStatus(
NativeFeatureIdentifier.create(NativeFeatureIdentifier.TYPES.TokenVaultEditor).getValue(),
) === FeatureStatus.Entitled
return [await this.aegisConverter.convertAegisBackupFileToNote(file, isEntitledToAuthenticator)]
} else if (type === 'google-keep') {
return [await this.googleKeepConverter.convertGoogleKeepBackupFileToNote(file, true)]
return [await this.googleKeepConverter.convertGoogleKeepBackupFileToNote(file, isEntitledToSuper)]
} else if (type === 'simplenote') {
return await this.simplenoteConverter.convertSimplenoteBackupFileToNotes(file)
} else if (type === 'evernote') {
return await this.evernoteConverter.convertENEXFileToNotesAndTags(file, false)
} else if (type === 'plaintext') {
return [await this.plaintextConverter.convertPlaintextFileToNote(file)]
} else if (type === 'html') {
return [await this.htmlConverter.convertHTMLFileToNote(file, isEntitledToSuper)]
}
return []
@@ -0,0 +1,43 @@
import { SuperConverterServiceInterface } from '@standardnotes/files'
import { DecryptedTransferPayload, NoteContent } from '@standardnotes/models'
import { GenerateUuid } from '@standardnotes/services'
import { readFileAsText } from '../Utils'
import { parseFileName } from '@standardnotes/filepicker'
import { ContentType } from '@standardnotes/domain-core'
import { NativeFeatureIdentifier, NoteType } from '@standardnotes/features'
export class SuperConverter {
constructor(
private converterService: SuperConverterServiceInterface,
private _generateUuid: GenerateUuid,
) {}
async convertSuperFileToNote(file: File): Promise<DecryptedTransferPayload<NoteContent>> {
const content = await readFileAsText(file)
if (!this.converterService.isValidSuperString(content)) {
throw new Error('Content is not valid Super JSON')
}
const { name } = parseFileName(file.name)
const createdAtDate = file.lastModified ? new Date(file.lastModified) : new Date()
const updatedAtDate = file.lastModified ? new Date(file.lastModified) : new Date()
return {
created_at: createdAtDate,
created_at_timestamp: createdAtDate.getTime(),
updated_at: updatedAtDate,
updated_at_timestamp: updatedAtDate.getTime(),
uuid: this._generateUuid.execute().getValue(),
content_type: ContentType.TYPES.Note,
content: {
title: name,
text: content,
references: [],
noteType: NoteType.Super,
editorIdentifier: NativeFeatureIdentifier.TYPES.SuperEditor,
},
}
}
}
@@ -337,10 +337,11 @@ export class ThemeManager extends AbstractUIService {
link.onload = () => {
this.syncThemeColorMetadata()
if (this.application.isNativeMobileWeb() && !theme.layerable) {
const packageInfo = theme.featureDescription
if (this.application.isNativeMobileWeb()) {
setTimeout(() => {
this.application.mobileDevice.handleThemeSchemeChange(packageInfo.isDark ?? false, this.getBackgroundColor())
const backgroundColorString = this.getBackgroundColor()
const backgroundColor = new Color(backgroundColorString)
this.application.mobileDevice.handleThemeSchemeChange(backgroundColor.isDark(), backgroundColorString)
})
}
+69
View File
@@ -3,6 +3,75 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [3.171.3](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-21)
**Note:** Version bump only for package @standardnotes/web
## [3.171.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-18)
**Note:** Version bump only for package @standardnotes/web
## [3.171.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-18)
### Bug Fixes
* Fixed issue where dragging a list item with a link in Super would only re-order the link ([d794847](https://github.com/standardnotes/app/commit/d79484739b2a324f09cb821c39f402f8c65d477e))
# [3.171.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-18)
### Features
* Add toggle to disable creating a new tag on import ([f26ad41](https://github.com/standardnotes/app/commit/f26ad410e2888cb90e34c25d19d746f54db1e53e))
* Added Super & HTML import options in Import modal. Google Keep notes will now also be imported as Super notes, with attachments if importing from HTML ([#2433](https://github.com/standardnotes/app/issues/2433)) ([ca9895c](https://github.com/standardnotes/app/commit/ca9895cac117aad16cd2f89633d7613ed54b67bf))
## [3.170.4](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-17)
**Note:** Version bump only for package @standardnotes/web
## [3.170.3](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-17)
**Note:** Version bump only for package @standardnotes/web
## [3.170.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-16)
**Note:** Version bump only for package @standardnotes/web
## [3.170.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-16)
**Note:** Version bump only for package @standardnotes/web
# [3.170.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-16)
### Features
* Super formatting toolbar on mobile now shows whether an option is active in the selection, and also shows hints when an option is long-pressed ([#2432](https://github.com/standardnotes/app/issues/2432)) ([77f72ff](https://github.com/standardnotes/app/commit/77f72ff7b67a5dab502d1db95dc512e3bf348541))
## [3.169.35](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-15)
**Note:** Version bump only for package @standardnotes/web
## [3.169.34](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-15)
**Note:** Version bump only for package @standardnotes/web
## [3.169.33](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-14)
**Note:** Version bump only for package @standardnotes/web
## [3.169.32](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-14)
**Note:** Version bump only for package @standardnotes/web
## [3.169.31](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-14)
**Note:** Version bump only for package @standardnotes/web
## [3.169.30](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-12)
### Bug Fixes
* Fixed issue where note context menu would not open if right-clicking multiple times ([5af0ff8](https://github.com/standardnotes/app/commit/5af0ff8f2eba32bce46f4e2359e9198f86bf7f4e))
## [3.169.29](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-12)
**Note:** Version bump only for package @standardnotes/web
+179
View File
@@ -1,5 +1,184 @@
{
"versions": [
{
"version": "3.171.3",
"title": "[3.171.3](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-21)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.171.2",
"title": "[3.171.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-18)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.171.1",
"title": "[3.171.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-18)",
"date": null,
"body": "### Bug Fixes\n\n* Fixed issue where dragging a list item with a link in Super would only re-order the link ([d794847](https://github.com/standardnotes/app/commit/d79484739b2a324f09cb821c39f402f8c65d477e))",
"parsed": {
"_": [
"Fixed issue where dragging a list item with a link in Super would only re-order the link (d794847)"
],
"Bug Fixes": [
"Fixed issue where dragging a list item with a link in Super would only re-order the link (d794847)"
]
}
},
{
"version": "3.171.0",
"title": "[3.171.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-18)",
"date": null,
"body": "### Features\n\n* Add toggle to disable creating a new tag on import ([f26ad41](https://github.com/standardnotes/app/commit/f26ad410e2888cb90e34c25d19d746f54db1e53e))\n* Added Super & HTML import options in Import modal. Google Keep notes will now also be imported as Super notes, with attachments if importing from HTML ([#2433](https://github.com/standardnotes/app/issues/2433)) ([ca9895c](https://github.com/standardnotes/app/commit/ca9895cac117aad16cd2f89633d7613ed54b67bf))",
"parsed": {
"_": [
"Add toggle to disable creating a new tag on import (f26ad41)",
"Added Super & HTML import options in Import modal. Google Keep notes will now also be imported as Super notes, with attachments if importing from HTML (#2433) (ca9895c)"
],
"Features": [
"Add toggle to disable creating a new tag on import (f26ad41)",
"Added Super & HTML import options in Import modal. Google Keep notes will now also be imported as Super notes, with attachments if importing from HTML (#2433) (ca9895c)"
]
}
},
{
"version": "3.170.4",
"title": "[3.170.4](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-17)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.170.3",
"title": "[3.170.3](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-17)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.170.2",
"title": "[3.170.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-16)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.170.1",
"title": "[3.170.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-16)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.170.0",
"title": "[3.170.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-16)",
"date": null,
"body": "### Features\n\n* Super formatting toolbar on mobile now shows whether an option is active in the selection, and also shows hints when an option is long-pressed ([#2432](https://github.com/standardnotes/app/issues/2432)) ([77f72ff](https://github.com/standardnotes/app/commit/77f72ff7b67a5dab502d1db95dc512e3bf348541))",
"parsed": {
"_": [
"Super formatting toolbar on mobile now shows whether an option is active in the selection, and also shows hints when an option is long-pressed (#2432) (77f72ff)"
],
"Features": [
"Super formatting toolbar on mobile now shows whether an option is active in the selection, and also shows hints when an option is long-pressed (#2432) (77f72ff)"
]
}
},
{
"version": "3.169.35",
"title": "[3.169.35](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-15)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.169.34",
"title": "[3.169.34](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-15)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.169.33",
"title": "[3.169.33](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-14)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.169.32",
"title": "[3.169.32](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-14)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.169.31",
"title": "[3.169.31](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-14)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.169.30",
"title": "[3.169.30](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-12)",
"date": null,
"body": "### Bug Fixes\n\n* Fixed issue where note context menu would not open if right-clicking multiple times ([5af0ff8](https://github.com/standardnotes/app/commit/5af0ff8f2eba32bce46f4e2359e9198f86bf7f4e))",
"parsed": {
"_": [
"Fixed issue where note context menu would not open if right-clicking multiple times (5af0ff8)"
],
"Bug Fixes": [
"Fixed issue where note context menu would not open if right-clicking multiple times (5af0ff8)"
]
}
},
{
"version": "3.169.29",
"title": "[3.169.29](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-08-12)",
+3 -3
View File
@@ -1,9 +1,9 @@
{
"name": "@standardnotes/web",
"version": "3.169.29",
"version": "3.171.3",
"license": "CC BY-NC-SA 4.0",
"main": "dist/app.js",
"author": "Standard Notes.",
"author": "Standard Notes",
"private": true,
"files": [
"dist"
@@ -51,7 +51,7 @@
"@standardnotes/sncrypto-web": "workspace:*",
"@standardnotes/snjs": "workspace:*",
"@standardnotes/solarized-dark-theme": "^1.4.6",
"@standardnotes/spreadsheets": "^1.8.0",
"@standardnotes/spreadsheets": "^1.8.1",
"@standardnotes/styles": "workspace:*",
"@standardnotes/titanium-theme": "^1.4.7",
"@standardnotes/toast": "workspace:*",
@@ -7,6 +7,7 @@ export const Web_TYPES = {
AutolockService: Symbol.for('AutolockService'),
ChangelogService: Symbol.for('ChangelogService'),
DesktopManager: Symbol.for('DesktopManager'),
SuperConverter: Symbol.for('SuperConverter'),
Importer: Symbol.for('Importer'),
ItemGroupController: Symbol.for('ItemGroupController'),
KeyboardService: Symbol.for('KeyboardService'),
@@ -48,13 +48,24 @@ import { PanesForLayout } from '../UseCase/PanesForLayout'
import { LoadPurchaseFlowUrl } from '../UseCase/LoadPurchaseFlowUrl'
import { GetPurchaseFlowUrl } from '../UseCase/GetPurchaseFlowUrl'
import { OpenSubscriptionDashboard } from '../UseCase/OpenSubscriptionDashboard'
import { HeadlessSuperConverter } from '@/Components/SuperEditor/Tools/HeadlessSuperConverter'
export class WebDependencies extends DependencyContainer {
constructor(private application: WebApplicationInterface) {
super()
this.bind(Web_TYPES.SuperConverter, () => {
return new HeadlessSuperConverter()
})
this.bind(Web_TYPES.Importer, () => {
return new Importer(application.features, application.mutator, application.items, application.generateUuid)
return new Importer(
application.features,
application.mutator,
application.items,
this.get<HeadlessSuperConverter>(Web_TYPES.SuperConverter),
application.generateUuid,
)
})
this.bind(Web_TYPES.IsNativeIOS, () => {
@@ -32,7 +32,7 @@ const WorkspaceSwitcherOption: FunctionComponent<Props> = ({ mainApplicationGrou
<Popover
title="Switch workspace"
align="end"
anchorElement={buttonRef.current}
anchorElement={buttonRef}
className="py-2"
open={isOpen}
side="right"
@@ -27,7 +27,7 @@ const LockscreenWorkspaceSwitcher: FunctionComponent<Props> = ({ mainApplication
<Popover
title="Switch workspace"
align="center"
anchorElement={buttonRef.current}
anchorElement={buttonRef}
className="py-2"
open={isOpen}
overrideZIndex="z-modal"
@@ -77,7 +77,7 @@ const ChangeEditorButton: FunctionComponent<Props> = ({ noteViewController, onCl
title="Change note type"
togglePopover={toggleMenu}
disableClickOutside={isClickOutsideDisabled}
anchorElement={buttonRef.current}
anchorElement={buttonRef}
open={isOpen}
className="pt-2 md:pt-0"
>
@@ -23,7 +23,7 @@ const ChangeMultipleButton = ({ application, notesController }: Props) => {
title="Change note type"
togglePopover={toggleMenu}
disableClickOutside={disableClickOutside}
anchorElement={changeButtonRef.current}
anchorElement={changeButtonRef}
open={isChangeMenuOpen}
className="pt-2 md:pt-0"
>
@@ -67,47 +67,49 @@ const AddItemMenuButton = ({
<Icon type="add" size="custom" className="h-5 w-5" />
</button>
</StyledTooltip>
<Popover
title="Add item"
open={canShowMenu && isMenuOpen}
anchorElement={addItemButtonRef.current}
togglePopover={() => {
setIsMenuOpen((isOpen) => !isOpen)
}}
side="bottom"
align="center"
className="py-2"
>
<Menu a11yLabel={'test'} isOpen={isMenuOpen}>
<MenuItem
onClick={() => {
addNewItem()
setIsMenuOpen(false)
}}
>
<Icon type="add" className="mr-2" />
{addButtonLabel}
</MenuItem>
<MenuItem
onClick={async () => {
setCaptureType('photo')
setIsMenuOpen(false)
}}
>
<Icon type="camera" className="mr-2" />
Take photo
</MenuItem>
<MenuItem
onClick={async () => {
setCaptureType('video')
setIsMenuOpen(false)
}}
>
<Icon type="camera" className="mr-2" />
Record video
</MenuItem>
</Menu>
</Popover>
{canShowMenu && (
<Popover
title="Add item"
open={isMenuOpen}
anchorElement={addItemButtonRef}
togglePopover={() => {
setIsMenuOpen((isOpen) => !isOpen)
}}
side="bottom"
align="center"
className="py-2"
>
<Menu a11yLabel={'test'} isOpen={isMenuOpen}>
<MenuItem
onClick={() => {
addNewItem()
setIsMenuOpen(false)
}}
>
<Icon type="add" className="mr-2" />
{addButtonLabel}
</MenuItem>
<MenuItem
onClick={async () => {
setCaptureType('photo')
setIsMenuOpen(false)
}}
>
<Icon type="camera" className="mr-2" />
Take photo
</MenuItem>
<MenuItem
onClick={async () => {
setCaptureType('video')
setIsMenuOpen(false)
}}
>
<Icon type="camera" className="mr-2" />
Record video
</MenuItem>
</Menu>
</Popover>
)}
<ModalOverlay isOpen={captureType === 'photo'} close={closeCaptureModal}>
<PhotoCaptureModal filesController={filesController} close={closeCaptureModal} />
</ModalOverlay>
@@ -116,7 +116,7 @@ const ContentListHeader = ({
/>
<Popover
open={showDisplayOptionsMenu}
anchorElement={displayOptionsButtonRef.current}
anchorElement={displayOptionsButtonRef}
togglePopover={toggleDisplayOptionsMenu}
align="start"
className="py-2"
@@ -43,12 +43,10 @@ const NoteListItem: FunctionComponent<DisplayableListItemProps<SNNote>> = ({
const hasFiles = application.items.itemsReferencingItem(item).filter(isFile).length > 0
const openNoteContextMenu = (posX: number, posY: number) => {
notesController.setContextMenuOpen(false)
notesController.setContextMenuClickLocation({
x: posX,
y: posY,
})
notesController.reloadContextMenuLayout()
notesController.setContextMenuOpen(true)
}
@@ -67,7 +67,7 @@ const ContextMenuCell = ({ items }: { items: DecryptedItemInterface[] }) => {
<Popover
title="File options"
open={contextMenuVisible}
anchorElement={anchorElementRef.current}
anchorElement={anchorElementRef}
togglePopover={() => {
setContextMenuVisible(false)
}}
@@ -120,7 +120,7 @@ const ItemLinksCell = ({ item }: { item: DecryptedItemInterface }) => {
<Popover
title="Linked items"
open={contextMenuVisible}
anchorElement={anchorElementRef.current}
anchorElement={anchorElementRef}
togglePopover={() => {
setContextMenuVisible(false)
}}
@@ -19,13 +19,7 @@ const FilesOptionsPanel = ({ itemListController }: Props) => {
return (
<>
<RoundIconButton label="File options menu" onClick={toggleMenu} ref={buttonRef} icon="more" />
<Popover
title="File options"
togglePopover={toggleMenu}
anchorElement={buttonRef.current}
open={isOpen}
className="py-2"
>
<Popover title="File options" togglePopover={toggleMenu} anchorElement={buttonRef} open={isOpen} className="py-2">
<Menu a11yLabel="File options panel" isOpen={isOpen}>
<FileMenuOptions
selectedFiles={itemListController.selectedFiles}
@@ -212,7 +212,7 @@ const FilePreviewModal = observer(({ application }: Props) => {
<Popover
title="File options"
open={showOptionsMenu}
anchorElement={menuButtonRef.current}
anchorElement={menuButtonRef}
togglePopover={closeOptionsMenu}
side="bottom"
align="start"
@@ -100,7 +100,7 @@ const FileViewWithoutProtection = ({ application, file }: FileViewProps) => {
title="Details"
open={isFileInfoPanelOpen}
togglePopover={toggleFileInfoPanel}
anchorElement={fileInfoButtonRef.current}
anchorElement={fileInfoButtonRef}
side="bottom"
align="center"
>
@@ -36,7 +36,7 @@ const AccountMenuButton = ({ hasError, controller, mainApplicationGroup, onClick
</StyledTooltip>
<Popover
title="Account"
anchorElement={buttonRef.current}
anchorElement={buttonRef}
open={isOpen}
togglePopover={toggleMenu}
side="top"
@@ -51,7 +51,7 @@ const QuickSettingsButton = ({ application, isMobileNavigation = false }: Props)
<Popover
title="Quick settings"
togglePopover={toggleMenu}
anchorElement={buttonRef.current}
anchorElement={buttonRef}
open={isOpen}
side="top"
align="start"
@@ -56,7 +56,7 @@ const VaultSelectionButton = ({ isMobileNavigation = false }: { isMobileNavigati
<Popover
title="Vault options"
togglePopover={toggleMenu}
anchorElement={buttonRef.current}
anchorElement={buttonRef}
open={isOpen}
side="top"
align="start"
@@ -6,11 +6,22 @@ import Modal, { ModalAction } from '../Modal/Modal'
import ModalOverlay from '../Modal/ModalOverlay'
import { ImportModalController } from '@/Controllers/ImportModalController'
import { useApplication } from '../ApplicationProvider'
import Switch from '../Switch/Switch'
const ImportModal = ({ importModalController }: { importModalController: ImportModalController }) => {
const application = useApplication()
const { files, setFiles, updateFile, removeFile, parseAndImport, isVisible, close } = importModalController
const {
files,
setFiles,
shouldCreateTag,
setShouldCreateTag,
updateFile,
removeFile,
parseAndImport,
isVisible,
close,
} = importModalController
const isReadyToImport = files.length > 0 && files.every((file) => file.status === 'ready')
const importSuccessOrError =
@@ -54,6 +65,12 @@ const ImportModal = ({ importModalController }: { importModalController: ImportM
</div>
)}
</div>
{files.length > 0 && (
<label className="py-2 px-4 flex items-center gap-2 border-t border-border">
<Switch checked={shouldCreateTag} onChange={setShouldCreateTag} />
<span className="text-sm">Create tag with all imported notes</span>
</label>
)}
</Modal>
</ModalOverlay>
)
@@ -11,6 +11,8 @@ const NoteImportTypeColors: Record<NoteImportType, string> = {
'google-keep': 'bg-[#fbbd00] text-[#000]',
aegis: 'bg-[#0d47a1] text-default',
plaintext: 'bg-default border border-border',
html: 'bg-accessory-tint-2',
super: 'bg-accessory-tint-1 text-accessory-tint-1',
}
const NoteImportTypeIcons: Record<NoteImportType, string> = {
@@ -19,6 +21,8 @@ const NoteImportTypeIcons: Record<NoteImportType, string> = {
'google-keep': 'gkeep',
aegis: 'aegis',
plaintext: 'plain-text',
html: 'rich-text',
super: 'file-doc',
}
const ImportModalFileItem = ({
@@ -53,13 +57,13 @@ const ImportModalFileItem = ({
useEffect(() => {
const detect = async () => {
const detectedService = await Importer.detectService(file.file)
const detectedService = await importer.detectService(file.file)
void setFileService(detectedService)
}
if (file.service === undefined) {
void detect()
}
}, [file, setFileService])
}, [file, importer, setFileService])
const notePayloads =
file.status === 'ready' && file.payloads
@@ -5,12 +5,17 @@ import { observer } from 'mobx-react-lite'
import { useCallback } from 'react'
import Button from '../Button/Button'
import Icon from '../Icon/Icon'
import { useApplication } from '../ApplicationProvider'
import { FeatureStatus, NativeFeatureIdentifier } from '@standardnotes/snjs'
import { FeatureName } from '@/Controllers/FeatureName'
type Props = {
setFiles: ImportModalController['setFiles']
}
const ImportModalInitialPage = ({ setFiles }: Props) => {
const application = useApplication()
const selectFiles = useCallback(
async (service?: NoteImportType) => {
const files = await ClassicFileReader.selectFiles()
@@ -38,41 +43,46 @@ const ImportModalInitialPage = ({ setFiles }: Props) => {
</button>
<div className="text-center my-4 w-full">or import from:</div>
<div className="flex flex-wrap items-center justify-center gap-4">
<Button
className="flex items-center bg-[#14cc45] !py-2 text-[#000]"
primary
onClick={() => selectFiles('evernote')}
>
<Icon type="evernote" className="mr-2" />
<Button className="flex items-center !py-2" onClick={() => selectFiles('evernote')}>
<Icon type="evernote" className="text-[#14cc45] mr-2" />
Evernote
</Button>
<Button
className="flex items-center bg-[#fbbd00] !py-2 text-[#000]"
primary
onClick={() => selectFiles('google-keep')}
>
<Icon type="gkeep" className="mr-2" />
<Button className="flex items-center !py-2" onClick={() => selectFiles('google-keep')}>
<Icon type="gkeep" className="text-[#fbbd00] mr-2" />
Google Keep
</Button>
<Button className="flex items-center bg-[#3360cc] !py-2" primary onClick={() => selectFiles('simplenote')}>
<Icon type="simplenote" className="mr-2" />
<Button className="flex items-center !py-2" onClick={() => selectFiles('simplenote')}>
<Icon type="simplenote" className="text-[#3360cc] mr-2" />
Simplenote
</Button>
<Button className="flex items-center bg-[#0d47a1] !py-2" primary onClick={() => selectFiles('aegis')}>
<Icon type="aegis" className="mr-2" />
Aegis Authenticator
<Button className="flex items-center !py-2" onClick={() => selectFiles('aegis')}>
<Icon type="aegis" className="bg-[#0d47a1] text-[#fff] rounded mr-2 p-1" size="normal" />
Aegis
</Button>
<Button className="flex items-center bg-info !py-2" onClick={() => selectFiles('plaintext')} primary>
<Icon type="plain-text" className="mr-2" />
Plaintext
<Button className="flex items-center !py-2" onClick={() => selectFiles('plaintext')}>
<Icon type="plain-text" className="text-info mr-2" />
Plaintext / Markdown
</Button>
<Button className="flex items-center !py-2" onClick={() => selectFiles('html')}>
<Icon type="rich-text" className="text-accessory-tint-2 mr-2" />
HTML
</Button>
<Button
className="flex items-center bg-accessory-tint-4 !py-2"
primary
onClick={() => selectFiles('plaintext')}
className="flex items-center !py-2"
onClick={() => {
const isEntitledToSuper =
application.features.getFeatureStatus(
NativeFeatureIdentifier.create(NativeFeatureIdentifier.TYPES.SuperEditor).getValue(),
) === FeatureStatus.Entitled
if (!isEntitledToSuper) {
application.showPremiumModal(FeatureName.Super)
return
}
selectFiles('super').catch(console.error)
}}
>
<Icon type="markdown" className="mr-2" />
Markdown
<Icon type="file-doc" className="text-accessory-tint-1 mr-2" />
Super (JSON)
</Button>
</div>
</>
@@ -32,7 +32,7 @@ const LinkedItemsButton = ({ linkingController, onClickPreprocessing }: Props) =
<Popover
title="Linked items"
togglePopover={toggleMenu}
anchorElement={buttonRef.current}
anchorElement={buttonRef}
open={isLinkingPanelOpen}
className="pb-2"
>
@@ -101,7 +101,7 @@ export const LinkedItemsSectionItem = ({
title="Options"
open={isMenuOpen}
togglePopover={toggleMenu}
anchorElement={menuButtonRef.current}
anchorElement={menuButtonRef}
side="bottom"
align="center"
className="py-2"
@@ -8,6 +8,7 @@ import {
MouseEventHandler,
ReactNode,
useCallback,
useRef,
useState,
} from 'react'
import Icon from '../Icon/Icon'
@@ -27,12 +28,12 @@ const Tooltip = ({ text }: { text: string }) => {
[visible],
)
const [anchorElement, setAnchorElement] = useState<HTMLDivElement | null>(null)
const anchorElement = useRef(null)
return (
<div className="relative">
<div
ref={setAnchorElement}
ref={anchorElement}
className={classNames('peer z-0 flex h-5 w-5 items-center justify-center rounded-full')}
onClick={onClickMobile}
onMouseEnter={() => setVisible(true)}
@@ -131,7 +131,7 @@ const Modal = ({
<Popover
title="Advanced"
open={showAdvanced}
anchorElement={advancedOptionRef.current}
anchorElement={advancedOptionRef}
disableMobileFullscreenTakeover={true}
togglePopover={() => setShowAdvanced((show) => !show)}
align="start"
@@ -78,7 +78,8 @@ const ModalOverlay = forwardRef(
<Dialog
tabIndex={0}
className={classNames(
'pointer-events-auto m-0 flex h-full w-full flex-col border-[--popover-border-color] bg-default md:bg-[--popover-background-color] md:[backdrop-filter:var(--popover-backdrop-filter)] p-0 md:h-auto md:max-h-[85vh] md:w-160 md:rounded md:border md:shadow-main',
'z-[1] pointer-events-auto m-0 flex h-full w-full flex-col border-[--popover-border-color] bg-default md:bg-[--popover-background-color] md:[backdrop-filter:var(--popover-backdrop-filter)] p-0 md:h-auto md:max-h-[85vh] md:w-160 md:rounded md:border md:shadow-main',
'focus-visible:shadow-none focus-visible:outline-none',
className,
)}
backdrop={
@@ -31,14 +31,14 @@ export const DiffView = ({
const firstTitle = firstNote.title
const firstText =
firstNote.noteType === NoteType.Super && convertSuperToMarkdown
? new HeadlessSuperConverter().convertString(firstNote.text, 'md')
? new HeadlessSuperConverter().convertSuperStringToOtherFormat(firstNote.text, 'md')
: firstNote.text
const secondNote = selectedNotes[1]
const secondTitle = secondNote.title
const secondText =
secondNote.noteType === NoteType.Super && convertSuperToMarkdown
? new HeadlessSuperConverter().convertString(secondNote.text, 'md')
? new HeadlessSuperConverter().convertSuperStringToOtherFormat(secondNote.text, 'md')
: secondNote.text
const titleDiff = fastdiff(firstTitle, secondTitle, undefined, true)
@@ -67,7 +67,7 @@ const AddTagOption: FunctionComponent<Props> = ({
<Popover
title="Add tag"
togglePopover={toggleMenu}
anchorElement={buttonRef.current}
anchorElement={buttonRef}
open={isOpen}
side="right"
align="start"
@@ -52,7 +52,7 @@ const ChangeEditorOption: FunctionComponent<ChangeEditorOptionProps> = ({ applic
<Popover
title="Change note type"
align="start"
anchorElement={buttonRef.current}
anchorElement={buttonRef}
className="pt-2 md:pt-0"
open={isOpen}
side="right"
@@ -50,7 +50,7 @@ const ListedActionsOption: FunctionComponent<Props> = ({ application, note, icon
<Popover
title="Listed"
togglePopover={toggleMenu}
anchorElement={buttonRef.current}
anchorElement={buttonRef}
open={isOpen}
side="right"
align="end"
@@ -35,7 +35,7 @@ const NotesOptionsPanel = ({ notesController, onClickPreprocessing }: Props) =>
title="Note options"
disableClickOutside={disableClickOutside}
togglePopover={toggleMenu}
anchorElement={buttonRef.current}
anchorElement={buttonRef}
open={isOpen}
className="select-none pt-2"
>
@@ -63,13 +63,19 @@ const getStylesFromRect = (options: {
side: PopoverSide
align: PopoverAlignment
disableMobileFullscreenTakeover?: boolean
disableApplyingMobileWidth?: boolean
maxHeight?: number | 'none'
offset?: number
}): PopoverCSSProperties => {
const { rect, disableMobileFullscreenTakeover = false, maxHeight = 'none' } = options
const {
rect,
disableMobileFullscreenTakeover = false,
disableApplyingMobileWidth = false,
maxHeight = 'none',
} = options
const canApplyMaxHeight = maxHeight !== 'none' && (!isMobileScreen() || disableMobileFullscreenTakeover)
const shouldApplyMobileWidth = isMobileScreen() && disableMobileFullscreenTakeover
const shouldApplyMobileWidth = isMobileScreen() && disableMobileFullscreenTakeover && !disableApplyingMobileWidth
const marginForMobile = percentOf(10, window.innerWidth)
return {
@@ -96,6 +102,7 @@ type Options = {
popoverRect?: DOMRect
side: PopoverSide
disableMobileFullscreenTakeover?: boolean
disableApplyingMobileWidth?: boolean
maxHeightFunction?: (calculatedMaxHeight: number) => number | 'none'
offset?: number
}
@@ -107,6 +114,7 @@ export const getPositionedPopoverStyles = ({
popoverRect,
side,
disableMobileFullscreenTakeover,
disableApplyingMobileWidth,
maxHeightFunction,
offset,
}: Options): PopoverCSSProperties | null => {
@@ -159,6 +167,7 @@ export const getPositionedPopoverStyles = ({
side: sideWithLessOverflows,
align: finalAlignment,
disableMobileFullscreenTakeover,
disableApplyingMobileWidth,
maxHeight,
offset,
})
@@ -52,6 +52,7 @@ const MobilePopoverContent = ({
<div
ref={mergeRefs([setPopoverElement, addCloseMethod])}
className="fixed left-0 top-0 z-modal flex h-full w-full flex-col bg-default pb-safe-bottom pt-safe-top"
id={'popover/' + id}
data-popover={id}
data-mobile-popover
>
@@ -1,7 +1,6 @@
import { MutuallyExclusiveMediaQueryBreakpoints, useMediaQuery } from '@/Hooks/useMediaQuery'
import { useAndroidBackHandler } from '@/NativeMobileWeb/useAndroidBackHandler'
import { UuidGenerator } from '@standardnotes/snjs'
import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'
import { createContext, useCallback, useContext, useEffect, useId, useMemo, useState } from 'react'
import MobilePopoverContent from './MobilePopoverContent'
import PositionedPopoverContent from './PositionedPopoverContent'
import { PopoverProps } from './Types'
@@ -62,11 +61,11 @@ const PositionedPopoverContentWithAnimation = (
}
const Popover = (props: PopoverProps) => {
const popoverId = useRef(UuidGenerator.GenerateUuid())
const popoverId = useId()
const addAndroidBackHandler = useAndroidBackHandler()
useRegisterPopoverToParent(popoverId.current)
useRegisterPopoverToParent(popoverId)
const [childPopovers, setChildPopovers] = useState<Set<string>>(new Set())
@@ -106,6 +105,27 @@ const Popover = (props: PopoverProps) => {
}
}, [addAndroidBackHandler, props, props.open])
useEffect(() => {
const anchorElement =
props.anchorElement && 'current' in props.anchorElement ? props.anchorElement.current : props.anchorElement
if (anchorElement) {
anchorElement.setAttribute('aria-haspopup', 'true')
if (props.open) {
anchorElement.setAttribute('aria-expanded', 'true')
} else {
anchorElement.removeAttribute('aria-expanded')
}
}
return () => {
if (anchorElement) {
anchorElement.removeAttribute('aria-haspopup')
anchorElement.removeAttribute('aria-expanded')
}
}
}, [props.anchorElement, props.open])
const isMobileScreen = useMediaQuery(MutuallyExclusiveMediaQueryBreakpoints.sm)
if (isMobileScreen && !props.disableMobileFullscreenTakeover) {
@@ -117,7 +137,7 @@ const Popover = (props: PopoverProps) => {
}}
title={props.title}
className={props.className}
id={popoverId.current}
id={popoverId}
>
{props.children}
</MobilePopoverContent>
@@ -126,7 +146,7 @@ const Popover = (props: PopoverProps) => {
return (
<PopoverContext.Provider value={contextValue}>
<PositionedPopoverContentWithAnimation {...props} childPopovers={childPopovers} id={popoverId.current} />
<PositionedPopoverContentWithAnimation {...props} childPopovers={childPopovers} id={popoverId} />
</PopoverContext.Provider>
)
}
@@ -1,7 +1,7 @@
import { useDocumentRect } from '@/Hooks/useDocumentRect'
import { useAutoElementRect } from '@/Hooks/useElementRect'
import { classNames } from '@standardnotes/utils'
import { CSSProperties, useCallback, useLayoutEffect, useState } from 'react'
import { CSSProperties, useCallback, useLayoutEffect, useRef, useState } from 'react'
import Portal from '../Portal/Portal'
import { PopoverCSSProperties, getPositionedPopoverStyles } from './GetPositionedPopoverStyles'
import { PopoverContentProps } from './Types'
@@ -35,7 +35,8 @@ const PositionedPopoverContent = ({
}: PopoverContentProps) => {
const [popoverElement, setPopoverElement] = useState<HTMLDivElement | null>(null)
const popoverRect = useAutoElementRect(popoverElement)
const anchorElementRect = useAutoElementRect(anchorElement, {
const resolvedAnchorElement = anchorElement && 'current' in anchorElement ? anchorElement.current : anchorElement
const anchorElementRect = useAutoElementRect(resolvedAnchorElement, {
updateOnWindowResize: true,
})
const anchorPointRect = DOMRect.fromRect({
@@ -75,7 +76,7 @@ const PositionedPopoverContent = ({
usePopoverCloseOnClickOutside({
popoverElement,
anchorElement,
anchorElement: resolvedAnchorElement,
togglePopover,
childPopovers,
hideOnClickInModal,
@@ -84,17 +85,13 @@ const PositionedPopoverContent = ({
useDisableBodyScrollOnMobile()
const correctInitialScrollForOverflowedContent = useCallback(() => {
if (popoverElement) {
setTimeout(() => {
popoverElement.scrollTop = 0
}, 10)
const canCorrectInitialScroll = useRef(true)
const correctInitialScrollForOverflowedContent = useCallback((element: HTMLElement | null) => {
if (element && element.scrollTop > 0 && canCorrectInitialScroll.current) {
element.scrollTop = 0
canCorrectInitialScroll.current = false
}
}, [popoverElement])
useLayoutEffect(() => {
correctInitialScrollForOverflowedContent()
}, [popoverElement, correctInitialScrollForOverflowedContent])
}, [])
const addCloseMethod = useCallback(
(element: HTMLDivElement | null) => {
@@ -122,13 +119,14 @@ const PositionedPopoverContent = ({
} as CSSProperties
}
ref={mergeRefs([setPopoverElement, addCloseMethod])}
id={'popover/' + id}
data-popover={id}
onKeyDown={(event) => {
if (event.key === KeyboardKey.Escape) {
event.stopPropagation()
togglePopover?.()
if (anchorElement) {
anchorElement.focus()
if (resolvedAnchorElement) {
resolvedAnchorElement.focus()
}
}
}}
@@ -148,7 +146,10 @@ const PositionedPopoverContent = ({
styles ? 'scale-100 opacity-100' : 'scale-95 opacity-0',
className,
)}
ref={setAnimationElement}
ref={mergeRefs([correctInitialScrollForOverflowedContent, setAnimationElement])}
onScroll={() => {
canCorrectInitialScroll.current = false
}}
>
{children}
</div>
@@ -1,4 +1,4 @@
import { ReactNode } from 'react'
import { ReactNode, RefObject } from 'react'
export type PopoverState = 'closed' | 'positioning' | 'open'
@@ -20,8 +20,10 @@ type Point = {
y: number
}
type AnchorElementOrRef = RefObject<HTMLElement | null> | HTMLElement | null
type PopoverAnchorElementProps = {
anchorElement: HTMLElement | null
anchorElement: AnchorElementOrRef
anchorPoint?: never
}
@@ -49,7 +51,7 @@ type CommonPopoverProps = {
}
export type PopoverContentProps = CommonPopoverProps & {
anchorElement?: HTMLElement | null
anchorElement?: AnchorElementOrRef
anchorPoint?: Point
childPopovers: Set<string>
togglePopover?: () => void
@@ -26,7 +26,9 @@ export const usePopoverCloseOnClickOutside = ({
const closestPopoverId = target.closest('[data-popover]')?.getAttribute('data-popover')
const isDescendantOfChildPopover = closestPopoverId && childPopovers.has(closestPopoverId)
const isPopoverInModal = popoverElement?.closest('[data-dialog], .sk-modal')
const isDescendantOfModal = isPopoverInModal ? false : !!target.closest('[data-dialog], .sk-modal')
const isDescendantOfModal = isPopoverInModal
? false
: !!target.closest('[data-dialog], [data-backdrop], .sk-modal')
const isDescendantOfDesktopTitlebar = !!target.closest('#desktop-title-bar')
if (
@@ -7,6 +7,7 @@ import { PackageProvider } from '@/Components/Preferences/Panes/General/Advanced
import AccordionItem from '@/Components/Shared/AccordionItem'
import PreferencesGroup from '../../../PreferencesComponents/PreferencesGroup'
import PreferencesSegment from '../../../PreferencesComponents/PreferencesSegment'
import { Platform } from '@standardnotes/snjs'
type Props = {
application: WebApplication
@@ -20,7 +21,7 @@ const Advanced: FunctionComponent<Props> = ({ application, extensionsLatestVersi
<AccordionItem title={'Advanced options'}>
<div className="flex flex-row items-center">
<div className="flex max-w-full flex-grow flex-col">
<OfflineSubscription application={application} />
{application.platform !== Platform.Ios && <OfflineSubscription application={application} />}
<PackagesPreferencesSection
className={'mt-3'}
application={application}
@@ -96,7 +96,7 @@ const EditSmartViewModal = ({ controller, platform }: Props) => {
<div className="flex items-center gap-2.5">
<div className="text-sm font-semibold">Title:</div>
<input
className="rounded border border-border bg-default px-2 py-1"
className="rounded border border-border bg-default md:translucent-ui:bg-transparent px-2 py-1"
value={title}
onChange={(event) => {
setTitle(event.target.value)
@@ -117,7 +117,7 @@ const EditSmartViewModal = ({ controller, platform }: Props) => {
<Popover
title="Choose icon"
open={shouldShowIconPicker}
anchorElement={iconPickerButtonRef.current}
anchorElement={iconPickerButtonRef}
togglePopover={toggleIconPicker}
align="start"
overrideZIndex="z-modal"
@@ -139,7 +139,7 @@ const EditSmartViewModal = ({ controller, platform }: Props) => {
<div className="text-sm font-semibold">Predicate:</div>
<div className="flex flex-grow flex-col overflow-hidden rounded-md border border-border">
<textarea
className="h-full min-h-[10rem] w-full flex-grow resize-none bg-default px-2.5 py-1.5 font-mono text-sm"
className="h-full min-h-[10rem] w-full flex-grow resize-none bg-default px-2.5 py-1.5 font-mono text-sm md:translucent-ui:bg-transparent"
value={predicateJson}
onChange={(event) => {
setPredicateJson(event.target.value)
@@ -244,7 +244,7 @@ const EditVaultModal: FunctionComponent<Props> = ({ onCloseDialog, existingVault
<Popover
title="Choose icon"
open={shouldShowIconPicker}
anchorElement={iconPickerButtonRef.current}
anchorElement={iconPickerButtonRef}
togglePopover={toggleIconPicker}
align="start"
overrideZIndex="z-modal"
@@ -50,7 +50,7 @@ const PreferencesViewWrapper: FunctionComponent<PreferencesViewWrapperProps> = (
animate="mobile"
animationVariant="horizontal"
close={application.preferencesController.closePreferences}
className="md:h-full md:!max-h-full md:!w-full"
className="md:!border-0 md:h-full md:!max-h-full md:!w-full"
>
<PreferencesView
closePreferences={application.preferencesController.closePreferences}
@@ -1,17 +1,16 @@
import AlertDialog from '../AlertDialog/AlertDialog'
import { FunctionComponent, useRef } from 'react'
import { WebApplication } from '@/Application/WebApplication'
import { PremiumFeatureModalType } from './PremiumFeatureModalType'
import { FeatureName } from '@/Controllers/FeatureName'
import { SuccessPrompt } from './Subviews/SuccessPrompt'
import { UpgradePrompt } from './Subviews/UpgradePrompt'
import Modal from '../Modal/Modal'
type Props = {
application: WebApplication
featureName?: FeatureName | string
hasSubscription: boolean
onClose: () => void
showModal: boolean
type: PremiumFeatureModalType
}
@@ -20,17 +19,12 @@ const PremiumFeaturesModal: FunctionComponent<Props> = ({
featureName,
hasSubscription,
onClose,
showModal,
type = PremiumFeatureModalType.UpgradePrompt,
}) => {
const ctaButtonRef = useRef<HTMLButtonElement>(null)
if (!showModal) {
return null
}
return (
<AlertDialog closeDialog={onClose} className="w-full max-w-[90vw] md:max-w-89">
<Modal close={onClose} title="Upgrade" className="px-6 py-5" customHeader={<></>}>
<div tabIndex={-1} className="sn-component">
<div tabIndex={0}>
{type === PremiumFeatureModalType.UpgradePrompt && (
@@ -46,7 +40,7 @@ const PremiumFeaturesModal: FunctionComponent<Props> = ({
{type === PremiumFeatureModalType.UpgradeSuccess && <SuccessPrompt ctaRef={ctaButtonRef} onClose={onClose} />}
</div>
</div>
</AlertDialog>
</Modal>
)
}
@@ -17,7 +17,7 @@ export const UpgradePrompt = ({
onClose: () => void
}) => {
const handleClick = useCallback(() => {
if (hasSubscription) {
if (hasSubscription && !application.isNativeIOS()) {
void application.openSubscriptionDashboard.execute()
} else {
void application.openPurchaseFlow()
@@ -51,7 +51,7 @@ const HistoryModalDialogContent = ({ dismissModal, note }: RevisionHistoryModalC
<Popover
title="Advanced"
open={showTabMenu}
anchorElement={tabOptionRef.current}
anchorElement={tabOptionRef}
disableMobileFullscreenTakeover={true}
togglePopover={toggleTabMenu}
align="start"
@@ -168,7 +168,7 @@ const AddSmartViewModal = ({ controller, platform }: Props) => {
<Popover
title="Choose icon"
open={shouldShowIconPicker}
anchorElement={iconPickerButtonRef.current}
anchorElement={iconPickerButtonRef}
togglePopover={toggleIconPicker}
align="start"
overrideZIndex="z-modal"
@@ -1,10 +1,11 @@
import { classNames } from '@standardnotes/snjs'
import { ReactNode, useState } from 'react'
import { ReactNode, useState, useRef, useEffect } from 'react'
import { Tooltip, TooltipAnchor, TooltipOptions, useTooltipStore } from '@ariakit/react'
import { Slot } from '@radix-ui/react-slot'
import { MutuallyExclusiveMediaQueryBreakpoints, useMediaQuery } from '@/Hooks/useMediaQuery'
import { getPositionedPopoverStyles } from '../Popover/GetPositionedPopoverStyles'
import { getAdjustedStylesForNonPortalPopover } from '../Popover/Utils/getAdjustedStylesForNonPortal'
import { useLongPressEvent } from '@/Hooks/useLongPress'
const StyledTooltip = ({
children,
@@ -24,13 +25,43 @@ const StyledTooltip = ({
} & Partial<TooltipOptions>) => {
const [forceOpen, setForceOpen] = useState<boolean | undefined>()
const isMobile = useMediaQuery(MutuallyExclusiveMediaQueryBreakpoints.sm)
const tooltip = useTooltipStore({
timeout: 500,
timeout: isMobile && showOnMobile ? 100 : 500,
hideTimeout: 0,
skipTimeout: 0,
open: forceOpen,
animated: true,
})
const isMobile = useMediaQuery(MutuallyExclusiveMediaQueryBreakpoints.sm)
const anchorRef = useRef<HTMLElement>(null)
const { attachEvents: attachLongPressEvents, cleanupEvents: cleanupLongPressEvents } = useLongPressEvent(
anchorRef,
() => {
tooltip.show()
setTimeout(() => {
tooltip.hide()
}, 2000)
},
)
useEffect(() => {
if (!isMobile || !showOnMobile) {
return
}
attachLongPressEvents()
return () => {
cleanupLongPressEvents()
}
}, [attachLongPressEvents, cleanupLongPressEvents, isMobile, showOnMobile])
const clickProps = isMobile
? {}
: {
onClick: () => setForceOpen(false),
}
if (isMobile && !showOnMobile) {
return <>{children}</>
@@ -39,7 +70,8 @@ const StyledTooltip = ({
return (
<>
<TooltipAnchor
onClick={() => setForceOpen(false)}
ref={anchorRef}
{...clickProps}
onBlur={() => setForceOpen(undefined)}
store={tooltip}
as={Slot}
@@ -53,6 +85,8 @@ const StyledTooltip = ({
store={tooltip}
className={classNames(
'z-tooltip max-w-max rounded border border-border translucent-ui:border-[--popover-border-color] bg-contrast translucent-ui:bg-[--popover-background-color] [backdrop-filter:var(--popover-backdrop-filter)] px-3 py-1.5 text-sm text-foreground shadow',
'opacity-60 [&[data-enter]]:opacity-100 [&[data-leave]]:opacity-60 transition-opacity duration-75',
'focus-visible:shadow-none focus-visible:outline-none',
className,
)}
updatePosition={() => {
@@ -79,6 +113,7 @@ const StyledTooltip = ({
popoverRect,
documentRect,
disableMobileFullscreenTakeover: true,
disableApplyingMobileWidth: true,
offset: props.gutter ? props.gutter : 6,
})
@@ -19,7 +19,7 @@ import AutoEmbedPlugin from './Plugins/AutoEmbedPlugin'
import CollapsiblePlugin from './Plugins/CollapsiblePlugin'
import DraggableBlockPlugin from './Plugins/DraggableBlockPlugin'
import CodeHighlightPlugin from './Plugins/CodeHighlightPlugin'
import FloatingTextFormatToolbarPlugin from './Plugins/FloatingTextFormatToolbarPlugin'
import FloatingTextFormatToolbarPlugin from './Plugins/ToolbarPlugins/FloatingTextFormatToolbarPlugin'
import { TabIndentationPlugin } from './Plugins/TabIndentationPlugin'
import { handleEditorChange } from './Utils'
import { SuperEditorContentId } from './Constants'
@@ -1,11 +1,12 @@
import { LexicalEditor } from 'lexical'
import { INSERT_UNORDERED_LIST_COMMAND } from '@lexical/list'
export function GetBulletedListBlock(editor: LexicalEditor) {
export function GetBulletedListBlock(editor: LexicalEditor, isActive = false) {
return {
name: 'Bulleted List',
iconName: 'list-bulleted',
keywords: ['bulleted list', 'unordered list', 'ul'],
onSelect: () => editor.dispatchCommand(INSERT_UNORDERED_LIST_COMMAND, undefined),
active: isActive,
}
}
@@ -1,11 +1,12 @@
import { LexicalEditor } from 'lexical'
import { INSERT_ORDERED_LIST_COMMAND } from '@lexical/list'
export function GetNumberedListBlock(editor: LexicalEditor) {
export function GetNumberedListBlock(editor: LexicalEditor, isActive = false) {
return {
name: 'Numbered List',
iconName: 'list-numbered',
keywords: ['numbered list', 'ordered list', 'ol'],
onSelect: () => editor.dispatchCommand(INSERT_ORDERED_LIST_COMMAND, undefined),
active: isActive,
}
}

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