glide: extract notification helper into utils
Glide configs cannot import runtime code between files, so shared helpers are registered on globalThis with declare-global typing.

Assisted-by: GLM-5.3 via pi
change tttqxyktwqnsztrpmuvrsvpvvyvwoqxl
commit f4859a9a513a4a3aa03b97cd1d6c3b659e4ab32d
author Alpha Chen <alpha@kejadlen.dev>
date
parent svpzkrxs
diff --git a/.config/glide/glide.ts b/.config/glide/glide.ts
index 7e7f752e..e41d979d 100644
--- a/.config/glide/glide.ts
+++ b/.config/glide/glide.ts
@@ -21,6 +21,7 @@ glide.include("pihole.glide.ts");
 glide.include("splits.glide.ts");
 glide.include("styles.glide.ts");
 glide.include("tridactyl.glide.ts");
+glide.include("utils.glide.ts");
 glide.fs.exists("local.glide.ts").then(exists => {
   if (exists) glide.include("local.glide.ts");
 });
@@ -118,37 +119,10 @@ browser.webRequest.onBeforeRequest.addListener(
   ["blocking"]
 );
 
-glide.styles.add(`
-  .yank-notification {
-    position: fixed;
-    bottom: 2rem;
-    right: 2rem;
-    z-index: 2147483646;
-    background: var(--glide-cmdl-bg);
-    color: var(--glide-cmdl-fg);
-    border: 1px solid hsla(0, 0%, 100%, 0.1);
-    border-radius: 4px;
-    box-shadow: 0 -8px 32px hsla(0, 0%, 0%, 0.4);
-    font-family: var(--glide-cmdl-font-family);
-    font-size: var(--glide-cmdl-font-size);
-    line-height: var(--glide-cmdl-line-height);
-    padding: 0.75rem 1rem;
-    max-width: 600px;
-    word-break: break-all;
-  }
-`);
-
 glide.keymaps.set("normal", "yy", async () => {
   const url = glide.ctx.url;
   await navigator.clipboard.writeText(url.toString());
-
-  const notification = DOM.create_element("div", {
-    className: "yank-notification",
-    textContent: `Yanked: ${url}`,
-  });
-
-  document.documentElement.appendChild(notification);
-  setTimeout(() => notification.remove(), 2000);
+  glide.g["dev.kejadlen"]!.notify(`Yanked: ${url}`);
 });
 
 async function getStashesFolder() {
diff --git a/.config/glide/pihole.glide.ts b/.config/glide/pihole.glide.ts
index 5bafbb81..a5cf2865 100644
--- a/.config/glide/pihole.glide.ts
+++ b/.config/glide/pihole.glide.ts
@@ -59,27 +59,14 @@ async function piholeSleep(seconds: number): Promise<void> {
   if (status.blocking !== "disabled") throw new Error(`blocking status is "${status.blocking}"`);
 }
 
-// Reuses the .yank-notification class styled in glide.ts. The injected
-// function is stringified across processes, so it can't capture anything.
-async function notify(text: string): Promise<void> {
-  await glide.content.execute(
-    (message: string) => {
-      const el = DOM.create_element("div", { className: "yank-notification", textContent: message });
-      document.documentElement.appendChild(el);
-      setTimeout(() => el.remove(), 2000);
-    },
-    { tab_id: await glide.tabs.active(), args: [text] },
-  );
-}
-
 const piholeSleepCmd = glide.excmds.create(
   { name: "pihole-sleep", description: `Disable Pi-hole blocking for ${SLEEP_SECONDS} seconds` },
   async () => {
     try {
       await piholeSleep(SLEEP_SECONDS);
-      await notify(`Pi-hole disabled for ${SLEEP_SECONDS}s`);
+      glide.g["dev.kejadlen"]!.notify(`Pi-hole disabled for ${SLEEP_SECONDS}s`);
     } catch (err) {
-      await notify(`Pi-hole: ${err instanceof Error ? err.message : String(err)}`);
+      glide.g["dev.kejadlen"]!.notify(`Pi-hole: ${err instanceof Error ? err.message : String(err)}`);
     }
   },
 );
diff --git a/.config/glide/utils.glide.ts b/.config/glide/utils.glide.ts
new file mode 100644
index 00000000..7ce7d93b
--- /dev/null
+++ b/.config/glide/utils.glide.ts
@@ -0,0 +1,52 @@
+/**
+ * Shared utilities — Glide config
+ *
+ * Glide configs can't import runtime code between files (only type
+ * imports, which are stripped), and each included file gets its own
+ * global scope. Shared state goes through `glide.g`, which crosses
+ * include boundaries; types are added with `declare global`. Keys
+ * under `glide.g["dev.kejadlen"]` are this dotfiles repo's own
+ * namespace (reverse-DNS, so glide's own GlideGlobals state can never
+ * collide — it already uses `mapleader` there).
+ */
+
+glide.styles.add(`
+  .glide-notification {
+    position: fixed;
+    bottom: 2rem;
+    right: 2rem;
+    z-index: 2147483646;
+    background: var(--glide-cmdl-bg);
+    color: var(--glide-cmdl-fg);
+    border: 1px solid hsla(0, 0%, 100%, 0.1);
+    border-radius: 4px;
+    box-shadow: 0 -8px 32px hsla(0, 0%, 0%, 0.4);
+    font-family: var(--glide-cmdl-font-family);
+    font-size: var(--glide-cmdl-font-size);
+    line-height: var(--glide-cmdl-line-height);
+    padding: 0.75rem 1rem;
+    max-width: 600px;
+    word-break: break-all;
+  }
+`);
+
+interface Utils {
+  /** Show a transient notification overlay in the browser UI. */
+  notify(text: string): void;
+}
+
+declare global {
+  interface GlideGlobals {
+    "dev.kejadlen"?: Utils;
+  }
+}
+
+// Keymap and excmd callbacks run in the main process, where `document`
+// is the browser UI itself; `DOM` is main-process-only by design.
+glide.g["dev.kejadlen"] = {
+  notify(text: string): void {
+    const el = DOM.create_element("div", { className: "glide-notification", textContent: text });
+    document.documentElement.appendChild(el);
+    setTimeout(() => el.remove(), 2000);
+  },
+};