mirror of
https://github.com/standardnotes/app
synced 2026-09-20 21:13:51 -04:00
Compare commits
43
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
61cdfc6030 | ||
|
|
f408950aa4 | ||
|
|
d1c295751d | ||
|
|
e42e2d6130 | ||
|
|
572c9b7dfa | ||
|
|
14ea00dc28 | ||
|
|
daaee89639 | ||
|
|
da37c421db | ||
|
|
85bd411d8f | ||
|
|
63f14d318d | ||
|
|
95cd682d49 | ||
|
|
941eeea4e3 | ||
|
|
991de1ddf5 | ||
|
|
044776d937 | ||
|
|
83fa6adbeb | ||
|
|
ce908c8ec4 | ||
|
|
98c61de501 | ||
|
|
198efdc41c | ||
|
|
cace6522f6 | ||
|
|
f3a9717883 | ||
|
|
00d30ca003 | ||
|
|
8574c42706 | ||
|
|
0f73ea8c4e | ||
|
|
12ccd22d78 | ||
|
|
d891ac7578 | ||
|
|
ce0db04646 | ||
|
|
f9c624cfdc | ||
|
|
abc8f371aa | ||
|
|
66c7d183ab | ||
|
|
96d4d814b2 | ||
|
|
49e643b6a0 | ||
|
|
64d3b01b6b | ||
|
|
0b9116934b | ||
|
|
c8dec9bfec | ||
|
|
66a6c61ffa | ||
|
|
aa31fe483a | ||
|
|
54a4c86a81 | ||
|
|
874961a7cd | ||
|
|
ad02f90cb1 | ||
|
|
a04590eb78 | ||
|
|
d7a47d01f2 | ||
|
|
86e8d49368 | ||
|
|
c1ee705402 |
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -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.26.69](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/api
|
||||
|
||||
## [1.26.68](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-26)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/api
|
||||
|
||||
## [1.26.67](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-25)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/api
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/api",
|
||||
"version": "1.26.67",
|
||||
"version": "1.26.69",
|
||||
"engines": {
|
||||
"node": ">=16.0.0 <17.0.0"
|
||||
},
|
||||
@@ -36,7 +36,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@standardnotes/common": "^1.50.0",
|
||||
"@standardnotes/domain-core": "^1.34.1",
|
||||
"@standardnotes/domain-core": "^1.40.0",
|
||||
"@standardnotes/models": "workspace:*",
|
||||
"@standardnotes/responses": "workspace:*",
|
||||
"@standardnotes/utils": "workspace:*",
|
||||
|
||||
@@ -3,6 +3,78 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.1.301](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/clipper
|
||||
|
||||
## [1.1.300](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/clipper
|
||||
|
||||
## [1.1.299](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/clipper
|
||||
|
||||
## [1.1.298](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/clipper
|
||||
|
||||
## [1.1.297](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/clipper
|
||||
|
||||
## [1.1.296](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/clipper
|
||||
|
||||
## [1.1.295](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-29)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/clipper
|
||||
|
||||
## [1.1.294](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-29)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/clipper
|
||||
|
||||
## [1.1.293](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-29)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/clipper
|
||||
|
||||
## [1.1.292](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-28)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/clipper
|
||||
|
||||
## [1.1.291](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-27)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/clipper
|
||||
|
||||
## [1.1.290](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-27)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/clipper
|
||||
|
||||
## [1.1.289](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-27)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/clipper
|
||||
|
||||
## [1.1.288](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-27)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/clipper
|
||||
|
||||
## [1.1.287](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-26)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/clipper
|
||||
|
||||
## [1.1.286](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-26)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/clipper
|
||||
|
||||
## [1.1.285](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-26)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/clipper
|
||||
|
||||
## [1.1.284](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-25)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/clipper
|
||||
|
||||
## [1.1.283](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-25)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/clipper
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@standardnotes/clipper",
|
||||
"description": "Web clipper browser extension for Standard Notes",
|
||||
"version": "1.1.283",
|
||||
"version": "1.1.301",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build-mv2": "yarn clean && webpack --config ./webpack.config.prod.js",
|
||||
|
||||
@@ -3,6 +3,78 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [3.108.235](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/desktop
|
||||
|
||||
## [3.108.234](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/desktop
|
||||
|
||||
## [3.108.233](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/desktop
|
||||
|
||||
## [3.108.232](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/desktop
|
||||
|
||||
## [3.108.231](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/desktop
|
||||
|
||||
## [3.108.230](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/desktop
|
||||
|
||||
## [3.108.229](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-29)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/desktop
|
||||
|
||||
## [3.108.228](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-29)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/desktop
|
||||
|
||||
## [3.108.227](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-29)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/desktop
|
||||
|
||||
## [3.108.226](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-28)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/desktop
|
||||
|
||||
## [3.108.225](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-27)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/desktop
|
||||
|
||||
## [3.108.224](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-27)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/desktop
|
||||
|
||||
## [3.108.223](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-27)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/desktop
|
||||
|
||||
## [3.108.222](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-27)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/desktop
|
||||
|
||||
## [3.108.221](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-26)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/desktop
|
||||
|
||||
## [3.108.220](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-26)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/desktop
|
||||
|
||||
## [3.108.219](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-26)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/desktop
|
||||
|
||||
## [3.108.218](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-25)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/desktop
|
||||
|
||||
## [3.108.217](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-25)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/desktop
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@standardnotes/desktop",
|
||||
"main": "./app/dist/index.js",
|
||||
"version": "3.108.217",
|
||||
"version": "3.108.235",
|
||||
"license": "AGPL-3.0",
|
||||
"author": "Standard Notes.",
|
||||
"private": true,
|
||||
@@ -35,7 +35,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@electron/remote": "^2.0.12",
|
||||
"@standardnotes/domain-core": "^1.34.1",
|
||||
"@standardnotes/domain-core": "^1.40.0",
|
||||
"@standardnotes/electron-clear-data": "1.1.1",
|
||||
"@standardnotes/web": "workspace:*",
|
||||
"axios": "^1.4.0",
|
||||
|
||||
@@ -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.21.91](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/encryption
|
||||
|
||||
## [1.21.90](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-26)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/encryption
|
||||
|
||||
## [1.21.89](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-25)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/encryption
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/encryption",
|
||||
"version": "1.21.89",
|
||||
"version": "1.21.91",
|
||||
"engines": {
|
||||
"node": ">=16.0.0 <17.0.0"
|
||||
},
|
||||
@@ -29,7 +29,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@standardnotes/common": "^1.50.0",
|
||||
"@standardnotes/domain-core": "^1.34.1",
|
||||
"@standardnotes/domain-core": "^1.40.0",
|
||||
"@standardnotes/models": "workspace:*",
|
||||
"@standardnotes/responses": "workspace:*",
|
||||
"@standardnotes/sncrypto-common": "workspace:*",
|
||||
|
||||
@@ -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.60.4](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-26)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/features
|
||||
|
||||
## [1.60.3](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-23)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/features
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/features",
|
||||
"version": "1.60.3",
|
||||
"version": "1.60.4",
|
||||
"engines": {
|
||||
"node": ">=16.0.0 <17.0.0"
|
||||
},
|
||||
@@ -26,7 +26,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@standardnotes/common": "^1.50.0",
|
||||
"@standardnotes/domain-core": "^1.34.1",
|
||||
"@standardnotes/domain-core": "^1.40.0",
|
||||
"reflect-metadata": "^0.1.13"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -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.102](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/filepicker
|
||||
|
||||
## [1.28.101](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-26)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/filepicker
|
||||
|
||||
## [1.28.100](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-25)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/filepicker
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/filepicker",
|
||||
"version": "1.28.100",
|
||||
"version": "1.28.102",
|
||||
"engines": {
|
||||
"node": ">=16.0.0 <17.0.0"
|
||||
},
|
||||
|
||||
@@ -3,6 +3,16 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [1.18.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
|
||||
|
||||
### Features
|
||||
|
||||
* When exporting a Super note, embedded files can be inlined in the note or exported along the note in a zip file. You can now also choose to include frontmatter when exporting to Markdown format. ([991de1d](https://github.com/standardnotes/app/commit/991de1ddf5dbb1016348d603d244699c676d9b5f)), closes [#2610](https://github.com/standardnotes/app/issues/2610)
|
||||
|
||||
## [1.17.20](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-26)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/files
|
||||
|
||||
## [1.17.19](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-25)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/files
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/files",
|
||||
"version": "1.17.19",
|
||||
"version": "1.18.0",
|
||||
"engines": {
|
||||
"node": ">=16.0.0 <17.0.0"
|
||||
},
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
export interface SuperConverterServiceInterface {
|
||||
isValidSuperString(superString: string): boolean
|
||||
convertSuperStringToOtherFormat: (superString: string, toFormat: 'txt' | 'md' | 'html' | 'json') => string
|
||||
convertSuperStringToOtherFormat: (superString: string, toFormat: 'txt' | 'md' | 'html' | 'json') => Promise<string>
|
||||
convertOtherFormatToSuperString: (otherFormatString: string, fromFormat: 'txt' | 'md' | 'html' | 'json') => string
|
||||
getEmbeddedFileIDsFromSuperString(superString: string): string[]
|
||||
}
|
||||
|
||||
@@ -3,6 +3,84 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [3.56.215](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/mobile
|
||||
|
||||
## [3.56.214](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Fixed issue where a brief flash of white would appear when starting the app on mobile ([572c9b7](https://github.com/standardnotes/app/commit/572c9b7dfaa42773c050772940e383df2940a79f))
|
||||
|
||||
## [3.56.213](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/mobile
|
||||
|
||||
## [3.56.212](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/mobile
|
||||
|
||||
## [3.56.211](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/mobile
|
||||
|
||||
## [3.56.210](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/mobile
|
||||
|
||||
## [3.56.209](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/mobile
|
||||
|
||||
## [3.56.208](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-29)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/mobile
|
||||
|
||||
## [3.56.207](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-29)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/mobile
|
||||
|
||||
## [3.56.206](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-29)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/mobile
|
||||
|
||||
## [3.56.205](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-28)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/mobile
|
||||
|
||||
## [3.56.204](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-27)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/mobile
|
||||
|
||||
## [3.56.203](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-27)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/mobile
|
||||
|
||||
## [3.56.202](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-27)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/mobile
|
||||
|
||||
## [3.56.201](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-27)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/mobile
|
||||
|
||||
## [3.56.200](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-26)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/mobile
|
||||
|
||||
## [3.56.199](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-26)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/mobile
|
||||
|
||||
## [3.56.198](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-26)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/mobile
|
||||
|
||||
## [3.56.197](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-25)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/mobile
|
||||
|
||||
## [3.56.196](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-25)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/mobile
|
||||
|
||||
@@ -3,13 +3,17 @@ GEM
|
||||
specs:
|
||||
CFPropertyList (3.0.6)
|
||||
rexml
|
||||
activesupport (6.1.5)
|
||||
activesupport (7.1.1)
|
||||
base64
|
||||
bigdecimal
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
connection_pool (>= 2.2.5)
|
||||
drb
|
||||
i18n (>= 1.6, < 2)
|
||||
minitest (>= 5.1)
|
||||
mutex_m
|
||||
tzinfo (~> 2.0)
|
||||
zeitwerk (~> 2.3)
|
||||
addressable (2.8.4)
|
||||
addressable (2.8.5)
|
||||
public_suffix (>= 2.0.2, < 6.0)
|
||||
algoliasearch (1.27.5)
|
||||
httpclient (~> 2.8, >= 2.8.3)
|
||||
@@ -17,32 +21,34 @@ GEM
|
||||
artifactory (3.0.15)
|
||||
atomos (0.1.3)
|
||||
aws-eventstream (1.2.0)
|
||||
aws-partitions (1.755.0)
|
||||
aws-sdk-core (3.171.0)
|
||||
aws-partitions (1.843.0)
|
||||
aws-sdk-core (3.185.1)
|
||||
aws-eventstream (~> 1, >= 1.0.2)
|
||||
aws-partitions (~> 1, >= 1.651.0)
|
||||
aws-sigv4 (~> 1.5)
|
||||
jmespath (~> 1, >= 1.6.1)
|
||||
aws-sdk-kms (1.63.0)
|
||||
aws-sdk-core (~> 3, >= 3.165.0)
|
||||
aws-sdk-kms (1.72.0)
|
||||
aws-sdk-core (~> 3, >= 3.184.0)
|
||||
aws-sigv4 (~> 1.1)
|
||||
aws-sdk-s3 (1.121.0)
|
||||
aws-sdk-core (~> 3, >= 3.165.0)
|
||||
aws-sdk-s3 (1.136.0)
|
||||
aws-sdk-core (~> 3, >= 3.181.0)
|
||||
aws-sdk-kms (~> 1)
|
||||
aws-sigv4 (~> 1.4)
|
||||
aws-sigv4 (1.5.2)
|
||||
aws-sigv4 (~> 1.6)
|
||||
aws-sigv4 (1.6.1)
|
||||
aws-eventstream (~> 1, >= 1.0.2)
|
||||
babosa (1.0.4)
|
||||
claide (1.0.3)
|
||||
cocoapods (1.11.3)
|
||||
base64 (0.1.1)
|
||||
bigdecimal (3.1.4)
|
||||
claide (1.1.0)
|
||||
cocoapods (1.14.2)
|
||||
addressable (~> 2.8)
|
||||
claide (>= 1.0.2, < 2.0)
|
||||
cocoapods-core (= 1.11.3)
|
||||
cocoapods-core (= 1.14.2)
|
||||
cocoapods-deintegrate (>= 1.0.3, < 2.0)
|
||||
cocoapods-downloader (>= 1.4.0, < 2.0)
|
||||
cocoapods-downloader (>= 2.0)
|
||||
cocoapods-plugins (>= 1.0.0, < 2.0)
|
||||
cocoapods-search (>= 1.0.0, < 2.0)
|
||||
cocoapods-trunk (>= 1.4.0, < 2.0)
|
||||
cocoapods-trunk (>= 1.6.0, < 2.0)
|
||||
cocoapods-try (>= 1.1.0, < 2.0)
|
||||
colored2 (~> 3.1)
|
||||
escape (~> 0.0.4)
|
||||
@@ -50,10 +56,10 @@ GEM
|
||||
gh_inspector (~> 1.0)
|
||||
molinillo (~> 0.8.0)
|
||||
nap (~> 1.0)
|
||||
ruby-macho (>= 1.0, < 3.0)
|
||||
xcodeproj (>= 1.21.0, < 2.0)
|
||||
cocoapods-core (1.11.3)
|
||||
activesupport (>= 5.0, < 7)
|
||||
ruby-macho (>= 2.3.0, < 3.0)
|
||||
xcodeproj (>= 1.23.0, < 2.0)
|
||||
cocoapods-core (1.14.2)
|
||||
activesupport (>= 5.0, < 8)
|
||||
addressable (~> 2.8)
|
||||
algoliasearch (~> 1.0)
|
||||
concurrent-ruby (~> 1.1)
|
||||
@@ -63,7 +69,7 @@ GEM
|
||||
public_suffix (~> 4.0)
|
||||
typhoeus (~> 1.0)
|
||||
cocoapods-deintegrate (1.0.5)
|
||||
cocoapods-downloader (1.5.1)
|
||||
cocoapods-downloader (2.0)
|
||||
cocoapods-plugins (1.0.0)
|
||||
nap
|
||||
cocoapods-search (1.0.1)
|
||||
@@ -75,18 +81,21 @@ GEM
|
||||
colored2 (3.1.2)
|
||||
commander (4.6.0)
|
||||
highline (~> 2.0.0)
|
||||
concurrent-ruby (1.1.9)
|
||||
concurrent-ruby (1.2.2)
|
||||
connection_pool (2.4.1)
|
||||
declarative (0.0.20)
|
||||
digest-crc (0.6.4)
|
||||
digest-crc (0.6.5)
|
||||
rake (>= 12.0.0, < 14.0.0)
|
||||
domain_name (0.5.20190701)
|
||||
unf (>= 0.0.5, < 1.0.0)
|
||||
dotenv (2.8.1)
|
||||
drb (2.1.1)
|
||||
ruby2_keywords
|
||||
emoji_regex (3.2.3)
|
||||
escape (0.0.4)
|
||||
ethon (0.15.0)
|
||||
ethon (0.16.0)
|
||||
ffi (>= 1.15.0)
|
||||
excon (0.99.0)
|
||||
excon (0.104.0)
|
||||
faraday (1.10.3)
|
||||
faraday-em_http (~> 1.0)
|
||||
faraday-em_synchrony (~> 1.0)
|
||||
@@ -115,8 +124,8 @@ GEM
|
||||
faraday-retry (1.0.3)
|
||||
faraday_middleware (1.2.0)
|
||||
faraday (~> 1.0)
|
||||
fastimage (2.2.6)
|
||||
fastlane (2.212.2)
|
||||
fastimage (2.2.7)
|
||||
fastlane (2.216.0)
|
||||
CFPropertyList (>= 2.3, < 4.0.0)
|
||||
addressable (>= 2.8, < 3.0.0)
|
||||
artifactory (~> 3.0)
|
||||
@@ -137,10 +146,11 @@ GEM
|
||||
google-apis-playcustomapp_v1 (~> 0.1)
|
||||
google-cloud-storage (~> 1.31)
|
||||
highline (~> 2.0)
|
||||
http-cookie (~> 1.0.5)
|
||||
json (< 3.0.0)
|
||||
jwt (>= 2.1.0, < 3)
|
||||
mini_magick (>= 4.9.4, < 5.0.0)
|
||||
multipart-post (~> 2.0.0)
|
||||
multipart-post (>= 2.0.0, < 3.0.0)
|
||||
naturally (~> 2.2)
|
||||
optparse (~> 0.1.1)
|
||||
plist (>= 3.1.0, < 4.0.0)
|
||||
@@ -148,21 +158,21 @@ GEM
|
||||
security (= 0.1.3)
|
||||
simctl (~> 1.6.3)
|
||||
terminal-notifier (>= 2.0.0, < 3.0.0)
|
||||
terminal-table (>= 1.4.5, < 2.0.0)
|
||||
terminal-table (~> 3)
|
||||
tty-screen (>= 0.6.3, < 1.0.0)
|
||||
tty-spinner (>= 0.8.0, < 1.0.0)
|
||||
word_wrap (~> 1.0.0)
|
||||
xcodeproj (>= 1.13.0, < 2.0.0)
|
||||
xcpretty (~> 0.3.0)
|
||||
xcpretty-travis-formatter (>= 0.0.3)
|
||||
fastlane-plugin-bundletool (1.0.5)
|
||||
ffi (1.15.5)
|
||||
fastlane-plugin-bundletool (1.0.9)
|
||||
ffi (1.16.3)
|
||||
fourflusher (2.3.1)
|
||||
fuzzy_match (2.0.4)
|
||||
gh_inspector (1.1.3)
|
||||
google-apis-androidpublisher_v3 (0.40.0)
|
||||
google-apis-androidpublisher_v3 (0.51.0)
|
||||
google-apis-core (>= 0.11.0, < 2.a)
|
||||
google-apis-core (0.11.0)
|
||||
google-apis-core (0.11.2)
|
||||
addressable (~> 2.5, >= 2.5.1)
|
||||
googleauth (>= 0.16.2, < 2.a)
|
||||
httpclient (>= 2.8.1, < 3.a)
|
||||
@@ -191,10 +201,9 @@ GEM
|
||||
google-cloud-core (~> 1.6)
|
||||
googleauth (>= 0.16.2, < 2.a)
|
||||
mini_mime (~> 1.0)
|
||||
googleauth (1.5.2)
|
||||
googleauth (1.8.1)
|
||||
faraday (>= 0.17.3, < 3.a)
|
||||
jwt (>= 1.4, < 3.0)
|
||||
memoist (~> 0.16)
|
||||
multi_json (~> 1.11)
|
||||
os (>= 0.9, < 2.0)
|
||||
signet (>= 0.16, < 2.a)
|
||||
@@ -202,18 +211,18 @@ GEM
|
||||
http-cookie (1.0.5)
|
||||
domain_name (~> 0.5)
|
||||
httpclient (2.8.3)
|
||||
i18n (1.10.0)
|
||||
i18n (1.14.1)
|
||||
concurrent-ruby (~> 1.0)
|
||||
jmespath (1.6.2)
|
||||
json (2.6.3)
|
||||
jwt (2.7.0)
|
||||
memoist (0.16.2)
|
||||
jwt (2.7.1)
|
||||
mini_magick (4.12.0)
|
||||
mini_mime (1.1.2)
|
||||
minitest (5.15.0)
|
||||
mini_mime (1.1.5)
|
||||
minitest (5.20.0)
|
||||
molinillo (0.8.0)
|
||||
multi_json (1.15.0)
|
||||
multipart-post (2.0.0)
|
||||
multipart-post (2.3.0)
|
||||
mutex_m (0.1.2)
|
||||
nanaimo (0.3.0)
|
||||
nap (1.1.0)
|
||||
naturally (2.2.1)
|
||||
@@ -222,19 +231,19 @@ GEM
|
||||
os (1.1.4)
|
||||
plist (3.7.0)
|
||||
public_suffix (4.0.7)
|
||||
rake (13.0.6)
|
||||
rake (13.1.0)
|
||||
representable (3.2.0)
|
||||
declarative (< 0.1.0)
|
||||
trailblazer-option (>= 0.1.1, < 0.2.0)
|
||||
uber (< 0.2.0)
|
||||
retriable (3.1.2)
|
||||
rexml (3.2.5)
|
||||
rexml (3.2.6)
|
||||
rouge (2.0.7)
|
||||
ruby-macho (2.5.1)
|
||||
ruby2_keywords (0.0.5)
|
||||
rubyzip (2.3.2)
|
||||
security (0.1.3)
|
||||
signet (0.17.0)
|
||||
signet (0.18.0)
|
||||
addressable (~> 2.8)
|
||||
faraday (>= 0.17.5, < 3.a)
|
||||
jwt (>= 1.5, < 3.0)
|
||||
@@ -243,8 +252,8 @@ GEM
|
||||
CFPropertyList
|
||||
naturally
|
||||
terminal-notifier (2.0.0)
|
||||
terminal-table (1.8.0)
|
||||
unicode-display_width (~> 1.1, >= 1.1.1)
|
||||
terminal-table (3.0.2)
|
||||
unicode-display_width (>= 1.1.1, < 3)
|
||||
trailblazer-option (0.1.2)
|
||||
tty-cursor (0.7.1)
|
||||
tty-screen (0.8.1)
|
||||
@@ -252,19 +261,19 @@ GEM
|
||||
tty-cursor (~> 0.7)
|
||||
typhoeus (1.4.0)
|
||||
ethon (>= 0.9.0)
|
||||
tzinfo (2.0.4)
|
||||
tzinfo (2.0.6)
|
||||
concurrent-ruby (~> 1.0)
|
||||
uber (0.1.0)
|
||||
unf (0.1.4)
|
||||
unf_ext
|
||||
unf_ext (0.0.8.2)
|
||||
unicode-display_width (1.8.0)
|
||||
unicode-display_width (2.5.0)
|
||||
webrick (1.8.1)
|
||||
word_wrap (1.0.0)
|
||||
xcode-install (2.8.0)
|
||||
claide (>= 0.9.1, < 1.1.0)
|
||||
xcode-install (2.8.1)
|
||||
claide (>= 0.9.1)
|
||||
fastlane (>= 2.1.0, < 3.0.0)
|
||||
xcodeproj (1.22.0)
|
||||
xcodeproj (1.23.0)
|
||||
CFPropertyList (>= 2.3.3, < 4.0)
|
||||
atomos (~> 0.1.3)
|
||||
claide (>= 1.0.2, < 2.0)
|
||||
@@ -275,14 +284,13 @@ GEM
|
||||
rouge (~> 2.0.7)
|
||||
xcpretty-travis-formatter (1.0.1)
|
||||
xcpretty (~> 0.2, >= 0.0.7)
|
||||
zeitwerk (2.5.4)
|
||||
|
||||
PLATFORMS
|
||||
arm64-darwin-21
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
cocoapods (~> 1.11, >= 1.11.3)
|
||||
cocoapods (~> 1.12)
|
||||
fastlane
|
||||
fastlane-plugin-bundletool
|
||||
xcode-install
|
||||
|
||||
@@ -25,6 +25,11 @@
|
||||
};
|
||||
</script>
|
||||
<script src="web-src/app.js"></script>
|
||||
<style>
|
||||
body {
|
||||
background-color: black;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/mobile",
|
||||
"version": "3.56.196",
|
||||
"version": "3.56.215",
|
||||
"author": "Standard Notes.",
|
||||
"private": true,
|
||||
"license": "AGPL-3.0",
|
||||
|
||||
@@ -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.49.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
|
||||
|
||||
### Features
|
||||
|
||||
* When exporting a Super note, embedded files can be inlined in the note or exported along the note in a zip file. You can now also choose to include frontmatter when exporting to Markdown format. ([991de1d](https://github.com/standardnotes/app/commit/991de1ddf5dbb1016348d603d244699c676d9b5f)), closes [#2610](https://github.com/standardnotes/app/issues/2610)
|
||||
|
||||
## [1.48.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-26)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/models
|
||||
|
||||
# [1.48.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-25)
|
||||
|
||||
### Features
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/models",
|
||||
"version": "1.48.0",
|
||||
"version": "1.49.0",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
@@ -20,7 +20,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@standardnotes/common": "^1.50.0",
|
||||
"@standardnotes/domain-core": "^1.34.1",
|
||||
"@standardnotes/domain-core": "^1.40.0",
|
||||
"@standardnotes/features": "workspace:*",
|
||||
"@standardnotes/responses": "workspace:*",
|
||||
"@standardnotes/sncrypto-common": "workspace:^",
|
||||
|
||||
@@ -40,6 +40,8 @@ export const PrefDefaults = {
|
||||
[PrefKey.ClipperDefaultTagUuid]: undefined,
|
||||
[PrefKey.DefaultEditorIdentifier]: NativeFeatureIdentifier.TYPES.PlainEditor,
|
||||
[PrefKey.SuperNoteExportFormat]: 'json',
|
||||
[PrefKey.SuperNoteExportEmbedBehavior]: 'reference',
|
||||
[PrefKey.SuperNoteExportUseMDFrontmatter]: true,
|
||||
[PrefKey.SystemViewPreferences]: {},
|
||||
[PrefKey.AuthenticatorNames]: '',
|
||||
[PrefKey.ComponentPreferences]: {},
|
||||
|
||||
@@ -41,6 +41,8 @@ export enum PrefKey {
|
||||
ClipperDefaultTagUuid = 'clipperDefaultTagUuid',
|
||||
SystemViewPreferences = 'systemViewPreferences',
|
||||
SuperNoteExportFormat = 'superNoteExportFormat',
|
||||
SuperNoteExportEmbedBehavior = 'superNoteExportEmbedBehavior',
|
||||
SuperNoteExportUseMDFrontmatter = 'superNoteExportUseMDFrontmatter',
|
||||
AuthenticatorNames = 'authenticatorNames',
|
||||
PaneGesturesEnabled = 'paneGesturesEnabled',
|
||||
ComponentPreferences = 'componentPreferences',
|
||||
@@ -83,6 +85,8 @@ export type PrefValue = {
|
||||
[PrefKey.ClipperDefaultTagUuid]: string | undefined
|
||||
[PrefKey.SystemViewPreferences]: Partial<Record<SystemViewId, TagPreferences>>
|
||||
[PrefKey.SuperNoteExportFormat]: 'json' | 'md' | 'html'
|
||||
[PrefKey.SuperNoteExportEmbedBehavior]: 'reference' | 'inline' | 'separate'
|
||||
[PrefKey.SuperNoteExportUseMDFrontmatter]: boolean
|
||||
[PrefKey.AuthenticatorNames]: string
|
||||
[PrefKey.PaneGesturesEnabled]: boolean
|
||||
[PrefKey.ComponentPreferences]: AllComponentPreferences
|
||||
|
||||
@@ -3,6 +3,82 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.4.590](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/releases
|
||||
|
||||
## [1.4.589](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/releases
|
||||
|
||||
## [1.4.588](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/releases
|
||||
|
||||
## [1.4.587](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/releases
|
||||
|
||||
## [1.4.586](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/releases
|
||||
|
||||
## [1.4.585](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/releases
|
||||
|
||||
## [1.4.584](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/releases
|
||||
|
||||
## [1.4.583](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-29)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/releases
|
||||
|
||||
## [1.4.582](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-29)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/releases
|
||||
|
||||
## [1.4.581](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-29)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/releases
|
||||
|
||||
## [1.4.580](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-28)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/releases
|
||||
|
||||
## [1.4.579](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-27)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/releases
|
||||
|
||||
## [1.4.578](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-27)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/releases
|
||||
|
||||
## [1.4.577](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-27)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/releases
|
||||
|
||||
## [1.4.576](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-27)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/releases
|
||||
|
||||
## [1.4.575](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-26)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/releases
|
||||
|
||||
## [1.4.574](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-26)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/releases
|
||||
|
||||
## [1.4.573](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-26)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/releases
|
||||
|
||||
## [1.4.572](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-25)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/releases
|
||||
|
||||
## [1.4.571](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-25)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/releases
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/releases",
|
||||
"version": "1.4.571",
|
||||
"version": "1.4.590",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "dist/releases.json",
|
||||
"types": "dist/index.d.ts",
|
||||
|
||||
@@ -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.51](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-26)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/responses
|
||||
|
||||
## [1.13.50](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-23)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/responses
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/responses",
|
||||
"version": "1.13.50",
|
||||
"version": "1.13.51",
|
||||
"engines": {
|
||||
"node": ">=16.0.0 <17.0.0"
|
||||
},
|
||||
|
||||
@@ -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.65.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
|
||||
|
||||
### Features
|
||||
|
||||
* When exporting a Super note, embedded files can be inlined in the note or exported along the note in a zip file. You can now also choose to include frontmatter when exporting to Markdown format. ([991de1d](https://github.com/standardnotes/app/commit/991de1ddf5dbb1016348d603d244699c676d9b5f)), closes [#2610](https://github.com/standardnotes/app/issues/2610)
|
||||
|
||||
## [1.64.38](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-26)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/services
|
||||
|
||||
## [1.64.37](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-25)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/services
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/services",
|
||||
"version": "1.64.37",
|
||||
"version": "1.65.0",
|
||||
"engines": {
|
||||
"node": ">=16.0.0 <17.0.0"
|
||||
},
|
||||
@@ -18,7 +18,7 @@
|
||||
"dependencies": {
|
||||
"@standardnotes/api": "workspace:^",
|
||||
"@standardnotes/common": "^1.50.0",
|
||||
"@standardnotes/domain-core": "^1.34.1",
|
||||
"@standardnotes/domain-core": "^1.40.0",
|
||||
"@standardnotes/encryption": "workspace:^",
|
||||
"@standardnotes/features": "workspace:^",
|
||||
"@standardnotes/files": "workspace:^",
|
||||
|
||||
@@ -462,7 +462,7 @@ export class FilesBackupService
|
||||
const tagNames = tags.map((tag) => this.items.getTagLongTitle(tag))
|
||||
const text =
|
||||
note.noteType === NoteType.Super
|
||||
? this.markdownConverter.convertSuperStringToOtherFormat(note.text, 'md')
|
||||
? await this.markdownConverter.convertSuperStringToOtherFormat(note.text, 'md')
|
||||
: note.text
|
||||
await this.device.savePlaintextNoteBackup(location, note.uuid, note.title, tagNames, text)
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
## [2.202.104](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/snjs
|
||||
|
||||
## [2.202.103](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-26)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/snjs
|
||||
|
||||
## [2.202.102](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-25)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/snjs
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { AuthClientInterface } from '@standardnotes/services'
|
||||
import { Result, UseCaseInterface } from '@standardnotes/domain-core'
|
||||
import { SettingName } from '@standardnotes/settings'
|
||||
import { Result, SettingName, UseCaseInterface } from '@standardnotes/domain-core'
|
||||
|
||||
import { SettingsClientInterface } from '@Lib/Services/Settings/SettingsClientInterface'
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { ItemInterface, SNFeatureRepo } from '@standardnotes/models'
|
||||
import { SyncService } from '../Sync/SyncService'
|
||||
import { SettingName } from '@standardnotes/settings'
|
||||
import { FeaturesService } from '@Lib/Services/Features'
|
||||
import { RoleName, ContentType, Uuid, Result } from '@standardnotes/domain-core'
|
||||
import { RoleName, ContentType, Uuid, Result, SettingName } from '@standardnotes/domain-core'
|
||||
import { NativeFeatureIdentifier, GetFeatures } from '@standardnotes/features'
|
||||
import { SettingsService } from '../Settings'
|
||||
import { PureCryptoInterface } from '@standardnotes/sncrypto-common'
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { SettingsClientInterface } from '@Lib/Services/Settings/SettingsClientInterface'
|
||||
import { SettingName } from '@standardnotes/domain-core'
|
||||
import { SNFeatureRepo } from '@standardnotes/models'
|
||||
import { MutatorClientInterface } from '@standardnotes/services'
|
||||
import { SettingName } from '@standardnotes/settings'
|
||||
|
||||
export class MigrateFeatureRepoToUserSettingUseCase {
|
||||
constructor(
|
||||
|
||||
@@ -2,7 +2,6 @@ import { isString, lastElement, sleep } from '@standardnotes/utils'
|
||||
import { UuidString } from '@Lib/Types/UuidString'
|
||||
import { ItemManager } from '@Lib/Services/Items/ItemManager'
|
||||
import { DeprecatedHttpService } from '../Api/DeprecatedHttpService'
|
||||
import { SettingName } from '@standardnotes/settings'
|
||||
import { SettingsService } from '../Settings/SNSettingsService'
|
||||
import { ListedClientInterface } from './ListedClientInterface'
|
||||
import { LegacyApiService } from '../Api/ApiService'
|
||||
@@ -15,7 +14,7 @@ import {
|
||||
SyncServiceInterface,
|
||||
} from '@standardnotes/services'
|
||||
import { ProtectionService } from '../Protection'
|
||||
import { ContentType } from '@standardnotes/domain-core'
|
||||
import { ContentType, SettingName } from '@standardnotes/domain-core'
|
||||
|
||||
export class ListedService extends AbstractService implements ListedClientInterface {
|
||||
constructor(
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import { SettingName } from '@standardnotes/settings'
|
||||
|
||||
import { SettingsService } from '../Settings'
|
||||
import { PureCryptoInterface } from '@standardnotes/sncrypto-common'
|
||||
import { FeaturesService } from '../Features/FeaturesService'
|
||||
import { AbstractService, InternalEventBusInterface, MfaServiceInterface, SignInStrings } from '@standardnotes/services'
|
||||
import { SettingName } from '@standardnotes/domain-core'
|
||||
|
||||
export class MfaService extends AbstractService implements MfaServiceInterface {
|
||||
constructor(
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { LegacyApiService } from '../Api/ApiService'
|
||||
import { SettingsGateway } from './SettingsGateway'
|
||||
import { SessionManager } from '../Session/SessionManager'
|
||||
import { EmailBackupFrequency, SettingName } from '@standardnotes/settings'
|
||||
import { EmailBackupFrequency } from '@standardnotes/settings'
|
||||
import { AbstractService, InternalEventBusInterface } from '@standardnotes/services'
|
||||
import { SettingsClientInterface } from './SettingsClientInterface'
|
||||
import { SettingName } from '@standardnotes/domain-core'
|
||||
|
||||
export class SettingsService extends AbstractService implements SettingsClientInterface {
|
||||
private provider!: SettingsGateway
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { SettingName, EmailBackupFrequency } from '@standardnotes/settings'
|
||||
import { EmailBackupFrequency } from '@standardnotes/settings'
|
||||
import { SettingsList } from './SettingsList'
|
||||
import { SettingName } from '@standardnotes/domain-core'
|
||||
|
||||
export interface SettingsClientInterface {
|
||||
listSettings(): Promise<SettingsList>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { SettingsList } from './SettingsList'
|
||||
import { SettingName } from '@standardnotes/settings'
|
||||
import { API_MESSAGE_INVALID_SESSION } from '@standardnotes/services'
|
||||
import { getErrorFromErrorResponse, HttpStatusCode, isErrorResponse, User } from '@standardnotes/responses'
|
||||
import { SettingsServerInterface } from './SettingsServerInterface'
|
||||
import { SettingName } from '@standardnotes/domain-core'
|
||||
|
||||
/**
|
||||
* SettingsGateway coordinates communication with the API service
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { SettingName } from '@standardnotes/domain-core'
|
||||
import { SettingData } from '@standardnotes/responses'
|
||||
import {
|
||||
MuteSignInEmailsOption,
|
||||
@@ -5,7 +6,6 @@ import {
|
||||
EmailBackupFrequency,
|
||||
ListedAuthorSecretsData,
|
||||
LogSessionUserAgentOption,
|
||||
SettingName,
|
||||
MuteMarketingEmailsOption,
|
||||
} from '@standardnotes/settings'
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/snjs",
|
||||
"version": "2.202.102",
|
||||
"version": "2.202.104",
|
||||
"engines": {
|
||||
"node": ">=16.0.0 <17.0.0"
|
||||
},
|
||||
@@ -37,7 +37,7 @@
|
||||
"@babel/preset-env": "*",
|
||||
"@standardnotes/api": "workspace:*",
|
||||
"@standardnotes/common": "^1.50.0",
|
||||
"@standardnotes/domain-core": "^1.34.1",
|
||||
"@standardnotes/domain-core": "^1.40.0",
|
||||
"@standardnotes/domain-events": "^2.122.0",
|
||||
"@standardnotes/encryption": "workspace:*",
|
||||
"@standardnotes/features": "workspace:*",
|
||||
@@ -45,7 +45,7 @@
|
||||
"@standardnotes/models": "workspace:*",
|
||||
"@standardnotes/responses": "workspace:*",
|
||||
"@standardnotes/services": "workspace:*",
|
||||
"@standardnotes/settings": "^1.20.0",
|
||||
"@standardnotes/settings": "^1.22.0",
|
||||
"@standardnotes/sncrypto-common": "workspace:*",
|
||||
"@standardnotes/sncrypto-web": "workspace:*",
|
||||
"@standardnotes/utils": "workspace:*",
|
||||
|
||||
@@ -3,6 +3,22 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.33.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Fixed issue where exporting multiple files with the same name would error ([f408950](https://github.com/standardnotes/app/commit/f408950aa4e59389db81a4ca2b9db5ea49147aaf))
|
||||
|
||||
# [1.33.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
|
||||
|
||||
### Features
|
||||
|
||||
* When exporting a Super note, embedded files can be inlined in the note or exported along the note in a zip file. You can now also choose to include frontmatter when exporting to Markdown format. ([991de1d](https://github.com/standardnotes/app/commit/991de1ddf5dbb1016348d603d244699c676d9b5f)), closes [#2610](https://github.com/standardnotes/app/issues/2610)
|
||||
|
||||
## [1.32.7](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-26)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/ui-services
|
||||
|
||||
## [1.32.6](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-25)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/ui-services
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/ui-services",
|
||||
"version": "1.32.6",
|
||||
"version": "1.33.1",
|
||||
"engines": {
|
||||
"node": ">=16.0.0 <17.0.0"
|
||||
},
|
||||
@@ -16,7 +16,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@standardnotes/common": "^1.50.0",
|
||||
"@standardnotes/domain-core": "^1.34.1",
|
||||
"@standardnotes/domain-core": "^1.40.0",
|
||||
"@standardnotes/features": "workspace:^",
|
||||
"@standardnotes/filepicker": "workspace:^",
|
||||
"@standardnotes/models": "workspace:^",
|
||||
|
||||
@@ -19,6 +19,11 @@ function zippableFileName(name: string, suffix = '', format = 'txt'): string {
|
||||
return sanitizedName.slice(0, maxFileNameLength - nameEnd.length) + nameEnd
|
||||
}
|
||||
|
||||
export function parseAndCreateZippableFileName(name: string, suffix = '') {
|
||||
const { name: parsedName, ext } = parseFileName(name)
|
||||
return zippableFileName(parsedName, suffix, ext)
|
||||
}
|
||||
|
||||
type ZippableData = {
|
||||
name: string
|
||||
content: Blob
|
||||
|
||||
@@ -31,7 +31,8 @@ describe('EvernoteConverter', () => {
|
||||
const superConverterService: SuperConverterServiceInterface = {
|
||||
isValidSuperString: () => true,
|
||||
convertOtherFormatToSuperString: (data: string) => data,
|
||||
convertSuperStringToOtherFormat: (data: string) => data,
|
||||
convertSuperStringToOtherFormat: async (data: string) => data,
|
||||
getEmbeddedFileIDsFromSuperString: () => [],
|
||||
}
|
||||
|
||||
const generateUuid = new GenerateUuid(crypto)
|
||||
|
||||
@@ -16,7 +16,8 @@ describe('GoogleKeepConverter', () => {
|
||||
const superConverterService: SuperConverterServiceInterface = {
|
||||
isValidSuperString: () => true,
|
||||
convertOtherFormatToSuperString: (data: string) => data,
|
||||
convertSuperStringToOtherFormat: (data: string) => data,
|
||||
convertSuperStringToOtherFormat: async (data: string) => data,
|
||||
getEmbeddedFileIDsFromSuperString: () => [],
|
||||
}
|
||||
const generateUuid = new GenerateUuid(crypto)
|
||||
|
||||
|
||||
@@ -36,7 +36,6 @@ export const SUPER_SHOW_MARKDOWN_PREVIEW = createKeyboardCommand('SUPER_SHOW_MAR
|
||||
|
||||
export const SUPER_EXPORT_JSON = createKeyboardCommand('SUPER_EXPORT_JSON')
|
||||
export const SUPER_EXPORT_MARKDOWN = createKeyboardCommand('SUPER_EXPORT_MARKDOWN')
|
||||
export const SUPER_EXPORT_HTML = createKeyboardCommand('SUPER_EXPORT_HTML')
|
||||
export const OPEN_PREFERENCES_COMMAND = createKeyboardCommand('OPEN_PREFERENCES_COMMAND')
|
||||
|
||||
export const CHANGE_EDITOR_WIDTH_COMMAND = createKeyboardCommand('CHANGE_EDITOR_WIDTH_COMMAND')
|
||||
|
||||
@@ -3,11 +3,97 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [3.181.4](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Fixed issue where exporting multiple files with the same name would error ([f408950](https://github.com/standardnotes/app/commit/f408950aa4e59389db81a4ca2b9db5ea49147aaf))
|
||||
|
||||
## [3.181.3](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Fixed issue where a brief flash of white would appear when starting the app on mobile ([572c9b7](https://github.com/standardnotes/app/commit/572c9b7dfaa42773c050772940e383df2940a79f))
|
||||
|
||||
## [3.181.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/web
|
||||
|
||||
## [3.181.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/web
|
||||
|
||||
# [3.181.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
|
||||
|
||||
### Features
|
||||
|
||||
* When exporting a Super note, embedded files can be inlined in the note or exported along the note in a zip file. You can now also choose to include frontmatter when exporting to Markdown format.
|
||||
|
||||
## [3.180.8](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/web
|
||||
|
||||
## [3.180.7](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-29)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Fixed issue with checklist items in Super notes not being correctly exported to HTML ([198efdc](https://github.com/standardnotes/app/commit/198efdc41c403ce10a40fc2f20345d5b44c83462))
|
||||
|
||||
## [3.180.6](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-29)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/web
|
||||
|
||||
## [3.180.5](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-29)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/web
|
||||
|
||||
## [3.180.4](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-28)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Fixed check list indentation in Super notes ([ce0db04](https://github.com/standardnotes/app/commit/ce0db04646737ec1dcb88ac989cd12927c46a156))
|
||||
|
||||
## [3.180.3](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-27)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/web
|
||||
|
||||
## [3.180.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-27)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/web
|
||||
|
||||
## [3.180.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-27)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/web
|
||||
|
||||
# [3.180.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-27)
|
||||
|
||||
### Features
|
||||
|
||||
* Re-enabled multiple selection on mobile, with improved UI ([#2609](https://github.com/standardnotes/app/issues/2609)) ([c8dec9b](https://github.com/standardnotes/app/commit/c8dec9bfecc77257e686fe02e36973318145c16e))
|
||||
|
||||
## [3.179.4](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-26)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/web
|
||||
|
||||
## [3.179.3](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-26)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/web
|
||||
|
||||
## [3.179.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-26)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/web
|
||||
|
||||
## [3.179.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-25)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Fixed issue where some menus would get hidden behind the keyboard on iOS ([c1ee705](https://github.com/standardnotes/app/commit/c1ee705402ed63910ef733464796ab5f848c5ac4))
|
||||
|
||||
# [3.179.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-25)
|
||||
|
||||
### Features
|
||||
|
||||
* Added preference to toggle Super note toolbar visibility. When toggled off, the toolbar will only be visible when text is selected as a floating toolbar. [skip e2e] ([a616750](https://github.com/standardnotes/app/commit/a616750aea3666079aa6ae301662ce4cd4d5c954))
|
||||
* Added preference to toggle Super note toolbar visibility. When toggled off, the toolbar will only be visible when text is selected as a floating toolbar. ([a616750](https://github.com/standardnotes/app/commit/a616750aea3666079aa6ae301662ce4cd4d5c954))
|
||||
|
||||
## [3.178.19](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-25)
|
||||
|
||||
|
||||
@@ -1,16 +1,235 @@
|
||||
{
|
||||
"versions": [
|
||||
{
|
||||
"version": "3.181.4",
|
||||
"title": "[3.181.4](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)",
|
||||
"date": null,
|
||||
"body": "### Bug Fixes\n\n* Fixed issue where exporting multiple files with the same name would error ([f408950](https://github.com/standardnotes/app/commit/f408950aa4e59389db81a4ca2b9db5ea49147aaf))",
|
||||
"parsed": {
|
||||
"_": [
|
||||
"Fixed issue where exporting multiple files with the same name would error (f408950)"
|
||||
],
|
||||
"Bug Fixes": [
|
||||
"Fixed issue where exporting multiple files with the same name would error (f408950)"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"version": "3.181.3",
|
||||
"title": "[3.181.3](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)",
|
||||
"date": null,
|
||||
"body": "### Bug Fixes\n\n* Fixed issue where a brief flash of white would appear when starting the app on mobile ([572c9b7](https://github.com/standardnotes/app/commit/572c9b7dfaa42773c050772940e383df2940a79f))",
|
||||
"parsed": {
|
||||
"_": [
|
||||
"Fixed issue where a brief flash of white would appear when starting the app on mobile (572c9b7)"
|
||||
],
|
||||
"Bug Fixes": [
|
||||
"Fixed issue where a brief flash of white would appear when starting the app on mobile (572c9b7)"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"version": "3.181.2",
|
||||
"title": "[3.181.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-31)",
|
||||
"date": null,
|
||||
"body": "**Note:** Version bump only for package @standardnotes/web",
|
||||
"parsed": {
|
||||
"_": [
|
||||
"Note: Version bump only for package @standardnotes/web"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"version": "3.181.1",
|
||||
"title": "[3.181.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)",
|
||||
"date": null,
|
||||
"body": "**Note:** Version bump only for package @standardnotes/web",
|
||||
"parsed": {
|
||||
"_": [
|
||||
"Note: Version bump only for package @standardnotes/web"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"version": "3.181.0",
|
||||
"title": "[3.181.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)",
|
||||
"date": null,
|
||||
"body": "### Features\n\n* When exporting a Super note, embedded files can be inlined in the note or exported along the note in a zip file. You can now also choose to include frontmatter when exporting to Markdown format.",
|
||||
"parsed": {
|
||||
"_": [
|
||||
"When exporting a Super note, embedded files can be inlined in the note or exported along the note in a zip file. You can now also choose to include frontmatter when exporting to Markdown format."
|
||||
],
|
||||
"Features": [
|
||||
"When exporting a Super note, embedded files can be inlined in the note or exported along the note in a zip file. You can now also choose to include frontmatter when exporting to Markdown format."
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"version": "3.180.8",
|
||||
"title": "[3.180.8](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-30)",
|
||||
"date": null,
|
||||
"body": "**Note:** Version bump only for package @standardnotes/web",
|
||||
"parsed": {
|
||||
"_": [
|
||||
"Note: Version bump only for package @standardnotes/web"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"version": "3.180.7",
|
||||
"title": "[3.180.7](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-29)",
|
||||
"date": null,
|
||||
"body": "### Bug Fixes\n\n* Fixed issue with checklist items in Super notes not being correctly exported to HTML ([198efdc](https://github.com/standardnotes/app/commit/198efdc41c403ce10a40fc2f20345d5b44c83462))",
|
||||
"parsed": {
|
||||
"_": [
|
||||
"Fixed issue with checklist items in Super notes not being correctly exported to HTML (198efdc)"
|
||||
],
|
||||
"Bug Fixes": [
|
||||
"Fixed issue with checklist items in Super notes not being correctly exported to HTML (198efdc)"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"version": "3.180.6",
|
||||
"title": "[3.180.6](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-29)",
|
||||
"date": null,
|
||||
"body": "**Note:** Version bump only for package @standardnotes/web",
|
||||
"parsed": {
|
||||
"_": [
|
||||
"Note: Version bump only for package @standardnotes/web"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"version": "3.180.5",
|
||||
"title": "[3.180.5](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-29)",
|
||||
"date": null,
|
||||
"body": "**Note:** Version bump only for package @standardnotes/web",
|
||||
"parsed": {
|
||||
"_": [
|
||||
"Note: Version bump only for package @standardnotes/web"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"version": "3.180.4",
|
||||
"title": "[3.180.4](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-28)",
|
||||
"date": null,
|
||||
"body": "### Bug Fixes\n\n* Fixed check list indentation in Super notes ([ce0db04](https://github.com/standardnotes/app/commit/ce0db04646737ec1dcb88ac989cd12927c46a156))",
|
||||
"parsed": {
|
||||
"_": [
|
||||
"Fixed check list indentation in Super notes (ce0db04)"
|
||||
],
|
||||
"Bug Fixes": [
|
||||
"Fixed check list indentation in Super notes (ce0db04)"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"version": "3.180.3",
|
||||
"title": "[3.180.3](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-27)",
|
||||
"date": null,
|
||||
"body": "**Note:** Version bump only for package @standardnotes/web",
|
||||
"parsed": {
|
||||
"_": [
|
||||
"Note: Version bump only for package @standardnotes/web"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"version": "3.180.2",
|
||||
"title": "[3.180.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-27)",
|
||||
"date": null,
|
||||
"body": "**Note:** Version bump only for package @standardnotes/web",
|
||||
"parsed": {
|
||||
"_": [
|
||||
"Note: Version bump only for package @standardnotes/web"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"version": "3.180.1",
|
||||
"title": "[3.180.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-27)",
|
||||
"date": null,
|
||||
"body": "**Note:** Version bump only for package @standardnotes/web",
|
||||
"parsed": {
|
||||
"_": [
|
||||
"Note: Version bump only for package @standardnotes/web"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"version": "3.180.0",
|
||||
"title": "[3.180.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-27)",
|
||||
"date": null,
|
||||
"body": "### Features\n\n* Re-enabled multiple selection on mobile, with improved UI ([#2609](https://github.com/standardnotes/app/issues/2609)) ([c8dec9b](https://github.com/standardnotes/app/commit/c8dec9bfecc77257e686fe02e36973318145c16e))",
|
||||
"parsed": {
|
||||
"_": [
|
||||
"Re-enabled multiple selection on mobile, with improved UI (#2609) (c8dec9b)"
|
||||
],
|
||||
"Features": [
|
||||
"Re-enabled multiple selection on mobile, with improved UI (#2609) (c8dec9b)"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"version": "3.179.4",
|
||||
"title": "[3.179.4](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-26)",
|
||||
"date": null,
|
||||
"body": "**Note:** Version bump only for package @standardnotes/web",
|
||||
"parsed": {
|
||||
"_": [
|
||||
"Note: Version bump only for package @standardnotes/web"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"version": "3.179.3",
|
||||
"title": "[3.179.3](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-26)",
|
||||
"date": null,
|
||||
"body": "**Note:** Version bump only for package @standardnotes/web",
|
||||
"parsed": {
|
||||
"_": [
|
||||
"Note: Version bump only for package @standardnotes/web"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"version": "3.179.2",
|
||||
"title": "[3.179.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-26)",
|
||||
"date": null,
|
||||
"body": "**Note:** Version bump only for package @standardnotes/web",
|
||||
"parsed": {
|
||||
"_": [
|
||||
"Note: Version bump only for package @standardnotes/web"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"version": "3.179.1",
|
||||
"title": "[3.179.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-25)",
|
||||
"date": null,
|
||||
"body": "### Bug Fixes\n\n* Fixed issue where some menus would get hidden behind the keyboard on iOS ([c1ee705](https://github.com/standardnotes/app/commit/c1ee705402ed63910ef733464796ab5f848c5ac4))",
|
||||
"parsed": {
|
||||
"_": [
|
||||
"Fixed issue where some menus would get hidden behind the keyboard on iOS (c1ee705)"
|
||||
],
|
||||
"Bug Fixes": [
|
||||
"Fixed issue where some menus would get hidden behind the keyboard on iOS (c1ee705)"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"version": "3.179.0",
|
||||
"title": "[3.179.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2023-10-25)",
|
||||
"date": null,
|
||||
"body": "### Features\n\n* Added preference to toggle Super note toolbar visibility. When toggled off, the toolbar will only be visible when text is selected as a floating toolbar. [skip e2e] ([a616750](https://github.com/standardnotes/app/commit/a616750aea3666079aa6ae301662ce4cd4d5c954))",
|
||||
"body": "### Features\n\n* Added preference to toggle Super note toolbar visibility. When toggled off, the toolbar will only be visible when text is selected as a floating toolbar. ([a616750](https://github.com/standardnotes/app/commit/a616750aea3666079aa6ae301662ce4cd4d5c954))",
|
||||
"parsed": {
|
||||
"_": [
|
||||
"Added preference to toggle Super note toolbar visibility. When toggled off, the toolbar will only be visible when text is selected as a floating toolbar. skip e2e] ([a616750)"
|
||||
"Added preference to toggle Super note toolbar visibility. When toggled off, the toolbar will only be visible when text is selected as a floating toolbar. (a616750)"
|
||||
],
|
||||
"Features": [
|
||||
"Added preference to toggle Super note toolbar visibility. When toggled off, the toolbar will only be visible when text is selected as a floating toolbar. skip e2e] ([a616750)"
|
||||
"Added preference to toggle Super note toolbar visibility. When toggled off, the toolbar will only be visible when text is selected as a floating toolbar. (a616750)"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/web",
|
||||
"version": "3.179.0",
|
||||
"version": "3.181.4",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "dist/app.js",
|
||||
"author": "Standard Notes",
|
||||
|
||||
@@ -7,7 +7,7 @@ import { ListableContentItem } from './Types/ListableContentItem'
|
||||
import ContentListItem from './ContentListItem'
|
||||
import { ElementIds } from '@/Constants/ElementIDs'
|
||||
import { classNames } from '@standardnotes/utils'
|
||||
import { ContentType, SNTag } from '@standardnotes/snjs'
|
||||
import { SNTag } from '@standardnotes/snjs'
|
||||
import { ItemListController } from '@/Controllers/ItemList/ItemListController'
|
||||
|
||||
type Props = {
|
||||
@@ -78,15 +78,12 @@ const ContentList: FunctionComponent<Props> = ({ application, items, selectedUui
|
||||
[hideTags, selectedTag, application],
|
||||
)
|
||||
|
||||
const hasNotes = items.some((item) => item.content_type === ContentType.TYPES.Note)
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classNames(
|
||||
'infinite-scroll overflow-y-auto overflow-x-hidden focus:shadow-none focus:outline-none',
|
||||
'md:max-h-full md:overflow-y-hidden md:hover:overflow-y-auto pointer-coarse:md:overflow-y-auto',
|
||||
'flex flex-wrap pb-2 md:hover:[overflow-y:_overlay]',
|
||||
hasNotes ? 'justify-center' : 'justify-center md:justify-start md:pl-1',
|
||||
'flex-grow pb-2 md:hover:[overflow-y:_overlay]',
|
||||
)}
|
||||
id={ElementIds.ContentList}
|
||||
onScroll={onScroll}
|
||||
|
||||
@@ -33,6 +33,9 @@ import EmptyFilesView from './EmptyFilesView'
|
||||
import { PaneLayout } from '@/Controllers/PaneController/PaneLayout'
|
||||
import { usePaneSwipeGesture } from '../Panes/usePaneGesture'
|
||||
import { mergeRefs } from '@/Hooks/mergeRefs'
|
||||
import Icon from '../Icon/Icon'
|
||||
import MobileMultiSelectionToolbar from './MobileMultiSelectionToolbar'
|
||||
import StyledTooltip from '../StyledTooltip/StyledTooltip'
|
||||
|
||||
type Props = {
|
||||
application: WebApplication
|
||||
@@ -53,6 +56,7 @@ const ContentListView = forwardRef<HTMLDivElement, Props>(
|
||||
noAccountWarningController,
|
||||
searchOptionsController,
|
||||
linkingController,
|
||||
notesController,
|
||||
} = application
|
||||
|
||||
const { setPaneLayout, panes } = useResponsiveAppPane()
|
||||
@@ -285,7 +289,7 @@ const ContentListView = forwardRef<HTMLDivElement, Props>(
|
||||
aria-label={'Notes & Files'}
|
||||
ref={mergeRefs([innerRef, setElement])}
|
||||
>
|
||||
{isMobileScreen && (
|
||||
{isMobileScreen && !itemListController.isMultipleSelectionMode && (
|
||||
<FloatingAddButton onClick={addNewItem} label={addButtonLabel} style={dailyMode ? 'danger' : 'info'} />
|
||||
)}
|
||||
<div id="items-title-bar" className="section-title-bar border-b border-solid border-border">
|
||||
@@ -319,6 +323,33 @@ const ContentListView = forwardRef<HTMLDivElement, Props>(
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{itemListController.isMultipleSelectionMode && (
|
||||
<div className="flex items-center border-b border-l-2 border-border border-l-transparent py-2.5 pr-4">
|
||||
<div className="px-4">
|
||||
<StyledTooltip label="Select all items" showOnHover showOnMobile>
|
||||
<button
|
||||
className="ml-auto rounded border border-border p-1 hover:bg-contrast"
|
||||
onClick={() => {
|
||||
itemListController.selectAll()
|
||||
}}
|
||||
>
|
||||
<Icon type="select-all" size="medium" />
|
||||
</button>
|
||||
</StyledTooltip>
|
||||
</div>
|
||||
<div className="text-base font-semibold md:text-sm">{itemListController.selectedItemsCount} selected</div>
|
||||
<StyledTooltip label="Cancel multiple selection" showOnHover showOnMobile>
|
||||
<button
|
||||
className="ml-auto rounded border border-border p-1 hover:bg-contrast"
|
||||
onClick={() => {
|
||||
itemListController.cancelMultipleSelection()
|
||||
}}
|
||||
>
|
||||
<Icon type="close" size="medium" />
|
||||
</button>
|
||||
</StyledTooltip>
|
||||
</div>
|
||||
)}
|
||||
{selectedAsTag && dailyMode && (
|
||||
<DailyContentList
|
||||
items={items}
|
||||
@@ -350,6 +381,9 @@ const ContentListView = forwardRef<HTMLDivElement, Props>(
|
||||
/>
|
||||
)
|
||||
) : null}
|
||||
{isMobileScreen && itemListController.isMultipleSelectionMode && (
|
||||
<MobileMultiSelectionToolbar notesController={notesController} />
|
||||
)}
|
||||
<div className="absolute bottom-0 h-safe-bottom w-full" />
|
||||
{children}
|
||||
</div>
|
||||
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
import { NotesController } from '@/Controllers/NotesController/NotesController'
|
||||
import Icon from '../Icon/Icon'
|
||||
|
||||
type Props = {
|
||||
notesController: NotesController
|
||||
}
|
||||
|
||||
const MobileMultiSelectionToolbar = ({ notesController }: Props) => {
|
||||
const { selectedNotes } = notesController
|
||||
|
||||
const archived = selectedNotes.some((note) => note.archived)
|
||||
|
||||
return (
|
||||
<div className="flex w-full bg-contrast pb-safe-bottom">
|
||||
<button
|
||||
className="flex-grow px-2 py-3 active:bg-passive-3"
|
||||
onClick={() => notesController.togglePinSelectedNotes()}
|
||||
>
|
||||
<Icon type="pin" className="mx-auto text-info" size="large" />
|
||||
</button>
|
||||
<button
|
||||
className="flex-grow px-2 py-3 active:bg-passive-3"
|
||||
onClick={() => notesController.toggleArchiveSelectedNotes().catch(console.error)}
|
||||
>
|
||||
<Icon type={archived ? 'unarchive' : 'archive'} className="mx-auto text-info" size="large" />
|
||||
</button>
|
||||
<button
|
||||
className="flex-grow px-2 py-3 active:bg-passive-3"
|
||||
onClick={() => notesController.setTrashSelectedNotes(true).catch(console.error)}
|
||||
>
|
||||
<Icon type="trash" className="mx-auto text-info" size="large" />
|
||||
</button>
|
||||
<button
|
||||
className="flex-grow px-2 py-3 active:bg-passive-3"
|
||||
onClick={() => notesController.setContextMenuOpen(true)}
|
||||
>
|
||||
<Icon type="more" className="mx-auto text-info" size="large" />
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default MobileMultiSelectionToolbar
|
||||
@@ -1,6 +1,6 @@
|
||||
import { isFile, SNNote } from '@standardnotes/snjs'
|
||||
import { observer } from 'mobx-react-lite'
|
||||
import { FunctionComponent, useCallback, useRef } from 'react'
|
||||
import { FunctionComponent, MouseEvent, useCallback, useRef } from 'react'
|
||||
import Icon from '@/Components/Icon/Icon'
|
||||
import ListItemConflictIndicator from './ListItemConflictIndicator'
|
||||
import ListItemFlagIcons from './ListItemFlagIcons'
|
||||
@@ -17,6 +17,7 @@ import ListItemVaultInfo from './ListItemVaultInfo'
|
||||
import { NoteDragDataFormat } from '../Tags/DragNDrop'
|
||||
import { MutuallyExclusiveMediaQueryBreakpoints, useMediaQuery } from '@/Hooks/useMediaQuery'
|
||||
import useItem from '@/Hooks/useItem'
|
||||
import CheckIndicator from '../Checkbox/CheckIndicator'
|
||||
|
||||
const NoteListItem: FunctionComponent<DisplayableListItemProps<SNNote>> = ({
|
||||
application,
|
||||
@@ -50,7 +51,17 @@ const NoteListItem: FunctionComponent<DisplayableListItemProps<SNNote>> = ({
|
||||
notesController.setContextMenuOpen(true)
|
||||
}
|
||||
|
||||
const openContextMenu = async (posX: number, posY: number) => {
|
||||
const isMobileScreen = useMediaQuery(MutuallyExclusiveMediaQueryBreakpoints.sm)
|
||||
|
||||
const handleContextMenuEvent = async (posX: number, posY: number) => {
|
||||
if (isMobileScreen) {
|
||||
if (!application.itemListController.isMultipleSelectionMode) {
|
||||
application.itemListController.replaceSelection(item)
|
||||
}
|
||||
application.itemListController.enableMultipleSelectionMode()
|
||||
return
|
||||
}
|
||||
|
||||
let shouldOpenContextMenu = selected
|
||||
|
||||
if (!selected) {
|
||||
@@ -65,17 +76,26 @@ const NoteListItem: FunctionComponent<DisplayableListItemProps<SNNote>> = ({
|
||||
}
|
||||
}
|
||||
|
||||
const onClick = useCallback(async () => {
|
||||
await onSelect(item, true)
|
||||
}, [item, onSelect])
|
||||
const onClick = useCallback(
|
||||
(event: MouseEvent) => {
|
||||
if ((event.ctrlKey || event.metaKey) && !application.itemListController.isMultipleSelectionMode) {
|
||||
application.itemListController.enableMultipleSelectionMode()
|
||||
}
|
||||
if (selected && !application.itemListController.isMultipleSelectionMode) {
|
||||
application.itemListController.openSingleSelectedItem({ userTriggered: true }).catch(console.error)
|
||||
return
|
||||
}
|
||||
onSelect(item, true).catch(console.error)
|
||||
},
|
||||
[application.itemListController, item, onSelect, selected],
|
||||
)
|
||||
|
||||
useContextMenuEvent(listItemRef, openContextMenu)
|
||||
useContextMenuEvent(listItemRef, handleContextMenuEvent)
|
||||
|
||||
log(LoggingDomain.ItemsList, 'Rendering note list item', item.title)
|
||||
|
||||
const hasOffsetBorder = !isNextItemTiled
|
||||
|
||||
const isMobileScreen = useMediaQuery(MutuallyExclusiveMediaQueryBreakpoints.sm)
|
||||
const dragPreview = useRef<HTMLDivElement>()
|
||||
|
||||
const createDragPreview = () => {
|
||||
@@ -108,14 +128,18 @@ const NoteListItem: FunctionComponent<DisplayableListItemProps<SNNote>> = ({
|
||||
ref={listItemRef}
|
||||
role="button"
|
||||
className={classNames(
|
||||
'content-list-item flex w-full cursor-pointer items-stretch text-text',
|
||||
selected && `selected border-l-2 border-solid border-accessory-tint-${tint}`,
|
||||
isPreviousItemTiled && 'mt-3 border-t border-solid border-t-border',
|
||||
isNextItemTiled && 'mb-3 border-b border-solid border-b-border',
|
||||
'content-list-item flex w-full cursor-pointer items-stretch border-l-2 text-text',
|
||||
selected
|
||||
? `selected ${
|
||||
application.itemListController.isMultipleSelectionMode ? 'border-info' : `border-accessory-tint-${tint}`
|
||||
}`
|
||||
: 'border-transparent',
|
||||
isPreviousItemTiled && 'mt-3 border-t border-t-border',
|
||||
isNextItemTiled && 'mb-3 border-b border-b-border',
|
||||
)}
|
||||
id={item.uuid}
|
||||
onClick={onClick}
|
||||
draggable={!isMobileScreen}
|
||||
draggable={!isMobileScreen && !application.itemListController.isMultipleSelectionMode}
|
||||
onDragStart={(event) => {
|
||||
if (!listItemRef.current) {
|
||||
return
|
||||
@@ -133,7 +157,11 @@ const NoteListItem: FunctionComponent<DisplayableListItemProps<SNNote>> = ({
|
||||
}
|
||||
}}
|
||||
>
|
||||
{!hideIcon ? (
|
||||
{application.itemListController.isMultipleSelectionMode ? (
|
||||
<div className="mr-0 flex flex-col items-center justify-between gap-2 p-4 pr-4">
|
||||
<CheckIndicator className="md:!h-5 md:!w-5" checked={selected} />
|
||||
</div>
|
||||
) : !hideIcon ? (
|
||||
<div className="mr-0 flex flex-col items-center justify-between gap-2 p-4 pr-4">
|
||||
<Icon type={icon} className={`text-accessory-tint-${tint}`} />
|
||||
</div>
|
||||
|
||||
@@ -65,6 +65,7 @@ export const IconNameToSvgMapping = {
|
||||
'premium-feature': icons.PremiumFeatureIcon,
|
||||
'rich-text': icons.RichTextIcon,
|
||||
'safe-square': icons.SafeSquareIcon,
|
||||
'select-all': icons.SelectAllIcon,
|
||||
'sort-descending': icons.SortDescendingIcon,
|
||||
'star-circle-filled': icons.StarCircleFilled,
|
||||
'star-filled': icons.StarFilledIcon,
|
||||
|
||||
@@ -35,6 +35,7 @@ const LinkedItemsButton = ({ linkingController, onClickPreprocessing }: Props) =
|
||||
anchorElement={buttonRef}
|
||||
open={isLinkingPanelOpen}
|
||||
className="pb-2"
|
||||
forceFullHeightOnMobile
|
||||
>
|
||||
<LinkedItemsPanel item={activeItem} />
|
||||
</Popover>
|
||||
|
||||
@@ -41,7 +41,7 @@ const MenuItem = forwardRef(
|
||||
tabIndex={typeof tabIndex === 'number' ? tabIndex : FOCUSABLE_BUT_NOT_TABBABLE}
|
||||
className={classNames(
|
||||
'flex w-full cursor-pointer select-none border-0 bg-transparent px-3 py-2.5 text-left md:py-1.5',
|
||||
'text-mobile-menu-item text-text enabled:hover:bg-contrast enabled:hover:text-foreground',
|
||||
'text-mobile-menu-item text-text enabled:hover:bg-passive-3 enabled:hover:text-foreground',
|
||||
'focus:bg-info-backdrop focus:shadow-none md:text-tablet-menu-item lg:text-menu-item',
|
||||
'disabled:cursor-not-allowed disabled:opacity-60',
|
||||
className,
|
||||
|
||||
@@ -75,7 +75,7 @@ const MenuRadioButtonItem = forwardRef(
|
||||
tabIndex={typeof tabIndex === 'number' ? tabIndex : FOCUSABLE_BUT_NOT_TABBABLE}
|
||||
className={classNames(
|
||||
'flex w-full cursor-pointer gap-2 border-0 bg-transparent px-3 py-2.5 text-left md:py-1.5',
|
||||
'text-mobile-menu-item text-text hover:bg-contrast hover:text-foreground',
|
||||
'text-mobile-menu-item text-text hover:bg-passive-3 hover:text-foreground',
|
||||
'focus:bg-info-backdrop focus:shadow-none md:text-tablet-menu-item lg:text-menu-item',
|
||||
className,
|
||||
className?.includes('items-') ? '' : 'items-center',
|
||||
|
||||
@@ -18,7 +18,7 @@ const MenuSection = ({
|
||||
)}
|
||||
>
|
||||
{title && <div className="px-3 py-1 text-sm font-semibold uppercase text-text lg:text-xs">{title}</div>}
|
||||
<div className="divide-y divide-passive-3 overflow-hidden rounded-md bg-passive-4 md:divide-none md:rounded-none md:bg-transparent">
|
||||
<div className="divide-y divide-passive-3 overflow-hidden rounded-md bg-default md:divide-none md:rounded-none md:bg-transparent">
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -37,7 +37,7 @@ const MenuSwitchButtonItem = forwardRef(
|
||||
ref={ref}
|
||||
className={classNames(
|
||||
'flex w-full cursor-pointer items-center border-0 bg-transparent px-3 py-2 md:py-1.5',
|
||||
'text-left text-text focus:bg-info-backdrop focus:shadow-none enabled:hover:bg-contrast enabled:hover:text-foreground',
|
||||
'text-left text-text focus:bg-info-backdrop focus:shadow-none enabled:hover:bg-passive-3 enabled:hover:text-foreground',
|
||||
'text-mobile-menu-item md:text-tablet-menu-item lg:text-menu-item',
|
||||
'disabled:cursor-not-allowed disabled:opacity-60',
|
||||
className,
|
||||
|
||||
+20
-16
@@ -27,25 +27,29 @@ export const DiffView = ({
|
||||
const [textDiff, setTextDiff] = useState<fastdiff.Diff[]>([])
|
||||
|
||||
useEffect(() => {
|
||||
const firstNote = selectedNotes[0]
|
||||
const firstTitle = firstNote.title
|
||||
const firstText =
|
||||
firstNote.noteType === NoteType.Super && convertSuperToMarkdown
|
||||
? new HeadlessSuperConverter().convertSuperStringToOtherFormat(firstNote.text, 'md')
|
||||
: firstNote.text
|
||||
const setDiffs = async () => {
|
||||
const firstNote = selectedNotes[0]
|
||||
const firstTitle = firstNote.title
|
||||
const firstText =
|
||||
firstNote.noteType === NoteType.Super && convertSuperToMarkdown
|
||||
? await 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().convertSuperStringToOtherFormat(secondNote.text, 'md')
|
||||
: secondNote.text
|
||||
const secondNote = selectedNotes[1]
|
||||
const secondTitle = secondNote.title
|
||||
const secondText =
|
||||
secondNote.noteType === NoteType.Super && convertSuperToMarkdown
|
||||
? await new HeadlessSuperConverter().convertSuperStringToOtherFormat(secondNote.text, 'md')
|
||||
: secondNote.text
|
||||
|
||||
const titleDiff = fastdiff(firstTitle, secondTitle, undefined, true)
|
||||
const textDiff = fastdiff(firstText, secondText, undefined, true)
|
||||
const titleDiff = fastdiff(firstTitle, secondTitle, undefined, true)
|
||||
const textDiff = fastdiff(firstText, secondText, undefined, true)
|
||||
|
||||
setTitleDiff(titleDiff)
|
||||
setTextDiff(textDiff)
|
||||
setTitleDiff(titleDiff)
|
||||
setTextDiff(textDiff)
|
||||
}
|
||||
|
||||
setDiffs().catch(console.error)
|
||||
}, [convertSuperToMarkdown, selectedNotes])
|
||||
|
||||
const [preElement, setPreElement] = useState<HTMLPreElement | null>(null)
|
||||
|
||||
@@ -29,7 +29,7 @@ import {
|
||||
VaultUserServiceEvent,
|
||||
} from '@standardnotes/snjs'
|
||||
import { confirmDialog, DELETE_NOTE_KEYBOARD_COMMAND, KeyboardKey } from '@standardnotes/ui-services'
|
||||
import { ChangeEventHandler, createRef, CSSProperties, KeyboardEventHandler, RefObject } from 'react'
|
||||
import { ChangeEventHandler, createRef, CSSProperties, FocusEvent, KeyboardEventHandler, RefObject } from 'react'
|
||||
import { SuperEditor } from '../SuperEditor/SuperEditor'
|
||||
import IndicatorCircle from '../IndicatorCircle/IndicatorCircle'
|
||||
import LinkedItemBubblesContainer from '../LinkedItems/LinkedItemBubblesContainer'
|
||||
@@ -826,7 +826,10 @@ class NoteView extends AbstractComponent<NoteViewProps, State> {
|
||||
this.setState({ plainEditorFocused: true })
|
||||
}
|
||||
|
||||
onPlainBlur = () => {
|
||||
onPlainBlur = (event: FocusEvent) => {
|
||||
if (event.relatedTarget?.id === ElementIds.NoteOptionsButton) {
|
||||
return
|
||||
}
|
||||
this.setState({ plainEditorFocused: false })
|
||||
}
|
||||
|
||||
@@ -897,8 +900,9 @@ class NoteView extends AbstractComponent<NoteViewProps, State> {
|
||||
>
|
||||
<div
|
||||
className={classNames(
|
||||
'mb-2 flex flex-wrap justify-between gap-2 md:mb-0 md:flex-nowrap md:gap-4 xl:items-center',
|
||||
'mb-2 flex justify-between md:mb-0 md:flex-nowrap md:gap-4 xl:items-center',
|
||||
shouldShowConflictsButton ? 'items-center' : 'items-start',
|
||||
!renderHeaderOptions ? 'flex-nowrap gap-4' : 'flex-wrap gap-2 ',
|
||||
)}
|
||||
>
|
||||
<div className={classNames(this.state.noteLocked && 'locked', 'flex flex-grow items-center')}>
|
||||
@@ -937,30 +941,33 @@ class NoteView extends AbstractComponent<NoteViewProps, State> {
|
||||
{pluralize(this.state.conflictedNotes.length, 'conflict', 'conflicts')}
|
||||
</Button>
|
||||
)}
|
||||
{renderHeaderOptions && (
|
||||
<div className="note-view-options-buttons flex items-center gap-3">
|
||||
{!this.state.readonly && (
|
||||
<>
|
||||
<LinkedItemsButton
|
||||
linkingController={this.application.linkingController}
|
||||
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
|
||||
/>
|
||||
<ChangeEditorButton
|
||||
noteViewController={this.controller}
|
||||
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
|
||||
/>
|
||||
<PinNoteButton
|
||||
notesController={this.application.notesController}
|
||||
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
<NotesOptionsPanel
|
||||
notesController={this.application.notesController}
|
||||
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div className="note-view-options-buttons flex items-center gap-3">
|
||||
{!this.state.readonly && renderHeaderOptions && (
|
||||
<>
|
||||
<LinkedItemsButton
|
||||
linkingController={this.application.linkingController}
|
||||
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
|
||||
/>
|
||||
<ChangeEditorButton
|
||||
noteViewController={this.controller}
|
||||
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
|
||||
/>
|
||||
<PinNoteButton
|
||||
notesController={this.application.notesController}
|
||||
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
<NotesOptionsPanel
|
||||
notesController={this.application.notesController}
|
||||
onClickPreprocessing={this.ensureNoteIsInsertedBeforeUIAction}
|
||||
onButtonBlur={() => {
|
||||
this.setState({
|
||||
plainEditorFocused: false,
|
||||
})
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mb-1 mt-2.5 md:hidden">
|
||||
<CollaborationInfoHUD item={this.note} />
|
||||
|
||||
@@ -16,7 +16,16 @@ import {
|
||||
PrefDefaults,
|
||||
} from '@standardnotes/snjs'
|
||||
import { TAB_COMMAND } from '@standardnotes/ui-services'
|
||||
import { ChangeEventHandler, forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState } from 'react'
|
||||
import {
|
||||
ChangeEventHandler,
|
||||
forwardRef,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useImperativeHandle,
|
||||
useRef,
|
||||
useState,
|
||||
FocusEvent,
|
||||
} from 'react'
|
||||
import { NoteViewController } from '../Controller/NoteViewController'
|
||||
|
||||
type Props = {
|
||||
@@ -25,7 +34,7 @@ type Props = {
|
||||
controller: NoteViewController
|
||||
locked: boolean
|
||||
onFocus: () => void
|
||||
onBlur: () => void
|
||||
onBlur: (event: FocusEvent) => void
|
||||
}
|
||||
|
||||
export type PlainEditorInterface = {
|
||||
@@ -106,13 +115,16 @@ export const PlainEditor = forwardRef<PlainEditorInterface, Props>(
|
||||
onFocus()
|
||||
}, [application, isAdjustingMobileCursor, lastEditorFocusEventSource, onFocus])
|
||||
|
||||
const onContentBlur = useCallback(() => {
|
||||
if (lastEditorFocusEventSource.current) {
|
||||
application.notifyWebEvent(WebAppEvent.EditorFocused, { eventSource: lastEditorFocusEventSource })
|
||||
}
|
||||
lastEditorFocusEventSource.current = undefined
|
||||
onBlur()
|
||||
}, [application, lastEditorFocusEventSource, onBlur])
|
||||
const onContentBlur = useCallback(
|
||||
(event: FocusEvent) => {
|
||||
if (lastEditorFocusEventSource.current) {
|
||||
application.notifyWebEvent(WebAppEvent.EditorFocused, { eventSource: lastEditorFocusEventSource })
|
||||
}
|
||||
lastEditorFocusEventSource.current = undefined
|
||||
onBlur(event)
|
||||
},
|
||||
[application, lastEditorFocusEventSource, onBlur],
|
||||
)
|
||||
|
||||
const scrollMobileCursorIntoViewAfterWebviewResize = useCallback(() => {
|
||||
if (needsAdjustMobileCursor.current) {
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
import Icon from '@/Components/Icon/Icon'
|
||||
import { observer } from 'mobx-react-lite'
|
||||
import { useState, useEffect, useMemo, useCallback, useRef } from 'react'
|
||||
import { NoteType, Platform, SNNote } from '@standardnotes/snjs'
|
||||
import { useState, useEffect, useMemo, useCallback } from 'react'
|
||||
import { NoteType, Platform, SNNote, pluralize } from '@standardnotes/snjs'
|
||||
import {
|
||||
CHANGE_EDITOR_WIDTH_COMMAND,
|
||||
OPEN_NOTE_HISTORY_COMMAND,
|
||||
PIN_NOTE_COMMAND,
|
||||
SHOW_HIDDEN_OPTIONS_KEYBOARD_COMMAND,
|
||||
STAR_NOTE_COMMAND,
|
||||
SUPER_EXPORT_HTML,
|
||||
SUPER_EXPORT_JSON,
|
||||
SUPER_EXPORT_MARKDOWN,
|
||||
SUPER_SHOW_MARKDOWN_PREVIEW,
|
||||
} from '@standardnotes/ui-services'
|
||||
import ChangeEditorOption from './ChangeEditorOption'
|
||||
@@ -20,9 +17,7 @@ import { addToast, dismissToast, ToastType } from '@standardnotes/toast'
|
||||
import { NotesOptionsProps } from './NotesOptionsProps'
|
||||
import { useResponsiveAppPane } from '../Panes/ResponsivePaneProvider'
|
||||
import { AppPaneId } from '../Panes/AppPaneMetadata'
|
||||
import { getNoteBlob, getNoteFileName } from '@/Utils/NoteExportUtils'
|
||||
import { shareSelectedNotes } from '@/NativeMobileWeb/ShareSelectedNotes'
|
||||
import { downloadSelectedNotesOnAndroid } from '@/NativeMobileWeb/DownloadSelectedNotesOnAndroid'
|
||||
import { createNoteExport } from '@/Utils/NoteExportUtils'
|
||||
import ProtectedUnauthorizedLabel from '../ProtectedItemOverlay/ProtectedUnauthorizedLabel'
|
||||
import { MenuItemIconSize } from '@/Constants/TailwindClassNames'
|
||||
import { KeyboardShortcutIndicator } from '../KeyboardShortcutIndicator/KeyboardShortcutIndicator'
|
||||
@@ -39,9 +34,9 @@ import SuperExportModal from './SuperExportModal'
|
||||
import { useApplication } from '../ApplicationProvider'
|
||||
import { MutuallyExclusiveMediaQueryBreakpoints } from '@/Hooks/useMediaQuery'
|
||||
import AddToVaultMenuOption from '../Vaults/AddToVaultMenuOption'
|
||||
import Menu from '../Menu/Menu'
|
||||
import Popover from '../Popover/Popover'
|
||||
import MenuSection from '../Menu/MenuSection'
|
||||
import { downloadOrShareBlobBasedOnPlatform } from '@/Utils/DownloadOrShareBasedOnPlatform'
|
||||
import { shareBlobOnMobile } from '@/NativeMobileWeb/ShareBlobOnMobile'
|
||||
|
||||
const iconSize = MenuItemIconSize
|
||||
const iconClassDanger = `text-danger mr-2 ${iconSize}`
|
||||
@@ -104,33 +99,48 @@ const NotesOptions = ({ notes, closeMenu }: NotesOptionsProps) => {
|
||||
}, [])
|
||||
|
||||
const downloadSelectedItems = useCallback(async () => {
|
||||
if (notes.length === 1) {
|
||||
const note = notes[0]
|
||||
const blob = getNoteBlob(application, note)
|
||||
application.archiveService.downloadData(blob, getNoteFileName(application, note))
|
||||
if (notes.length === 0) {
|
||||
return
|
||||
}
|
||||
const toast = addToast({
|
||||
type: ToastType.Progress,
|
||||
message: `Exporting ${notes.length} ${pluralize(notes.length, 'note', 'notes')}...`,
|
||||
})
|
||||
try {
|
||||
const result = await createNoteExport(application, notes)
|
||||
if (!result) {
|
||||
return
|
||||
}
|
||||
const { blob, fileName } = result
|
||||
void downloadOrShareBlobBasedOnPlatform({
|
||||
archiveService: application.archiveService,
|
||||
platform: application.platform,
|
||||
mobileDevice: application.mobileDevice,
|
||||
blob: blob,
|
||||
filename: fileName,
|
||||
isNativeMobileWeb: application.isNativeMobileWeb(),
|
||||
})
|
||||
dismissToast(toast)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
addToast({
|
||||
type: ToastType.Error,
|
||||
message: 'Could not export notes',
|
||||
})
|
||||
dismissToast(toast)
|
||||
}
|
||||
}, [application, notes])
|
||||
|
||||
const exportSelectedItems = useCallback(() => {
|
||||
const hasSuperNote = notes.some((note) => note.noteType === NoteType.Super)
|
||||
|
||||
if (hasSuperNote) {
|
||||
setShowExportSuperModal(true)
|
||||
return
|
||||
}
|
||||
|
||||
if (notes.length > 1) {
|
||||
const loadingToastId = addToast({
|
||||
type: ToastType.Loading,
|
||||
message: `Exporting ${notes.length} notes...`,
|
||||
})
|
||||
await application.archiveService.downloadDataAsZip(
|
||||
notes.map((note) => {
|
||||
return {
|
||||
name: getNoteFileName(application, note),
|
||||
content: getNoteBlob(application, note),
|
||||
}
|
||||
}),
|
||||
)
|
||||
dismissToast(loadingToastId)
|
||||
addToast({
|
||||
type: ToastType.Success,
|
||||
message: `Exported ${notes.length} notes`,
|
||||
})
|
||||
}
|
||||
}, [application, notes])
|
||||
downloadSelectedItems().catch(console.error)
|
||||
}, [downloadSelectedItems, notes])
|
||||
|
||||
const closeMenuAndToggleNotesList = useCallback(() => {
|
||||
const isMobileScreen = matchMedia(MutuallyExclusiveMediaQueryBreakpoints.sm).matches
|
||||
@@ -199,9 +209,6 @@ const NotesOptions = ({ notes, closeMenu }: NotesOptionsProps) => {
|
||||
[application],
|
||||
)
|
||||
|
||||
const superExportButtonRef = useRef<HTMLButtonElement>(null)
|
||||
const [isSuperExportMenuOpen, setIsSuperExportMenuOpen] = useState(false)
|
||||
|
||||
const unauthorized = notes.some((note) => !application.isAuthorizedToRenderItem(note))
|
||||
if (unauthorized) {
|
||||
return <ProtectedUnauthorizedLabel />
|
||||
@@ -224,8 +231,6 @@ const NotesOptions = ({ notes, closeMenu }: NotesOptionsProps) => {
|
||||
return null
|
||||
}
|
||||
|
||||
const isOnlySuperNoteSelected = notes.length === 1 && notes[0].noteType === NoteType.Super
|
||||
|
||||
return (
|
||||
<>
|
||||
{notes.length === 1 && (
|
||||
@@ -289,7 +294,7 @@ const NotesOptions = ({ notes, closeMenu }: NotesOptionsProps) => {
|
||||
</MenuSection>
|
||||
)}
|
||||
|
||||
<MenuSection>
|
||||
<MenuSection className={notes.length > 1 ? 'md:!mb-2' : ''}>
|
||||
{application.featuresController.isVaultsEnabled() && (
|
||||
<AddToVaultMenuOption
|
||||
iconClassName={iconClass}
|
||||
@@ -342,77 +347,35 @@ const NotesOptions = ({ notes, closeMenu }: NotesOptionsProps) => {
|
||||
{pinShortcut && <KeyboardShortcutIndicator className="ml-auto" shortcut={pinShortcut} />}
|
||||
</MenuItem>
|
||||
)}
|
||||
{isOnlySuperNoteSelected ? (
|
||||
<>
|
||||
<MenuItem
|
||||
ref={superExportButtonRef}
|
||||
onClick={() => {
|
||||
setIsSuperExportMenuOpen((open) => !open)
|
||||
}}
|
||||
>
|
||||
<div className="flex items-center">
|
||||
<Icon type="download" className={iconClass} />
|
||||
Export
|
||||
</div>
|
||||
<Icon type="chevron-right" className="ml-auto text-neutral" />
|
||||
</MenuItem>
|
||||
<Popover
|
||||
title="Export note"
|
||||
side="left"
|
||||
align="start"
|
||||
open={isSuperExportMenuOpen}
|
||||
anchorElement={superExportButtonRef.current}
|
||||
togglePopover={() => {
|
||||
setIsSuperExportMenuOpen(!isSuperExportMenuOpen)
|
||||
}}
|
||||
className="md:py-1"
|
||||
>
|
||||
<Menu a11yLabel={'Super note export menu'}>
|
||||
<MenuSection>
|
||||
<MenuItem onClick={() => commandService.triggerCommand(SUPER_EXPORT_JSON, notes[0].title)}>
|
||||
<Icon type="code" className={iconClass} />
|
||||
Export as JSON
|
||||
</MenuItem>
|
||||
<MenuItem onClick={() => commandService.triggerCommand(SUPER_EXPORT_MARKDOWN, notes[0].title)}>
|
||||
<Icon type="markdown" className={iconClass} />
|
||||
Export as Markdown
|
||||
</MenuItem>
|
||||
<MenuItem onClick={() => commandService.triggerCommand(SUPER_EXPORT_HTML, notes[0].title)}>
|
||||
<Icon type="rich-text" className={iconClass} />
|
||||
Export as HTML
|
||||
</MenuItem>
|
||||
</MenuSection>
|
||||
</Menu>
|
||||
</Popover>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
if (application.isNativeMobileWeb()) {
|
||||
void shareSelectedNotes(application, notes)
|
||||
} else {
|
||||
const hasSuperNote = notes.some((note) => note.noteType === NoteType.Super)
|
||||
|
||||
if (hasSuperNote) {
|
||||
setShowExportSuperModal(true)
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
if (application.isNativeMobileWeb()) {
|
||||
createNoteExport(application, notes)
|
||||
.then((result) => {
|
||||
if (!result) {
|
||||
return
|
||||
}
|
||||
|
||||
void downloadSelectedItems()
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Icon type={application.platform === Platform.Android ? 'share' : 'download'} className={iconClass} />
|
||||
{application.platform === Platform.Android ? 'Share' : 'Export'}
|
||||
</MenuItem>
|
||||
{application.platform === Platform.Android && (
|
||||
<MenuItem onClick={() => downloadSelectedNotesOnAndroid(application, notes)}>
|
||||
<Icon type="download" className={iconClass} />
|
||||
Export
|
||||
</MenuItem>
|
||||
)}
|
||||
</>
|
||||
const { blob, fileName } = result
|
||||
|
||||
shareBlobOnMobile(application.mobileDevice, application.isNativeMobileWeb(), blob, fileName).catch(
|
||||
console.error,
|
||||
)
|
||||
})
|
||||
.catch(console.error)
|
||||
} else {
|
||||
exportSelectedItems()
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Icon type={application.platform === Platform.Android ? 'share' : 'download'} className={iconClass} />
|
||||
{application.platform === Platform.Android ? 'Share' : 'Export'}
|
||||
</MenuItem>
|
||||
{application.platform === Platform.Android && (
|
||||
<MenuItem onClick={exportSelectedItems}>
|
||||
<Icon type="download" className={iconClass} />
|
||||
Export
|
||||
</MenuItem>
|
||||
)}
|
||||
<MenuItem onClick={duplicateSelectedItems} disabled={areSomeNotesInReadonlySharedVault}>
|
||||
<Icon type="copy" className={iconClass} />
|
||||
@@ -507,7 +470,7 @@ const NotesOptions = ({ notes, closeMenu }: NotesOptionsProps) => {
|
||||
)}
|
||||
</MenuSection>
|
||||
|
||||
{notes.length === 1 ? (
|
||||
{notes.length === 1 && (
|
||||
<>
|
||||
{notes[0].noteType === NoteType.Super && (
|
||||
<SuperNoteOptions
|
||||
@@ -538,8 +501,6 @@ const NotesOptions = ({ notes, closeMenu }: NotesOptionsProps) => {
|
||||
|
||||
<NoteSizeWarning note={notes[0]} />
|
||||
</>
|
||||
) : (
|
||||
<div className="h-2" />
|
||||
)}
|
||||
|
||||
<ModalOverlay isOpen={showExportSuperModal} close={closeSuperExportModal}>
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
import { useCallback, useRef, useState } from 'react'
|
||||
import { FocusEvent, useCallback, useRef, useState } from 'react'
|
||||
import { observer } from 'mobx-react-lite'
|
||||
import NotesOptions from './NotesOptions'
|
||||
import { NotesController } from '@/Controllers/NotesController/NotesController'
|
||||
import Popover from '../Popover/Popover'
|
||||
import RoundIconButton from '../Button/RoundIconButton'
|
||||
import Menu from '../Menu/Menu'
|
||||
import { ElementIds } from '@/Constants/ElementIDs'
|
||||
|
||||
type Props = {
|
||||
notesController: NotesController
|
||||
onClickPreprocessing?: () => Promise<void>
|
||||
onButtonBlur?: (event: FocusEvent) => void
|
||||
}
|
||||
|
||||
const NotesOptionsPanel = ({ notesController, onClickPreprocessing }: Props) => {
|
||||
const NotesOptionsPanel = ({ notesController, onClickPreprocessing, onButtonBlur }: Props) => {
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
const buttonRef = useRef<HTMLButtonElement>(null)
|
||||
|
||||
@@ -30,7 +32,14 @@ const NotesOptionsPanel = ({ notesController, onClickPreprocessing }: Props) =>
|
||||
|
||||
return (
|
||||
<>
|
||||
<RoundIconButton label="Note options menu" onClick={toggleMenu} ref={buttonRef} icon="more" />
|
||||
<RoundIconButton
|
||||
id={ElementIds.NoteOptionsButton}
|
||||
label="Note options menu"
|
||||
onClick={toggleMenu}
|
||||
onBlur={onButtonBlur}
|
||||
ref={buttonRef}
|
||||
icon="more"
|
||||
/>
|
||||
<Popover
|
||||
title="Note options"
|
||||
disableClickOutside={disableClickOutside}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { PrefKey, PrefValue } from '@standardnotes/snjs'
|
||||
import { useApplication } from '../ApplicationProvider'
|
||||
import Dropdown from '../Dropdown/Dropdown'
|
||||
import Modal from '../Modal/Modal'
|
||||
import usePreference from '@/Hooks/usePreference'
|
||||
import RadioButtonGroup from '../RadioButtonGroup/RadioButtonGroup'
|
||||
import { useEffect } from 'react'
|
||||
import Switch from '../Switch/Switch'
|
||||
|
||||
type Props = {
|
||||
exportNotes: () => void
|
||||
@@ -12,6 +14,17 @@ type Props = {
|
||||
const SuperExportModal = ({ exportNotes, close }: Props) => {
|
||||
const application = useApplication()
|
||||
const superNoteExportFormat = usePreference(PrefKey.SuperNoteExportFormat)
|
||||
const superNoteExportEmbedBehavior = usePreference(PrefKey.SuperNoteExportEmbedBehavior)
|
||||
const superNoteExportUseMDFrontmatter = usePreference(PrefKey.SuperNoteExportUseMDFrontmatter)
|
||||
|
||||
useEffect(() => {
|
||||
if (superNoteExportFormat === 'json' && superNoteExportEmbedBehavior === 'separate') {
|
||||
void application.setPreference(PrefKey.SuperNoteExportEmbedBehavior, 'reference')
|
||||
}
|
||||
if (superNoteExportFormat === 'md' && superNoteExportEmbedBehavior === 'reference') {
|
||||
void application.setPreference(PrefKey.SuperNoteExportEmbedBehavior, 'separate')
|
||||
}
|
||||
}, [application, superNoteExportEmbedBehavior, superNoteExportFormat])
|
||||
|
||||
return (
|
||||
<Modal
|
||||
@@ -28,20 +41,21 @@ const SuperExportModal = ({ exportNotes, close }: Props) => {
|
||||
{
|
||||
label: 'Export',
|
||||
type: 'primary',
|
||||
onClick: exportNotes,
|
||||
onClick: () => {
|
||||
close()
|
||||
exportNotes()
|
||||
},
|
||||
mobileSlot: 'right',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<div className="mb-4">
|
||||
<div className="mb-1 text-base">
|
||||
We detected your selection includes Super notes. How do you want to export them?
|
||||
</div>
|
||||
<Dropdown
|
||||
label="Super notes export format"
|
||||
<div className="mb-2">
|
||||
<div className="mb-3 text-base">We detected your selection includes Super notes.</div>
|
||||
<div className="mb-1">What format do you want to export them in?</div>
|
||||
<RadioButtonGroup
|
||||
items={[
|
||||
{ label: 'Keep as Super', value: 'json' },
|
||||
{ label: 'Markdown', value: 'md' },
|
||||
{ label: 'Super (.json)', value: 'json' },
|
||||
{ label: 'Markdown (.md)', value: 'md' },
|
||||
{ label: 'HTML', value: 'html' },
|
||||
]}
|
||||
value={superNoteExportFormat}
|
||||
@@ -52,12 +66,47 @@ const SuperExportModal = ({ exportNotes, close }: Props) => {
|
||||
)
|
||||
}}
|
||||
/>
|
||||
{superNoteExportFormat === 'md' && (
|
||||
<div className="mt-2 text-xs text-passive-0">
|
||||
Note that conversion to Markdown is not lossless. Some features like collapsible blocks and formatting like
|
||||
superscript/subscript may not be correctly converted.
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="text-passive-0">
|
||||
Note that if you convert Super notes to Markdown then import them back into Standard Notes in the future, you
|
||||
will lose some formatting that the Markdown format is incapable of expressing, such as collapsible blocks and
|
||||
embeds.
|
||||
</div>
|
||||
{superNoteExportFormat === 'md' && (
|
||||
<div className="mt-4">
|
||||
<Switch
|
||||
checked={superNoteExportUseMDFrontmatter}
|
||||
onChange={(checked) => {
|
||||
void application.setPreference(
|
||||
PrefKey.SuperNoteExportUseMDFrontmatter,
|
||||
checked as PrefValue[PrefKey.SuperNoteExportUseMDFrontmatter],
|
||||
)
|
||||
}}
|
||||
className="!flex items-center"
|
||||
>
|
||||
<span className="ml-2">Export with frontmatter</span>
|
||||
</Switch>
|
||||
</div>
|
||||
)}
|
||||
{superNoteExportFormat !== 'json' && (
|
||||
<div className="mb-2 mt-4">
|
||||
<div className="mb-1">How do you want embedded files to be handled?</div>
|
||||
<RadioButtonGroup
|
||||
items={[
|
||||
{ label: 'Inline', value: 'inline' },
|
||||
{ label: 'Export separately', value: 'separate' },
|
||||
].concat(superNoteExportFormat !== 'md' ? [{ label: 'Keep as reference', value: 'reference' }] : [])}
|
||||
value={superNoteExportEmbedBehavior}
|
||||
onChange={(value) => {
|
||||
void application.setPreference(
|
||||
PrefKey.SuperNoteExportEmbedBehavior,
|
||||
value as PrefValue[PrefKey.SuperNoteExportEmbedBehavior],
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ const MobilePopoverContent = ({
|
||||
title,
|
||||
className,
|
||||
id,
|
||||
forceFullHeightOnMobile,
|
||||
}: {
|
||||
open: boolean
|
||||
requestClose: () => void
|
||||
@@ -31,6 +32,7 @@ const MobilePopoverContent = ({
|
||||
title: string
|
||||
id: string
|
||||
className?: string
|
||||
forceFullHeightOnMobile?: boolean
|
||||
}) => {
|
||||
const isMobileScreen = useMediaQuery(MutuallyExclusiveMediaQueryBreakpoints.sm)
|
||||
const [isMounted, setPopoverElement, element] = useModalAnimation(open, isMobileScreen)
|
||||
@@ -164,24 +166,35 @@ const MobilePopoverContent = ({
|
||||
return (
|
||||
<Portal>
|
||||
<DisableScroll />
|
||||
<div className="fixed inset-0 z-modal">
|
||||
<div className="absolute inset-0 z-0 bg-passive-4 opacity-0" ref={setUnderlayElement} />
|
||||
<div className="fixed left-0 top-0 z-modal h-full max-h-[var(--ios-viewport-height,_none)] w-full">
|
||||
<div className="absolute z-0 h-full w-full bg-passive-4 opacity-0" ref={setUnderlayElement} />
|
||||
<div
|
||||
ref={mergeRefs([setPopoverElement, addCloseMethod])}
|
||||
className="z-1 absolute bottom-0 flex max-h-[calc(100%_-_max(var(--safe-area-inset-top),2rem))] min-h-[40%] w-full flex-col rounded-t-xl bg-default pb-safe-bottom"
|
||||
className={classNames(
|
||||
'z-1 absolute bottom-0 flex max-h-[calc(100%_-_max(var(--safe-area-inset-top),2rem))] min-h-[40%] w-full flex-col rounded-t-xl bg-passive-5 pb-safe-bottom',
|
||||
forceFullHeightOnMobile && 'h-full',
|
||||
)}
|
||||
style={{
|
||||
boxShadow: '0px -4px 8px rgba(0, 0, 0, 0.075)',
|
||||
}}
|
||||
id={'popover/' + id}
|
||||
data-popover={id}
|
||||
data-mobile-popover
|
||||
>
|
||||
<div className="mx-auto mt-2 min-h-[0.3rem] w-12 rounded-full bg-passive-2" />
|
||||
<MobileModalHeader className="border-b border-border px-2 py-1.5 text-lg">
|
||||
<div className="w-full rounded-t-xl bg-default">
|
||||
<div className="mx-auto mt-2 min-h-[0.3rem] w-12 rounded-full bg-passive-2" />
|
||||
</div>
|
||||
<MobileModalHeader className="border-b border-border bg-default px-2 py-1.5 text-lg">
|
||||
<div />
|
||||
<div className="flex items-center justify-center font-semibold">{title}</div>
|
||||
<MobileModalAction type="primary" slot="right" action={requestClose}>
|
||||
Done
|
||||
</MobileModalAction>
|
||||
</MobileModalHeader>
|
||||
<div className={classNames('h-full overflow-y-auto overscroll-none', className)} ref={scrollContainerRef}>
|
||||
<div
|
||||
className={classNames('h-full overflow-y-auto overscroll-none bg-passive-5', className)}
|
||||
ref={scrollContainerRef}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -138,6 +138,7 @@ const Popover = (props: PopoverProps) => {
|
||||
title={props.title}
|
||||
className={props.className}
|
||||
id={popoverId}
|
||||
forceFullHeightOnMobile={props.forceFullHeightOnMobile}
|
||||
>
|
||||
{props.children}
|
||||
</MobilePopoverContent>
|
||||
|
||||
@@ -44,6 +44,7 @@ type CommonPopoverProps = {
|
||||
togglePopover?: () => void
|
||||
disableMobileFullscreenTakeover?: boolean
|
||||
disableFlip?: boolean
|
||||
forceFullHeightOnMobile?: boolean
|
||||
title: string
|
||||
portal?: boolean
|
||||
offset?: number
|
||||
|
||||
@@ -2,7 +2,6 @@ import { FunctionComponent, UIEventHandler, useCallback, useState } from 'react'
|
||||
import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin'
|
||||
import { ContentEditable } from '@lexical/react/LexicalContentEditable'
|
||||
import { OnChangePlugin } from '@lexical/react/LexicalOnChangePlugin'
|
||||
import { CheckListPlugin } from '@lexical/react/LexicalCheckListPlugin'
|
||||
import { ClearEditorPlugin } from '@lexical/react/LexicalClearEditorPlugin'
|
||||
import { MarkdownShortcutPlugin } from '@lexical/react/LexicalMarkdownShortcutPlugin'
|
||||
import { TablePlugin } from '@lexical/react/LexicalTablePlugin'
|
||||
@@ -28,6 +27,8 @@ import { RemoveBrokenTablesPlugin } from './Plugins/TablePlugin'
|
||||
import TableActionMenuPlugin from './Plugins/TableCellActionMenuPlugin'
|
||||
import ToolbarPlugin from './Plugins/ToolbarPlugin/ToolbarPlugin'
|
||||
import { useMediaQuery, MutuallyExclusiveMediaQueryBreakpoints } from '@/Hooks/useMediaQuery'
|
||||
import { CheckListPlugin } from './Plugins/List/CheckListPlugin'
|
||||
import { EmptyLinePlaceholderPlugin } from './Plugins/EmptyLinePlaceholderPlugin'
|
||||
|
||||
type BlocksEditorProps = {
|
||||
onChange?: (value: string, preview: string) => void
|
||||
@@ -113,6 +114,7 @@ export const BlocksEditor: FunctionComponent<BlocksEditorProps> = ({
|
||||
<CollapsiblePlugin />
|
||||
<TabIndentationPlugin />
|
||||
<RemoveBrokenTablesPlugin />
|
||||
<EmptyLinePlaceholderPlugin />
|
||||
{!readonly && floatingAnchorElem && (
|
||||
<>
|
||||
<DraggableBlockPlugin anchorElem={floatingAnchorElem} />
|
||||
|
||||
@@ -16,8 +16,11 @@ import { FileNode } from '../../Plugins/EncryptedFilePlugin/Nodes/FileNode'
|
||||
import { BubbleNode } from '../../Plugins/ItemBubblePlugin/Nodes/BubbleNode'
|
||||
import { RemoteImageNode } from '../../Plugins/RemoteImagePlugin/RemoteImageNode'
|
||||
import { InlineFileNode } from '../../Plugins/InlineFilePlugin/InlineFileNode'
|
||||
import { CreateEditorArgs } from 'lexical'
|
||||
import { ListHTMLExportNode } from '../../Plugins/List/ListHTMLExportNode'
|
||||
import { FileExportNode } from './FileExportNode'
|
||||
|
||||
export const BlockEditorNodes = [
|
||||
const CommonNodes = [
|
||||
AutoLinkNode,
|
||||
CodeHighlightNode,
|
||||
CodeNode,
|
||||
@@ -29,7 +32,6 @@ export const BlockEditorNodes = [
|
||||
HorizontalRuleNode,
|
||||
LinkNode,
|
||||
ListItemNode,
|
||||
ListNode,
|
||||
MarkNode,
|
||||
OverflowNode,
|
||||
QuoteNode,
|
||||
@@ -43,3 +45,17 @@ export const BlockEditorNodes = [
|
||||
RemoteImageNode,
|
||||
InlineFileNode,
|
||||
]
|
||||
|
||||
export const BlockEditorNodes = [...CommonNodes, ListNode]
|
||||
|
||||
export const SuperExportNodes: CreateEditorArgs['nodes'] = [
|
||||
...CommonNodes,
|
||||
FileExportNode,
|
||||
ListHTMLExportNode,
|
||||
{
|
||||
replace: ListNode,
|
||||
with(node) {
|
||||
return new ListHTMLExportNode(node.getListType(), node.getStart())
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
import { DecoratorBlockNode, SerializedDecoratorBlockNode } from '@lexical/react/LexicalDecoratorBlockNode'
|
||||
import { parseAndCreateZippableFileName } from '@standardnotes/ui-services'
|
||||
import { DOMExportOutput, Spread } from 'lexical'
|
||||
|
||||
type SerializedFileExportNode = Spread<
|
||||
{
|
||||
version: 1
|
||||
type: 'file-export'
|
||||
name: string
|
||||
mimeType: string
|
||||
},
|
||||
SerializedDecoratorBlockNode
|
||||
>
|
||||
|
||||
export class FileExportNode extends DecoratorBlockNode {
|
||||
__name: string
|
||||
__mimeType: string
|
||||
|
||||
static getType(): string {
|
||||
return 'file-export'
|
||||
}
|
||||
|
||||
constructor(name: string, mimeType: string) {
|
||||
super()
|
||||
this.__name = name
|
||||
this.__mimeType = mimeType
|
||||
}
|
||||
|
||||
static clone(node: FileExportNode): FileExportNode {
|
||||
return new FileExportNode(node.__name, node.__mimeType)
|
||||
}
|
||||
|
||||
static importJSON(serializedNode: SerializedFileExportNode): FileExportNode {
|
||||
const node = new FileExportNode(serializedNode.name, serializedNode.mimeType)
|
||||
return node
|
||||
}
|
||||
|
||||
exportJSON(): SerializedFileExportNode {
|
||||
return {
|
||||
...super.exportJSON(),
|
||||
name: this.__name,
|
||||
mimeType: this.__mimeType,
|
||||
version: 1,
|
||||
type: 'file-export',
|
||||
}
|
||||
}
|
||||
|
||||
getZippableFileName(): string {
|
||||
return parseAndCreateZippableFileName(this.__name)
|
||||
}
|
||||
|
||||
getTextContent(): string {
|
||||
return `${this.__mimeType.startsWith('image/') ? '!' : ''}[${this.__name}](./${this.getZippableFileName()})`
|
||||
}
|
||||
|
||||
exportDOM(): DOMExportOutput {
|
||||
const src = `./${this.getZippableFileName()}`
|
||||
if (this.__mimeType.startsWith('image/')) {
|
||||
const img = document.createElement('img')
|
||||
img.setAttribute('src', src)
|
||||
return { element: img }
|
||||
} else if (this.__mimeType.startsWith('audio')) {
|
||||
const audio = document.createElement('audio')
|
||||
audio.setAttribute('controls', '')
|
||||
const source = document.createElement('source')
|
||||
source.setAttribute('src', src)
|
||||
source.setAttribute('type', this.__mimeType)
|
||||
audio.appendChild(source)
|
||||
return { element: audio }
|
||||
} else if (this.__mimeType.startsWith('video')) {
|
||||
const video = document.createElement('video')
|
||||
video.setAttribute('controls', '')
|
||||
const source = document.createElement('source')
|
||||
source.setAttribute('src', src)
|
||||
source.setAttribute('type', this.__mimeType)
|
||||
video.appendChild(source)
|
||||
return { element: video }
|
||||
}
|
||||
const object = document.createElement('object')
|
||||
object.setAttribute('data', src)
|
||||
object.setAttribute('type', this.__mimeType)
|
||||
return { element: object }
|
||||
}
|
||||
|
||||
decorate(): JSX.Element {
|
||||
// Doesn't need to actually render anything since this is only used for export
|
||||
return <></>
|
||||
}
|
||||
}
|
||||
|
||||
export function $createFileExportNode(name: string, mimeType: string): FileExportNode {
|
||||
return new FileExportNode(name, mimeType)
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
@import 'lists';
|
||||
|
||||
.Lexical__ltr {
|
||||
text-align: left;
|
||||
}
|
||||
@@ -163,70 +165,6 @@
|
||||
box-shadow: 0 0 5px rgba(0, 0, 0, 0.4);
|
||||
border-radius: 3px;
|
||||
}
|
||||
.Lexical__tableAddColumns {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 20px;
|
||||
background-color: #eee;
|
||||
height: 100%;
|
||||
right: 0;
|
||||
animation: table-controls 0.2s ease;
|
||||
border: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
.Lexical__tableAddColumns:after {
|
||||
background-image: url(#{$blocks-editor-icons-path}/plus.svg);
|
||||
background-size: contain;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
display: block;
|
||||
content: ' ';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 0.4;
|
||||
}
|
||||
.Lexical__tableAddColumns:hover {
|
||||
background-color: #c9dbf0;
|
||||
}
|
||||
.Lexical__tableAddRows {
|
||||
position: absolute;
|
||||
bottom: -25px;
|
||||
width: calc(100% - 25px);
|
||||
background-color: #eee;
|
||||
height: 20px;
|
||||
left: 0;
|
||||
animation: table-controls 0.2s ease;
|
||||
border: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
.Lexical__tableAddRows:after {
|
||||
background-image: url(#{$blocks-editor-icons-path}/plus.svg);
|
||||
background-size: contain;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
display: block;
|
||||
content: ' ';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 0.4;
|
||||
}
|
||||
.Lexical__tableAddRows:hover {
|
||||
background-color: #c9dbf0;
|
||||
}
|
||||
@keyframes table-controls {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
.Lexical__tableCellResizeRuler {
|
||||
display: block;
|
||||
position: absolute;
|
||||
@@ -261,118 +199,6 @@
|
||||
display: inline;
|
||||
background-color: #ffbbbb !important;
|
||||
}
|
||||
:root {
|
||||
--lexical-ordered-list-left-margin: 16px;
|
||||
}
|
||||
.monospace-font {
|
||||
--lexical-ordered-list-left-margin: 42px;
|
||||
}
|
||||
@for $i from 1 through 5 {
|
||||
.Lexical__ol#{$i} {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
margin-left: var(--lexical-ordered-list-left-margin);
|
||||
list-style-position: outside;
|
||||
|
||||
&.Lexical__rtl {
|
||||
margin-left: 0;
|
||||
margin-right: var(--lexical-ordered-list-left-margin);
|
||||
}
|
||||
}
|
||||
}
|
||||
.Lexical__ol2 {
|
||||
list-style-type: upper-alpha;
|
||||
}
|
||||
.Lexical__ol3 {
|
||||
list-style-type: lower-alpha;
|
||||
}
|
||||
.Lexical__ol4 {
|
||||
list-style-type: upper-roman;
|
||||
}
|
||||
.Lexical__ol5 {
|
||||
list-style-type: lower-roman;
|
||||
}
|
||||
.Lexical__ul {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
margin-left: 16px;
|
||||
list-style-position: outside;
|
||||
|
||||
&.Lexical__rtl {
|
||||
margin-left: 0;
|
||||
margin-right: 16px;
|
||||
}
|
||||
}
|
||||
.Lexical__listItem {
|
||||
margin: 0 0px;
|
||||
}
|
||||
.Lexical__listItemChecked,
|
||||
.Lexical__listItemUnchecked {
|
||||
position: relative;
|
||||
margin-left: 8px;
|
||||
margin-right: 8px;
|
||||
padding-left: 24px;
|
||||
padding-right: 24px;
|
||||
list-style-type: none;
|
||||
outline: none;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.Lexical__listItemChecked {
|
||||
text-decoration: line-through;
|
||||
opacity: 0.4;
|
||||
}
|
||||
.Lexical__listItemUnchecked:before,
|
||||
.Lexical__listItemChecked:before {
|
||||
content: '';
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
left: 0;
|
||||
top: 5px;
|
||||
cursor: pointer;
|
||||
background-size: cover;
|
||||
position: absolute;
|
||||
}
|
||||
.Lexical__listItemUnchecked[dir='rtl']:before,
|
||||
.Lexical__listItemChecked[dir='rtl']:before {
|
||||
left: auto;
|
||||
right: 0;
|
||||
}
|
||||
.Lexical__listItemUnchecked:focus:before,
|
||||
.Lexical__listItemChecked:focus:before {
|
||||
box-shadow: 0 0 0 2px #a6cdfe;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.Lexical__listItemUnchecked:before {
|
||||
border: 1px solid #999;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.Lexical__listItemChecked:before {
|
||||
border: 1px solid var(--sn-stylekit-info-color);
|
||||
border-radius: 2px;
|
||||
background-color: var(--sn-stylekit-info-color);
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
.Lexical__listItemChecked:after {
|
||||
content: '';
|
||||
cursor: pointer;
|
||||
border-color: var(--sn-stylekit-info-contrast-color);
|
||||
border-style: solid;
|
||||
position: absolute;
|
||||
display: block;
|
||||
top: 7px;
|
||||
width: 5px;
|
||||
left: 6px;
|
||||
height: 10px;
|
||||
transform: rotate(45deg);
|
||||
border-width: 0 2px 2px 0;
|
||||
}
|
||||
.Lexical__nestedListItem {
|
||||
list-style-type: none;
|
||||
}
|
||||
.Lexical__nestedListItem:before,
|
||||
.Lexical__nestedListItem:after {
|
||||
display: none;
|
||||
}
|
||||
.Lexical__tokenComment {
|
||||
color: slategray;
|
||||
}
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
.Lexical__listItemUnchecked,
|
||||
.Lexical__listItemChecked {
|
||||
min-height: 18px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
.Lexical__listItemUnchecked:before,
|
||||
.Lexical__listItemChecked:before {
|
||||
top: 0px;
|
||||
}
|
||||
.Lexical__listItemChecked:after {
|
||||
top: 1px;
|
||||
}
|
||||
.Lexical__table {
|
||||
margin: 10px 0;
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
.icon.plus {
|
||||
background-image: url(#{$blocks-editor-icons-path}/plus.svg);
|
||||
}
|
||||
|
||||
/**
|
||||
.icon.dropdown-more {
|
||||
background-image: url(#{$blocks-editor-icons-path}/dropdown-more.svg);
|
||||
}
|
||||
|
||||
.icon.font-color {
|
||||
background-image: url(#{$blocks-editor-icons-path}/font-color.svg);
|
||||
}
|
||||
|
||||
.icon.font-family {
|
||||
background-image: url(#{$blocks-editor-icons-path}/font-family.svg);
|
||||
}
|
||||
|
||||
.icon.bg-color {
|
||||
background-image: url(#{$blocks-editor-icons-path}/bg-color.svg);
|
||||
}
|
||||
|
||||
i.palette {
|
||||
background-image: url(#{$blocks-editor-icons-path}/palette.svg);
|
||||
}
|
||||
|
||||
i.bucket {
|
||||
background-image: url(#{$blocks-editor-icons-path}/paint-bucket.svg);
|
||||
}
|
||||
|
||||
i.clear {
|
||||
background-image: url(#{$blocks-editor-icons-path}/trash.svg);
|
||||
}
|
||||
|
||||
i.image {
|
||||
background-image: url(#{$blocks-editor-icons-path}/file-image.svg);
|
||||
}
|
||||
|
||||
i.close {
|
||||
background-image: url(#{$blocks-editor-icons-path}/close.svg);
|
||||
}
|
||||
|
||||
i.figma {
|
||||
background-image: url(#{$blocks-editor-icons-path}/figma.svg);
|
||||
}
|
||||
|
||||
i.poll {
|
||||
background-image: url(#{$blocks-editor-icons-path}/card-checklist.svg);
|
||||
}
|
||||
|
||||
i.indent {
|
||||
background-image: url(#{$blocks-editor-icons-path}/indent.svg);
|
||||
}
|
||||
|
||||
i.markdown {
|
||||
background-image: url(#{$blocks-editor-icons-path}/markdown.svg);
|
||||
}
|
||||
|
||||
i.outdent {
|
||||
background-image: url(#{$blocks-editor-icons-path}/outdent.svg);
|
||||
}
|
||||
|
||||
i.undo {
|
||||
background-image: url(#{$blocks-editor-icons-path}/arrow-counterclockwise.svg);
|
||||
}
|
||||
|
||||
i.redo {
|
||||
background-image: url(#{$blocks-editor-icons-path}/arrow-clockwise.svg);
|
||||
}
|
||||
|
||||
i.sticky {
|
||||
background-image: url(#{$blocks-editor-icons-path}/sticky.svg);
|
||||
}
|
||||
|
||||
i.mic {
|
||||
background-image: url(#{$blocks-editor-icons-path}/mic.svg);
|
||||
}
|
||||
|
||||
i.import {
|
||||
background-image: url(#{$blocks-editor-icons-path}/upload.svg);
|
||||
}
|
||||
|
||||
i.export {
|
||||
background-image: url(#{$blocks-editor-icons-path}/download.svg);
|
||||
}
|
||||
|
||||
i.diagram-2 {
|
||||
background-image: url(#{$blocks-editor-icons-path}/diagram-2.svg);
|
||||
}
|
||||
|
||||
i.user {
|
||||
background-image: url(#{$blocks-editor-icons-path}/user.svg);
|
||||
}
|
||||
|
||||
i.equation {
|
||||
background-image: url(#{$blocks-editor-icons-path}/plus-slash-minus.svg);
|
||||
}
|
||||
|
||||
i.gif {
|
||||
background-image: url(#{$blocks-editor-icons-path}/filetype-gif.svg);
|
||||
}
|
||||
|
||||
i.copy {
|
||||
background-image: url(#{$blocks-editor-icons-path}/copy.svg);
|
||||
}
|
||||
|
||||
i.success {
|
||||
background-image: url(#{$blocks-editor-icons-path}/success.svg);
|
||||
}
|
||||
|
||||
i.prettier {
|
||||
background-image: url(#{$blocks-editor-icons-path}/prettier.svg);
|
||||
}
|
||||
|
||||
i.prettier-error {
|
||||
background-image: url(#{$blocks-editor-icons-path}/prettier-error.svg);
|
||||
}
|
||||
*/
|
||||
@@ -1,5 +1,3 @@
|
||||
@import 'base';
|
||||
@import 'custom';
|
||||
@import 'editor';
|
||||
@import 'icons';
|
||||
@import 'links';
|
||||
|
||||
@@ -1,110 +0,0 @@
|
||||
.button.active,
|
||||
.toolbar .button.active {
|
||||
background-color: var(--sn-stylekit-contrast-background-color);
|
||||
}
|
||||
|
||||
.link-editor {
|
||||
background-color: var(--sn-stylekit-secondary-background-color);
|
||||
border-radius: 8px;
|
||||
border: 0;
|
||||
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.3);
|
||||
box-sizing: border-box;
|
||||
display: absolute;
|
||||
font-family: inherit;
|
||||
font-size: 15px;
|
||||
left: 0;
|
||||
margin: 8px 12px;
|
||||
max-width: 400px;
|
||||
opacity: 0;
|
||||
outline: 0;
|
||||
padding: 8px 12px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
transition: opacity 0.5s;
|
||||
width: 100%;
|
||||
will-change: transform;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.link-input {
|
||||
background-color: var(--sn-stylekit-background-color);
|
||||
border-radius: 15px;
|
||||
border: 0;
|
||||
box-sizing: border-box;
|
||||
color: var(--sn-stylekit-contrast-color);
|
||||
display: absolute;
|
||||
font-family: inherit;
|
||||
font-size: 15px;
|
||||
margin: 8px 12px;
|
||||
outline: 0;
|
||||
padding: 8px 12px;
|
||||
position: relative;
|
||||
width: calc(100% - 24px);
|
||||
}
|
||||
|
||||
.link-editor div.link-edit {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-size: 16px;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
vertical-align: -0.25em;
|
||||
position: absolute;
|
||||
right: 12px;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.link-editor .link-input a {
|
||||
color: rgb(33, 111, 219);
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
margin-right: 30px;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.link-editor .link-input a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.link-editor .font-size-wrapper,
|
||||
.link-editor .font-family-wrapper {
|
||||
display: flex;
|
||||
margin: 0 4px;
|
||||
}
|
||||
|
||||
.link-editor select {
|
||||
padding: 6px;
|
||||
border: none;
|
||||
background-color: rgba(0, 0, 0, 0.075);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.link-editor .button {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
display: inline-block;
|
||||
padding: 6px;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
margin: 0 2px;
|
||||
}
|
||||
|
||||
.link-editor .button.hovered {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
display: inline-block;
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
.link-editor .button i,
|
||||
.actions i {
|
||||
background-size: contain;
|
||||
display: inline-block;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
vertical-align: -0.25em;
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
:root {
|
||||
--lexical-ordered-list-left-margin: 16px;
|
||||
}
|
||||
.monospace-font {
|
||||
--lexical-ordered-list-left-margin: 42px;
|
||||
}
|
||||
@for $i from 1 through 5 {
|
||||
.Lexical__ol#{$i} {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
margin-left: var(--lexical-ordered-list-left-margin);
|
||||
list-style-position: outside;
|
||||
|
||||
&.Lexical__rtl {
|
||||
margin-left: 0;
|
||||
margin-right: var(--lexical-ordered-list-left-margin);
|
||||
}
|
||||
}
|
||||
}
|
||||
.Lexical__ol2 {
|
||||
list-style-type: upper-alpha;
|
||||
}
|
||||
.Lexical__ol3 {
|
||||
list-style-type: lower-alpha;
|
||||
}
|
||||
.Lexical__ol4 {
|
||||
list-style-type: upper-roman;
|
||||
}
|
||||
.Lexical__ol5 {
|
||||
list-style-type: lower-roman;
|
||||
}
|
||||
.Lexical__ul {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
margin-left: 16px;
|
||||
list-style-position: outside;
|
||||
|
||||
&.Lexical__rtl {
|
||||
margin-left: 0;
|
||||
margin-right: 16px;
|
||||
}
|
||||
}
|
||||
.Lexical__checkList {
|
||||
margin-left: 0;
|
||||
.Lexical__nestedListItem & {
|
||||
margin-left: 16px;
|
||||
}
|
||||
}
|
||||
.Lexical__listItem {
|
||||
margin: 0 0px;
|
||||
}
|
||||
.Lexical__listItemChecked,
|
||||
.Lexical__listItemUnchecked {
|
||||
position: relative;
|
||||
padding-left: 24px;
|
||||
padding-right: 24px;
|
||||
list-style-type: none;
|
||||
outline: none;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.Lexical__listItemChecked {
|
||||
text-decoration: line-through;
|
||||
opacity: 0.4;
|
||||
}
|
||||
.Lexical__listItemUnchecked:before,
|
||||
.Lexical__listItemChecked:before {
|
||||
content: '';
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
left: 0;
|
||||
top: 7px;
|
||||
cursor: pointer;
|
||||
background-size: cover;
|
||||
position: absolute;
|
||||
}
|
||||
.Lexical__listItemUnchecked[dir='rtl']:before,
|
||||
.Lexical__listItemChecked[dir='rtl']:before {
|
||||
left: auto;
|
||||
right: 0;
|
||||
}
|
||||
.Lexical__listItemUnchecked:focus:before,
|
||||
.Lexical__listItemChecked:focus:before {
|
||||
box-shadow: 0 0 0 2px #a6cdfe;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.Lexical__listItemUnchecked:before {
|
||||
border: 1px solid #999;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.Lexical__listItemChecked:before {
|
||||
border: 1px solid var(--sn-stylekit-info-color);
|
||||
border-radius: 2px;
|
||||
background-color: var(--sn-stylekit-info-color);
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
.Lexical__listItemChecked:after {
|
||||
content: '';
|
||||
cursor: pointer;
|
||||
border-color: var(--sn-stylekit-info-contrast-color);
|
||||
border-style: solid;
|
||||
position: absolute;
|
||||
display: block;
|
||||
top: 9px;
|
||||
width: 5px;
|
||||
left: 6px;
|
||||
height: 10px;
|
||||
transform: rotate(45deg);
|
||||
border-width: 0 2px 2px 0;
|
||||
}
|
||||
.Lexical__nestedListItem {
|
||||
list-style-type: none;
|
||||
&.Lexical__listItemUnchecked {
|
||||
padding-left: 0;
|
||||
}
|
||||
}
|
||||
.Lexical__nestedListItem:before,
|
||||
.Lexical__nestedListItem:after {
|
||||
display: none;
|
||||
}
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
|
||||
import {
|
||||
$getSelection,
|
||||
$isRangeSelection,
|
||||
$isParagraphNode,
|
||||
$isTextNode,
|
||||
SELECTION_CHANGE_COMMAND,
|
||||
COMMAND_PRIORITY_LOW,
|
||||
} from 'lexical'
|
||||
import { useCallback, useEffect, useRef } from 'react'
|
||||
import { getSelectedNode } from '../Lexical/Utils/getSelectedNode'
|
||||
import { mergeRegister } from '@lexical/utils'
|
||||
|
||||
export const EmptyLinePlaceholderPlugin = () => {
|
||||
const [editor] = useLexicalComposerContext()
|
||||
|
||||
const placeholderElementRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
const cursorUpdate = useCallback((): boolean => {
|
||||
const selection = $getSelection()
|
||||
if (selection && $isRangeSelection(selection)) {
|
||||
if (!placeholderElementRef.current) {
|
||||
return false
|
||||
}
|
||||
const node = getSelectedNode(selection)
|
||||
if (!node) {
|
||||
return false
|
||||
}
|
||||
const isParagraph = $isParagraphNode(node) || $isTextNode(node)
|
||||
const text = node.getTextContent()
|
||||
if (!isParagraph) {
|
||||
return false
|
||||
}
|
||||
const rootElement = editor.getRootElement()
|
||||
const nodeElement = editor.getElementByKey(node.getKey())
|
||||
const placeholder = placeholderElementRef.current
|
||||
if (!nodeElement || !placeholder.parentElement || !rootElement) {
|
||||
return false
|
||||
}
|
||||
const rect = nodeElement.getBoundingClientRect()
|
||||
const parentRect = placeholder.parentElement.getBoundingClientRect()
|
||||
const rootRect = rootElement.getBoundingClientRect()
|
||||
if (!text && editor.isEditable()) {
|
||||
placeholder.style.top = `${rect.y}px`
|
||||
placeholder.style.left = `${rect.x - parentRect.x + rootRect.x}px`
|
||||
placeholder.style.opacity = '1'
|
||||
} else {
|
||||
placeholder.style.opacity = '0'
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}, [editor])
|
||||
|
||||
useEffect(() => {
|
||||
return mergeRegister(
|
||||
editor.registerCommand(SELECTION_CHANGE_COMMAND, cursorUpdate, COMMAND_PRIORITY_LOW),
|
||||
editor.registerEditableListener(cursorUpdate),
|
||||
)
|
||||
}, [cursorUpdate, editor])
|
||||
|
||||
useEffect(() => {
|
||||
const scrollerElem = editor.getRootElement()
|
||||
|
||||
const update = () => {
|
||||
editor.getEditorState().read(() => {
|
||||
cursorUpdate()
|
||||
})
|
||||
}
|
||||
|
||||
window.addEventListener('resize', update)
|
||||
if (scrollerElem) {
|
||||
scrollerElem.addEventListener('scroll', update)
|
||||
}
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('resize', update)
|
||||
if (scrollerElem) {
|
||||
scrollerElem.removeEventListener('scroll', update)
|
||||
}
|
||||
}
|
||||
}, [cursorUpdate, editor])
|
||||
|
||||
return (
|
||||
<div
|
||||
className="super-empty-line-placeholder pointer-events-none fixed text-passive-1 opacity-0"
|
||||
ref={placeholderElementRef}
|
||||
>
|
||||
Type <span className="rounded border border-border bg-passive-4-opacity-variant px-1 py-0.5">/</span> for
|
||||
commands...
|
||||
</div>
|
||||
)
|
||||
}
|
||||
-111
@@ -1,111 +0,0 @@
|
||||
import { useApplication } from '@/Components/ApplicationProvider'
|
||||
import { downloadBlobOnAndroid } from '@/NativeMobileWeb/DownloadBlobOnAndroid'
|
||||
import { shareBlobOnMobile } from '@/NativeMobileWeb/ShareBlobOnMobile'
|
||||
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
|
||||
import { Platform } from '@standardnotes/snjs'
|
||||
import {
|
||||
sanitizeFileName,
|
||||
SUPER_EXPORT_HTML,
|
||||
SUPER_EXPORT_JSON,
|
||||
SUPER_EXPORT_MARKDOWN,
|
||||
} from '@standardnotes/ui-services'
|
||||
import { useCallback, useEffect, useRef } from 'react'
|
||||
import { useCommandService } from '@/Components/CommandProvider'
|
||||
import { HeadlessSuperConverter } from '../../Tools/HeadlessSuperConverter'
|
||||
|
||||
export const ExportPlugin = () => {
|
||||
const application = useApplication()
|
||||
const [editor] = useLexicalComposerContext()
|
||||
const commandService = useCommandService()
|
||||
|
||||
const converter = useRef(new HeadlessSuperConverter())
|
||||
|
||||
const downloadData = useCallback(
|
||||
(data: Blob, fileName: string) => {
|
||||
if (!application.isNativeMobileWeb()) {
|
||||
application.archiveService.downloadData(data, fileName)
|
||||
return
|
||||
}
|
||||
|
||||
if (application.platform === Platform.Android) {
|
||||
downloadBlobOnAndroid(application.mobileDevice, data, fileName).catch(console.error)
|
||||
} else {
|
||||
shareBlobOnMobile(application.mobileDevice, application.isNativeMobileWeb(), data, fileName).catch(
|
||||
console.error,
|
||||
)
|
||||
}
|
||||
},
|
||||
[application],
|
||||
)
|
||||
|
||||
const exportJson = useCallback(
|
||||
(title: string) => {
|
||||
const content = converter.current.convertSuperStringToOtherFormat(JSON.stringify(editor.getEditorState()), 'json')
|
||||
const blob = new Blob([content], { type: 'application/json' })
|
||||
downloadData(blob, `${sanitizeFileName(title)}.json`)
|
||||
},
|
||||
[downloadData, editor],
|
||||
)
|
||||
|
||||
const exportMarkdown = useCallback(
|
||||
(title: string) => {
|
||||
const content = converter.current.convertSuperStringToOtherFormat(JSON.stringify(editor.getEditorState()), 'md')
|
||||
const blob = new Blob([content], { type: 'text/markdown' })
|
||||
downloadData(blob, `${sanitizeFileName(title)}.md`)
|
||||
},
|
||||
[downloadData, editor],
|
||||
)
|
||||
|
||||
const exportHtml = useCallback(
|
||||
(title: string) => {
|
||||
const content = converter.current.convertSuperStringToOtherFormat(JSON.stringify(editor.getEditorState()), 'html')
|
||||
const blob = new Blob([content], { type: 'text/html' })
|
||||
downloadData(blob, `${sanitizeFileName(title)}.html`)
|
||||
},
|
||||
[downloadData, editor],
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
return commandService.addCommandHandler({
|
||||
command: SUPER_EXPORT_JSON,
|
||||
onKeyDown: (_, data) => {
|
||||
if (!data) {
|
||||
throw new Error('No data provided for export command')
|
||||
}
|
||||
|
||||
const title = data as string
|
||||
exportJson(title)
|
||||
},
|
||||
})
|
||||
}, [commandService, exportJson])
|
||||
|
||||
useEffect(() => {
|
||||
return commandService.addCommandHandler({
|
||||
command: SUPER_EXPORT_MARKDOWN,
|
||||
onKeyDown: (_, data) => {
|
||||
if (!data) {
|
||||
throw new Error('No data provided for export command')
|
||||
}
|
||||
|
||||
const title = data as string
|
||||
exportMarkdown(title)
|
||||
},
|
||||
})
|
||||
}, [commandService, exportMarkdown])
|
||||
|
||||
useEffect(() => {
|
||||
return commandService.addCommandHandler({
|
||||
command: SUPER_EXPORT_HTML,
|
||||
onKeyDown: (_, data) => {
|
||||
if (!data) {
|
||||
throw new Error('No data provided for export command')
|
||||
}
|
||||
|
||||
const title = data as string
|
||||
exportHtml(title)
|
||||
},
|
||||
})
|
||||
}, [commandService, exportHtml])
|
||||
|
||||
return null
|
||||
}
|
||||
+4
@@ -148,6 +148,10 @@ export class InlineFileNode extends DecoratorBlockNode {
|
||||
return { element: object }
|
||||
}
|
||||
|
||||
getTextContent(): string {
|
||||
return `${this.__mimeType.startsWith('image/') ? '!' : ''}[${this.__fileName}](${this.__src})`
|
||||
}
|
||||
|
||||
decorate(_editor: LexicalEditor, config: EditorConfig): JSX.Element {
|
||||
const embedBlockTheme = config.theme.embedBlock || {}
|
||||
const className = {
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
import { CheckListPlugin as LexicalCheckListPlugin } from '@lexical/react/LexicalCheckListPlugin'
|
||||
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
|
||||
import { ListNode } from '@lexical/list'
|
||||
import { useEffect } from 'react'
|
||||
|
||||
export function CheckListPlugin() {
|
||||
const [editor] = useLexicalComposerContext()
|
||||
|
||||
useEffect(() => {
|
||||
return editor.registerNodeTransform(ListNode, (node) => {
|
||||
if (node.getListType() !== 'check') {
|
||||
return
|
||||
}
|
||||
editor.getEditorState().read(() => {
|
||||
const element = editor.getElementByKey(node.getKey())
|
||||
if (!element) {
|
||||
return
|
||||
}
|
||||
element.classList.add('Lexical__checkList')
|
||||
})
|
||||
})
|
||||
}, [editor])
|
||||
|
||||
return <LexicalCheckListPlugin />
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
import { ListNode, SerializedListNode } from '@lexical/list'
|
||||
import { DOMExportOutput, LexicalEditor, Spread } from 'lexical'
|
||||
|
||||
export type SerializedListHTMLExportNode = Spread<
|
||||
{
|
||||
type: 'list-html-export'
|
||||
},
|
||||
SerializedListNode
|
||||
>
|
||||
|
||||
export class ListHTMLExportNode extends ListNode {
|
||||
static getType(): string {
|
||||
return 'list-html-export'
|
||||
}
|
||||
|
||||
static clone(node: ListNode): ListHTMLExportNode {
|
||||
return new ListHTMLExportNode(node.getListType(), node.getStart(), node.getKey())
|
||||
}
|
||||
|
||||
static importJSON(serializedNode: SerializedListNode): ListNode {
|
||||
return super.importJSON(serializedNode)
|
||||
}
|
||||
|
||||
exportDOM(editor: LexicalEditor): DOMExportOutput {
|
||||
const { element } = super.exportDOM(editor)
|
||||
if (this.getListType() === 'check' && element instanceof HTMLElement) {
|
||||
element.classList.add('Lexical__checkList')
|
||||
}
|
||||
return { element }
|
||||
}
|
||||
|
||||
exportJSON(): SerializedListHTMLExportNode {
|
||||
return {
|
||||
...super.exportJSON(),
|
||||
type: 'list-html-export',
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
-1
@@ -366,6 +366,10 @@ const ToolbarPlugin = () => {
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
if (isMobile) {
|
||||
return
|
||||
}
|
||||
|
||||
const scrollerElem = activeEditor.getRootElement()
|
||||
|
||||
const update = () => {
|
||||
@@ -386,7 +390,7 @@ const ToolbarPlugin = () => {
|
||||
scrollerElem.removeEventListener('scroll', debouncedUpdate)
|
||||
}
|
||||
}
|
||||
}, [activeEditor, updateToolbarFloatingPosition])
|
||||
}, [activeEditor, isMobile, updateToolbarFloatingPosition])
|
||||
|
||||
useEffect(() => {
|
||||
return mergeRegister(
|
||||
|
||||
@@ -37,7 +37,6 @@ import PasswordPlugin from './Plugins/PasswordPlugin/PasswordPlugin'
|
||||
import { useCommandService } from '@/Components/CommandProvider'
|
||||
import { SUPER_SHOW_MARKDOWN_PREVIEW } from '@standardnotes/ui-services'
|
||||
import { SuperNoteMarkdownPreview } from './SuperNoteMarkdownPreview'
|
||||
import { ExportPlugin } from './Plugins/ExportPlugin/ExportPlugin'
|
||||
import GetMarkdownPlugin, { GetMarkdownPluginInterface } from './Plugins/GetMarkdownPlugin/GetMarkdownPlugin'
|
||||
import { useResponsiveEditorFontSize } from '@/Utils/getPlaintextFontSize'
|
||||
import ReadonlyPlugin from './Plugins/ReadonlyPlugin/ReadonlyPlugin'
|
||||
@@ -211,7 +210,14 @@ export const SuperEditor: FunctionComponent<Props> = ({
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className="font-editor relative flex h-full w-full flex-col" ref={ref}>
|
||||
<div
|
||||
className={classNames(
|
||||
'font-editor relative flex h-full w-full flex-col',
|
||||
lineHeight && `leading-${lineHeight.toLowerCase()}`,
|
||||
responsiveFontSize,
|
||||
)}
|
||||
ref={ref}
|
||||
>
|
||||
{featureStatus !== FeatureStatus.Entitled && (
|
||||
<NotEntitledBanner featureStatus={featureStatus} feature={GetSuperNoteFeature()} />
|
||||
)}
|
||||
@@ -243,7 +249,6 @@ export const SuperEditor: FunctionComponent<Props> = ({
|
||||
/>
|
||||
<NodeObserverPlugin nodeType={BubbleNode} onRemove={handleBubbleRemove} />
|
||||
<NodeObserverPlugin nodeType={FileNode} onRemove={handleBubbleRemove} />
|
||||
<ExportPlugin />
|
||||
{readonly === undefined && <ReadonlyPlugin note={note.current} />}
|
||||
<AutoFocusPlugin isEnabled={controller.isTemplateNote} />
|
||||
<SuperSearchContextProvider>
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
isUIFeatureAnIframeFeature,
|
||||
spaceSeparatedStrings,
|
||||
} from '@standardnotes/snjs'
|
||||
import { useCallback, useEffect, useMemo } from 'react'
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import { useApplication } from '../ApplicationProvider'
|
||||
import IframeFeatureView from '../ComponentView/IframeFeatureView'
|
||||
import Icon from '../Icon/Icon'
|
||||
@@ -52,18 +52,23 @@ const SuperNoteConverter = ({
|
||||
return 'json'
|
||||
}, [uiFeature])
|
||||
|
||||
const convertedContent = useMemo(() => {
|
||||
if (note.text.length === 0) {
|
||||
const [convertedContent, setConvertedContent] = useState<string>('')
|
||||
|
||||
useEffect(() => {
|
||||
const convertContent = async () => {
|
||||
if (note.text.length === 0) {
|
||||
return note.text
|
||||
}
|
||||
|
||||
try {
|
||||
return new HeadlessSuperConverter().convertSuperStringToOtherFormat(note.text, format)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
|
||||
return note.text
|
||||
}
|
||||
|
||||
try {
|
||||
return new HeadlessSuperConverter().convertSuperStringToOtherFormat(note.text, format)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
|
||||
return note.text
|
||||
convertContent().then(setConvertedContent).catch(console.error)
|
||||
}, [format, note])
|
||||
|
||||
const componentViewer = useMemo(() => {
|
||||
|
||||
+91
-5
@@ -1,6 +1,6 @@
|
||||
import { createHeadlessEditor } from '@lexical/headless'
|
||||
import { $convertToMarkdownString, $convertFromMarkdownString } from '@lexical/markdown'
|
||||
import { SuperConverterServiceInterface } from '@standardnotes/snjs'
|
||||
import { FileItem, PrefKey, PrefValue, SuperConverterServiceInterface } from '@standardnotes/snjs'
|
||||
import {
|
||||
$createParagraphNode,
|
||||
$getRoot,
|
||||
@@ -11,10 +11,12 @@ import {
|
||||
ParagraphNode,
|
||||
} from 'lexical'
|
||||
import BlocksEditorTheme from '../Lexical/Theme/Theme'
|
||||
import { BlockEditorNodes } from '../Lexical/Nodes/AllNodes'
|
||||
import { SuperExportNodes } from '../Lexical/Nodes/AllNodes'
|
||||
import { MarkdownTransformers } from '../MarkdownTransformers'
|
||||
import { $generateHtmlFromNodes, $generateNodesFromDOM } from '@lexical/html'
|
||||
|
||||
import { FileNode } from '../Plugins/EncryptedFilePlugin/Nodes/FileNode'
|
||||
import { $createFileExportNode } from '../Lexical/Nodes/FileExportNode'
|
||||
import { $createInlineFileNode } from '../Plugins/InlineFilePlugin/InlineFileNode'
|
||||
export class HeadlessSuperConverter implements SuperConverterServiceInterface {
|
||||
private editor: LexicalEditor
|
||||
|
||||
@@ -24,7 +26,7 @@ export class HeadlessSuperConverter implements SuperConverterServiceInterface {
|
||||
theme: BlocksEditorTheme,
|
||||
editable: false,
|
||||
onError: (error: Error) => console.error(error),
|
||||
nodes: [...BlockEditorNodes],
|
||||
nodes: SuperExportNodes,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -37,15 +39,80 @@ export class HeadlessSuperConverter implements SuperConverterServiceInterface {
|
||||
}
|
||||
}
|
||||
|
||||
convertSuperStringToOtherFormat(superString: string, toFormat: 'txt' | 'md' | 'html' | 'json'): string {
|
||||
async convertSuperStringToOtherFormat(
|
||||
superString: string,
|
||||
toFormat: 'txt' | 'md' | 'html' | 'json',
|
||||
config?: {
|
||||
embedBehavior?: PrefValue[PrefKey.SuperNoteExportEmbedBehavior]
|
||||
getFileItem?: (id: string) => FileItem | undefined
|
||||
getFileBase64?: (id: string) => Promise<string | undefined>
|
||||
},
|
||||
): Promise<string> {
|
||||
if (superString.length === 0) {
|
||||
return superString
|
||||
}
|
||||
|
||||
const { embedBehavior, getFileItem, getFileBase64 } = config ?? { embedBehavior: 'reference' }
|
||||
|
||||
if (embedBehavior === 'separate' && !getFileItem) {
|
||||
throw new Error('getFileItem must be provided when embedBehavior is "separate"')
|
||||
}
|
||||
if (embedBehavior === 'inline' && !getFileItem && !getFileBase64) {
|
||||
throw new Error('getFileItem and getFileBase64 must be provided when embedBehavior is "inline"')
|
||||
}
|
||||
|
||||
this.editor.setEditorState(this.editor.parseEditorState(superString))
|
||||
|
||||
let content: string | undefined
|
||||
|
||||
await new Promise<void>((resolve) => {
|
||||
this.editor.update(
|
||||
() => {
|
||||
if (embedBehavior === 'reference') {
|
||||
resolve()
|
||||
return
|
||||
}
|
||||
if (!getFileItem) {
|
||||
resolve()
|
||||
return
|
||||
}
|
||||
const fileNodes = $nodesOfType(FileNode)
|
||||
Promise.all(
|
||||
fileNodes.map(async (fileNode) => {
|
||||
const fileItem = getFileItem(fileNode.getId())
|
||||
if (!fileItem) {
|
||||
return
|
||||
}
|
||||
if (embedBehavior === 'inline' && getFileBase64) {
|
||||
const fileBase64 = await getFileBase64(fileNode.getId())
|
||||
if (!fileBase64) {
|
||||
return
|
||||
}
|
||||
this.editor.update(
|
||||
() => {
|
||||
const inlineFileNode = $createInlineFileNode(fileBase64, fileItem.mimeType, fileItem.name)
|
||||
fileNode.replace(inlineFileNode)
|
||||
},
|
||||
{ discrete: true },
|
||||
)
|
||||
} else {
|
||||
this.editor.update(
|
||||
() => {
|
||||
const fileExportNode = $createFileExportNode(fileItem.name, fileItem.mimeType)
|
||||
fileNode.replace(fileExportNode)
|
||||
},
|
||||
{ discrete: true },
|
||||
)
|
||||
}
|
||||
}),
|
||||
)
|
||||
.then(() => resolve())
|
||||
.catch(console.error)
|
||||
},
|
||||
{ discrete: true },
|
||||
)
|
||||
})
|
||||
|
||||
this.editor.update(
|
||||
() => {
|
||||
switch (toFormat) {
|
||||
@@ -159,4 +226,23 @@ export class HeadlessSuperConverter implements SuperConverterServiceInterface {
|
||||
|
||||
return JSON.stringify(this.editor.getEditorState())
|
||||
}
|
||||
|
||||
getEmbeddedFileIDsFromSuperString(superString: string): string[] {
|
||||
if (superString.length === 0) {
|
||||
return []
|
||||
}
|
||||
|
||||
this.editor.setEditorState(this.editor.parseEditorState(superString))
|
||||
|
||||
const ids: string[] = []
|
||||
|
||||
this.editor.getEditorState().read(() => {
|
||||
const fileNodes = $nodesOfType(FileNode)
|
||||
fileNodes.forEach((fileNode) => {
|
||||
ids.push(fileNode.getId())
|
||||
})
|
||||
})
|
||||
|
||||
return ids
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ const Switch = ({
|
||||
disabled = false,
|
||||
tabIndex,
|
||||
forceDesktopStyle,
|
||||
children,
|
||||
}: {
|
||||
checked: boolean
|
||||
onChange: (checked: boolean) => void
|
||||
@@ -15,20 +16,12 @@ const Switch = ({
|
||||
disabled?: boolean
|
||||
tabIndex?: number
|
||||
forceDesktopStyle?: boolean
|
||||
children?: React.ReactNode
|
||||
}) => {
|
||||
const isActive = checked && !disabled
|
||||
|
||||
return (
|
||||
<label
|
||||
className={classNames(
|
||||
'relative box-content inline-block flex-shrink-0 cursor-pointer rounded-full border-2 border-solid border-transparent bg-clip-padding transition-colors duration-150 ease-out',
|
||||
'ring-2 ring-transparent focus-within:border-default focus-within:shadow-none focus-within:outline-none focus-within:ring-info',
|
||||
disabled ? 'opacity-50' : '',
|
||||
isActive ? 'bg-info' : 'bg-neutral',
|
||||
forceDesktopStyle ? 'h-4.5 w-8' : 'h-7 w-12 md:h-4.5 md:w-8',
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<label className={classNames(disabled ? 'opacity-50' : '', className)}>
|
||||
<VisuallyHidden>
|
||||
<Checkbox
|
||||
checked={checked}
|
||||
@@ -40,15 +33,25 @@ const Switch = ({
|
||||
</VisuallyHidden>
|
||||
<div
|
||||
className={classNames(
|
||||
'absolute top-1/2 block -translate-y-1/2 rounded-full bg-default transition-transform duration-150 ease-out',
|
||||
forceDesktopStyle ? 'left-[2px] h-3.5 w-3.5' : 'left-[0.15rem] h-6 w-6 md:left-[2px] md:h-3.5 md:w-3.5',
|
||||
checked
|
||||
? forceDesktopStyle
|
||||
? 'translate-x-[calc(2rem-1.125rem)]'
|
||||
: 'translate-x-[calc(3.25rem-1.5rem-0.5rem)] md:translate-x-[calc(2rem-1.125rem)]'
|
||||
: '',
|
||||
'relative box-content inline-block flex-shrink-0 cursor-pointer rounded-full border-2 border-solid border-transparent bg-clip-padding transition-colors duration-150 ease-out',
|
||||
'ring-2 ring-transparent focus-within:border-default focus-within:shadow-none focus-within:outline-none focus-within:ring-info',
|
||||
isActive ? 'bg-info' : 'bg-neutral',
|
||||
forceDesktopStyle ? 'h-4.5 w-8' : 'h-7 w-12 md:h-4.5 md:w-8',
|
||||
)}
|
||||
/>
|
||||
>
|
||||
<div
|
||||
className={classNames(
|
||||
'absolute top-1/2 block -translate-y-1/2 rounded-full bg-default transition-transform duration-150 ease-out',
|
||||
forceDesktopStyle ? 'left-[2px] h-3.5 w-3.5' : 'left-[0.15rem] h-6 w-6 md:left-[2px] md:h-3.5 md:w-3.5',
|
||||
checked
|
||||
? forceDesktopStyle
|
||||
? 'translate-x-[calc(2rem-1.125rem)]'
|
||||
: 'translate-x-[calc(3.25rem-1.5rem-0.5rem)] md:translate-x-[calc(2rem-1.125rem)]'
|
||||
: '',
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
{children}
|
||||
</label>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ const SmartViewsListItem: FunctionComponent<Props> = ({ view, tagsState, setEdit
|
||||
<div
|
||||
role="button"
|
||||
tabIndex={FOCUSABLE_BUT_NOT_TABBABLE}
|
||||
className={classNames('tag group px-3.5', isSelected && 'selected', isFaded && 'opacity-50')}
|
||||
className={classNames('tag group px-3.5 py-1 md:py-0', isSelected && 'selected', isFaded && 'opacity-50')}
|
||||
onClick={selectCurrentTag}
|
||||
onContextMenu={(event) => {
|
||||
event.preventDefault()
|
||||
|
||||
@@ -30,7 +30,9 @@ const TagsList: FunctionComponent<Props> = ({ type }: Props) => {
|
||||
|
||||
const onContextMenu = useCallback(
|
||||
(tag: SNTag, posX: number, posY: number) => {
|
||||
void application.navigationController.setSelectedTag(tag, type)
|
||||
if (application.navigationController.selected !== tag) {
|
||||
void application.navigationController.setSelectedTag(tag, type)
|
||||
}
|
||||
openTagContextMenu(posX, posY)
|
||||
},
|
||||
[application, openTagContextMenu, type],
|
||||
|
||||
@@ -260,7 +260,11 @@ export const TagsListItem: FunctionComponent<Props> = observer(
|
||||
<div
|
||||
role="button"
|
||||
tabIndex={FOCUSABLE_BUT_NOT_TABBABLE}
|
||||
className={classNames('tag group px-3.5', isSelected && 'selected', isBeingDraggedOver && 'is-drag-over')}
|
||||
className={classNames(
|
||||
'tag group px-3.5 py-1 md:py-0',
|
||||
isSelected && 'selected',
|
||||
isBeingDraggedOver && 'is-drag-over',
|
||||
)}
|
||||
onClick={selectCurrentTag}
|
||||
ref={tagRef}
|
||||
style={{
|
||||
|
||||
@@ -8,6 +8,7 @@ export const ElementIds = {
|
||||
NavigationColumn: 'navigation',
|
||||
NoteTextEditor: 'note-text-editor',
|
||||
NoteTitleEditor: 'note-title-editor',
|
||||
NoteOptionsButton: 'note-options-button',
|
||||
RootId: 'app-group-root',
|
||||
NoteStatusTooltip: 'note-status-tooltip',
|
||||
ItemLinkAutocompleteInput: 'item-link-autocomplete-input',
|
||||
|
||||
@@ -275,6 +275,20 @@ export class FilesController extends AbstractViewController<FilesControllerEvent
|
||||
}
|
||||
}
|
||||
|
||||
getFileBlob = async (file: FileItem): Promise<Blob | undefined> => {
|
||||
const chunks: Uint8Array[] = []
|
||||
const error = await this.files.downloadFile(file, async (decryptedChunk) => {
|
||||
chunks.push(decryptedChunk)
|
||||
})
|
||||
if (error) {
|
||||
return
|
||||
}
|
||||
const finalDecryptedBytes = concatenateUint8Arrays(chunks)
|
||||
return new Blob([finalDecryptedBytes], {
|
||||
type: file.mimeType,
|
||||
})
|
||||
}
|
||||
|
||||
private async downloadFile(file: FileItem): Promise<void> {
|
||||
let downloadingToastId = ''
|
||||
|
||||
|
||||
@@ -101,6 +101,8 @@ export class ItemListController
|
||||
selectedUuids: Set<UuidString> = observable(new Set<UuidString>())
|
||||
selectedItems: Record<UuidString, ListableContentItem> = {}
|
||||
|
||||
isMultipleSelectionMode = false
|
||||
|
||||
override deinit() {
|
||||
super.deinit()
|
||||
;(this.noteFilterText as unknown) = undefined
|
||||
@@ -169,6 +171,10 @@ export class ItemListController
|
||||
setSelectedItems: action,
|
||||
|
||||
hydrateFromPersistedValue: action,
|
||||
|
||||
isMultipleSelectionMode: observable,
|
||||
enableMultipleSelectionMode: action,
|
||||
cancelMultipleSelection: action,
|
||||
})
|
||||
|
||||
eventBus.addEventHandler(this, CrossControllerEvent.TagChanged)
|
||||
@@ -257,6 +263,19 @@ export class ItemListController
|
||||
),
|
||||
)
|
||||
|
||||
this.disposers.push(
|
||||
reaction(
|
||||
() => this.selectedItemsCount,
|
||||
(count, prevCount) => {
|
||||
const hasNoSelectedItem = count === 0
|
||||
const onlyOneSelectedItemAfterChange = prevCount > count && count === 1
|
||||
if (hasNoSelectedItem || onlyOneSelectedItemAfterChange) {
|
||||
this.cancelMultipleSelection()
|
||||
}
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
window.onresize = () => {
|
||||
this.resetPagination(true)
|
||||
}
|
||||
@@ -1079,6 +1098,9 @@ export class ItemListController
|
||||
runInAction(() => {
|
||||
this.setSelectedUuids(this.selectedUuids.add(item.uuid))
|
||||
this.lastSelectedItem = item
|
||||
if (this.selectedItemsCount > 1 && !this.isMultipleSelectionMode) {
|
||||
this.enableMultipleSelectionMode()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1086,6 +1108,8 @@ export class ItemListController
|
||||
cancelMultipleSelection = () => {
|
||||
this.keyboardService.cancelAllKeyboardModifiers()
|
||||
|
||||
this.isMultipleSelectionMode = false
|
||||
|
||||
const firstSelectedItem = this.firstSelectedItem
|
||||
|
||||
if (firstSelectedItem) {
|
||||
@@ -1095,7 +1119,7 @@ export class ItemListController
|
||||
}
|
||||
}
|
||||
|
||||
private replaceSelection = (item: ListableContentItem): void => {
|
||||
replaceSelection = (item: ListableContentItem): void => {
|
||||
this.deselectAll()
|
||||
runInAction(() => this.setSelectedUuids(this.selectedUuids.add(item.uuid)))
|
||||
|
||||
@@ -1103,10 +1127,11 @@ export class ItemListController
|
||||
}
|
||||
|
||||
selectAll = () => {
|
||||
void this.selectItemsRange({
|
||||
startingIndex: 0,
|
||||
endingIndex: this.listLength - 1,
|
||||
})
|
||||
const allItems = this.items.filter((item) => !item.protected)
|
||||
const lastItem = allItems[allItems.length - 1]
|
||||
this.setSelectedUuids(new Set(Uuids(allItems)))
|
||||
this.lastSelectedItem = lastItem
|
||||
this.enableMultipleSelectionMode()
|
||||
}
|
||||
|
||||
deselectAll = (): void => {
|
||||
@@ -1136,6 +1161,10 @@ export class ItemListController
|
||||
}
|
||||
}
|
||||
|
||||
enableMultipleSelectionMode = () => {
|
||||
this.isMultipleSelectionMode = true
|
||||
}
|
||||
|
||||
selectItem = async (
|
||||
uuid: UuidString,
|
||||
userTriggered?: boolean,
|
||||
@@ -1152,14 +1181,13 @@ export class ItemListController
|
||||
|
||||
log(LoggingDomain.Selection, 'Select item', item.uuid)
|
||||
|
||||
const supportsMultipleSelection = this.options.allowMultipleSelection
|
||||
const hasMeta = this.keyboardService.activeModifiers.has(KeyboardModifier.Meta)
|
||||
const hasCtrl = this.keyboardService.activeModifiers.has(KeyboardModifier.Ctrl)
|
||||
const hasShift = this.keyboardService.activeModifiers.has(KeyboardModifier.Shift)
|
||||
const hasMoreThanOneSelected = this.selectedItemsCount > 1
|
||||
const isAuthorizedForAccess = await this.protections.authorizeItemAccess(item)
|
||||
|
||||
if (supportsMultipleSelection && userTriggered && (hasMeta || hasCtrl)) {
|
||||
if (userTriggered && hasShift) {
|
||||
await this.selectItemsRange({ selectedItem: item })
|
||||
} else if (userTriggered && this.isMultipleSelectionMode) {
|
||||
if (this.selectedUuids.has(uuid) && hasMoreThanOneSelected) {
|
||||
this.removeSelectedItem(uuid)
|
||||
} else if (isAuthorizedForAccess) {
|
||||
@@ -1167,17 +1195,14 @@ export class ItemListController
|
||||
this.setSelectedUuids(this.selectedUuids)
|
||||
this.lastSelectedItem = item
|
||||
}
|
||||
} else if (supportsMultipleSelection && userTriggered && hasShift) {
|
||||
await this.selectItemsRange({ selectedItem: item })
|
||||
} else {
|
||||
const shouldSelectNote = hasMoreThanOneSelected || !this.selectedUuids.has(uuid)
|
||||
if (shouldSelectNote && isAuthorizedForAccess) {
|
||||
this.replaceSelection(item)
|
||||
await this.openSingleSelectedItem({ userTriggered: userTriggered ?? false })
|
||||
}
|
||||
}
|
||||
|
||||
await this.openSingleSelectedItem({ userTriggered: userTriggered ?? false })
|
||||
|
||||
return {
|
||||
didSelect: this.selectedUuids.has(uuid),
|
||||
}
|
||||
|
||||
@@ -609,7 +609,9 @@ export class NavigationController
|
||||
public setEditingTag(editingTag: SNTag | SmartView | undefined) {
|
||||
runInAction(() => {
|
||||
this.editing_ = editingTag
|
||||
void this.setSelectedTag(editingTag, this.selectedLocation || 'all')
|
||||
if (this.selected !== editingTag) {
|
||||
void this.setSelectedTag(editingTag, this.selectedLocation || 'all')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -293,6 +293,17 @@ export class NotesController
|
||||
})
|
||||
}
|
||||
|
||||
async toggleArchiveSelectedNotes(): Promise<void> {
|
||||
const notes = this.selectedNotes
|
||||
const archived = notes.some((note) => note.archived)
|
||||
|
||||
if (!archived) {
|
||||
await this.setArchiveSelectedNotes(true)
|
||||
} else {
|
||||
await this.setArchiveSelectedNotes(false)
|
||||
}
|
||||
}
|
||||
|
||||
async setProtectSelectedNotes(protect: boolean): Promise<void> {
|
||||
const selectedNotes = this.getSelectedNotesList()
|
||||
if (protect) {
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
import { WebApplication } from '@/Application/WebApplication'
|
||||
import { getNoteBlob, getNoteFileName } from '@/Utils/NoteExportUtils'
|
||||
import { parseFileName } from '@standardnotes/filepicker'
|
||||
import { Platform, SNNote } from '@standardnotes/snjs'
|
||||
import { sanitizeFileName } from '@standardnotes/ui-services'
|
||||
import { downloadBlobOnAndroid } from './DownloadBlobOnAndroid'
|
||||
|
||||
export const downloadSelectedNotesOnAndroid = async (application: WebApplication, notes: SNNote[]) => {
|
||||
if (!application.isNativeMobileWeb() || application.platform !== Platform.Android) {
|
||||
throw new Error('Function being used on non-android platform')
|
||||
}
|
||||
if (notes.length === 1) {
|
||||
const note = notes[0]
|
||||
const blob = getNoteBlob(application, note)
|
||||
const { name, ext } = parseFileName(getNoteFileName(application, note))
|
||||
const filename = `${sanitizeFileName(name)}.${ext}`
|
||||
await downloadBlobOnAndroid(application.mobileDevice, blob, filename)
|
||||
return
|
||||
}
|
||||
if (notes.length > 1) {
|
||||
const zippedDataBlob = await application.archiveService.zipData(
|
||||
notes.map((note) => {
|
||||
return {
|
||||
name: getNoteFileName(application, note),
|
||||
content: getNoteBlob(application, note),
|
||||
}
|
||||
}),
|
||||
)
|
||||
const filename = `Standard Notes Export - ${application.archiveService.formattedDateForExports()}.zip`
|
||||
await downloadBlobOnAndroid(application.mobileDevice, zippedDataBlob, filename)
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user