galerie/web/www/settings.ts

257 lines
5.9 KiB
TypeScript

/*
Copyright 2023 0xf8.dev@proton.me
This file is part of Galerie
Galerie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
Galerie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with Galerie. If not, see <https://www.gnu.org/licenses/>.
*/
let apiUrl: string = `${ location.protocol }//${location.hostname}:8856/`;
class Favorites {
private data: string[] = [];
constructor() {
console.log("Loading favorites");
this.data = JSON.parse(localStorage.getItem("settings.favorites")) || [];
this.sync();
}
public async sync(): Promise<void> {
localStorage.setItem("settings.favorites", JSON.stringify(this.data));
}
public async clear(): Promise<void> {
this.data = [];
this.sync();
}
public async pop(): Promise<string> {
let item: any = this.data.pop();
this.sync();
return item;
}
public async push(toadd): Promise<void> {
this.data.push(toadd);
this.sync();
}
public async delete(d): Promise<void> {
this.data = this.data.filter((v) => { return v != d });
this.sync();
}
public async at(d): Promise<string> {
return this.data.at(d);
}
public async contains(d): Promise<boolean> {
return this.data.includes(d);
}
public async shuffle(): Promise<string[]> {
let data: string[] = this.data;
for (let i = 0; i < await this.data.length; i++) {
data.sort(() => { return Math.random() - 0.5 });
}
return data;
}
}
class Blacklist {
private data: string[] = [];
constructor() {
console.log("Loading blacklist");
this.data = JSON.parse(localStorage.getItem("settings.blacklist")) || [];
this.sync();
}
public async sync(): Promise<void> {
localStorage.setItem("settings.blacklist", JSON.stringify(this.data));
}
public async clear(): Promise<void> {
this.data = [];
this.sync();
}
public async pop(): Promise<string> {
let item: any = this.data.pop();
this.sync();
return item;
}
public async push(toadd): Promise<void> {
this.data.push(toadd);
this.sync();
}
public async delete(d): Promise<void> {
this.data = this.data.filter((v) => { return v != d });
this.sync();
}
public async at(d): Promise<string> {
return this.data.at(d);
}
public async contains(d): Promise<boolean> {
return this.data.includes(d);
}
}
class Cache {
private cache: string[];
private checksum: string;
last: string[];
constructor() {}
async load(): Promise<void> {
console.log("Loading cache");
this.cache = JSON.parse(localStorage.getItem("cache")) || [];
this.checksum = localStorage.getItem("cache.checksum");
if (!this.cache || !this.checksum) {
await this.sync();
} else if (!await this.validate()) {
await this.sync();
}
}
async sync(): Promise<void> {
console.log("Syncing cache");
try {
let sync = await fetch(apiUrl + "sync", {
body: JSON.stringify({ action: "fullUpdate", checksum: this.checksum }),
method: "POST",
});
let data = await sync.json();
if (!sync.ok)
throw Error(sync.statusText);
console.log(data);
if (!data.valid) {
this.checksum = data.checksum,
this.cache = data.files;
}
await this.update();
} catch (e) {
throw e;
}
}
private async update(): Promise<void> {
localStorage.setItem("cache", JSON.stringify(this.cache));
localStorage.setItem("cache.checksum", this.checksum);
}
private async validate(): Promise<boolean> {
try {
let sync = await fetch(apiUrl + "sync", {
body: JSON.stringify({ action: "validateChecksum", checksum: localStorage.getItem("cache.checksum") }),
method: "POST",
});
if (!sync.ok)
throw Error(sync.statusText);
return (await sync.json()).valid;
} catch(e) {
throw e;
}
}
public async at(d): Promise<string> {
return this.cache.at(d);
}
public async order(): Promise<string[]> {
let data: string[] = this.cache;
if (JSON.parse(localStorage.getItem("config")).deterministic) {
data = this.cache.sort((a, b) => a.localeCompare(b));
} else {
for (let i = 0; i < await this.length(); i++) {
data.sort(() => { return Math.random() - 0.5 });
}
}
this.last = data;
return data;
}
public async length(): Promise<Number> {
return this.cache.length;
}
}
class Config {
private data = {};
private defaultConfig = {
"ignoreBlacklist": false,
"onlyFavorites": false,
"deterministic": false
}
constructor() {
console.log("Loading config");
if (!localStorage.getItem("config"))
localStorage.setItem("config", JSON.stringify(this.defaultConfig));
this.data = JSON.parse(localStorage.getItem("config"));
this.verify();
this.sync();
}
private verify() {
for (let k in this.defaultConfig)
if (!this.get(k))
this.data[k] = this.defaultConfig[k];
}
public sync() {
localStorage.setItem("config", JSON.stringify(this.data));
}
public set(vr, vl) {
this.data[vr] = vl;
}
public get(vr) {
return this.data[vr];
}
public keys() {
return Object.keys(this.data);
}
}
export default class Settings {
favorites: Favorites;
blacklist: Blacklist;
cache: Cache;
config: Config;
constructor() {
this.favorites = new Favorites();
this.blacklist = new Blacklist();
this.cache = new Cache();
this.config = new Config();
}
}
export { apiUrl };