Merge branch 'master' into beta

This commit is contained in:
Abdullah Atta
2025-11-27 11:04:57 +05:00
12 changed files with 98 additions and 38 deletions

View File

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

View File

@@ -1095,7 +1095,7 @@
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2156; CURRENT_PROJECT_VERSION = 2157;
DEVELOPMENT_TEAM = 53CWBG3QUC; DEVELOPMENT_TEAM = 53CWBG3QUC;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64; "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
@@ -1169,7 +1169,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 3.3.8; MARKETING_VERSION = 3.3.9;
OTHER_LDFLAGS = ( OTHER_LDFLAGS = (
"$(inherited)", "$(inherited)",
"-ObjC", "-ObjC",
@@ -1200,7 +1200,7 @@
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Manual; CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 2156; CURRENT_PROJECT_VERSION = 2157;
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 53CWBG3QUC; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 53CWBG3QUC;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64; "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
@@ -1274,7 +1274,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 3.3.8; MARKETING_VERSION = 3.3.9;
ONLY_ACTIVE_ARCH = NO; ONLY_ACTIVE_ARCH = NO;
OTHER_LDFLAGS = ( OTHER_LDFLAGS = (
"$(inherited)", "$(inherited)",
@@ -1433,7 +1433,7 @@
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2156; CURRENT_PROJECT_VERSION = 2157;
DEBUG_INFORMATION_FORMAT = dwarf; DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = 53CWBG3QUC; DEVELOPMENT_TEAM = 53CWBG3QUC;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64; "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
@@ -1445,7 +1445,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 3.3.8; MARKETING_VERSION = 3.3.9;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.notewidget; PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.notewidget;
@@ -1476,7 +1476,7 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Manual; CODE_SIGN_STYLE = Manual;
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 2156; CURRENT_PROJECT_VERSION = 2157;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 53CWBG3QUC; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 53CWBG3QUC;
@@ -1489,7 +1489,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 3.3.8; MARKETING_VERSION = 3.3.9;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.notewidget; PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.notewidget;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
@@ -1519,7 +1519,7 @@
CODE_SIGN_ENTITLEMENTS = "Make Note/Make Note.entitlements"; CODE_SIGN_ENTITLEMENTS = "Make Note/Make Note.entitlements";
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2156; CURRENT_PROJECT_VERSION = 2157;
DEBUG_INFORMATION_FORMAT = dwarf; DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = 53CWBG3QUC; DEVELOPMENT_TEAM = 53CWBG3QUC;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64; "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
@@ -1600,7 +1600,7 @@
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift$(inherited)"; LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift$(inherited)";
MARKETING_VERSION = 3.3.8; MARKETING_VERSION = 3.3.9;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.share; PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.share;
@@ -1631,7 +1631,7 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Manual; CODE_SIGN_STYLE = Manual;
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 2156; CURRENT_PROJECT_VERSION = 2157;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 53CWBG3QUC; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 53CWBG3QUC;
@@ -1713,7 +1713,7 @@
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift$(inherited)"; LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift$(inherited)";
MARKETING_VERSION = 3.3.8; MARKETING_VERSION = 3.3.9;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.share; PRODUCT_BUNDLE_IDENTIFIER = org.streetwriters.notesnook.share;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";

View File

@@ -1,6 +1,6 @@
{ {
"name": "@notesnook/mobile", "name": "@notesnook/mobile",
"version": "3.3.8", "version": "3.3.9",
"private": true, "private": true,
"license": "GPL-3.0-or-later", "license": "GPL-3.0-or-later",
"workspaces": [ "workspaces": [
@@ -56,4 +56,4 @@
"react": "18.2.0", "react": "18.2.0",
"react-native": "0.77.2" "react-native": "0.77.2"
} }
} }

View File

@@ -30,13 +30,18 @@ export async function handleDrop(
item: item:
| ItemReference | ItemReference
| Context | Context
| { type: "trash" | "notebooks" | "favorites" | undefined } | { type: "trash" | "notebooks" | "favorites" | "archive" | undefined }
) { ) {
if (!item.type) return; if (!item.type) return;
const noteIds = getDragData(dataTransfer, "note"); const noteIds = getDragData(dataTransfer, "note");
const notebookIds = getDragData(dataTransfer, "notebook"); const notebookIds = getDragData(dataTransfer, "notebook");
const { setColor, favorite, delete: trashNotes } = useNoteStore.getState(); const {
setColor,
favorite,
delete: trashNotes,
archive
} = useNoteStore.getState();
switch (item.type) { switch (item.type) {
case "notebook": case "notebook":
if (noteIds.length > 0) { if (noteIds.length > 0) {
@@ -83,5 +88,8 @@ export async function handleDrop(
await useNoteStore.getState().refresh(); await useNoteStore.getState().refresh();
} }
break; break;
case "archive":
archive(true, ...noteIds);
break;
} }
} }

View File

@@ -92,7 +92,11 @@ export async function exportNotes(
const { createZipStream } = await import("../utils/streams/zip-stream"); const { createZipStream } = await import("../utils/streams/zip-stream");
const errors: Error[] = []; const errors: Error[] = [];
const exportStream = new ExportStream(report, (e) => errors.push(e)); const exportStream = new ExportStream(
report,
(e) => errors.push(e),
await notes.count()
);
await fromAsyncIterator( await fromAsyncIterator(
_exportNotes(notes, { format, unlockVault: Vault.unlockVault }) _exportNotes(notes, { format, unlockVault: Vault.unlockVault })
) )

View File

@@ -118,7 +118,7 @@ function countCharacters(text: string) {
function countParagraphs(fragment: Fragment) { function countParagraphs(fragment: Fragment) {
let count = 0; let count = 0;
fragment.nodesBetween(0, fragment.size, (node) => { fragment.nodesBetween(0, fragment.size, (node) => {
if (node.type.name === "paragraph") { if (node.type.name === "paragraph" && node.content.size > 0) {
count++; count++;
} }
return true; return true;
@@ -737,7 +737,7 @@ function toIEditor(editor: Editor): IEditor {
function getSelectedParagraphs(editor: Editor, selection: Selection): number { function getSelectedParagraphs(editor: Editor, selection: Selection): number {
let count = 0; let count = 0;
editor.state.doc.nodesBetween(selection.from, selection.to, (node) => { editor.state.doc.nodesBetween(selection.from, selection.to, (node) => {
if (node.type.name === "paragraph") { if (node.type.name === "paragraph" && node.content.size > 0) {
count++; count++;
} }
return true; return true;

View File

@@ -506,6 +506,8 @@ function RouteItem({
? "trash" ? "trash"
: item.path === "/favorites" : item.path === "/favorites"
? "favorites" ? "favorites"
: item.path == "/archive"
? "archive"
: undefined : undefined
}); });
}} }}

View File

@@ -28,8 +28,13 @@ export class ExportStream extends TransformStream<
> { > {
progress = 0; progress = 0;
constructor( constructor(
report: (progress: { text: string; current?: number }) => void, report: (progress: {
handleError: (error: Error) => void text: string;
current?: number;
total?: number;
}) => void,
handleError: (error: Error) => void,
totalItems?: number
) { ) {
super({ super({
transform: async (item, controller) => { transform: async (item, controller) => {
@@ -69,7 +74,8 @@ export class ExportStream extends TransformStream<
controller.enqueue(item); controller.enqueue(item);
report({ report({
current: this.progress++, current: this.progress++,
text: `Exporting note: ${item.path}` text: `Exporting note: ${item.path}`,
total: totalItems
}); });
} }
} }

View File

@@ -0,0 +1,3 @@
- Minor bug fixes and improvements
Thank you for using Notesnook!

View File

@@ -666,6 +666,15 @@ class UserManager {
usesFallback: await this.usesFallbackPWHash(old_password) usesFallback: await this.usesFallbackPWHash(old_password)
}); });
// retrieve user keys before deriving a new encryption key
const oldUserKeys = {
attachmentsKey: await this.getAttachmentsKey(),
monographPasswordsKey: await this.getMonographPasswordsKey(),
inboxKeys: (await this.hasInboxKeys())
? await this.getInboxKeys()
: undefined
} as const;
await this.db.storage().deriveCryptoKey({ await this.db.storage().deriveCryptoKey({
password: new_password, password: new_password,
salt salt
@@ -678,27 +687,33 @@ class UserManager {
const userEncryptionKey = await this.getEncryptionKey(); const userEncryptionKey = await this.getEncryptionKey();
if (userEncryptionKey) { if (userEncryptionKey) {
const updateUserPayload: Partial<User> = {}; const updateUserPayload: Partial<User> = {};
const attachmentsKey = await this.getAttachmentsKey(); if (oldUserKeys.attachmentsKey) {
if (attachmentsKey) {
user.attachmentsKey = await this.db user.attachmentsKey = await this.db
.storage() .storage()
.encrypt(userEncryptionKey, JSON.stringify(attachmentsKey)); .encrypt(
userEncryptionKey,
JSON.stringify(oldUserKeys.attachmentsKey)
);
updateUserPayload.attachmentsKey = user.attachmentsKey; updateUserPayload.attachmentsKey = user.attachmentsKey;
} }
const monographPasswordsKey = await this.getMonographPasswordsKey(); if (oldUserKeys.monographPasswordsKey) {
if (monographPasswordsKey) {
user.monographPasswordsKey = await this.db user.monographPasswordsKey = await this.db
.storage() .storage()
.encrypt(userEncryptionKey, JSON.stringify(monographPasswordsKey)); .encrypt(
userEncryptionKey,
JSON.stringify(oldUserKeys.monographPasswordsKey)
);
updateUserPayload.monographPasswordsKey = user.monographPasswordsKey; updateUserPayload.monographPasswordsKey = user.monographPasswordsKey;
} }
const inboxKeys = await this.getInboxKeys(); if (oldUserKeys.inboxKeys) {
if (inboxKeys) {
user.inboxKeys = { user.inboxKeys = {
public: inboxKeys.publicKey, public: oldUserKeys.inboxKeys.publicKey,
private: await this.db private: await this.db
.storage() .storage()
.encrypt(userEncryptionKey, JSON.stringify(inboxKeys.privateKey)) .encrypt(
userEncryptionKey,
JSON.stringify(oldUserKeys.inboxKeys.privateKey)
)
}; };
updateUserPayload.inboxKeys = user.inboxKeys; updateUserPayload.inboxKeys = user.inboxKeys;
} }

View File

@@ -184,11 +184,14 @@ export const Heading = TiptapHeading.extend({
if (typeof pos !== "number") return; if (typeof pos !== "number") return;
const resolvedPos = editor.state.doc.resolve(pos); const resolvedPos = editor.state.doc.resolve(pos);
const calloutAncestor = findParentNodeClosestToPos( const forbiddenParents = ["callout", "table"];
resolvedPos, if (
(node) => node.type.name === "callout" findParentNodeClosestToPos(resolvedPos, (node) =>
); forbiddenParents.includes(node.type.name)
if (calloutAncestor) return; )
) {
return;
}
if ( if (
isClickWithinBounds( isClickWithinBounds(

View File

@@ -707,6 +707,10 @@ p > *::selection {
mask-size: cover; mask-size: cover;
} }
.simple-checklist > li.checked p {
opacity: 0.8;
}
/* Callout */ /* Callout */
.ProseMirror div.callout { .ProseMirror div.callout {
padding: 15px; padding: 15px;
@@ -978,6 +982,21 @@ del.diffdel {
display: none; display: none;
} }
.ProseMirror table h1::before,
.ProseMirror table h2::before,
.ProseMirror table h3::before,
.ProseMirror table h4::before,
.ProseMirror table h5::before,
.ProseMirror table h6::before,
.ProseMirror table h1::after,
.ProseMirror table h2::after,
.ProseMirror table h3::after,
.ProseMirror table h4::after,
.ProseMirror table h5::after,
.ProseMirror table h6::after {
display: none;
}
[data-hidden="true"] { [data-hidden="true"] {
display: none !important; display: none !important;
} }