save in localStorage instead of sessionStorage, don't prompt persistence on chrome

This commit is contained in:
Reimar 2025-10-16 12:36:49 +02:00
parent 4a9ea3604c
commit c93586bdf9
4 changed files with 79 additions and 31 deletions

View File

@ -91,8 +91,18 @@ export class AssetStore {
return new AssetStore(db);
}
static async requestPersistance() {
static async requestPersistence() {
const storage = globalThis.navigator.storage;
// Chrome silently allows/denies based on user interaction
if (globalThis.chrome) {
if (!await storage.persisted()) {
await storage.persist();
}
return;
}
let isAlreadyPersisted;
try {
isAlreadyPersisted = await storage.persisted();
@ -101,11 +111,11 @@ export class AssetStore {
return;
}
if (isAlreadyPersisted) {
console.log("[AssetStore] already got persistant storage!");
console.log("[AssetStore] already got persistent storage!");
return;
}
if (globalThis.localStorage.getItem("persistance-denied")) {
console.log("[AssetStore] already denied persistant storage!");
if (globalThis.localStorage.getItem("persistence-denied")) {
console.log("[AssetStore] already denied persistent storage!");
return;
}
const dialog = document.querySelector("#AssetStore-popup");
@ -125,7 +135,7 @@ export class AssetStore {
}
});
deny.addEventListener("click", () => {
globalThis.localStorage.setItem("persistance-denied", true);
globalThis.localStorage.setItem("persistence-denied", true);
dialog.close();
});
dialog.showModal();

View File

@ -1,6 +1,5 @@
/// <reference types="ace" />
import { Debounce } from "./debounce.js";
import { PlaygroundConsole } from "./playground_console.js";
import { CodeRunner } from "./code_runner.js";
import { AssetEditor } from "./asset_editor.js";
@ -9,6 +8,7 @@ import { Gamelib } from "./gamelib.js";
import { ConsoleInput } from "./console_input.js";
import { ProjectSaveHandler } from "./project_save_handler.js";
import { AssetStore } from "./asset_store.js";
import { SessionSaveHandler } from "./session_save_handler.js";
const editor = ace.edit("editor");
editor.setTheme("ace/theme/gruvbox");
@ -20,8 +20,6 @@ editor.setOptions({
copyWithEmptySelection: true,
});
editor.setValue(sessionStorage.getItem("code") ?? editor.getValue(), -1);
const languageProvider = LanguageProvider.fromCdn(
"https://www.unpkg.com/ace-linters@latest/build",
undefined,
@ -83,22 +81,15 @@ const loadButton = document.querySelector("#load-button");
const exportButton = document.querySelector("#export-button");
const dropZone = document.querySelector("main");
const projectSaveHandler = new ProjectSaveHandler(editor, assetEditor, assetProvider, projectName);
const sessionSaveHandler = new SessionSaveHandler(editor, projectName);
sessionSaveHandler.loadAll();
const sessionSaveDebounce = new Debounce(1000);
editor.addEventListener("change", () => {
sessionSaveDebounce.run(() => {
sessionStorage.setItem("code", editor.getValue());
});
});
if (sessionStorage.getItem("project-name")) {
projectName.value = sessionStorage.getItem("project-name");
}
projectName.onchange = () => {
sessionStorage.setItem("project-name", projectName.value);
};
const projectSaveHandler = new ProjectSaveHandler(
editor,
assetEditor,
assetProvider,
sessionSaveHandler,
);
runButton.onclick = async () => {
const code = editor.getValue();
@ -166,4 +157,4 @@ dropZone.ondrop = async (ev) => {
ev.preventDefault();
};
AssetStore.requestPersistance();
AssetStore.requestPersistence();

View File

@ -4,10 +4,10 @@ import { HtmlExporter } from "./html_exporter.js";
import { KarlkoderCodec } from "./karlkoder_codec.js";
export class ProjectSaveHandler {
constructor(editor, assetEditor, assetProvider, projectName) {
constructor(editor, assetEditor, assetProvider, sessionSaveHandler) {
this.editor = editor;
this.assetEditor = assetEditor;
this.projectName = projectName;
this.sessionSaveHandler = sessionSaveHandler;
this.htmlExporter = new HtmlExporter(assetProvider);
@ -36,7 +36,7 @@ export class ProjectSaveHandler {
);
}
this.loadFromFile(files[0]);
await this.loadFromFile(files[0]);
}
async loadFromFile(file) {
@ -71,11 +71,9 @@ export class ProjectSaveHandler {
}),
);
this.projectName.value = code.name;
sessionStorage.setItem("project-name", code.name);
const dec = new TextDecoder();
this.editor.setValue(dec.decode(code.content));
this.sessionSaveHandler.saveEditorCode(dec.decode(code.content));
this.sessionSaveHandler.saveProjectName(code.name);
this.isSaved = true;
this.fileHandles = {};

View File

@ -0,0 +1,49 @@
import { Debounce } from "./debounce.js";
export class SessionSaveHandler {
constructor(editor, projectName) {
this.editor = editor;
this.projectName = projectName;
const sessionSaveDebounce = new Debounce(1000);
editor.addEventListener("change", () => {
sessionSaveDebounce.run(() => this.saveEditorCode());
});
projectName.addEventListener("change", () => this.saveProjectName());
}
saveEditorCode(code = null) {
if (code) {
this.editor.setValue(code, -1);
}
localStorage.setItem("code", this.editor.getValue());
}
saveProjectName(name = null) {
if (name) {
this.projectName.value = name;
}
localStorage.setItem("project-name", this.projectName.value);
}
saveAll() {
this.saveEditorCode();
this.saveProjectName();
}
loadEditorCode() {
this.editor.setValue(localStorage.getItem("code") ?? this.editor.getValue(), -1);
}
loadProjectName() {
this.projectName.value = localStorage.getItem("project-name") ?? "";
}
loadAll() {
this.loadEditorCode();
this.loadProjectName();
}
}