Compare commits

..

11 Commits

Author SHA1 Message Date
Ammar Ahmed
67a61dd3f3 mobile: release v3.0.22 2024-11-20 12:40:37 +05:00
Ammar Ahmed
13df01d55a mobile: fix readonly editor not loading 2024-11-20 12:38:17 +05:00
Ammar Ahmed
af4ea036c8 mobile: fix sync on iOS 2024-11-20 12:37:38 +05:00
Abdullah Atta
97a75d9498 ci: generate & publish flatpak sources during desktop release 2024-11-20 11:51:04 +05:00
Abdullah Atta
950028e3b4 web: bump version to v3.0.21 2024-11-20 11:26:23 +05:00
Abdullah Atta
874726c712 global: update lockfiles 2024-11-20 11:25:28 +05:00
Abdullah Atta
0f380b9962 Revert "editor: fix heading and p gap (#6530)"
This reverts commit c26988134f.
2024-11-20 11:21:48 +05:00
Abdullah Atta
2ce569726c editor: fix image on load animation 2024-11-20 11:17:25 +05:00
Abdullah Atta
a38fe7da43 web: fix editor margins state reset on restart 2024-11-20 11:09:45 +05:00
Abdullah Atta
057b563608 web: fix password app lock stuck on "wrong password" 2024-11-20 11:07:05 +05:00
Ammar Ahmed
3741e26219 mobile: fix error when changing 2fa method 2024-11-20 10:25:11 +05:00
29 changed files with 453 additions and 886 deletions

View File

@@ -84,6 +84,26 @@ jobs:
files: ./notesnook_build_v${{ steps.app_metadata.outputs.app_version }}.zip
prerelease: ${{ endsWith(steps.app_metadata.outputs.app_version, '-beta') }}
- name: Generate flatpak sources
if: inputs.publish-github && inputs.build-linux
run: |
sudo apt-get install -y flatpak flatpak-builder pipx
git clone https://github.com/flatpak/flatpak-builder-tools.git /tmp/flatpak-builder-tools
cd /tmp/flatpak-builder-tools/node
pipx install .
cd -
node scripts/generate-sources.mjs
- name: Upload flatpak sources
uses: softprops/action-gh-release@v1
if: inputs.publish-github && inputs.build-linux
with:
draft: true
name: Notesnook Desktop v${{ steps.app_metadata.outputs.app_version }}
tag_name: v${{ steps.app_metadata.outputs.app_version }}
files: ./generated-sources.json
prerelease: ${{ endsWith(steps.app_metadata.outputs.app_version, '-beta') }}
build-macos:
name: Build for macOS
needs: build

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,7 @@
"name": "@notesnook/desktop",
"productName": "Notesnook",
"description": "Your private note taking space",
"version": "3.0.20",
"version": "3.0.21",
"appAppleId": "1544027013",
"private": true,
"main": "./dist/cjs/index.js",

View File

@@ -162,7 +162,7 @@ const TwoFactorVerification = ({ onMfaLogin, mfaInfo, onCancel }) => {
textAlign: "center"
}}
>
{strings["2faCodeHelpText"][currentMethod.method]() ||
{strings["2faCodeHelpText"][currentMethod.method]?.() ||
strings.select2faCodeHelpText()}
</Paragraph>

View File

@@ -17,13 +17,11 @@
"phone": "^3.1.14",
"qclone": "^1.2.0",
"react-native-actions-sheet": "0.9.7",
"react-native-check-version": "https://github.com/flexible-agency/react-native-check-version",
"react-native-drax": "^0.10.2",
"react-native-image-zoom-viewer": "^3.0.1",
"react-native-keyboard-aware-scroll-view": "^0.9.5",
"react-native-progress": "^5.0.0",
"react-native-qrcode-svg": "^6.0.6",
"react-native-reanimated-material-menu": "github:ammarahm-ed/react-native-reanimated-material-menu",
"react-native-reanimated-progress-bar": "1.0.1",
"react-native-swiper-flatlist": "3.2.2",
"timeago.js": "4.0.2",
@@ -43,7 +41,9 @@
"pathe": "1.1.2",
"react-native-format-currency": "0.0.5",
"@lingui/react": "4.11.2",
"@lingui/core": "4.11.2"
"@lingui/core": "4.11.2",
"react-native-check-version": "^1.3.0",
"react-native-reanimated-material-menu": "github:ammarahm-ed/react-native-reanimated-material-menu"
},
"sideEffects": false
}

