feat: new settings popup

This commit is contained in:
2026-07-24 10:08:03 +09:30
parent b5347e2732
commit 928f05ec8e
12 changed files with 662 additions and 354 deletions
+48 -14
View File
@@ -440,22 +440,56 @@ async function addEngageUserInfo() {
});
}
async function setupEngageSettingsButton() {
try {
const notificationsWrapper = await waitForElm(
"#content > div.connectedNotificationsWrapper > div",
);
const parent = notificationsWrapper.parentElement!;
async function mountEngageToolbarControls(parent?: Element) {
// React can remount the notifications chrome — recreate missing controls.
if (!document.getElementById("LightDarkModeButton")) {
await addDarkLightToggle(parent);
await createSettingsButton(parent);
setupSettingsButton();
attachNotificationsPanelAnimation();
} catch {
await addDarkLightToggle();
await createSettingsButton();
setupSettingsButton();
attachNotificationsPanelAnimation();
}
if (!document.getElementById("AddedSettings")) {
await createSettingsButton(parent);
}
setupSettingsButton();
attachNotificationsPanelAnimation();
}
async function setupEngageSettingsButton() {
let mounting = false;
const tryMount = async () => {
if (mounting || document.getElementById("AddedSettings")) return;
mounting = true;
try {
try {
const notificationsWrapper = await waitForElm(
"#content > div.connectedNotificationsWrapper > div",
true,
100,
40,
);
const parent = notificationsWrapper.parentElement!;
await mountEngageToolbarControls(parent);
} catch {
await mountEngageToolbarControls();
}
} finally {
mounting = false;
}
};
await tryMount();
// Re-inject if Engage's React shell wipes the toolbar controls.
const content = document.getElementById("content");
if (!content || (content as HTMLElement).dataset.bsplusEngageSettingsWatch === "1") {
return;
}
(content as HTMLElement).dataset.bsplusEngageSettingsWatch = "1";
const observer = new MutationObserver(() => {
if (document.getElementById("AddedSettings")) return;
void tryMount();
});
observer.observe(content, { childList: true, subtree: true });
}
function GetLightDarkModeString() {
+6 -6
View File
@@ -1,7 +1,7 @@
import debounce from "@/seqta/utils/debounce";
/**
* Automatically resizes the popup to fit the screen, checks on resize but is debounced to prevent intense utilisation.
* Keeps the settings overlay covering the viewport.
*/
export class SettingsResizer {
constructor() {
@@ -17,10 +17,10 @@ export class SettingsResizer {
const iframePopup = document.getElementById("ExtensionPopup");
if (!iframePopup) return;
const viewportHeight = window.innerHeight;
const rawIdeal = viewportHeight - 80 - 15; // room below top chrome
const idealHeight = Math.min(Math.max(rawIdeal, 280), 600);
iframePopup.style.height = `${idealHeight}px`;
iframePopup.style.inset = "0";
iframePopup.style.top = "0";
iframePopup.style.right = "0";
iframePopup.style.width = "100%";
iframePopup.style.height = "100%";
}
}
+4 -4
View File
@@ -12,10 +12,10 @@ export async function renderStore() {
import("@/interface/pages/store.svelte"),
]);
const container = document.querySelector("#container");
if (!container) {
throw new Error("Container not found");
}
const container =
document.querySelector("#container") ??
document.getElementById("content") ??
document.body;
document.getElementById("store")?.remove();