Add context management

This commit is contained in:
Idrees Hassan
2025-11-02 14:16:24 -05:00
parent 32a871b773
commit 18749acff6
5 changed files with 367 additions and 142 deletions

View File

@@ -2,6 +2,7 @@ import Frame from './frame.js';
import Layer from './layer.js';
import Anim from './anim.js';
import { Birb, Animations } from './birb.js';
import { getContext } from './context.js';
import {
Directions,
@@ -270,34 +271,9 @@ Promise.all([
/** @type {StickyNote[]} */
let stickyNotes = [];
/**
* @returns {boolean} Whether the script is running in a userscript extension context
*/
function isUserScript() {
// @ts-expect-error
return typeof GM_getValue === "function";
}
function isTestEnvironment() {
return window.location.hostname === "127.0.0.1"
|| window.location.hostname === "localhost"
|| window.location.hostname.startsWith("192.168.");
}
function load() {
/** @type {Record<string, any>} */
let saveData = {};
if (isUserScript()) {
log("Loading save data from UserScript storage");
// @ts-expect-error
saveData = GM_getValue("birbSaveData", {}) ?? {};
} else if (isTestEnvironment()) {
log("Test environment detected, loading save data from localStorage");
saveData = JSON.parse(localStorage.getItem("birbSaveData") ?? "{}");
} else {
log("Not a UserScript");
}
let saveData = getContext().getSaveData();
debug("Loaded data: " + JSON.stringify(saveData));
@@ -340,29 +316,11 @@ Promise.all([
}));
}
if (isUserScript()) {
log("Saving data to UserScript storage");
// @ts-expect-error
GM_setValue("birbSaveData", saveData);
} else if (isTestEnvironment()) {
log("Test environment detected, saving data to localStorage");
localStorage.setItem("birbSaveData", JSON.stringify(saveData));
} else {
log("Not a UserScript");
}
getContext().putSaveData(saveData);
}
function resetSaveData() {
if (isUserScript()) {
log("Resetting save data in UserScript storage");
// @ts-expect-error
GM_deleteValue("birbSaveData");
} else if (isTestEnvironment()) {
log("Test environment detected, resetting save data in localStorage");
localStorage.removeItem("birbSaveData");
} else {
log("Not a UserScript");
}
getContext().resetSaveData();
load();
}

119
src/context.js Normal file
View File

@@ -0,0 +1,119 @@
import { debug, log, error } from "./shared.js";
/**
* @typedef {import('./application.js').BirbSaveData} BirbSaveData
*/
/**
* @abstract
*/
export class Context {
/**
* @abstract
* @returns {boolean} Whether this context is applicable
*/
isContextActive() {
throw new Error("Method not implemented");
}
/**
* @abstract
* @returns {BirbSaveData|{}}
*/
getSaveData() {
throw new Error("Method not implemented");
}
/**
* @abstract
* @param {BirbSaveData} saveData
*/
putSaveData(saveData) {
throw new Error("Method not implemented");
}
/**
* @abstract
*/
resetSaveData() {
throw new Error("Method not implemented");
}
}
export class LocalContext extends Context {
isContextActive() {
return window.location.hostname === "127.0.0.1"
|| window.location.hostname === "localhost"
|| window.location.hostname.startsWith("192.168.");
}
getSaveData() {
log("Loading save data from localStorage");
return JSON.parse(localStorage.getItem("birbSaveData") ?? "{}");
}
/**
* @override
* @param {BirbSaveData} saveData
*/
putSaveData(saveData) {
log("Saving data to localStorage");
localStorage.setItem("birbSaveData", JSON.stringify(saveData));
}
resetSaveData() {
log("Resetting save data in localStorage");
localStorage.removeItem("birbSaveData");
}
}
export class UserScriptContext extends Context {
isContextActive() {
// @ts-expect-error
return typeof GM_getValue === "function";
}
getSaveData() {
log("Loading save data from UserScript storage");
/** @type {BirbSaveData|{}} */
let saveData = {};
// @ts-expect-error
saveData = GM_getValue("birbSaveData", {}) ?? {};
return saveData;
}
/**
* @override
* @param {BirbSaveData} saveData
*/
putSaveData(saveData) {
log("Saving data to UserScript storage");
// @ts-expect-error
GM_setValue("birbSaveData", saveData);
}
resetSaveData() {
log("Resetting save data in UserScript storage");
// @ts-expect-error
GM_deleteValue("birbSaveData");
}
}
const CONTEXTS = [
new LocalContext(),
new UserScriptContext(),
];
export function getContext() {
for (const context of CONTEXTS) {
if (context.isContextActive()) {
return context;
}
}
error("No applicable context found, defaulting to LocalContext");
return CONTEXTS[0];
}