mirror of
https://github.com/tobspr/shapez.io.git
synced 2026-03-02 03:39:21 +00:00
Add ability to import savegames, add game menu, multiple smaller improvements
This commit is contained in:
@@ -20,6 +20,7 @@ export class StorageImplBrowser extends StorageInterface {
|
||||
}
|
||||
|
||||
initialize() {
|
||||
logger.error("Using localStorage, please update to a newer browser");
|
||||
return new Promise((resolve, reject) => {
|
||||
// Check for local storage availability in general
|
||||
if (!window.localStorage) {
|
||||
|
||||
155
src/js/platform/browser/storage_indexed_db.js
Normal file
155
src/js/platform/browser/storage_indexed_db.js
Normal file
@@ -0,0 +1,155 @@
|
||||
import { FILE_NOT_FOUND, StorageInterface } from "../storage";
|
||||
import { createLogger } from "../../core/logging";
|
||||
|
||||
const logger = createLogger("storage/browserIDB");
|
||||
|
||||
const LOCAL_STORAGE_UNAVAILABLE = "local-storage-unavailable";
|
||||
const LOCAL_STORAGE_NO_WRITE_PERMISSION = "local-storage-no-write-permission";
|
||||
|
||||
let randomDelay = () => 0;
|
||||
|
||||
if (G_IS_DEV) {
|
||||
// Random delay for testing
|
||||
// randomDelay = () => 500;
|
||||
}
|
||||
|
||||
export class StorageImplBrowserIndexedDB extends StorageInterface {
|
||||
constructor(app) {
|
||||
super(app);
|
||||
this.currentBusyFilename = false;
|
||||
|
||||
/** @type {IDBDatabase} */
|
||||
this.database = null;
|
||||
}
|
||||
|
||||
initialize() {
|
||||
logger.log("Using indexed DB storage");
|
||||
return new Promise((resolve, reject) => {
|
||||
const request = window.indexedDB.open("app_storage", 10);
|
||||
request.onerror = event => {
|
||||
logger.error("IDB error:", event);
|
||||
reject("Indexed DB access error");
|
||||
};
|
||||
|
||||
request.onsuccess = event => resolve(event.target.result);
|
||||
|
||||
request.onupgradeneeded = /** @type {IDBVersionChangeEvent} */ event => {
|
||||
/** @type {IDBDatabase} */
|
||||
const database = event.target.result;
|
||||
|
||||
const objectStore = database.createObjectStore("files", {
|
||||
keyPath: "filename",
|
||||
});
|
||||
|
||||
objectStore.createIndex("filename", "filename", { unique: true });
|
||||
|
||||
objectStore.transaction.onerror = event => {
|
||||
logger.error("IDB transaction error:", event);
|
||||
reject("Indexed DB transaction error during migration, check console output.");
|
||||
};
|
||||
|
||||
objectStore.transaction.oncomplete = event => {
|
||||
logger.log("Object store completely initialized");
|
||||
resolve(database);
|
||||
};
|
||||
};
|
||||
}).then(database => {
|
||||
this.database = database;
|
||||
});
|
||||
}
|
||||
|
||||
writeFileAsync(filename, contents) {
|
||||
if (this.currentBusyFilename === filename) {
|
||||
logger.warn("Attempt to write", filename, "while write process is not finished!");
|
||||
}
|
||||
if (!this.database) {
|
||||
return Promise.reject("Storage not ready");
|
||||
}
|
||||
|
||||
this.currentBusyFilename = filename;
|
||||
const transaction = this.database.transaction(["files"], "readwrite");
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
transaction.oncomplete = () => {
|
||||
this.currentBusyFilename = null;
|
||||
resolve();
|
||||
};
|
||||
|
||||
transaction.onerror = error => {
|
||||
this.currentBusyFilename = null;
|
||||
logger.error("Error while writing", filename, ":", error);
|
||||
reject(error);
|
||||
};
|
||||
|
||||
const store = transaction.objectStore("files");
|
||||
store.put({
|
||||
filename,
|
||||
contents,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
writeFileSyncIfSupported(filename, contents) {
|
||||
// Not supported
|
||||
this.writeFileAsync(filename, contents);
|
||||
return true;
|
||||
}
|
||||
|
||||
readFileAsync(filename) {
|
||||
if (!this.database) {
|
||||
return Promise.reject("Storage not ready");
|
||||
}
|
||||
|
||||
this.currentBusyFilename = filename;
|
||||
const transaction = this.database.transaction(["files"], "readonly");
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const store = transaction.objectStore("files");
|
||||
const request = store.get(filename);
|
||||
|
||||
request.onsuccess = event => {
|
||||
this.currentBusyFilename = null;
|
||||
if (!request.result) {
|
||||
reject(FILE_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
resolve(request.result.contents);
|
||||
};
|
||||
|
||||
request.onerror = error => {
|
||||
this.currentBusyFilename = null;
|
||||
logger.error("Error while reading", filename, ":", error);
|
||||
reject(error);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
deleteFileAsync(filename) {
|
||||
if (this.currentBusyFilename === filename) {
|
||||
logger.warn("Attempt to delete", filename, "while write progres on it is ongoing!");
|
||||
}
|
||||
|
||||
if (!this.database) {
|
||||
return Promise.reject("Storage not ready");
|
||||
}
|
||||
|
||||
this.currentBusyFilename = filename;
|
||||
const transaction = this.database.transaction(["files"], "readwrite");
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
transaction.oncomplete = () => {
|
||||
this.currentBusyFilename = null;
|
||||
resolve();
|
||||
};
|
||||
|
||||
transaction.onerror = error => {
|
||||
this.currentBusyFilename = null;
|
||||
logger.error("Error while deleting", filename, ":", error);
|
||||
reject(error);
|
||||
};
|
||||
|
||||
const store = transaction.objectStore("files");
|
||||
store.delete(filename);
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user