diff --git a/src/plugins/built-in/notificationCollector/index.ts b/src/plugins/built-in/notificationCollector/index.ts index dc4576c1..779183cb 100644 --- a/src/plugins/built-in/notificationCollector/index.ts +++ b/src/plugins/built-in/notificationCollector/index.ts @@ -1,4 +1,5 @@ import type { Plugin } from "../../core/types"; +import { isSeqtaEngageExperience } from "@/seqta/utils/isSeqtaEngage"; interface NotificationCollectorStorage { lastNotificationCount: number; @@ -15,6 +16,10 @@ const notificationCollectorPlugin: Plugin<{}, NotificationCollectorStorage> = { disableToggle: true, run: async (api) => { + if (isSeqtaEngageExperience()) { + return () => {}; + } + let pollInterval: number | null = null; let isVisible = !document.hidden; let baseInterval = 30000; // 30 seconds diff --git a/src/plugins/monofile.ts b/src/plugins/monofile.ts index 1a65bb96..4892c7df 100644 --- a/src/plugins/monofile.ts +++ b/src/plugins/monofile.ts @@ -509,6 +509,9 @@ function CheckNoticeTextColour(notice: any) { } function watchForEngageLogin() { + if (!document.querySelector(".login")) { + return; + } const observer = new MutationObserver(() => { if (!document.querySelector(".login")) { observer.disconnect(); @@ -518,24 +521,69 @@ function watchForEngageLogin() { observer.observe(document.body, { childList: true, subtree: true }); } +/** Wait until Engage shows either the login shell or the main app (`#content`), so we never call `LoadPageElements` while still on login (which would hang on `waitForElm("#content")`). */ +function waitForEngageLoginOrContent(): Promise<"login" | "app" | "timeout"> { + if (document.querySelector(".login")) { + return Promise.resolve("login"); + } + if (document.getElementById("content")) { + return Promise.resolve("app"); + } + return new Promise((resolve) => { + let settled = false; + const finish = (mode: "login" | "app") => { + if (settled) return; + settled = true; + mo.disconnect(); + window.clearTimeout(tid); + resolve(mode); + }; + const check = () => { + if (document.querySelector(".login")) finish("login"); + else if (document.getElementById("content")) finish("app"); + }; + const mo = new MutationObserver(check); + mo.observe(document.documentElement, { subtree: true, childList: true }); + const tid = window.setTimeout(() => { + if (settled) return; + mo.disconnect(); + settled = true; + if (document.querySelector(".login")) resolve("login"); + else if (document.getElementById("content")) resolve("app"); + else { + console.warn( + "[BetterSEQTA+] Engage: timed out waiting for .login or #content; unblocking load UI.", + ); + resolve("timeout"); + } + }, 120_000); + }); +} + export function tryLoad() { if (isSeqtaEngageExperience()) { updateIframesWithDarkMode(); window.addEventListener("load", () => removeThemeTagsFromNotices(), { once: true }); - const runEngageLoad = () => { - if (document.querySelector(".login")) { + const runEngageLoad = async () => { + const mode = await waitForEngageLoginOrContent(); + if (mode === "login") { finishLoad(); watchForEngageLogin(); return; } - void LoadPageElements(); + if (mode === "timeout") { + finishLoad(); + void waitForElm("#content").then(() => void LoadPageElements()); + return; + } + await LoadPageElements(); }; if (document.readyState === "complete") { - runEngageLoad(); + void runEngageLoad(); } else { - window.addEventListener("load", () => runEngageLoad(), { once: true }); + window.addEventListener("load", () => void runEngageLoad(), { once: true }); } return; }