General code refactoring, move Notyf code into toast.ts

This commit is contained in:
wearrrrr 2024-11-24 00:42:35 -06:00
parent 5fc3995257
commit 10ac39b46f
13 changed files with 127 additions and 136 deletions

View file

@ -13,7 +13,7 @@ module.exports = {
"no-unused-vars": "error",
"no-undef": "off",
"prefer-const": "error",
"no-case-declarations": "off"
"no-case-declarations": "off",
},
ignorePatterns: ["env.d.ts", "middleware/", "public/"],
overrides: [
@ -35,7 +35,7 @@ module.exports = {
extends: ["plugin:@typescript-eslint/recommended"],
rules: {
"@typescript-eslint/no-explicit-any": "off",
}
},
},
{
// Define the configuration for `<script>` tag.

View file

@ -25,7 +25,7 @@ if (existsSync("exempt_masqr.txt")) {
const exemptDomains = file.split("\n");
exemptDomains.forEach((domain) => {
whiteListedDomains.push(domain.trim());
})
});
}
const LICENSE_SERVER_URL = "https://license.mercurywork.shop/validate?license=";

View file

@ -18,7 +18,7 @@ function loadExtensionScripts() {
let extensions = request.result.filter((extension) => extension.type == "serviceWorker");
extensions.forEach((extension) => {
const decoder = new TextDecoder();
const contents = decoder.decode(extension.script);
const contents = decoder.decode(extension.scriptCopy);
eval(contents);

7
src/alu.d.ts vendored
View file

@ -1,11 +1,4 @@
export declare global {
type AluStore = {
get: (key: Alu.ValidStoreKeys) => Alu.KeyObj;
set: (key: Alu.ValidStoreKeys, value: Alu.KeyObj) => void;
remove: (key: Alu.ValidStoreKeys) => void;
reset: (key: Alu.ValidStoreKeys) => void;
};
// Hacky way to not have to cast the "event" type that lib.dom has to CustomEvent, which is what we actually use.
interface Document {
addEventListener(type: "setting-tabLoad", listener: (this: Document, ev: CustomEvent) => any, options?: boolean | AddEventListenerOptions);

View file

@ -7,7 +7,6 @@ const { type } = Astro.props;
type Props = {
type: ExtType;
};
---
<div class="marketplace-icon">

View file

@ -1,6 +1,6 @@
<script>
import IDBManager from "@components/ts/IDBManager";
const idb = IDBManager.loadIDB("AluDB", 1)
const idb = IDBManager.loadIDB("AluDB", 1);
idb.onsuccess = () => {
IDBManager.GetStore("InstalledExtensions", "readonly").getAll().onsuccess = (event) => {
@ -25,6 +25,4 @@
}
};
};
</script>

View file

@ -23,7 +23,6 @@
const decoder = new TextDecoder();
const style = decoder.decode(extension.scriptCopy!);
loadStyleFromString(style);
document.addEventListener("astro:after-swap", () => {

View file

@ -1,83 +1,51 @@
import "notyf/notyf.min.css";
import { Notyf } from "notyf";
import marketplaceManifest from "../../json/marketplace.json";
import IDBManager, { loadIDBPromise } from "./IDBManager";
import Toast from "./toast";
const installButtons = document.getElementsByClassName("btn-install");
const extManifest = marketplaceManifest as ExtensionMetadataJSON;
// This just makes it shorter to type
interface HTMLButton extends HTMLButtonElement {}
enum EXT_RETURN {
ACTION_SUCCESS = 0,
INSTALL_FAILED = -1,
ALREADY_INSTALLED = 1,
const EXT_RETURN = {
INSTALL_FAILED: -1,
INSTALL_SUCCESS: 0,
ALREADY_INSTALLED: 1,
}
Array.from(installButtons).forEach((btn) => {
btn.addEventListener("click", async (event) => {
const ele = event.target as HTMLButton;
const title = ele.dataset.title;
const notification = new Notyf({
duration: 999999,
position: { x: "right", y: "bottom" },
dismissible: true,
ripple: true,
});
const installNotif = notification.success(`Installing ${title}...`);
if (ele.dataset.slug) {
const obj = await getMarketplaceObj(ele.dataset.slug);
installExtension(obj, ele.dataset.slug)
.then((ret) => {
let notifMessage: string;
let timeout = 2000;
switch (ret.code) {
case EXT_RETURN.ACTION_SUCCESS:
notifMessage = `Installed ${title} Successfully!`;
// Unregister the service worker if it's a service worker
if (obj.type === "serviceWorker") {
const ext = await getMarketplaceExt(ele.dataset.slug);
const install = await installExtension(ext, ele.dataset.slug)
switch (install.code) {
case EXT_RETURN.INSTALL_SUCCESS:
Toast.success(`Installed ${title} Successfully!`);
if (ext.type === "serviceWorker") {
navigator.serviceWorker.getRegistration().then((reg) => {
if (reg) {
reg.unregister().then(() => {
console.log("Service worker unregistered!");
});
// Unregister the SW so that the installed plugin is loaded when the page is refreshed (automatically)
reg.unregister();
}
});
}
break;
case EXT_RETURN.ALREADY_INSTALLED:
notifMessage = `${title} is already installed!`;
timeout = 0;
Toast.success(`${title} is already installed!`);
break;
case EXT_RETURN.INSTALL_FAILED:
// We should NEVER get here, but just in case.
notifMessage = `Failed to install ${title}!`;
break;
Toast.error(`Failed to install ${title}!`);
}
setTimeout(() => {
notification.dismiss(installNotif);
notification.options.duration = 2000;
notification.success(notifMessage);
setTimeout(() => {
window.location.reload();
}, 1000);
notification.options.duration = 999999;
const btn = document.querySelector(`button[data-slug="${ret.slug}"]`) as HTMLButton;
}, 1500);
const btn = document.querySelector(`button[data-slug="${install.slug}"]`) as HTMLButton;
setInstallBtnText(btn);
}, timeout);
})
.catch(() => {
notification.dismiss(installNotif);
notification.options.duration = 2000;
notification.error(`Failed to install ${title}!`);
notification.options.duration = 999999;
});
}
});
});
async function getMarketplaceObj(slug: string): Promise<ExtensionMetadata> {
async function getMarketplaceExt(slug: string) {
const manifest = extManifest[slug];
if (manifest == null) {
throw new Error("Extension not found!");
@ -89,7 +57,7 @@ async function getMarketplaceObj(slug: string): Promise<ExtensionMetadata> {
return manifest;
}
async function installExtension(ext: ExtensionMetadata, slug: string): Promise<InstallReturn> {
async function installExtension(ext: ExtensionMetadata, slug: string) {
return new Promise<InstallReturn>((resolve, reject) => {
const request = IDBManager.GetIDB();
const transaction = request.transaction("InstalledExtensions", "readwrite");
@ -99,18 +67,18 @@ async function installExtension(ext: ExtensionMetadata, slug: string): Promise<I
...ext,
};
const slugCheck = store.get(slug);
slugCheck.onsuccess = async () => {
if (slugCheck.result != null) {
resolve({ code: EXT_RETURN.ALREADY_INSTALLED, slug: slug });
} else {
slugCheck.onsuccess = () => {
if (slugCheck.result == null) {
const addRequest = store.add(extensionObject);
addRequest.onerror = () => {
console.error(`Error installing ${slug}!`);
reject({ code: EXT_RETURN.INSTALL_FAILED, slug: slug });
};
addRequest.onsuccess = () => {
resolve({ code: EXT_RETURN.ACTION_SUCCESS, slug: slug });
resolve({ code: EXT_RETURN.INSTALL_SUCCESS, slug: slug });
};
} else {
resolve({ code: EXT_RETURN.ALREADY_INSTALLED, slug: slug });
}
};
});
@ -122,16 +90,11 @@ function addUninstallEventListeners() {
if (!confirm("Are you sure you want to uninstall this extension?")) {
return;
}
const uninst = await uninstallExtension((event.target as HTMLButton).dataset.uninstallSlug!);
const notification = new Notyf({
duration: 999999,
position: { x: "right", y: "bottom" },
dismissible: true,
ripple: true,
});
const button = event.target as HTMLButton;
const uninst = await uninstallExtension(button.dataset.uninstallSlug!);
switch (uninst.code) {
case EXT_RETURN.ACTION_SUCCESS:
notification.success(`Uninstalled ${uninst.title}!`);
case EXT_RETURN.INSTALL_SUCCESS:
Toast.success(`Uninstalled ${uninst.title}!`);
const btn = document.querySelector(`button[data-slug="${uninst.slug}"]`) as HTMLButton;
btn.disabled = false;
btn.textContent = "Install";
@ -139,7 +102,7 @@ function addUninstallEventListeners() {
(event.target as HTMLButton).classList.add("btn-hidden");
break;
case EXT_RETURN.INSTALL_FAILED:
notification.error(`Failed to uninstall ${uninst.title}!`);
Toast.error(`Failed to uninstall ${uninst.title}!`);
break;
}
setTimeout(() => {
@ -187,7 +150,7 @@ async function uninstallExtension(slug: string): Promise<InstallReturn> {
});
}
});
resolve({ code: EXT_RETURN.ACTION_SUCCESS, slug: slug, title: ext.result.title });
resolve({ code: EXT_RETURN.INSTALL_SUCCESS, slug: slug, title: ext.result.title });
};
};
});

View file

@ -0,0 +1,38 @@
import "notyf/notyf.min.css";
import { Notyf, NotyfNotification } from "notyf";
export default class Toast {
private static notyf = new Notyf({
duration: 999999,
position: { x: "right", y: "bottom" },
dismissible: true,
ripple: true,
});
public static get(): Notyf {
return this.notyf;
}
public static setDuration(duration: number) {
this.notyf.options.duration = duration;
}
public static success(message: string) {
return this.notyf.success(message);
}
public static error(message: string) {
return this.notyf.error(message);
}
public static info(message: string) {
return this.notyf.open({
type: "info",
message: message,
});
}
public static dismiss(toast: NotyfNotification) {
this.notyf.dismiss(toast);
}
}

View file

@ -102,9 +102,7 @@ export const getStaticPaths = () => {
width: 80%;
margin: 0 auto;
overflow: hidden;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
height: 40px;
height: 80px;
}
.marketplace-btn-container {

View file

@ -9,9 +9,8 @@ const gamesList = games as GameList;
sitemap(async ({ setSitemap }) => {
const gamesList = games as GameList;
const urls = Object.keys(gamesList);
setSitemap(
urls.map((game) => ({
Object.keys(gamesList).map((game) => ({
sitemap: true,
params: {
game: game,

4
src/types.d.ts vendored
View file

@ -17,8 +17,12 @@ type Extension = {
name: string;
script: string;
type: ExtType;
};
// This just makes it shorter to type
type HTMLButton = HTMLButtonElement;
/*
- title: The title of the extension
- description: A description of the extension