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)) { if (locked && isEncryptedContent(data)) {
const decryptedContent = await db.vault?.decryptContent(data, noteId); const decryptedContent = await db.vault?.decryptContent(data);
if (!decryptedContent) { if (!decryptedContent) {
useTabStore.getState().updateTab(tabId, { useTabStore.getState().updateTab(tabId, {
locked: true, locked: true,

View File

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

View File

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

View File

@@ -33,6 +33,7 @@ function ProgressDialog(props) {
try { try {
props.onDone(await props.action(setProgress)); props.onDone(await props.action(setProgress));
} catch (e) { } catch (e) {
console.error(e);
props.onDone(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 { ExportableItem } from "@notesnook/common";
import { db } from "../../common/db"; import { db } from "../../common/db";
import { showToast } from "../toast";
import { ZipFile } from "./zip-stream"; import { ZipFile } from "./zip-stream";
import { lazify } from "../lazify"; import { lazify } from "../lazify";
@@ -27,12 +26,15 @@ export class ExportStream extends TransformStream<
ExportableItem | Error, ExportableItem | Error,
ZipFile ZipFile
> { > {
constructor(report: (progress: { text: string; current?: number }) => void) { progress = 0;
let progress = 0; constructor(
report: (progress: { text: string; current?: number }) => void,
handleError: (error: Error) => void
) {
super({ super({
async transform(item, controller) { transform: async (item, controller) => {
if (item instanceof Error) { if (item instanceof Error) {
showToast("error", item.message); handleError(item);
return; return;
} }
if (item.type === "attachment") { if (item.type === "attachment") {
@@ -56,13 +58,13 @@ export class ExportStream extends TransformStream<
if (!stream) return; if (!stream) return;
controller.enqueue({ ...item, data: stream }); controller.enqueue({ ...item, data: stream });
report({ report({
current: progress++, current: this.progress++,
text: `Saving attachment: ${item.path}` text: `Saving attachment: ${item.path}`
}); });
} else { } else {
controller.enqueue(item); controller.enqueue(item);
report({ report({
current: progress++, current: this.progress++,
text: `Exporting note: ${item.path}` text: `Exporting note: ${item.path}`
}); });
} }

View File

@@ -104,6 +104,7 @@ export async function* exportNotes(
continue; continue;
} }
try {
const content = await exportContent(note, { const content = await exportContent(note, {
unlockVault: options.unlockVault, unlockVault: options.unlockVault,
format, format,
@@ -130,6 +131,11 @@ export async function* exportNotes(
ctime: new Date(note.dateCreated) ctime: new Date(note.dateCreated)
}; };
} }
} catch (e) {
yield new Error(
`Failed to export note "${note.title}": ${(e as Error).message}`
);
}
} }
for (const [path, attachment] of pendingAttachments) { for (const [path, attachment] of pendingAttachments) {
@@ -225,10 +231,15 @@ export async function exportContent(
} }
const contentItem = rawContent?.locked const contentItem = rawContent?.locked
? await database.vault ? await database.vault.decryptContent(rawContent)
.decryptContent(rawContent, note.id) : // .catch((e) => {
.catch(() => undefined) // console.error(e, note);
: rawContent; // return <NoteContent<false>>{
// type: "tiptap",
// data: `This note could not be decrypted: ${e}`
// };
// })
rawContent;
const { data, type } = const { data, type } =
format === "pdf" format === "pdf"