File size: 7,142 Bytes
2409829 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 |
import { createStore, del, get, set, update } from "idb-keyval";
import { get as getFromStore } from "svelte/store";
import { type Editor } from "@graphite/editor";
import {
TriggerIndexedDbWriteDocument,
TriggerIndexedDbRemoveDocument,
TriggerSavePreferences,
TriggerLoadPreferences,
TriggerLoadFirstAutoSaveDocument,
TriggerLoadRestAutoSaveDocuments,
TriggerSaveActiveDocument,
} from "@graphite/messages";
import { type PortfolioState } from "@graphite/state-providers/portfolio";
const graphiteStore = createStore("graphite", "store");
export function createPersistenceManager(editor: Editor, portfolio: PortfolioState) {
// DOCUMENTS
async function storeDocumentOrder() {
const documentOrder = getFromStore(portfolio).documents.map((doc) => String(doc.id));
await set("documents_tab_order", documentOrder, graphiteStore);
}
async function storeCurrentDocumentId(documentId: string) {
await set("current_document_id", String(documentId), graphiteStore);
}
async function storeDocument(autoSaveDocument: TriggerIndexedDbWriteDocument) {
await update<Record<string, TriggerIndexedDbWriteDocument>>(
"documents",
(old) => {
const documents = old || {};
documents[autoSaveDocument.details.id] = autoSaveDocument;
return documents;
},
graphiteStore,
);
await storeDocumentOrder();
await storeCurrentDocumentId(autoSaveDocument.details.id);
}
async function removeDocument(id: string) {
await update<Record<string, TriggerIndexedDbWriteDocument>>(
"documents",
(old) => {
const documents = old || {};
delete documents[id];
return documents;
},
graphiteStore,
);
await update<string[]>(
"documents_tab_order",
(old) => {
const order = old || [];
return order.filter((docId) => docId !== id);
},
graphiteStore,
);
const documentCount = getFromStore(portfolio).documents.length;
if (documentCount > 0) {
const documentIndex = getFromStore(portfolio).activeDocumentIndex;
const documentId = String(getFromStore(portfolio).documents[documentIndex].id);
const tabOrder = (await get<string[]>("documents_tab_order", graphiteStore)) || [];
if (tabOrder.includes(documentId)) {
await storeCurrentDocumentId(documentId);
}
} else {
await del("current_document_id", graphiteStore);
}
}
async function loadFirstDocument() {
const previouslySavedDocuments = await get<Record<string, TriggerIndexedDbWriteDocument>>("documents", graphiteStore);
const documentOrder = await get<string[]>("documents_tab_order", graphiteStore);
const currentDocumentId = await get<string>("current_document_id", graphiteStore);
if (!previouslySavedDocuments || !documentOrder) return;
const orderedSavedDocuments = documentOrder.flatMap((id) => (previouslySavedDocuments[id] ? [previouslySavedDocuments[id]] : []));
if (currentDocumentId && currentDocumentId in previouslySavedDocuments) {
const doc = previouslySavedDocuments[currentDocumentId];
editor.handle.openAutoSavedDocument(BigInt(doc.details.id), doc.details.name, doc.details.isSaved, doc.document, false);
editor.handle.selectDocument(BigInt(currentDocumentId));
} else {
const len = orderedSavedDocuments.length;
if (len > 0) {
const doc = orderedSavedDocuments[len - 1];
editor.handle.openAutoSavedDocument(BigInt(doc.details.id), doc.details.name, doc.details.isSaved, doc.document, false);
editor.handle.selectDocument(BigInt(doc.details.id));
}
}
}
async function loadRestDocuments() {
const previouslySavedDocuments = await get<Record<string, TriggerIndexedDbWriteDocument>>("documents", graphiteStore);
const documentOrder = await get<string[]>("documents_tab_order", graphiteStore);
const currentDocumentId = await get<string>("current_document_id", graphiteStore);
if (!previouslySavedDocuments || !documentOrder) return;
const orderedSavedDocuments = documentOrder.flatMap((id) => (previouslySavedDocuments[id] ? [previouslySavedDocuments[id]] : []));
if (currentDocumentId) {
const currentIndex = orderedSavedDocuments.findIndex((doc) => doc.details.id === currentDocumentId);
const beforeCurrentIndex = currentIndex - 1;
const afterCurrentIndex = currentIndex + 1;
for (let i = beforeCurrentIndex; i >= 0; i--) {
const { document, details } = orderedSavedDocuments[i];
const { id, name, isSaved } = details;
editor.handle.openAutoSavedDocument(BigInt(id), name, isSaved, document, true);
}
for (let i = afterCurrentIndex; i < orderedSavedDocuments.length; i++) {
const { document, details } = orderedSavedDocuments[i];
const { id, name, isSaved } = details;
editor.handle.openAutoSavedDocument(BigInt(id), name, isSaved, document, false);
}
editor.handle.selectDocument(BigInt(currentDocumentId));
} else {
const length = orderedSavedDocuments.length;
for (let i = length - 2; i >= 0; i--) {
const { document, details } = orderedSavedDocuments[i];
const { id, name, isSaved } = details;
editor.handle.openAutoSavedDocument(BigInt(id), name, isSaved, document, true);
}
if (length > 0) {
const id = orderedSavedDocuments[length - 1].details.id;
editor.handle.selectDocument(BigInt(id));
}
}
}
// PREFERENCES
async function savePreferences(preferences: TriggerSavePreferences["preferences"]) {
await set("preferences", preferences, graphiteStore);
}
async function loadPreferences() {
const preferences = await get<Record<string, unknown>>("preferences", graphiteStore);
if (!preferences) return;
editor.handle.loadPreferences(JSON.stringify(preferences));
}
// FRONTEND MESSAGE SUBSCRIPTIONS
// Subscribe to process backend events
editor.subscriptions.subscribeJsMessage(TriggerSavePreferences, async (preferences) => {
await savePreferences(preferences.preferences);
});
editor.subscriptions.subscribeJsMessage(TriggerLoadPreferences, async () => {
await loadPreferences();
});
editor.subscriptions.subscribeJsMessage(TriggerIndexedDbWriteDocument, async (autoSaveDocument) => {
await storeDocument(autoSaveDocument);
});
editor.subscriptions.subscribeJsMessage(TriggerIndexedDbRemoveDocument, async (removeAutoSaveDocument) => {
await removeDocument(removeAutoSaveDocument.documentId);
});
editor.subscriptions.subscribeJsMessage(TriggerLoadFirstAutoSaveDocument, async () => {
await loadFirstDocument();
});
editor.subscriptions.subscribeJsMessage(TriggerLoadRestAutoSaveDocuments, async () => {
await loadRestDocuments();
});
editor.subscriptions.subscribeJsMessage(TriggerSaveActiveDocument, async (triggerSaveActiveDocument) => {
const documentId = String(triggerSaveActiveDocument.documentId);
const previouslySavedDocuments = await get<Record<string, TriggerIndexedDbWriteDocument>>("documents", graphiteStore);
if (!previouslySavedDocuments) return;
if (documentId in previouslySavedDocuments) {
await storeCurrentDocumentId(documentId);
}
});
}
export async function wipeDocuments() {
await del("documents_tab_order", graphiteStore);
await del("current_document_id", graphiteStore);
await del("documents", graphiteStore);
}
|