View File

@@ -34,6 +34,7 @@ import { EditorEvents } from "./tiptap/utils";
import { useThemeColors } from "@notesnook/theme";
import useGlobalSafeAreaInsets from "../../hooks/use-global-safe-area-insets";
import { db } from "../../common/database";
import { i18n } from "@lingui/core";
const onShouldStartLoadWithRequest = (request: ShouldStartLoadRequest) => {
if (request.url.includes("https")) {
@@ -143,10 +144,17 @@ export function ReadonlyEditor(props: {
ref={editorRef}
key={"readonly-editor:" + props.editorId}
nestedScrollEnabled
injectedJavaScriptBeforeContentLoaded={`globalThis.readonlyEditor=true;`}
injectedJavaScript="globalThis.readonlyEditor=true;"
injectedJavaScript={`
globalThis.__DEV__ = ${__DEV__}
globalThis.readonlyEditor=true;
globalThis.LINGUI_LOCALE = "${i18n.locale}";
globalThis.LINGUI_LOCALE_DATA = ${JSON.stringify({
[i18n.locale]: i18n.messages
})};
globalThis.loadApp();`}
useSharedProcessPool={false}
javaScriptEnabled={true}
webviewDebuggingEnabled={__DEV__}
focusable={true}
setSupportMultipleWindows={false}
overScrollMode="never"

View File

@@ -30,24 +30,12 @@ import SettingsService from "./settings";
async function doInBackground(callback: () => Promise<void>) {
if (Platform.OS === "ios") {
try {
const bgTaskId = await beginBackgroundTask();
const result = await callback();
await endBackgroundTask(bgTaskId);
return result;
} catch (e) {
return (e as Error).message;
}
const bgTaskId = await beginBackgroundTask();
const result = await callback();
await endBackgroundTask(bgTaskId);
return result;
} else {
// eslint-disable-next-line no-async-promise-executor
return new Promise(async (resolve) => {
try {
const result = await callback();
resolve(result);
} catch (e) {
resolve((e as Error).message);
}
});
return await callback();
}
}

View File

@@ -20,7 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import { Platform } from "react-native";
import FingerprintScanner, {
AuthenticateIOS
} from "react-native-fingerprint-scanner";
} from "@ammarahmed/react-native-fingerprint-scanner";
import * as Keychain from "react-native-keychain";
import { MMKV } from "../common/database/mmkv";
import Storage from "../common/database/storage";

View File

@@ -116,7 +116,7 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
multiDexEnabled true
versionCode 3031
versionCode 3032
versionName getNpmVersion()
testBuildType System.getProperty('testBuildType', 'debug')
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'

View File

@@ -1063,7 +1063,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2118;
CURRENT_PROJECT_VERSION = 2119;
DEVELOPMENT_TEAM = 53CWBG3QUC;
ENABLE_BITCODE = NO;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
@@ -1137,7 +1137,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 3.0.21;
MARKETING_VERSION = 3.0.22;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
@@ -1168,7 +1168,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 2118;
CURRENT_PROJECT_VERSION = 2119;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 53CWBG3QUC;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
@@ -1242,7 +1242,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 3.0.21;
MARKETING_VERSION = 3.0.22;
ONLY_ACTIVE_ARCH = NO;
OTHER_LDFLAGS = (
"$(inherited)",
@@ -1401,7 +1401,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2118;
CURRENT_PROJECT_VERSION = 2119;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = 53CWBG3QUC;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
@@ -1413,7 +1413,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 3.0.21;
MARKETING_VERSION = 3.0.22;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.notewidget;
@@ -1444,7 +1444,7 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 2118;
CURRENT_PROJECT_VERSION = 2119;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 53CWBG3QUC;
@@ -1457,7 +1457,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 3.0.21;
MARKETING_VERSION = 3.0.22;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.notewidget;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -1487,7 +1487,7 @@
CODE_SIGN_ENTITLEMENTS = "Make Note/Make Note.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2118;
CURRENT_PROJECT_VERSION = 2119;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = 53CWBG3QUC;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
@@ -1561,7 +1561,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 3.0.21;
MARKETING_VERSION = 3.0.22;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.share;
@@ -1592,7 +1592,7 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 2118;
CURRENT_PROJECT_VERSION = 2119;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 53CWBG3QUC;
@@ -1667,7 +1667,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 3.0.21;
MARKETING_VERSION = 3.0.22;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.share;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -1744,7 +1744,10 @@
ONLY_ACTIVE_ARCH = YES;
OTHER_CFLAGS = "$(inherited)";
OTHER_CPLUSPLUSFLAGS = "$(inherited)";
OTHER_LDFLAGS = "$(inherited) ";
OTHER_LDFLAGS = (
"$(inherited)",
" ",
);
REACT_NATIVE_PATH = "${PODS_ROOT}/../../../node_modules/react-native";
SDKROOT = iphoneos;
USE_HERMES = true;
@@ -1808,7 +1811,10 @@
ONLY_ACTIVE_ARCH = NO;
OTHER_CFLAGS = "$(inherited)";
OTHER_CPLUSPLUSFLAGS = "$(inherited)";
OTHER_LDFLAGS = "$(inherited) ";
OTHER_LDFLAGS = (
"$(inherited)",
" ",
);
REACT_NATIVE_PATH = "${PODS_ROOT}/../../../node_modules/react-native";
SDKROOT = iphoneos;
USE_HERMES = true;

View File

@@ -970,6 +970,8 @@ PODS:
- React
- react-native-background-actions (2.6.7):
- React-Core
- react-native-begin-background-task (0.1.0):
- React
- react-native-blob-util (0.18.3):
- React-Core
- react-native-config (1.5.1):
@@ -981,7 +983,7 @@ PODS:
- react-native-document-picker (7.1.3):
- React-Core
- react-native-fingerprint-scanner (5.0.0):
- React
- React-Core
- react-native-get-random-values (1.9.0):
- React-Core
- react-native-gzip (1.1.0):
@@ -1486,11 +1488,12 @@ DEPENDENCIES:
- React-Mapbuffer (from `../../node_modules/react-native/ReactCommon`)
- react-native-actions-shortcuts (from `../../node_modules/react-native-actions-shortcuts`)
- react-native-background-actions (from `../../node_modules/react-native-background-actions`)
- react-native-begin-background-task (from `../../node_modules/react-native-begin-background-task`)
- react-native-blob-util (from `../../node_modules/react-native-blob-util`)
- react-native-config (from `../../node_modules/react-native-config`)
- react-native-date-picker (from `../../node_modules/react-native-date-picker`)
- react-native-document-picker (from `../../node_modules/react-native-document-picker`)
- react-native-fingerprint-scanner (from `../../node_modules/react-native-fingerprint-scanner`)
- "react-native-fingerprint-scanner (from `../../node_modules/@ammarahmed/react-native-fingerprint-scanner`)"
- react-native-get-random-values (from `../../node_modules/react-native-get-random-values`)
- react-native-gzip (from `../../node_modules/react-native-gzip`)
- react-native-html-to-pdf-lite (from `../../node_modules/react-native-html-to-pdf-lite`)
@@ -1642,6 +1645,8 @@ EXTERNAL SOURCES:
:path: "../../node_modules/react-native-actions-shortcuts"
react-native-background-actions:
:path: "../../node_modules/react-native-background-actions"
react-native-begin-background-task:
:path: "../../node_modules/react-native-begin-background-task"
react-native-blob-util:
:path: "../../node_modules/react-native-blob-util"
react-native-config:
@@ -1651,7 +1656,7 @@ EXTERNAL SOURCES:
react-native-document-picker:
:path: "../../node_modules/react-native-document-picker"
react-native-fingerprint-scanner:
:path: "../../node_modules/react-native-fingerprint-scanner"
:path: "../../node_modules/@ammarahmed/react-native-fingerprint-scanner"
react-native-get-random-values:
:path: "../../node_modules/react-native-get-random-values"
react-native-gzip:
@@ -1833,11 +1838,12 @@ SPEC CHECKSUMS:
React-Mapbuffer: 6c1cacdbf40b531f549eba249e531a7d0bfd8e7f
react-native-actions-shortcuts: 5d9cf0c9c308333dfcc1e05c3f9afa8c428e2533
react-native-background-actions: 2c251c986f23347f9c1722f05fd296938f60edb1
react-native-begin-background-task: 3b889e07458afc5822a7277cf9cbc7cd077e39ee
react-native-blob-util: 2d36383bb52c15c5451be81cb7ddf22bc34a12a6
react-native-config: 86038147314e2e6d10ea9972022aa171e6b1d4d8
react-native-date-picker: 93e43b3084cea595b4d68b1405d6d99849663bd6
react-native-document-picker: ec07866a30707f23660c0f3ae591d669d3e89096
react-native-fingerprint-scanner: 3e8c46641b5751a31f45e66789d4b6f342be5e6d
react-native-fingerprint-scanner: be63e626b31fb951780a5fac5328b065a61a3d6e
react-native-get-random-values: dee677497c6a740b71e5612e8dbd83e7539ed5bb
react-native-gzip: c5e87ee9e359f02350e3a2ee52eb35eddc398868
react-native-html-to-pdf-lite: 21bfb169bf4cbcd7bec9f736975ee1b3f5292d4a

View File

@@ -25,7 +25,6 @@
"react-native": "0.74.5",
"react-native-actions-shortcuts": "^1.0.1",
"react-native-background-actions": "^2.6.6",
"react-native-begin-background-task": "https://github.com/blockfirm/react-native-begin-background-task.git",
"react-native-blob-util": "^0.18.3",
"react-native-bootsplash": "4.1.4",
"react-native-config": "^1.4.6",
@@ -33,9 +32,7 @@
"react-native-device-info": "^8.4.1",
"react-native-document-picker": "^7.1.1",
"@ammarahmed/react-native-eventsource": "1.1.0",
"react-native-exit-app": "https://github.com/ammarahm-ed/react-native-exit-app.git",
"react-native-file-viewer": "^2.1.1",
"react-native-fingerprint-scanner": "https://github.com/ammarahm-ed/react-native-fingerprint-scanner.git",
"react-native-gesture-handler": "^2.18.0",
"react-native-reanimated": "3.14.0",
"react-native-safe-area-context": "^4.10.8",
@@ -52,9 +49,7 @@
"react-native-modal-datetime-picker": "14.0.0",
"react-native-navigation-bar-color": "2.0.2",
"react-native-notification-sounds": "0.5.5",
"react-native-orientation": "https://github.com/yamill/react-native-orientation.git",
"react-native-pdf": "6.6.2",
"react-native-privacy-snapshot": "github:standardnotes/react-native-privacy-snapshot",
"react-native-scoped-storage": "^1.9.5",
"react-native-securerandom": "^1.0.1",
"react-native-share": "^7.2.0",
@@ -70,13 +65,18 @@
"react-native-screenguard": "^1.0.0",
"@formatjs/intl-locale": "4.0.0",
"@formatjs/intl-pluralrules": "5.2.14",
"detox": "^20.27.6",
"@ammarahmed/react-native-share-extension": "^2.6.0",
"@ammarahmed/react-native-sodium": "1.5.6",
"react-native-mmkv-storage": "^0.10.2",
"@react-native-community/datetimepicker": "^8.2.0"
"@react-native-community/datetimepicker": "^8.2.0",
"react-native-exit-app": "github:ammarahm-ed/react-native-exit-app",
"react-native-orientation": "github:yamill/react-native-orientation",
"react-native-begin-background-task": "github:blockfirm/react-native-begin-background-task",
"react-native-privacy-snapshot": "github:standardnotes/react-native-privacy-snapshot",
"@ammarahmed/react-native-fingerprint-scanner": "^5.0.0"
},
"devDependencies": {
"detox": "^20.27.6",
"@babel/core": "^7.20.0",
"@babel/eslint-parser": "^7.16.5",
"@babel/plugin-transform-named-capturing-groups-regex": "^7.16.5",

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "@notesnook/mobile",
"version": "3.0.21",
"version": "3.0.22",
"private": true,
"license": "GPL-3.0-or-later",
"workspaces": [
@@ -48,4 +48,4 @@
"react-native": "0.74.5",
"react-native-actions-sheet": "^0.9.7"
}
}
}

View File

@@ -1,11 +0,0 @@
diff --git a/node_modules/react-native-fingerprint-scanner/android/build.gradle b/node_modules/react-native-fingerprint-scanner/android/build.gradle
index eaf3829..6c392ba 100644
--- a/node_modules/react-native-fingerprint-scanner/android/build.gradle
+++ b/node_modules/react-native-fingerprint-scanner/android/build.gradle
@@ -49,5 +49,5 @@ dependencies {
// 1.2.3 is the minimum version compatible with androidx.
// See https://github.com/uccmawei/FingerprintIdentify/issues/74
// (translation https://translate.google.com/translate?sl=zh-CN&tl=en&u=https://github.com/uccmawei/FingerprintIdentify/issues/74)
- implementation "com.wei.android.lib:fingerprintidentify:${safeExtGet("fingerprintidentify", "1.2.6")}"
+ implementation "com.github.uccmawei:FingerprintIdentify:1.2.6"
}

View File

@@ -91,7 +91,8 @@
"prismjs": "^1.29.0",
"qclone": "^1.2.0",
"rfdc": "^1.3.0",
"spark-md5": "^3.0.2"
"spark-md5": "^3.0.2",
"sqlite-better-trigram": "^0.0.1"
},
"devDependencies": {
"@notesnook/crypto": "file:../crypto",
@@ -106,7 +107,7 @@
"@types/ws": "^8.5.5",
"@vitest/coverage-v8": "^1.0.1",
"abortcontroller-polyfill": "^1.7.3",
"better-sqlite3-multiple-ciphers": "^9.4.0",
"better-sqlite3-multiple-ciphers": "^11.5.0",
"bson-objectid": "^2.0.4",
"dotenv": "^16.0.1",
"event-source-polyfill": "^1.0.31",

View File

@@ -973,7 +973,7 @@
},
"../web": {
"name": "@notesnook/web",
"version": "3.0.18",
"version": "3.0.20",
"hasInstallScript": true,
"license": "GPL-3.0-or-later",
"dependencies": {

View File

@@ -1,12 +1,12 @@
{
"name": "@notesnook/web",
"version": "3.0.20",
"version": "3.0.21",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@notesnook/web",
"version": "3.0.20",
"version": "3.0.21",
"hasInstallScript": true,
"license": "GPL-3.0-or-later",
"dependencies": {
@@ -25207,7 +25207,8 @@
"prismjs": "^1.29.0",
"qclone": "^1.2.0",
"rfdc": "^1.3.0",
"spark-md5": "^3.0.2"
"spark-md5": "^3.0.2",
"sqlite-better-trigram": "^0.0.1"
},
"devDependencies": {
"@notesnook/crypto": "file:../crypto",
@@ -25222,7 +25223,7 @@
"@types/ws": "^8.5.5",
"@vitest/coverage-v8": "^1.0.1",
"abortcontroller-polyfill": "^1.7.3",
"better-sqlite3-multiple-ciphers": "^9.4.0",
"better-sqlite3-multiple-ciphers": "^11.5.0",
"bson-objectid": "^2.0.4",
"dotenv": "^16.0.1",
"event-source-polyfill": "^1.0.31",
@@ -35614,7 +35615,7 @@
},
"../desktop": {
"name": "@notesnook/desktop",
"version": "3.0.18",
"version": "3.0.20",
"hasInstallScript": true,
"license": "GPL-3.0-or-later",
"dependencies": {
@@ -35622,10 +35623,11 @@
"@notesnook/intl": "file:../../packages/intl",
"@trpc/client": "10.45.2",
"@trpc/server": "10.45.2",
"better-sqlite3-multiple-ciphers": "11.2.1",
"better-sqlite3-multiple-ciphers": "11.5.0",
"electron-trpc": "0.6.1",
"electron-updater": "^6.3.4",
"icojs": "^0.19.4",
"sqlite-better-trigram": "^0.0.2",
"typed-emitter": "^2.1.0",
"yargs": "^17.7.2",
"zod": "^3.23.8"
@@ -35635,14 +35637,17 @@
"@types/node": "22.7.0",
"@types/yargs": "^17.0.33",
"chokidar": "^4.0.1",
"electron": "^30.5.1",
"electron": "^31.7.4",
"electron-builder": "^25.1.8",
"esbuild": "^0.24.0",
"node-abi": "^3.68.0",
"node-gyp-build": "^4.8.2",
"playwright": "^1.48.2",
"prebuildify": "^6.0.1",
"slugify": "^1.6.6",
"tree-kill": "^1.2.2",
"undici": "^6.19.8"
"undici": "^6.19.8",
"vitest": "^2.1.5"
},
"optionalDependencies": {
"dmg-license": "^1.0.11"

View File

@@ -1,7 +1,7 @@
{
"name": "@notesnook/web",
"description": "Your private note taking space",
"version": "3.0.20",
"version": "3.0.21",
"private": true,
"main": "./src/app.js",
"homepage": "https://notesnook.com/",

View File

@@ -25,6 +25,7 @@ import {
CredentialType,
CredentialWithSecret,
CredentialWithoutSecret,
DEFAULT_ITERATIONS,
useKeyStore,
wrongCredentialError
} from "../../interfaces/key-store";
@@ -53,17 +54,16 @@ export const AppLockSettings: SettingsGroup[] = [
type: "toggle",
toggle: async () => {
const { credentials } = useKeyStore.getState();
if (credentials.length <= 0) {
const defaultCredential = credentials
.filter((c) => c.active)
.at(0);
if (!defaultCredential) {
const verified = await verifyAccount();
if (!verified) return;
await registerCredential("password");
} else {
const { credentials } = useKeyStore.getState();
const defaultCredential = credentials
.filter((c) => c.active)
.at(0);
if (!defaultCredential) return;
await unlockAppLock(defaultCredential);
}
},
@@ -309,7 +309,8 @@ async function registerCredential(type: CredentialType) {
await register({
type,
id: "password",
salt: window.crypto.getRandomValues(new Uint8Array(16))
salt: window.crypto.getRandomValues(new Uint8Array(16)),
iterations: DEFAULT_ITERATIONS
}).then(() =>
activate({
type,

View File

@@ -41,6 +41,7 @@ type BaseCredential<T extends CredentialType> = { type: T; id: string };
type PasswordCredential = BaseCredential<"password"> & {
password: string;
salt: Uint8Array;
iterations: number | undefined;
};
type SecurityKeyCredential = BaseCredential<"securityKey"> & {
@@ -58,7 +59,7 @@ export type SerializableCredential = CredentialWithoutSecret & {
active: boolean;
};
export type CredentialWithSecret =
| Omit<PasswordCredential, "salt">
| Omit<PasswordCredential, "salt" | "iterations">
| Omit<SecurityKeyCredential, "config">;
export type CredentialQuery = BaseCredential<CredentialType> & {
active?: boolean;
@@ -82,6 +83,8 @@ const defaultSecrets = {
};
type Secrets = typeof defaultSecrets;
export const DEFAULT_ITERATIONS = 100000;
const FALLBACK_ITERATIONS = 650000;
const encoder = new TextEncoder();
const decoder = new TextDecoder();
@@ -169,12 +172,13 @@ class KeyStore extends BaseStore<KeyStore> {
const index = credentials.findIndex(
(c) => c.type === credential.type && c.id === credential.id
);
if (index > -1) return;
if (index > -1) return credentials[index];
this.set((store) =>
store.credentials.push(serializeCredential(credential, false))
);
await this.#metadataStore.set("credentials", this.get().credentials);
return credential;
};
unregister = async (
@@ -257,10 +261,14 @@ class KeyStore extends BaseStore<KeyStore> {
if (!encryptedKey)
throw new Error("Could not find credential's encrypted key.");
const key = await unwrapKey(
encryptedKey,
await getWrappingKey(deserializeCredential(cred, credential))
);
const key = await unwrapKey(encryptedKey, [
await getWrappingKey(deserializeCredential(cred, credential)),
await getWrappingKey(fallbackCredential(cred, credential))
]).catch((e) => {
if (e instanceof Error && e.message === "Could not unwrap key.")
throw new Error(wrongCredentialError(credential));
throw e;
});
if (options?.permanent) {
await this.resetCredentials();
await this.storeKey(key);
@@ -295,14 +303,15 @@ class KeyStore extends BaseStore<KeyStore> {
);
if (!encryptedKey) return;
const decryptedKey = await unwrapKey(
encryptedKey,
await getWrappingKey(deserializeCredential(cred, oldCredential))
);
const decryptedKey = await unwrapKey(encryptedKey, [
await getWrappingKey(deserializeCredential(cred, oldCredential)),
await getWrappingKey(fallbackCredential(cred, oldCredential))
]);
const newCred = deserializeCredential(cred, newCredential);
const reencryptedKey = await wrapKey(
decryptedKey,
await getWrappingKey(deserializeCredential(cred, newCredential))
await getWrappingKey(newCred)
);
if (!reencryptedKey) throw new Error(wrongCredentialError(newCredential));
@@ -310,6 +319,10 @@ class KeyStore extends BaseStore<KeyStore> {
this.getCredentialKey(newCredential),
reencryptedKey
);
await this.update(oldCredential, (c) => {
if (c.type === "password" && newCred.type === "password")
c.iterations = newCred.iterations;
});
};
verifyCredential = async (credential: CredentialWithSecret) => {
@@ -322,10 +335,10 @@ class KeyStore extends BaseStore<KeyStore> {
);
if (!encryptedKey) return false;
const decryptedKey = await unwrapKey(
encryptedKey,
await getWrappingKey(deserializeCredential(cred, credential))
);
const decryptedKey = await unwrapKey(encryptedKey, [
await getWrappingKey(deserializeCredential(cred, credential)),
await getWrappingKey(fallbackCredential(cred, credential))
]);
return !!decryptedKey;
} catch {
return false;
@@ -414,7 +427,7 @@ class KeyStore extends BaseStore<KeyStore> {
["encrypt", "decrypt"]
);
} else if (wrappingKey) {
return unwrapKey(wrappedKey, wrappingKey);
return unwrapKey(wrappedKey, [wrappingKey]);
} else throw new Error("Could not decrypt key.");
};
@@ -479,7 +492,8 @@ function serializeCredential(
type: "password",
id: credential.id,
active,
salt: credential.salt
salt: credential.salt,
iterations: credential.iterations
};
case "securityKey":
return {
@@ -500,7 +514,8 @@ function deserializeCredential(
type: "password",
id: credential.id,
salt: credential.salt,
password: secret.password
password: secret.password,
iterations: credential.iterations || DEFAULT_ITERATIONS
};
} else if (secret.type === "securityKey" && credential.type === "securityKey")
return {
@@ -513,6 +528,21 @@ function deserializeCredential(
throw new Error("Credentials are of different types.");
}
function fallbackCredential(
credential: SerializableCredential,
secret: CredentialWithSecret
): Credential | undefined {
if (secret.type === "password" && credential.type === "password") {
return {
type: "password",
id: credential.id,
salt: credential.salt,
password: secret.password,
iterations: FALLBACK_ITERATIONS
};
}
}
export function wrongCredentialError(query: CredentialQuery): string {
switch (query.type) {
case "password":
@@ -524,17 +554,23 @@ export function wrongCredentialError(query: CredentialQuery): string {
async function unwrapKey(
wrappedKey: ArrayBuffer,
wrappingKey: CryptoKey
wrappingKeys: CryptoKey[]
): Promise<CryptoKey> {
return await window.crypto.subtle.unwrapKey(
"raw",
wrappedKey,
wrappingKey,
"AES-KW",
{ name: "AES-GCM", length: 256 },
true,
["encrypt", "decrypt"]
);
for (const key of wrappingKeys) {
const unwrapped = await window.crypto.subtle
.unwrapKey(
"raw",
wrappedKey,
key,
"AES-KW",
{ name: "AES-GCM", length: 256 },
true,
["encrypt", "decrypt"]
)
.catch(() => undefined);
if (unwrapped) return unwrapped;
}
throw new Error("Could not unwrap key.");
}
async function wrapKey(key: CryptoKey, wrappingKey: CryptoKey) {
@@ -555,7 +591,7 @@ async function getWrappingKey(credential?: Credential): Promise<CryptoKey> {
{
name: "PBKDF2",
salt: credential.salt,
iterations: 100000,
iterations: credential.iterations || DEFAULT_ITERATIONS,
hash: "SHA-512"
},
await window.crypto.subtle.importKey(

View File

@@ -936,19 +936,19 @@ class EditorStore extends BaseStore<EditorStore> {
};
toggleTableOfContents = (toggleState?: boolean) => {
this.set((state) => {
state.isTOCVisible =
toggleState !== undefined ? toggleState : !state.isTOCVisible;
Config.set("editor:toc", !state.isTOCVisible);
});
const { isTOCVisible } = this.get();
const isTOCVisibleState =
toggleState !== undefined ? toggleState : !isTOCVisible;
this.set({ isTOCVisible: isTOCVisibleState });
Config.set("editor:toc", isTOCVisibleState);
};
toggleEditorMargins = (toggleState?: boolean) => {
this.set((state) => {
state.editorMargins =
toggleState !== undefined ? toggleState : !state.editorMargins;
Config.set("editor:margins", state.editorMargins);
});
const { editorMargins } = this.get();
const editorMarginsState =
toggleState !== undefined ? toggleState : !editorMargins;
this.set({ editorMargins: editorMarginsState });
Config.set("editor:margins", editorMarginsState);
};
}

View File

@@ -75,7 +75,8 @@ export default function AppLock(props: PropsWithChildren<unknown>) {
typeof e === "string"
? e
: "message" in e && typeof e.message === "string"
? e.message === "ciphertext cannot be decrypted using that key"
? e.message === "ciphertext cannot be decrypted using that key" ||
e.message === "Could not unwrap key."
? "Wrong password."
: e.message || "Wrong password."
: JSON.stringify(e)

View File

@@ -0,0 +1,9 @@
- Added full support for localization in Notesnook
- Improved search experience
- Allow user to cancel logging in
- Fixed scrolling focused line into view
- Support self hosted monograph server
- Fixed markdown link pasting in editor
- Many other bug fixes and improvements
Thank you for using Notesnook!

View File

@@ -71,7 +71,7 @@
"@types/ws": "^8.5.5",
"@vitest/coverage-v8": "^1.0.1",
"abortcontroller-polyfill": "^1.7.3",
"better-sqlite3-multiple-ciphers": "^9.4.0",
"better-sqlite3-multiple-ciphers": "^11.5.0",
"bson-objectid": "^2.0.4",
"dotenv": "^16.0.1",
"event-source-polyfill": "^1.0.31",
@@ -1857,7 +1857,7 @@
"@vitest/coverage-v8": "^1.0.1",
"abortcontroller-polyfill": "^1.7.3",
"async-mutex": "^0.3.2",
"better-sqlite3-multiple-ciphers": "^9.4.0",
"better-sqlite3-multiple-ciphers": "^11.5.0",
"bson-objectid": "^2.0.4",
"dayjs": "1.11.9",
"dom-serializer": "^2.0.0",

View File

@@ -4441,7 +4441,7 @@
"version": "15.7.11",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz",
"integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==",
"devOptional": true
"dev": true
},
"node_modules/@types/q": {
"version": "1.5.8",
@@ -4465,7 +4465,7 @@
"version": "18.2.39",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.39.tgz",
"integrity": "sha512-Oiw+ppED6IremMInLV4HXGbfbG6GyziY3kqAwJYOR0PNbkYDmLWQA3a95EhdSmamsvbkJN96ZNN+YD+fGjzSBA==",
"devOptional": true,
"dev": true,
"dependencies": {
"@types/prop-types": "*",
"@types/scheduler": "*",
@@ -4500,7 +4500,7 @@
"version": "0.16.8",
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz",
"integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==",
"devOptional": true
"dev": true
},
"node_modules/@types/semver": {
"version": "7.5.6",
@@ -9762,7 +9762,7 @@
"version": "9.0.21",
"resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz",
"integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==",
"devOptional": true,
"dev": true,
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/immer"
@@ -17856,21 +17856,6 @@
"is-typedarray": "^1.0.0"
}
},
"node_modules/typescript": {
"version": "4.9.5",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
"integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
"dev": true,
"license": "Apache-2.0",
"peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=4.2.0"
}
},
"node_modules/unbox-primitive": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",

View File

@@ -266,7 +266,6 @@ export function ImageComponent(
title={title}
sx={{
animation: bloburl || src ? "0.2s ease-in 0s 1 fadeIn" : "none",
opacity: 0,
objectFit: "contain",
width: editor.isEditable ? "100%" : size.width,
height: editor.isEditable ? "100%" : size.height,

View File

@@ -27,14 +27,6 @@
pointer-events: none;
}
.ProseMirror h1,
.ProseMirror h2,
.ProseMirror h3,
.ProseMirror h4,
.ProseMirror h5,
.ProseMirror h6 {
margin-bottom: -10px;
}
.ProseMirror p code {
background-color: var(--background-secondary);
}

View File

@@ -52,6 +52,10 @@ const directoryTree = {
"package.json": ["packages", "sodium", "package.json"],
"package-lock.json": ["packages", "sodium", "package-lock.json"]
},
intl: {
"package.json": ["packages", "intl", "package.json"],
"package-lock.json": ["packages", "intl", "package-lock.json"]
},
crypto: {
"package.json": ["packages", "crypto", "package.json"],
"package-lock.json": ["packages", "crypto", "package-lock.json"]