No more silly globals
This commit is contained in:
parent
1616fa21f2
commit
1bd272ec8d
8 changed files with 234 additions and 21 deletions
|
|
@ -27,6 +27,7 @@
|
|||
import { SW, createProxyScripts, checkProxyScripts, createBareMuxConn, setTransport } from "@utils/serviceWorker";
|
||||
import { Settings } from "@utils/settings";
|
||||
import { log } from "@utils/index";
|
||||
import { Marketplace } from "@utils/marketplace";
|
||||
const titleText = `
|
||||
_ _ _ _ ____ _
|
||||
| \\ | | ___| |__ _ _| | __ _ / ___| ___ _ ____ _(_) ___ ___ ___
|
||||
|
|
@ -46,9 +47,11 @@
|
|||
}
|
||||
await checkProxyScripts();
|
||||
const conn = await createBareMuxConn("/baremux/worker.js");
|
||||
window.sw = new SW(conn);
|
||||
for await (const _ of Settings.initDefaults()) {};
|
||||
const { serviceWorker, bareMuxConn, sj } = await window.sw.getSWInfo();
|
||||
const sw = new SW(conn);
|
||||
new Marketplace();
|
||||
// We don't do anything with the values (they aren't even any), so we just are iterating.
|
||||
for await (const _ of Settings.initDefaults());
|
||||
const { serviceWorker, bareMuxConn, sj } = await sw.getSWInfo();
|
||||
log({ type: 'info', bg: true, prefix: true }, `General init completed! \n\nServiceWorker: ${serviceWorker.active?.state} \nBareMuxConn: ${bareMuxConn ? 'Active': 'Not active'} \nScramjetController: ${sj ? 'Active' : 'Not active'}`);
|
||||
}
|
||||
const initSettings = async () => {
|
||||
|
|
|
|||
2
src/global.d.ts
vendored
2
src/global.d.ts
vendored
|
|
@ -1,10 +1,10 @@
|
|||
// LEGIT here for ONE global.
|
||||
|
||||
import type { Marketplace } from "@utils/marketplace";
|
||||
import type { SW } from "@utils/serviceWorker";
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
sw: SW;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ import { VERSION } from "astro:env/client";
|
|||
import { BareClient } from "@mercuryworkshop/bare-mux";
|
||||
import { defaultStore } from "@utils/storage";
|
||||
import { Settings } from "@utils/settings";
|
||||
import { setTransport } from "@utils/serviceWorker";
|
||||
import { setTransport, SW } from "@utils/serviceWorker";
|
||||
|
||||
type Suggestion = {
|
||||
phrase: string;
|
||||
|
|
@ -81,7 +81,8 @@ import { VERSION } from "astro:env/client";
|
|||
iframe.src = `${__uv$config.prefix}${__uv$config.encodeUrl!(val)}`;
|
||||
break;
|
||||
case "sj":
|
||||
const { sj } = await window.sw.getSWInfo();
|
||||
const sw = SW.getInstances().next().value as SW;
|
||||
const { sj } = await sw.getSWInfo();
|
||||
iframe.src = sj.encodeUrl(val);
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { log } from "./index";
|
||||
import { Elements, log } from "./index";
|
||||
import { StoreManager } from "./storage";
|
||||
import { SettingsVals } from "./values";
|
||||
|
||||
|
|
@ -54,25 +54,71 @@ interface Theme {
|
|||
bgImage?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* A class where for all of the Marketplace handlers.
|
||||
* It creates it's own StoreManager where all of it's values will live.
|
||||
* And it has 2 static items. instances and getInstances.
|
||||
*
|
||||
* @example
|
||||
* //Create a new Marketplace instance
|
||||
* const mp = new Marketplace();
|
||||
* //Use one of the very many methods available.
|
||||
*
|
||||
* //Get all instances of a Marketplace is as easy as:
|
||||
* // const mp = Marketplace.getInstances.next().value;
|
||||
* // Consume and use the class.
|
||||
*/
|
||||
class Marketplace {
|
||||
//create our own subsidized StoreManager with it's own prefix so the marketplace stuff NEVER touches the other data
|
||||
#storage: StoreManager<"nebula||marketplace">;
|
||||
static #instances = new Set();
|
||||
constructor() {
|
||||
this.#storage = new StoreManager("nebula||marketplace");
|
||||
log({ type: 'info', bg: true, prefix: true }, 'Marketplace instance created and ready!');
|
||||
Marketplace.#instances.add(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* A static method to aquire an instance of a marketplace object.
|
||||
*
|
||||
* @example
|
||||
* //Get the first insatnce available.
|
||||
* const mp = Marketplace.getInstances.next().value
|
||||
*
|
||||
* @example
|
||||
* // Iterate over every instance
|
||||
* for (const instance of Marketplace.getInstances()) {
|
||||
* // Do some work
|
||||
* }
|
||||
*/
|
||||
static *getInstances() {
|
||||
//Marketplace.instances.forEach((val) => yield val);
|
||||
for (const item of Marketplace.#instances.keys()) {
|
||||
yield item;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Install a theme into both localstorage AND set the theme.
|
||||
*
|
||||
* @example
|
||||
* const mp = new Marketplace() // OR get an instances from getInstances()
|
||||
* mp.installTheme({
|
||||
* name: "testTheme",
|
||||
* payload: "/packages/testTheme/index.css",
|
||||
* // video: if you have a bg video, pass it here.
|
||||
* //bgImage: pass the BG image here if you have one
|
||||
* });
|
||||
*/
|
||||
async installTheme(theme: Theme) {
|
||||
const themes = this.#storage.getVal(SettingsVals.marketPlace.themes)
|
||||
? JSON.parse(this.#storage.getVal(SettingsVals.marketPlace.themes))
|
||||
: [];
|
||||
const themes = JSON.parse(this.#storage.getVal(SettingsVals.marketPlace.themes)) || [];
|
||||
if (themes.find((t: any) => t === theme.name)) return log({ type: 'error', bg: false, prefix: false, throw: true }, `${theme.name} is already installed!`)
|
||||
themes.push(theme.name);
|
||||
this.#storage.setVal(SettingsVals.marketPlace.themes, JSON.stringify(themes));
|
||||
}
|
||||
|
||||
async installPlugin(plugin: Plug) {
|
||||
const plugins = this.#storage.getVal(SettingsVals.marketPlace.plugins)
|
||||
? JSON.parse(this.#storage.getVal(SettingsVals.marketPlace.plugins))
|
||||
: [];
|
||||
const plugins = JSON.parse(this.#storage.getVal(SettingsVals.marketPlace.plugins)) || [];
|
||||
|
||||
const plug = plugins.find(({ name }: { name: string }) => name === plugin.name);
|
||||
if (plug && plug.remove === false) return log({ type: 'error', bg: false, prefix: false, throw: true }, `${plugin.name} is already installed!`);
|
||||
|
|
@ -80,8 +126,140 @@ class Marketplace {
|
|||
plugins.push({ name: plugin.name, src: plugin.src, type: plugin.type } as unknown as Plug);
|
||||
this.#storage.setVal(SettingsVals.marketPlace.plugins, JSON.stringify(plugins));
|
||||
}
|
||||
|
||||
async uninstallTheme(theme: Theme) {
|
||||
const items = JSON.parse(this.#storage.getVal(SettingsVals.marketPlace.plugins)) || [];
|
||||
if (!items.find((th: string) => th === theme.name)) {
|
||||
return log({ type: 'error', bg: false, prefix: false, throw: true }, `Theme: ${theme.name} is not installed!`);
|
||||
}
|
||||
const idx = items.indexOf(theme.name.toLowerCase());
|
||||
items.splice(idx, 1);
|
||||
this.#storage.setVal(SettingsVals.marketPlace.themes, JSON.stringify(items));
|
||||
}
|
||||
|
||||
async uninstallPlugin(plug: Plug) {
|
||||
const items = JSON.parse(this.#storage.getVal(SettingsVals.marketPlace.plugins)) || [];
|
||||
const plugin = items.find(({ name }: { name: string }) => name === plug.name.toLowerCase());
|
||||
if (!plugin) return log({ type: 'error', bg: false, prefix: false, throw: true }, `Plugin: ${plug.name} is not installed!`);
|
||||
plugin.remove = true;
|
||||
this.#storage.setVal(SettingsVals.marketPlace.plugins, JSON.stringify(items));
|
||||
}
|
||||
|
||||
async handlePlugins(worker: ServiceWorkerRegistration) {
|
||||
let plugins = JSON.parse(this.#storage.getVal(SettingsVals.marketPlace.plugins)) || [];
|
||||
const pagePlugins: SWPagePlugin[] = [];
|
||||
const swPlugins: SWPlugin[] = [];
|
||||
if (plugins.length === 0) return log({ type: 'info', bg: false, prefix: true }, 'No plugins to add! Exiting.');
|
||||
plugins.map(async (plugin: Plug) => {
|
||||
if (plugin.type === "page") {
|
||||
const script = await fetch(`/packages/${plugin.name.toLowerCase()}/${plugin.src}`);
|
||||
const scriptRes = await script.text();
|
||||
const evaledScript = eval(scriptRes);
|
||||
const inject = (await evaledScript()) as unknown as SWPagePlugin;
|
||||
if (!plugin.remove) {
|
||||
pagePlugins.push({
|
||||
host: inject.host,
|
||||
html: inject.html,
|
||||
injectTo: inject.injectTo,
|
||||
type: 'page'
|
||||
});
|
||||
}
|
||||
else {
|
||||
plugins = plugins.filter(({ name }: { name: string }) => name !== plugin.name.toLowerCase());
|
||||
pagePlugins.push({
|
||||
remove: true,
|
||||
host: inject.host,
|
||||
html: inject.html,
|
||||
injectTo: inject.injectTo,
|
||||
type: 'page'
|
||||
});
|
||||
}
|
||||
worker.active?.postMessage(pagePlugins);
|
||||
}
|
||||
|
||||
if (plugin.type === "serviceWorker") {
|
||||
const s = await fetch(`/packages/${plugin.name.toLowerCase()}/${plugin.src}`);
|
||||
const sRes = await s.text();
|
||||
const eScript = eval(sRes);
|
||||
const inject = (await eScript()) as unknown as SWPlugin;
|
||||
if (!plugin.remove) {
|
||||
swPlugins.push({
|
||||
function: inject.function.toString(),
|
||||
name: plugin.name,
|
||||
events: inject.events,
|
||||
type: 'serviceWorker'
|
||||
});
|
||||
}
|
||||
else {
|
||||
plugins = plugins.filter(({ name }: { name: string }) => name !== plugin.name.toLowerCase());
|
||||
swPlugins.push({
|
||||
remove: true,
|
||||
function: inject.function.toString(),
|
||||
name: plugin.name,
|
||||
events: inject.events,
|
||||
type: 'serviceWorker'
|
||||
});
|
||||
}
|
||||
worker.active?.postMessage(swPlugins);
|
||||
}
|
||||
this.#storage.setVal(SettingsVals.marketPlace.plugins, JSON.stringify(plugins));
|
||||
});
|
||||
}
|
||||
|
||||
async theme(opts: { type: 'normal', payload: string, sources?: { video?: string, bg?: string }, name: string } | { type: 'remove', payload?: string, sources?: { video?: string, bg?: string }, name?: string }) {
|
||||
const elems = Elements.select([
|
||||
{ type: 'id', val: 'stylesheet' },
|
||||
{ type: 'id', val: 'nebulaVideo' },
|
||||
{ type: 'id', val: 'nebulaImage' }
|
||||
]);
|
||||
const s = Elements.exists<HTMLLinkElement>(await elems.next());
|
||||
const nv = Elements.exists<HTMLVideoElement>(await elems.next());
|
||||
const ni = Elements.exists<HTMLImageElement>(await elems.next());
|
||||
|
||||
const nvl = this.#storage.getVal(SettingsVals.marketPlace.appearance.video);
|
||||
const nil = this.#storage.getVal(SettingsVals.marketPlace.appearance.image);
|
||||
const tsp = this.#storage.getVal(SettingsVals.marketPlace.appearance.theme.payload);
|
||||
const tsn = this.#storage.getVal(SettingsVals.marketPlace.appearance.theme.name);
|
||||
|
||||
const reset = (style: boolean) => {
|
||||
const st = this.#storage;
|
||||
if (style) {
|
||||
st.removeVal(SettingsVals.marketPlace.appearance.theme.name);
|
||||
st.removeVal(SettingsVals.marketPlace.appearance.theme.payload);
|
||||
s.href = "/nebula.css";
|
||||
}
|
||||
st.removeVal(SettingsVals.marketPlace.appearance.video);
|
||||
nv.src = "";
|
||||
st.removeVal(SettingsVals.marketPlace.appearance.image);
|
||||
ni.style.display = "none";
|
||||
ni.src = "";
|
||||
}
|
||||
|
||||
if (opts.type === 'remove') return reset(true);
|
||||
|
||||
if (opts.sources?.video || nvl) {
|
||||
reset(false);
|
||||
if (!nvl) this.#storage.setVal(SettingsVals.marketPlace.appearance.video, opts.sources?.video || nvl);
|
||||
nv.src = `/packages/${opts.name}/${opts.sources?.video ? opts.sources.video : nvl}`
|
||||
}
|
||||
if (opts.sources?.bg || nil) {
|
||||
reset(false);
|
||||
if (!nil) this.#storage.setVal(SettingsVals.marketPlace.appearance.image, opts.sources?.bg || nil);
|
||||
ni.style.display = "block";
|
||||
ni.src = `/packages/${opts.name}/${opts.sources?.bg ? opts.sources.bg : nil}`
|
||||
}
|
||||
|
||||
if (opts.payload) {
|
||||
if (tsp !== opts.payload) {
|
||||
this.#storage.setVal(SettingsVals.marketPlace.appearance.theme.payload, opts.payload);
|
||||
this.#storage.setVal(SettingsVals.marketPlace.appearance.theme.name, opts.name);
|
||||
s.href = `/packages/${opts.name}/${opts.payload}`;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (tsp) return s.href = `/packages/${tsn}/${tsp}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
window.mp = Marketplace
|
||||
|
||||
export { Marketplace }
|
||||
|
|
|
|||
|
|
@ -101,7 +101,9 @@ type SWInit = {
|
|||
class SW {
|
||||
#init!: SWInit;
|
||||
#ready: boolean = false;
|
||||
static #instances = new Set();
|
||||
constructor(conn: BareMuxConnection) {
|
||||
SW.#instances.add(this);
|
||||
const sj = (): ScramjetController => {
|
||||
const sj = new ScramjetController({
|
||||
prefix: '/~/scramjet',
|
||||
|
|
@ -133,7 +135,25 @@ class SW {
|
|||
throw new Error('Your browser is not supported! This website uses Service Workers heavily.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Static method to get an already existing SW class
|
||||
*
|
||||
*
|
||||
* @example
|
||||
* SW.getInstances.next().value // Get the first instance.
|
||||
*
|
||||
* @example
|
||||
* // Loop through every instance
|
||||
* for (const sw of SW.getInstances()) {
|
||||
* console.log(sw) // DO some real work
|
||||
* }
|
||||
*/
|
||||
static *getInstances() {
|
||||
for (const value of SW.#instances.keys()) {
|
||||
yield value as SW;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Allows you to overrid the items set. Should be used sparingly or never.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { defaultStore } from "./storage";
|
||||
import { SettingsVals, WispServers } from "./values";
|
||||
import { Marketplace } from "./marketplace";
|
||||
import { setTransport } from "./serviceWorker";
|
||||
import { setTransport, SW } from "./serviceWorker";
|
||||
|
||||
const tab = {
|
||||
ab: (redirect: string) => {
|
||||
|
|
@ -86,7 +86,8 @@ const proxy = {
|
|||
defaultStore.setVal(SettingsVals.proxy.wispServer, s);
|
||||
},
|
||||
transport: async (t: "libcurl" | "epoxy") => {
|
||||
const { bareMuxConn } = await window.sw.getSWInfo();
|
||||
const sw = SW.getInstances().next().value!;
|
||||
const { bareMuxConn } = await sw.getSWInfo();
|
||||
await setTransport(bareMuxConn, t as "libcurl" | "epoxy");
|
||||
defaultStore.setVal(SettingsVals.proxy.transport.key, t);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,9 +25,13 @@ class StoreManager<Prefix extends string /* This is here so I know what prefix i
|
|||
return localStorage.getItem(`${this.#prefix}||${key}`) as string;
|
||||
}
|
||||
setVal(key: string, val: string): void {
|
||||
log({ type: 'info', bg: false, prefix: true }, `Setting ${key} with value: ${val}`);
|
||||
localStorage.setItem(`${this.#prefix}||${key}`, val);
|
||||
}
|
||||
|
||||
removeVal(key: string): void {
|
||||
log({ type: 'info', bg: true, prefix: true }, `Removing ${this.#prefix}||${key}`);
|
||||
localStorage.removeItem(`${this.#prefix}||${key}`);
|
||||
}
|
||||
}
|
||||
|
||||
//this is done so I can see the prefix used.
|
||||
|
|
|
|||
|
|
@ -62,7 +62,10 @@ interface SettingsVals {
|
|||
appearance: {
|
||||
video: string;
|
||||
image: string;
|
||||
themeName: string;
|
||||
theme: {
|
||||
payload: string;
|
||||
name: string;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -105,7 +108,10 @@ const SettingsVals: SettingsVals = {
|
|||
appearance: {
|
||||
video: "video",
|
||||
image: "image",
|
||||
themeName: "themeName"
|
||||
theme: {
|
||||
name: "themeName",
|
||||
payload: "themePayload"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue