Skip to content

Commit

Permalink
common: fix locked notes not getting exported
Browse files Browse the repository at this point in the history
  • Loading branch information
thecodrr committed May 9, 2024
1 parent 734f491 commit 9aed6fa
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 41 deletions.
2 changes: 1 addition & 1 deletion apps/mobile/app/screens/editor/tiptap/use-editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
28 changes: 24 additions & 4 deletions apps/web/src/common/export.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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 = {
Expand Down Expand Up @@ -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(
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/components/editor/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions apps/web/src/dialogs/progress-dialog.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ function ProgressDialog(props) {
try {
props.onDone(await props.action(setProgress));
} catch (e) {
console.error(e);
props.onDone(e);
}
})();
Expand Down
16 changes: 9 additions & 7 deletions apps/web/src/utils/streams/export-stream.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,22 @@ 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";

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") {
Expand All @@ -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}`
});
}
Expand Down
67 changes: 39 additions & 28 deletions packages/common/src/utils/export-notes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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]}}}`;
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)
};
}
});
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)
};
} catch (e) {
yield new Error(
`Failed to export note "${note.title}": ${(e as Error).message}`
);
}
}

Expand Down Expand Up @@ -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"
Expand Down

0 comments on commit 9aed6fa

Please sign in to comment.