mirror of
https://github.com/streetwriters/notesnook.git
synced 2026-08-30 02:29:18 +02:00
Compare commits
14 Commits
feature/im
...
fix-defaul
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
53baa1a852 | ||
|
|
c54759e766 | ||
|
|
f15446b1d6 | ||
|
|
aa2a8ab6f4 | ||
|
|
8e59ff1318 | ||
|
|
ad99c87f72 | ||
|
|
ba776b5854 | ||
|
|
e526145e48 | ||
|
|
45c5e65bf6 | ||
|
|
87bec4e2ab | ||
|
|
433e67a6dc | ||
|
|
6acba51b88 | ||
|
|
cf1322952d | ||
|
|
b5ac9dd430 |
4
apps/desktop/package-lock.json
generated
4
apps/desktop/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@notesnook/desktop",
|
||||
"version": "2.6.16",
|
||||
"version": "2.6.17",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@notesnook/desktop",
|
||||
"version": "2.6.16",
|
||||
"version": "2.6.17",
|
||||
"hasInstallScript": true,
|
||||
"license": "GPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "@notesnook/desktop",
|
||||
"productName": "Notesnook",
|
||||
"description": "Your private note taking space",
|
||||
"version": "2.6.16",
|
||||
"version": "2.6.17",
|
||||
"appAppleId": "1544027013",
|
||||
"private": true,
|
||||
"main": "./dist/index.js",
|
||||
|
||||
@@ -19,7 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { useThemeColors } from "@notesnook/theme";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Modal, View } from "react-native";
|
||||
import { View } from "react-native";
|
||||
import { db } from "../../common/database";
|
||||
import { MMKV } from "../../common/database/mmkv";
|
||||
import BiometricService from "../../services/biometrics";
|
||||
@@ -37,6 +37,7 @@ import { eLoginSessionExpired, eUserLoggedIn } from "../../utils/events";
|
||||
import { SIZE } from "../../utils/size";
|
||||
import { sleep } from "../../utils/time";
|
||||
import { Dialog } from "../dialog";
|
||||
import BaseDialog from "../dialog/base-dialog";
|
||||
import { presentDialog } from "../dialog/functions";
|
||||
import SheetProvider from "../sheet-provider";
|
||||
import { Toast } from "../toast";
|
||||
@@ -46,7 +47,6 @@ import Input from "../ui/input";
|
||||
import Heading from "../ui/typography/heading";
|
||||
import Paragraph from "../ui/typography/paragraph";
|
||||
import { LoginSteps, useLogin } from "./use-login";
|
||||
import BaseDialog from "../dialog/base-dialog";
|
||||
|
||||
function getObfuscatedEmail(email) {
|
||||
if (!email) return "";
|
||||
@@ -69,6 +69,9 @@ export const SessionExpired = () => {
|
||||
eSendEvent(eUserLoggedIn, true);
|
||||
setVisible(false);
|
||||
setFocused(false);
|
||||
useUserStore.setState({
|
||||
disableAppLockRequests: false
|
||||
});
|
||||
},
|
||||
true
|
||||
);
|
||||
@@ -84,6 +87,9 @@ export const SessionExpired = () => {
|
||||
MMKV.clearStore();
|
||||
clearAllStores();
|
||||
setVisible(false);
|
||||
useUserStore.setState({
|
||||
disableAppLockRequests: false
|
||||
});
|
||||
} catch (e) {
|
||||
ToastEvent.show({
|
||||
heading: e.message,
|
||||
@@ -127,6 +133,9 @@ export const SessionExpired = () => {
|
||||
email.current = user.email;
|
||||
setFocused(false);
|
||||
setVisible(true);
|
||||
useUserStore.setState({
|
||||
disableAppLockRequests: true
|
||||
});
|
||||
}
|
||||
}, [email]);
|
||||
|
||||
@@ -142,6 +151,9 @@ export const SessionExpired = () => {
|
||||
await sleep(300);
|
||||
passwordInputRef.current?.focus();
|
||||
setFocused(true);
|
||||
useUserStore.setState({
|
||||
disableAppLockRequests: true
|
||||
});
|
||||
}}
|
||||
enableSheetKeyboardHandler={true}
|
||||
visible={true}
|
||||
|
||||
@@ -61,7 +61,10 @@ export const getGithubVersion = async () => {
|
||||
if (!res?.ok) return null;
|
||||
const data = (await res?.json()) as GithubRelease[];
|
||||
|
||||
const versions = data?.filter((tag) => tag.tag_name.endsWith("android"));
|
||||
const versions = data?.filter(
|
||||
(tag) =>
|
||||
tag.tag_name.endsWith("android") && !tag.tag_name.endsWith("beta-android")
|
||||
);
|
||||
const latestVersion = versions[0];
|
||||
const version = latestVersion.tag_name.replace("-android", "");
|
||||
return {
|
||||
|
||||
@@ -111,7 +111,7 @@ android {
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
multiDexEnabled true
|
||||
versionCode 2084
|
||||
versionCode 2090
|
||||
versionName getNpmVersion()
|
||||
testBuildType System.getProperty('testBuildType', 'debug')
|
||||
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
# Default value: -Xmx10248m -XX:MaxPermSize=256m
|
||||
org.gradle.jvmargs=-Xmx4096m -XX:MaxPermSize=1024m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
|
||||
org.gradle.jvmargs=-Xmx4096m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
|
||||
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. More details, visit
|
||||
@@ -47,4 +47,4 @@ hermesEnabled=true
|
||||
# v8.android.tools.dir=/home/ammarahm-ed/Repos/notesnook-mobile/node_modules/v8-android-jit-nointl/dist/tools/android
|
||||
|
||||
# fdroid
|
||||
fdroidBuild=false
|
||||
fdroidBuild=false
|
||||
|
||||
@@ -1,10 +1,3 @@
|
||||
- Support for exporting locked notes
|
||||
- Maintain directory structure in exports based on Notebooks/Topics
|
||||
- Match color of navigation bar in sheets with app theme
|
||||
- Improved image loading and show progress when loading images
|
||||
- Support for setting trash interval to daily
|
||||
- Fix android app UI issues with RTL languages
|
||||
- Fix pasting links in editor
|
||||
- Other Bug fixes and performance improvements
|
||||
- Minor bug fixes
|
||||
|
||||
Thank you for using Notesnook!
|
||||
@@ -997,7 +997,7 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 2085;
|
||||
CURRENT_PROJECT_VERSION = 2090;
|
||||
DEVELOPMENT_TEAM = 53CWBG3QUC;
|
||||
ENABLE_BITCODE = NO;
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
|
||||
@@ -1071,7 +1071,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.6.17;
|
||||
MARKETING_VERSION = 2.6.18;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
@@ -1102,7 +1102,7 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 2085;
|
||||
CURRENT_PROJECT_VERSION = 2090;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 53CWBG3QUC;
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
|
||||
@@ -1176,7 +1176,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.6.17;
|
||||
MARKETING_VERSION = 2.6.18;
|
||||
ONLY_ACTIVE_ARCH = NO;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
@@ -1335,7 +1335,7 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 2085;
|
||||
CURRENT_PROJECT_VERSION = 2090;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_TEAM = 53CWBG3QUC;
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
|
||||
@@ -1347,7 +1347,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.6.17;
|
||||
MARKETING_VERSION = 2.6.18;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.notewidget;
|
||||
@@ -1378,7 +1378,7 @@
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 2085;
|
||||
CURRENT_PROJECT_VERSION = 2090;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = "";
|
||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 53CWBG3QUC;
|
||||
@@ -1391,7 +1391,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.6.17;
|
||||
MARKETING_VERSION = 2.6.18;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.notewidget;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
@@ -1421,7 +1421,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = "Make Note/Make Note.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 2085;
|
||||
CURRENT_PROJECT_VERSION = 2090;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_TEAM = 53CWBG3QUC;
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
|
||||
@@ -1495,7 +1495,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.6.17;
|
||||
MARKETING_VERSION = 2.6.18;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.share;
|
||||
@@ -1526,7 +1526,7 @@
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 2085;
|
||||
CURRENT_PROJECT_VERSION = 2090;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = "";
|
||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 53CWBG3QUC;
|
||||
@@ -1601,7 +1601,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.6.17;
|
||||
MARKETING_VERSION = 2.6.18;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.share;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
|
||||
15
apps/mobile/package-lock.json
generated
15
apps/mobile/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@notesnook/mobile",
|
||||
"version": "2.6.15",
|
||||
"version": "2.6.17",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@notesnook/mobile",
|
||||
"version": "2.6.15",
|
||||
"version": "2.6.17",
|
||||
"hasInstallScript": true,
|
||||
"license": "GPL-3.0-or-later",
|
||||
"workspaces": [
|
||||
@@ -57,13 +57,13 @@
|
||||
"../../packages/core": {
|
||||
"name": "@notesnook/core",
|
||||
"version": "7.4.1",
|
||||
"hasInstallScript": true,
|
||||
"license": "GPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@microsoft/signalr": "^7.0.10",
|
||||
"@microsoft/signalr-protocol-msgpack": "^7.0.10",
|
||||
"@microsoft/signalr": "^8.0.0",
|
||||
"@notesnook/logger": "file:../logger",
|
||||
"@readme/data-urls": "^3.0.0",
|
||||
"@streetwriters/showdown": "^3.0.4-alpha",
|
||||
"@streetwriters/showdown": "^3.0.5-alpha",
|
||||
"async-mutex": "^0.3.2",
|
||||
"dayjs": "1.11.9",
|
||||
"entities": "^4.3.1",
|
||||
@@ -26837,12 +26837,11 @@
|
||||
"@notesnook/core": {
|
||||
"version": "file:../../packages/core",
|
||||
"requires": {
|
||||
"@microsoft/signalr": "^7.0.10",
|
||||
"@microsoft/signalr-protocol-msgpack": "^7.0.10",
|
||||
"@microsoft/signalr": "^8.0.0",
|
||||
"@notesnook/crypto": "file:../crypto",
|
||||
"@notesnook/logger": "file:../logger",
|
||||
"@readme/data-urls": "^3.0.0",
|
||||
"@streetwriters/showdown": "^3.0.4-alpha",
|
||||
"@streetwriters/showdown": "^3.0.5-alpha",
|
||||
"@types/html-to-text": "^9.0.0",
|
||||
"@types/katex": "^0.16.1",
|
||||
"@types/prismjs": "^1.26.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@notesnook/mobile",
|
||||
"version": "2.6.17",
|
||||
"version": "2.6.18",
|
||||
"private": true,
|
||||
"license": "GPL-3.0-or-later",
|
||||
"workspaces": [
|
||||
@@ -45,4 +45,4 @@
|
||||
"react-native": "0.72.0",
|
||||
"react-native-iap": "12.11.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
2
apps/theme-builder/package-lock.json
generated
2
apps/theme-builder/package-lock.json
generated
@@ -1377,7 +1377,7 @@
|
||||
},
|
||||
"../web": {
|
||||
"name": "@notesnook/web",
|
||||
"version": "2.6.14",
|
||||
"version": "2.6.17",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@aws-sdk/util-base64-browser": "^3.208.0",
|
||||
|
||||
@@ -26,20 +26,25 @@ import { consumeReadableStream } from "../src/utils/stream";
|
||||
import { xxhash64 } from "hash-wasm";
|
||||
import path from "path";
|
||||
|
||||
const CHUNK_SIZE = 512 * 1024;
|
||||
const CHUNK_SIZE = 512 * 1024 + 17;
|
||||
test("chunked stream should create equal sized chunks", async (t) => {
|
||||
const chunks = await consumeReadableStream(
|
||||
(
|
||||
Readable.toWeb(
|
||||
createReadStream(
|
||||
path.join(__dirname, "..", "__e2e__", "data", "importer-data.zip")
|
||||
)
|
||||
createReadStream(path.join(__dirname, "data", "35a4b0a78dbb9260"))
|
||||
) as ReadableStream<Uint8Array>
|
||||
).pipeThrough(new ChunkedStream(CHUNK_SIZE))
|
||||
).pipeThrough(new ChunkedStream(CHUNK_SIZE, "copy"))
|
||||
);
|
||||
|
||||
t.expect(await Promise.all(chunks.map((a) => xxhash64(a)))).toMatchObject([
|
||||
"6234b76401d9eb97",
|
||||
"338834da3f6500b2"
|
||||
"9a3fa91d341b245d",
|
||||
"c6b5d3ec17f14a5e",
|
||||
"5163243faf462ce4",
|
||||
"63aca6b8a7f68476",
|
||||
"cd9d082fa3015bd3"
|
||||
]);
|
||||
|
||||
t.expect(
|
||||
await Promise.all(chunks.map((a) => a.byteOffset === 0))
|
||||
).toMatchObject([true, true, true, true, true]);
|
||||
});
|
||||
|
||||
BIN
apps/web/__tests__/data/35a4b0a78dbb9260
Normal file
BIN
apps/web/__tests__/data/35a4b0a78dbb9260
Normal file
Binary file not shown.
12
apps/web/package-lock.json
generated
12
apps/web/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@notesnook/web",
|
||||
"version": "2.6.16",
|
||||
"version": "2.6.17",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@notesnook/web",
|
||||
"version": "2.6.16",
|
||||
"version": "2.6.17",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@aws-sdk/util-base64-browser": "^3.208.0",
|
||||
@@ -210,13 +210,13 @@
|
||||
"../../packages/core": {
|
||||
"name": "@notesnook/core",
|
||||
"version": "7.4.1",
|
||||
"hasInstallScript": true,
|
||||
"license": "GPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@microsoft/signalr": "^7.0.10",
|
||||
"@microsoft/signalr-protocol-msgpack": "^7.0.10",
|
||||
"@microsoft/signalr": "^8.0.0",
|
||||
"@notesnook/logger": "file:../logger",
|
||||
"@readme/data-urls": "^3.0.0",
|
||||
"@streetwriters/showdown": "^3.0.4-alpha",
|
||||
"@streetwriters/showdown": "^3.0.5-alpha",
|
||||
"async-mutex": "^0.3.2",
|
||||
"dayjs": "1.11.9",
|
||||
"entities": "^4.3.1",
|
||||
@@ -439,7 +439,7 @@
|
||||
},
|
||||
"../desktop": {
|
||||
"name": "@notesnook/desktop",
|
||||
"version": "2.6.15",
|
||||
"version": "2.6.17",
|
||||
"hasInstallScript": true,
|
||||
"license": "GPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@notesnook/web",
|
||||
"description": "Your private note taking space",
|
||||
"version": "2.6.16",
|
||||
"version": "2.6.17",
|
||||
"private": true,
|
||||
"main": "./src/app.js",
|
||||
"homepage": "https://notesnook.com/",
|
||||
|
||||
@@ -74,7 +74,7 @@ const menuItems: (topic: any, items?: any[]) => MenuItem[] = (
|
||||
type: "button",
|
||||
key: "set-as-default",
|
||||
title: "Set as default",
|
||||
checked:
|
||||
isChecked:
|
||||
defaultNotebook?.id === topic.notebookId &&
|
||||
defaultNotebook?.topic === topic.id,
|
||||
icon: TopicIcon.path,
|
||||
|
||||
5
apps/web/src/global.d.ts
vendored
5
apps/web/src/global.d.ts
vendored
@@ -36,4 +36,9 @@ declare global {
|
||||
os?: () => NodeJS.Platform | "mas";
|
||||
NativeNNCrypto?: new () => import("@notesnook/crypto").NNCrypto;
|
||||
}
|
||||
interface FileSystemFileHandle {
|
||||
createSyncAccessHandle(options?: {
|
||||
mode: "read-only" | "readwrite" | "readwrite-unsafe";
|
||||
}): Promise<FileSystemSyncAccessHandle>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -446,18 +446,19 @@ function reportProgress(
|
||||
}
|
||||
|
||||
async function downloadFile(filename: string, requestOptions: RequestOptions) {
|
||||
const { url, headers, chunkSize, signal } = requestOptions;
|
||||
const handle = await streamablefs.readFile(filename);
|
||||
|
||||
if (
|
||||
handle &&
|
||||
handle.file.size === (await handle.size()) - handle.file.chunks * ABYTES
|
||||
)
|
||||
return true;
|
||||
else if (handle) await handle.delete();
|
||||
|
||||
const attachment = db.attachments?.attachment(filename);
|
||||
try {
|
||||
const { url, headers, chunkSize, signal } = requestOptions;
|
||||
const handle = await streamablefs.readFile(filename);
|
||||
|
||||
if (
|
||||
handle &&
|
||||
handle.file.size === (await handle.size()) - handle.file.chunks * ABYTES
|
||||
)
|
||||
return true;
|
||||
else if (handle) await handle.delete();
|
||||
|
||||
const attachment = db.attachments?.attachment(filename);
|
||||
|
||||
reportProgress(
|
||||
{ total: 100, loaded: 0 },
|
||||
{ type: "download", hash: filename }
|
||||
|
||||
@@ -24,6 +24,7 @@ import { expose, transfer } from "comlink";
|
||||
|
||||
class OriginPrivateFileStore implements IFileStorage {
|
||||
private storage: IndexedDBKVStore;
|
||||
private locks: Map<string, Promise<any>> = new Map();
|
||||
constructor(
|
||||
name: string,
|
||||
private readonly directory: FileSystemDirectoryHandle
|
||||
@@ -33,7 +34,9 @@ class OriginPrivateFileStore implements IFileStorage {
|
||||
|
||||
async clear(): Promise<void> {
|
||||
for await (const [name] of this.directory) {
|
||||
await this.directory.removeEntry(name, { recursive: true });
|
||||
await this.safeOp(name, () =>
|
||||
this.directory.removeEntry(name, { recursive: true })
|
||||
);
|
||||
}
|
||||
await this.storage.clear();
|
||||
}
|
||||
@@ -47,33 +50,59 @@ class OriginPrivateFileStore implements IFileStorage {
|
||||
return this.storage.delete(filename);
|
||||
}
|
||||
async writeChunk(chunkName: string, data: Uint8Array): Promise<void> {
|
||||
const file = await this.directory.getFileHandle(chunkName, {
|
||||
create: true
|
||||
});
|
||||
const syncHandle = await file.createSyncAccessHandle();
|
||||
syncHandle.write(data);
|
||||
syncHandle.close();
|
||||
try {
|
||||
await this.safeOp(chunkName, () =>
|
||||
this.directory
|
||||
.getFileHandle(chunkName, {
|
||||
create: true
|
||||
})
|
||||
.then((file) => file.createSyncAccessHandle())
|
||||
.then((handle) => {
|
||||
handle.write(data);
|
||||
handle.close();
|
||||
})
|
||||
);
|
||||
} catch (e) {
|
||||
console.error("Failed to write chunk", e);
|
||||
}
|
||||
}
|
||||
|
||||
async deleteChunk(chunkName: string) {
|
||||
try {
|
||||
await this.directory.removeEntry(chunkName);
|
||||
await this.safeOp(chunkName, () => this.directory.removeEntry(chunkName));
|
||||
} catch (e) {
|
||||
console.error("Failed to delete chunk", e);
|
||||
}
|
||||
}
|
||||
|
||||
async readChunk(chunkName: string): Promise<Uint8Array | undefined> {
|
||||
try {
|
||||
const file = await this.directory.getFileHandle(chunkName);
|
||||
const syncHandle = await file.createSyncAccessHandle();
|
||||
const buffer = new Uint8Array(syncHandle.getSize());
|
||||
syncHandle.read(buffer);
|
||||
syncHandle.close();
|
||||
return buffer;
|
||||
if (Object.hasOwn(FileSystemSyncAccessHandle.prototype, "mode")) {
|
||||
return readFile(this.directory, chunkName);
|
||||
}
|
||||
|
||||
// OPFS currently does not support multiple readers on a single file
|
||||
// on all browsers so we wait for the file handle to be released before
|
||||
// continuing. This is temporary until all browsers start supporting
|
||||
// the read-only mode.
|
||||
return await this.safeOp(chunkName, () =>
|
||||
readFile(this.directory, chunkName)
|
||||
);
|
||||
} catch (e) {
|
||||
console.error("Failed to read chunk", e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private async safeOp<T>(chunkName: string, createPromise: () => Promise<T>) {
|
||||
const lock = this.locks.get(chunkName);
|
||||
if (lock) await lock;
|
||||
|
||||
const promise = createPromise();
|
||||
this.locks.set(chunkName, promise);
|
||||
|
||||
return await promise.finally(() => this.locks.delete(chunkName));
|
||||
}
|
||||
}
|
||||
|
||||
const fileStores: Map<string, OriginPrivateFileStore> = new Map();
|
||||
@@ -117,3 +146,12 @@ const workerModule = {
|
||||
expose(workerModule);
|
||||
|
||||
export type OriginPrivateFileStoreWorkerType = typeof workerModule;
|
||||
|
||||
async function readFile(directory: FileSystemDirectoryHandle, name: string) {
|
||||
const file = await directory.getFileHandle(name);
|
||||
const handle = await file.createSyncAccessHandle({ mode: "read-only" });
|
||||
const buffer = new Uint8Array(handle.getSize());
|
||||
handle.read(buffer);
|
||||
handle.close();
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@@ -72,9 +72,8 @@ class AttachmentStore extends BaseStore {
|
||||
await createWriteStream("attachments.zip", {
|
||||
signal: abortController.signal
|
||||
})
|
||||
);
|
||||
|
||||
this.set((state) => (state.status = undefined));
|
||||
)
|
||||
.finally(() => this.set((state) => (state.status = undefined)));
|
||||
};
|
||||
|
||||
cancel = async () => {
|
||||
|
||||
@@ -76,7 +76,7 @@ class SettingStore extends BaseStore {
|
||||
privacyMode: await desktop?.integration.privacyMode.query(),
|
||||
zoomFactor: await desktop?.integration.zoomFactor.query(),
|
||||
autoUpdates: await desktop?.updater.autoUpdates.query(),
|
||||
proxyRules: await desktop.integration.proxyRules.query()
|
||||
proxyRules: await desktop?.integration.proxyRules.query()
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -40,46 +40,51 @@ export class AttachmentStream extends ReadableStream<ZipFile> {
|
||||
super({
|
||||
start() {},
|
||||
async pull(controller) {
|
||||
if (signal?.aborted) {
|
||||
controller.close();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (signal?.aborted) {
|
||||
controller.close();
|
||||
return;
|
||||
}
|
||||
|
||||
onProgress && onProgress(index);
|
||||
const attachment = attachments[index++];
|
||||
onProgress && onProgress(index);
|
||||
const attachment = attachments[index++];
|
||||
|
||||
await db.fs?.downloadFile(
|
||||
GROUP_ID,
|
||||
attachment.metadata.hash,
|
||||
attachment.chunkSize,
|
||||
attachment.metadata
|
||||
);
|
||||
await db.fs?.downloadFile(
|
||||
GROUP_ID,
|
||||
attachment.metadata.hash,
|
||||
attachment.chunkSize,
|
||||
attachment.metadata
|
||||
);
|
||||
|
||||
const key = await db.attachments?.decryptKey(attachment.key);
|
||||
const file = await lazify(
|
||||
import("../../interfaces/fs"),
|
||||
({ decryptFile }) =>
|
||||
decryptFile(attachment.metadata.hash, {
|
||||
key,
|
||||
iv: attachment.iv,
|
||||
name: attachment.metadata.filename,
|
||||
type: attachment.metadata.type,
|
||||
isUploaded: !!attachment.dateUploaded
|
||||
})
|
||||
);
|
||||
const key = await db.attachments?.decryptKey(attachment.key);
|
||||
const file = await lazify(
|
||||
import("../../interfaces/fs"),
|
||||
({ decryptFile }) =>
|
||||
decryptFile(attachment.metadata.hash, {
|
||||
key,
|
||||
iv: attachment.iv,
|
||||
name: attachment.metadata.filename,
|
||||
type: attachment.metadata.type,
|
||||
isUploaded: !!attachment.dateUploaded
|
||||
})
|
||||
);
|
||||
|
||||
if (file) {
|
||||
const filePath: string = attachment.metadata.filename;
|
||||
controller.enqueue({
|
||||
path: makeUniqueFilename(filePath, counters),
|
||||
data: new Uint8Array(await file.arrayBuffer())
|
||||
});
|
||||
} else {
|
||||
controller.error(new Error("Failed to decrypt file."));
|
||||
}
|
||||
|
||||
if (index === attachments.length) {
|
||||
controller.close();
|
||||
if (file) {
|
||||
const filePath: string = attachment.metadata.filename;
|
||||
controller.enqueue({
|
||||
path: makeUniqueFilename(filePath, counters),
|
||||
data: new Uint8Array(await file.arrayBuffer())
|
||||
});
|
||||
} else {
|
||||
controller.error(new Error("Failed to decrypt file."));
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
controller.error(e);
|
||||
} finally {
|
||||
if (index === attachments.length) {
|
||||
controller.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -55,7 +55,11 @@ export class ChunkedStream extends TransformStream<Uint8Array, Uint8Array> {
|
||||
}
|
||||
},
|
||||
flush(controller) {
|
||||
if (backBuffer) controller.enqueue(backBuffer);
|
||||
if (backBuffer) {
|
||||
const buffer =
|
||||
mode === "copy" ? new Uint8Array(backBuffer) : backBuffer;
|
||||
controller.enqueue(buffer);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
3
fastlane/metadata/android/en-US/changelogs/10454.txt
Normal file
3
fastlane/metadata/android/en-US/changelogs/10454.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
- Minor bug fixes
|
||||
|
||||
Thank you for using Notesnook!
|
||||
11
packages/common/package-lock.json
generated
11
packages/common/package-lock.json
generated
@@ -26,13 +26,13 @@
|
||||
"name": "@notesnook/core",
|
||||
"version": "7.4.1",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "GPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@microsoft/signalr": "^7.0.10",
|
||||
"@microsoft/signalr-protocol-msgpack": "^7.0.10",
|
||||
"@microsoft/signalr": "^8.0.0",
|
||||
"@notesnook/logger": "file:../logger",
|
||||
"@readme/data-urls": "^3.0.0",
|
||||
"@streetwriters/showdown": "^3.0.4-alpha",
|
||||
"@streetwriters/showdown": "^3.0.5-alpha",
|
||||
"async-mutex": "^0.3.2",
|
||||
"dayjs": "1.11.9",
|
||||
"entities": "^4.3.1",
|
||||
@@ -144,12 +144,11 @@
|
||||
"@notesnook/core": {
|
||||
"version": "file:../core",
|
||||
"requires": {
|
||||
"@microsoft/signalr": "^7.0.10",
|
||||
"@microsoft/signalr-protocol-msgpack": "^7.0.10",
|
||||
"@microsoft/signalr": "^8.0.0",
|
||||
"@notesnook/crypto": "file:../crypto",
|
||||
"@notesnook/logger": "file:../logger",
|
||||
"@readme/data-urls": "^3.0.0",
|
||||
"@streetwriters/showdown": "^3.0.4-alpha",
|
||||
"@streetwriters/showdown": "^3.0.5-alpha",
|
||||
"@types/html-to-text": "^9.0.0",
|
||||
"@types/katex": "^0.16.1",
|
||||
"@types/prismjs": "^1.26.0",
|
||||
|
||||
6
packages/core/package-lock.json
generated
6
packages/core/package-lock.json
generated
@@ -4158,8 +4158,7 @@
|
||||
"version": "8.13.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz",
|
||||
"integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -4944,8 +4943,7 @@
|
||||
"ws": {
|
||||
"version": "7.5.9",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
|
||||
"integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
|
||||
"requires": {}
|
||||
"integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q=="
|
||||
},
|
||||
"xml-name-validator": {
|
||||
"version": "4.0.0",
|
||||
|
||||
@@ -113,7 +113,7 @@ class Database {
|
||||
this
|
||||
);
|
||||
EV.subscribe(EVENTS.attachmentDeleted, async (attachment) => {
|
||||
await this.fs.cancel(attachment.metadata.hash);
|
||||
await this.fs.cancel(attachment.metadata?.hash);
|
||||
});
|
||||
EV.subscribe(EVENTS.userLoggedOut, async () => {
|
||||
await this.monographs.deinit();
|
||||
|
||||
@@ -67,10 +67,10 @@ export default class Lookup {
|
||||
}
|
||||
|
||||
attachments(array, query) {
|
||||
return search(
|
||||
array,
|
||||
query,
|
||||
(n) => `${n.metadata.filename} ${n.metadata.type} ${n.metadata.hash}`
|
||||
return search(array, query, (n) =>
|
||||
n.metadata
|
||||
? `${n.metadata.filename} ${n.metadata.type} ${n.metadata.hash}`
|
||||
: ""
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -169,9 +169,13 @@ class Merger {
|
||||
if (!remoteItem.metadata) break;
|
||||
|
||||
const localItem = this._db.attachments.attachment(
|
||||
remoteItem.metadata.hash
|
||||
remoteItem.metadata?.hash
|
||||
);
|
||||
if (localItem && localItem.dateUploaded !== remoteItem.dateUploaded) {
|
||||
if (
|
||||
localItem &&
|
||||
localItem.metadata &&
|
||||
localItem.dateUploaded !== remoteItem.dateUploaded
|
||||
) {
|
||||
const noteIds = localItem.noteIds.slice();
|
||||
const isRemoved = await this._db.attachments.remove(
|
||||
localItem.metadata.hash,
|
||||
|
||||
@@ -40,7 +40,7 @@ export default class Attachments extends Collection {
|
||||
async ({ success, filename, groupId, eventData }) => {
|
||||
if (!success || !eventData || !eventData.readOnDownload) return;
|
||||
const attachment = this.attachment(filename);
|
||||
if (!attachment) return;
|
||||
if (!attachment || !attachment.metadata) return;
|
||||
|
||||
const src = await this.read(filename, getOutputType(attachment));
|
||||
if (!src) return;
|
||||
@@ -108,7 +108,7 @@ export default class Attachments extends Collection {
|
||||
if (!attachmentArg.hash) throw new Error("Please provide attachment hash.");
|
||||
|
||||
const oldAttachment =
|
||||
this.all.find((a) => a.metadata.hash === attachmentArg.hash) || {};
|
||||
this.all.find((a) => a.metadata?.hash === attachmentArg.hash) || {};
|
||||
let id = oldAttachment.id || getId();
|
||||
|
||||
const noteIds = oldAttachment.noteIds || [];
|
||||
@@ -205,7 +205,7 @@ export default class Attachments extends Collection {
|
||||
|
||||
async remove(hashOrId, localOnly) {
|
||||
const attachment = this.attachment(hashOrId);
|
||||
if (!attachment) return false;
|
||||
if (!attachment || !attachment.metadata) return false;
|
||||
|
||||
if (!localOnly && !(await this._canDetach(attachment)))
|
||||
throw new Error("This attachment is inside a locked note.");
|
||||
@@ -267,7 +267,7 @@ export default class Attachments extends Collection {
|
||||
}
|
||||
|
||||
exists(hash) {
|
||||
const attachment = this.all.find((a) => a.metadata.hash === hash);
|
||||
const attachment = this.all.find((a) => a.metadata?.hash === hash);
|
||||
return !!attachment;
|
||||
}
|
||||
|
||||
@@ -277,7 +277,7 @@ export default class Attachments extends Collection {
|
||||
* @returns {Promise<string>} dataurl formatted string
|
||||
*/
|
||||
async read(hash, outputType) {
|
||||
const attachment = this.all.find((a) => a.metadata.hash === hash);
|
||||
const attachment = this.all.find((a) => a.metadata?.hash === hash);
|
||||
if (!attachment) return;
|
||||
|
||||
const key = await this.decryptKey(attachment.key);
|
||||
@@ -302,7 +302,7 @@ export default class Attachments extends Collection {
|
||||
|
||||
attachment(hashOrId) {
|
||||
return this.all.find(
|
||||
(a) => a.id === hashOrId || a.metadata.hash === hashOrId
|
||||
(a) => a.id === hashOrId || a.metadata?.hash === hashOrId
|
||||
);
|
||||
}
|
||||
|
||||
@@ -348,8 +348,9 @@ export default class Attachments extends Collection {
|
||||
async downloadMedia(noteId, hashesToLoad) {
|
||||
const attachments = this.media.filter(
|
||||
(attachment) =>
|
||||
!!attachment.metadata &&
|
||||
hasItem(attachment.noteIds, noteId) &&
|
||||
(!hashesToLoad || hasItem(hashesToLoad, attachment.metadata.hash))
|
||||
(!hashesToLoad || hasItem(hashesToLoad, attachment.metadata?.hash))
|
||||
);
|
||||
|
||||
await this._db.fs.queueDownloads(
|
||||
@@ -366,7 +367,11 @@ export default class Attachments extends Collection {
|
||||
async cleanup() {
|
||||
const now = dayjs().unix();
|
||||
for (const attachment of this.deleted) {
|
||||
if (dayjs(attachment.dateDeleted).add(7, "days").unix() < now) continue;
|
||||
if (
|
||||
!attachment.metadata ||
|
||||
dayjs(attachment.dateDeleted).add(7, "days").unix() < now
|
||||
)
|
||||
continue;
|
||||
|
||||
const isDeleted = await this._db.fs.deleteFile(attachment.metadata.hash);
|
||||
if (!isDeleted) continue;
|
||||
@@ -377,7 +382,9 @@ export default class Attachments extends Collection {
|
||||
|
||||
get pending() {
|
||||
return this.all.filter(
|
||||
(attachment) => attachment.dateUploaded <= 0 || !attachment.dateUploaded
|
||||
(attachment) =>
|
||||
attachment.metadata &&
|
||||
(attachment.dateUploaded <= 0 || !attachment.dateUploaded)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -398,23 +405,30 @@ export default class Attachments extends Collection {
|
||||
}
|
||||
|
||||
get images() {
|
||||
return this.all.filter((attachment) => isImage(attachment.metadata.type));
|
||||
return this.all.filter(
|
||||
(attachment) => attachment.metadata && isImage(attachment.metadata.type)
|
||||
);
|
||||
}
|
||||
|
||||
get webclips() {
|
||||
return this.all.filter((attachment) => isWebClip(attachment.metadata.type));
|
||||
return this.all.filter(
|
||||
(attachment) => attachment.metadata && isWebClip(attachment.metadata.type)
|
||||
);
|
||||
}
|
||||
|
||||
get media() {
|
||||
return this.all.filter(
|
||||
(attachment) =>
|
||||
isImage(attachment.metadata.type) || isWebClip(attachment.metadata.type)
|
||||
attachment.metadata &&
|
||||
(isImage(attachment.metadata.type) ||
|
||||
isWebClip(attachment.metadata.type))
|
||||
);
|
||||
}
|
||||
|
||||
get files() {
|
||||
return this.all.filter(
|
||||
(attachment) =>
|
||||
attachment.metadata &&
|
||||
!isImage(attachment.metadata.type) &&
|
||||
!isWebClip(attachment.metadata.type)
|
||||
);
|
||||
|
||||
@@ -122,7 +122,9 @@ export default class Content extends Collection {
|
||||
const content = getContentFromData(contentItem.type, contentItem.data);
|
||||
if (!content) console.log(contentItem);
|
||||
contentItem.data = await content.insertMedia(async (hashes) => {
|
||||
const attachments = hashes.map((h) => this._db.attachments.attachment(h));
|
||||
const attachments = hashes
|
||||
.map((h) => this._db.attachments.attachment(h))
|
||||
.filter((a) => !!a && !!a.metadata);
|
||||
await this._db.fs.queueDownloads(
|
||||
attachments.map((a) => ({
|
||||
filename: a.metadata.hash,
|
||||
@@ -134,6 +136,8 @@ export default class Content extends Collection {
|
||||
);
|
||||
const sources = {};
|
||||
for (const attachment of attachments) {
|
||||
if (!attachment.metadata) continue;
|
||||
|
||||
const src = await this._db.attachments.read(
|
||||
attachment.metadata.hash,
|
||||
getOutputType(attachment)
|
||||
@@ -188,20 +192,23 @@ export default class Content extends Collection {
|
||||
|
||||
const toDelete = noteAttachments.filter((attachment) => {
|
||||
return attachments.every(
|
||||
(a) => a.hash && a.hash !== attachment.metadata.hash
|
||||
(a) => a && a.hash && a.hash !== attachment.metadata?.hash
|
||||
);
|
||||
});
|
||||
|
||||
const toAdd = attachments.filter((attachment) => {
|
||||
return (
|
||||
attachment &&
|
||||
attachment.hash &&
|
||||
noteAttachments.every((a) => attachment.hash !== a.metadata.hash)
|
||||
noteAttachments.every((a) => attachment.hash !== a.metadata?.hash)
|
||||
);
|
||||
});
|
||||
|
||||
for (let attachment of toDelete) {
|
||||
if (!attachment.metadata) continue;
|
||||
|
||||
await this._db.attachments.delete(
|
||||
attachment.metadata.hash,
|
||||
attachment.metadata?.hash,
|
||||
contentItem.noteId
|
||||
);
|
||||
}
|
||||
|
||||
@@ -251,6 +251,7 @@ export default class Notes extends Collection {
|
||||
|
||||
const attachments = this._db.attachments.ofNote(itemData.id, "all");
|
||||
for (let attachment of attachments) {
|
||||
if (!attachment || !attachment.metadata) continue;
|
||||
await this._db.attachments.delete(
|
||||
attachment.metadata.hash,
|
||||
itemData.id
|
||||
|
||||
11
packages/editor/package-lock.json
generated
11
packages/editor/package-lock.json
generated
@@ -90,13 +90,13 @@
|
||||
"../core": {
|
||||
"name": "@notesnook/core",
|
||||
"version": "7.4.1",
|
||||
"hasInstallScript": true,
|
||||
"license": "GPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@microsoft/signalr": "^7.0.10",
|
||||
"@microsoft/signalr-protocol-msgpack": "^7.0.10",
|
||||
"@microsoft/signalr": "^8.0.0",
|
||||
"@notesnook/logger": "file:../logger",
|
||||
"@readme/data-urls": "^3.0.0",
|
||||
"@streetwriters/showdown": "^3.0.4-alpha",
|
||||
"@streetwriters/showdown": "^3.0.5-alpha",
|
||||
"async-mutex": "^0.3.2",
|
||||
"dayjs": "1.11.9",
|
||||
"entities": "^4.3.1",
|
||||
@@ -4343,12 +4343,11 @@
|
||||
"@notesnook/core": {
|
||||
"version": "file:../core",
|
||||
"requires": {
|
||||
"@microsoft/signalr": "^7.0.10",
|
||||
"@microsoft/signalr-protocol-msgpack": "^7.0.10",
|
||||
"@microsoft/signalr": "^8.0.0",
|
||||
"@notesnook/crypto": "file:../crypto",
|
||||
"@notesnook/logger": "file:../logger",
|
||||
"@readme/data-urls": "^3.0.0",
|
||||
"@streetwriters/showdown": "^3.0.4-alpha",
|
||||
"@streetwriters/showdown": "^3.0.5-alpha",
|
||||
"@types/html-to-text": "^9.0.0",
|
||||
"@types/katex": "^0.16.1",
|
||||
"@types/prismjs": "^1.26.0",
|
||||
|
||||
Reference in New Issue
Block a user