common: fix locked notes not getting exported

This commit is contained in:
Abdullah Atta
2024-05-09 11:09:04 +05:00
committed by Abdullah Atta
parent 734f491e8d
commit 9aed6faed8
6 changed files with 75 additions and 41 deletions

View File

@@ -659,7 +659,7 @@ export const useEditor = (
}
if (locked && isEncryptedContent(data)) {
const decryptedContent = await db.vault?.decryptContent(data, noteId);
const decryptedContent = await db.vault?.decryptContent(data);
if (!decryptedContent) {
useTabStore.getState().updateTab(tabId, {
locked: true,

View File

@@ -31,6 +31,8 @@ import {
} from "@notesnook/common";
import Vault from "./vault";
import { ExportStream } from "../utils/streams/export-stream";
import { showToast } from "../utils/toast";
import { confirm } from "./dialog-controller";
export async function exportToPDF(
title: string,
@@ -79,20 +81,36 @@ export async function exportNotes(
format: "pdf" | "md" | "txt" | "html" | "md-frontmatter",
notes: FilteredSelector<Note>
): Promise<boolean> {
return await TaskManager.startTask({
const result = await TaskManager.startTask({
type: "modal",
title: "Exporting notes",
subtitle: "Please wait while your notes are exported.",
action: async (report) => {
const errors: Error[] = [];
const exportStream = new ExportStream(report, (e) => errors.push(e));
await fromAsyncIterator(
_exportNotes(notes, { format, unlockVault: Vault.unlockVault })
)
.pipeThrough(new ExportStream(report))
.pipeThrough(exportStream)
.pipeThrough(createZipStream())
.pipeTo(await createWriteStream("notes.zip"));
return true;
return {
errors,
count: exportStream.progress
};
}
});
confirm({
title: `Exported ${result.count} notes`,
message:
result.errors.length > 0
? `Export completed with ${result.errors.length} errors:
${result.errors.map((e, i) => `${i + 1}. ${e.message}`).join("\n")}`
: "Export completed with 0 errors.",
positiveButtonText: "Okay"
});
return true;
}
const FORMAT_TO_EXT = {
@@ -130,7 +148,9 @@ export async function exportNote(
unlockVault: Vault.unlockVault
})
)
.pipeThrough(new ExportStream(report))
.pipeThrough(
new ExportStream(report, (e) => showToast("error", e.message))
)
.pipeThrough(createZipStream())
.pipeTo(
await createWriteStream(

View File

@@ -246,7 +246,7 @@ function EditorView({
if (!item.locked) return editor.updateContent(item.data);
const result = await db.vault
.decryptContent(item, item.noteId)
.decryptContent(item)
.catch(() => EV.publish(EVENTS.vaultLocked));
if (!result) return;
editor.updateContent(result.data);

View File

@@ -33,6 +33,7 @@ function ProgressDialog(props) {
try {
props.onDone(await props.action(setProgress));
} catch (e) {
console.error(e);
props.onDone(e);
}
})();

View File

@@ -19,7 +19,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import { ExportableItem } from "@notesnook/common";
import { db } from "../../common/db";
import { showToast } from "../toast";
import { ZipFile } from "./zip-stream";
import { lazify } from "../lazify";
@@ -27,12 +26,15 @@ export class ExportStream extends TransformStream<
ExportableItem | Error,
ZipFile
> {
constructor(report: (progress: { text: string; current?: number }) => void) {
let progress = 0;
progress = 0;
constructor(
report: (progress: { text: string; current?: number }) => void,
handleError: (error: Error) => void
) {
super({
async transform(item, controller) {
transform: async (item, controller) => {
if (item instanceof Error) {
showToast("error", item.message);
handleError(item);
return;
}
if (item.type === "attachment") {
@@ -56,13 +58,13 @@ export class ExportStream extends TransformStream<
if (!stream) return;
controller.enqueue({ ...item, data: stream });
report({
current: progress++,
current: this.progress++,
text: `Saving attachment: ${item.path}`
});
} else {
controller.enqueue(item);
report({
current: progress++,
current: this.progress++,
text: `Exporting note: ${item.path}`
});
}

View File

@@ -104,31 +104,37 @@ export async function* exportNotes(
continue;
}
const content = await exportContent(note, {
unlockVault: options.unlockVault,
format,
attachmentsRoot,
pendingAttachments,
resolveInternalLink: (link) => {
const internalLink = parseInternalLink(link);
if (!internalLink) return link;
const paths = notePathMap.get(internalLink.id);
if (!paths) return link;
// if the internal link is linking within the same note
if (paths === notePaths) return `{{NOTE_PATH:}}`;
return `{{NOTE_PATH:${paths[0]}}}`;
}
});
if (!content) continue;
try {
const content = await exportContent(note, {
unlockVault: options.unlockVault,
format,
attachmentsRoot,
pendingAttachments,
resolveInternalLink: (link) => {
const internalLink = parseInternalLink(link);
if (!internalLink) return link;
const paths = notePathMap.get(internalLink.id);
if (!paths) return link;
// if the internal link is linking within the same note
if (paths === notePaths) return `{{NOTE_PATH:}}`;
return `{{NOTE_PATH:${paths[0]}}}`;
}
});
if (!content) continue;
for (const path of notePaths) {
yield <ExportableNote>{
type: "note",
path,
data: resolvePaths(content, path),
mtime: new Date(note.dateEdited),
ctime: new Date(note.dateCreated)
};
for (const path of notePaths) {
yield <ExportableNote>{
type: "note",
path,
data: resolvePaths(content, path),
mtime: new Date(note.dateEdited),
ctime: new Date(note.dateCreated)
};
}
} catch (e) {
yield new Error(
`Failed to export note "${note.title}": ${(e as Error).message}`
);
}
}
@@ -225,10 +231,15 @@ export async function exportContent(
}
const contentItem = rawContent?.locked
? await database.vault
.decryptContent(rawContent, note.id)
.catch(() => undefined)
: rawContent;
? await database.vault.decryptContent(rawContent)
: // .catch((e) => {
// console.error(e, note);
// return <NoteContent<false>>{
// type: "tiptap",
// data: `This note could not be decrypted: ${e}`
// };
// })
rawContent;
const { data, type } =
format === "pdf"