98 lines
3.1 KiB
TypeScript
98 lines
3.1 KiB
TypeScript
import * as electron from "electron";
|
|
import * as path from "path";
|
|
import * as fs from "fs-extra";
|
|
|
|
const APP_DATA = electron.remote.app.getPath("userData");
|
|
const SETTINGS_DIR = path.join(APP_DATA, "settings");
|
|
|
|
let _local_storage: {[key: string]: any} = {};
|
|
let _local_storage_save: {[key: string]: boolean} = {};
|
|
let _save_timer: NodeJS.Timer;
|
|
|
|
export async function initialize() {
|
|
await fs.mkdirp(SETTINGS_DIR);
|
|
|
|
const files = await fs.readdir(SETTINGS_DIR);
|
|
for(const file of files) {
|
|
const key = decodeURIComponent(file);
|
|
console.log("Load settings: %s", key);
|
|
|
|
try {
|
|
const data = await fs.readFile(path.join(SETTINGS_DIR, file));
|
|
_local_storage[key] = JSON.parse(data.toString() || "{}");
|
|
} catch(error) {
|
|
const target_file = path.join(SETTINGS_DIR, file + "." + Date.now() + ".broken");
|
|
console.error("Failed to load settings for %s: %o. Moving settings so the file does not get overridden. Target file: %s", key, error, target_file);
|
|
try {
|
|
await fs.move(path.join(SETTINGS_DIR, file), target_file);
|
|
} catch (error) {
|
|
console.warn("Failed to move broken settings file!");
|
|
}
|
|
}
|
|
}
|
|
|
|
let _new_storage: Storage = {} as any;
|
|
|
|
_new_storage.getItem = key => _local_storage[key] || null;
|
|
_new_storage.setItem = (key, value) => {
|
|
_local_storage[key] = value;
|
|
_local_storage_save[key] = true;
|
|
(_new_storage as any)["length"] = Object.keys(_local_storage).length;
|
|
};
|
|
|
|
_new_storage.clear = () => {
|
|
_local_storage = {};
|
|
_local_storage_save = {};
|
|
|
|
try {
|
|
fs.emptyDirSync(SETTINGS_DIR);
|
|
} catch(error) {
|
|
console.warn("Failed to empty settings dir");
|
|
}
|
|
(_new_storage as any)["length"] = 0;
|
|
};
|
|
|
|
_new_storage.key = index => Object.keys(_local_storage)[index];
|
|
_new_storage.removeItem = key => {
|
|
delete _local_storage[key];
|
|
delete_key(key).catch(error => {
|
|
console.warn("Failed to delete key on fs: %s => %o", key, error);
|
|
});
|
|
(_new_storage as any)["length"] = Object.keys(_local_storage).length;
|
|
};
|
|
|
|
Object.assign(window.localStorage, _new_storage);
|
|
|
|
/* try to save everything all 60 seconds */
|
|
_save_timer = setInterval(() => {
|
|
save_all_sync();
|
|
}, 60 * 1000);
|
|
}
|
|
|
|
export function save_all_sync() {
|
|
for(const key of Object.keys(_local_storage_save))
|
|
save_key_sync(key);
|
|
}
|
|
|
|
function key_path(key: string) {
|
|
return path.join(SETTINGS_DIR, encodeURIComponent(key));
|
|
}
|
|
|
|
export function save_key_sync(key: string) {
|
|
if(!_local_storage_save[key])
|
|
return;
|
|
|
|
delete _local_storage_save[key];
|
|
const setting_path = key_path(key);
|
|
fs.writeJsonSync(setting_path, _local_storage[key], {spaces: 0});
|
|
}
|
|
|
|
export async function delete_key(key: string) {
|
|
delete _local_storage_save[key];
|
|
const setting_path = key_path(key);
|
|
await fs.remove(setting_path); /* could be async because we're not carrying about data */
|
|
}
|
|
|
|
window.addEventListener("beforeunload", event => {
|
|
save_all_sync();
|
|
}); |