fix: fix login issue and improve google caledar flow

This commit is contained in:
2026-08-24 14:25:41 +09:30
parent dde5096d1c
commit 4f10930f24
7 changed files with 279 additions and 50 deletions
+2 -2
View File
@@ -5,7 +5,7 @@ import {
defineSettings, defineSettings,
hotkeySetting, hotkeySetting,
} from "../../core/settingsHelpers"; } from "../../core/settingsHelpers";
import { isSeqtaEngageExperience } from "@/seqta/utils/isSeqtaEngage"; import { isSeqtaEngageExperience, isSeqtaLoginPage } from "@/seqta/utils/isSeqtaEngage";
import styles from "./src/core/styles.css?inline"; import styles from "./src/core/styles.css?inline";
import { import {
resetSearchIndexes, resetSearchIndexes,
@@ -90,7 +90,7 @@ const globalSearchPlugin = defineLazyPlugin({
const runGlobalSearch = globalSearchPlugin.run!; const runGlobalSearch = globalSearchPlugin.run!;
globalSearchPlugin.run = async (api) => { globalSearchPlugin.run = async (api) => {
if (isSeqtaEngageExperience()) return () => {}; if (isSeqtaEngageExperience() || isSeqtaLoginPage()) return () => {};
// Eager chrome (like Analytics menu injection) — heavy chunk loads behind it. // Eager chrome (like Analytics menu injection) — heavy chunk loads behind it.
const hotkey = isValidHotkey(api.settings.searchHotkey ?? "") const hotkey = isValidHotkey(api.settings.searchHotkey ?? "")
@@ -58,6 +58,7 @@
let modalProvider = $state<CalendarProvider | null>(null); let modalProvider = $state<CalendarProvider | null>(null);
let showDisconnect = $state(false); let showDisconnect = $state(false);
let showDeleteEvents = $state(false); let showDeleteEvents = $state(false);
let disconnectOverlay = $state(false);
let toast = $state<{ message: string; error: boolean } | null>(null); let toast = $state<{ message: string; error: boolean } | null>(null);
let syncProgress = $state<GoogleCalendarSyncProgress | null>(null); let syncProgress = $state<GoogleCalendarSyncProgress | null>(null);
let syncWeeksAhead = $state(12); let syncWeeksAhead = $state(12);
@@ -67,20 +68,20 @@
let triggerEl = $state<HTMLButtonElement | null>(null); let triggerEl = $state<HTMLButtonElement | null>(null);
let menuEl = $state<HTMLDivElement | null>(null); let menuEl = $state<HTMLDivElement | null>(null);
let modalEl = $state<HTMLDivElement | null>(null); let modalEl = $state<HTMLDivElement | null>(null);
let overlayEl = $state<HTMLDivElement | null>(null);
let menuStyle = $state(""); let menuStyle = $state("");
let toastTimer: ReturnType<typeof setTimeout> | null = null; let toastTimer: ReturnType<typeof setTimeout> | null = null;
const isBusy = $derived(busy !== null); const isBusy = $derived(busy !== null);
const anyConnected = $derived(googleStatus.connected || outlookStatus.connected); const anyConnected = $derived(googleStatus.connected || outlookStatus.connected);
const modalOpen = $derived(showDisconnect || showDeleteEvents); const modalOpen = $derived(showDisconnect || showDeleteEvents);
const modalBusy = $derived( const modalBusy = $derived(showDisconnect ? busy?.phase === "disconnect" : busy?.phase === "delete");
showDisconnect ? busy?.phase === "disconnect" : busy?.phase === "delete",
);
const providerLabel = $derived(calendarProviderLabel(modalProvider ?? "google")); const providerLabel = $derived(calendarProviderLabel(modalProvider ?? "google"));
const showTriggerProgress = $derived( const showTriggerProgress = $derived(
isBusy && isBusy &&
(busy?.phase === "sync" || (busy?.phase === "sync" ||
busy?.phase === "delete" || busy?.phase === "delete" ||
busy?.phase === "disconnect" ||
busy?.phase === "connect" || busy?.phase === "connect" ||
(syncProgress !== null && syncProgress.phase !== "done")), (syncProgress !== null && syncProgress.phase !== "done")),
); );
@@ -93,7 +94,12 @@
}); });
const triggerStatusText = $derived.by(() => { const triggerStatusText = $derived.by(() => {
if (!showTriggerProgress) return "Sync with Calendar"; if (!showTriggerProgress) return "Sync with Calendar";
const verb = busy?.phase === "delete" ? "Deleting" : "Syncing"; const verb =
busy?.phase === "delete"
? "Deleting"
: busy?.phase === "disconnect"
? "Disconnecting"
: "Syncing";
if (syncProgress?.total) return `${verb} ${triggerProgressPercent}%`; if (syncProgress?.total) return `${verb} ${triggerProgressPercent}%`;
return `${verb}…`; return `${verb}…`;
}); });
@@ -102,15 +108,27 @@
return anyConnected ? "Calendar sync options" : "Sync with Calendar"; return anyConnected ? "Calendar sync options" : "Sync with Calendar";
} }
if (syncProgress?.total) { if (syncProgress?.total) {
const verb = busy?.phase === "delete" ? "Deleting" : "Syncing"; const verb =
busy?.phase === "delete"
? "Deleting"
: busy?.phase === "disconnect"
? "Disconnecting"
: "Syncing";
return `Calendar ${verb.toLowerCase()} in progress, ${triggerProgressPercent} percent complete`; return `Calendar ${verb.toLowerCase()} in progress, ${triggerProgressPercent} percent complete`;
} }
return busy?.phase === "delete" if (busy?.phase === "delete") return "Calendar deletion in progress";
? "Calendar deletion in progress" if (busy?.phase === "disconnect") return "Calendar disconnect in progress";
: "Calendar sync in progress"; return "Calendar sync in progress";
}); });
const accent = "var(--bsplus-cal-accent, var(--better-main, #3b82f6))"; const accent = "var(--bsplus-cal-accent, var(--better-main, #3b82f6))";
const overlayProgressPercent = $derived(syncProgressPercent(syncProgress));
const overlayStatusText = $derived.by(() => {
if (busy?.phase === "disconnect") return "Disconnecting account…";
if (syncProgress?.message) return syncProgress.message;
return "Removing synced classes…";
});
function providerPhase(provider: CalendarProvider): BusyPhase { function providerPhase(provider: CalendarProvider): BusyPhase {
return busy?.provider === provider ? busy.phase : null; return busy?.provider === provider ? busy.phase : null;
} }
@@ -225,6 +243,16 @@
} }
} }
async function deleteProviderEvents(provider: CalendarProvider) {
const deleteFn =
provider === "google"
? deleteSyncedEventsFromGoogleCalendar
: deleteSyncedEventsFromOutlookCalendar;
return deleteFn(location.origin, () => getCalendarAccessToken(provider), {
onProgress: handleSyncProgress,
});
}
async function confirmDeleteEvents() { async function confirmDeleteEvents() {
if (isBusy || !modalProvider) return; if (isBusy || !modalProvider) return;
const provider = modalProvider; const provider = modalProvider;
@@ -238,13 +266,7 @@
message: "Preparing removal…", message: "Preparing removal…",
}; };
try { try {
const deleteFn = const result = await deleteProviderEvents(provider);
provider === "google"
? deleteSyncedEventsFromGoogleCalendar
: deleteSyncedEventsFromOutlookCalendar;
const result = await deleteFn(location.origin, () => getCalendarAccessToken(provider), {
onProgress: handleSyncProgress,
});
if (!result.success) { if (!result.success) {
showToastMessage(result.error ?? "Could not remove calendar events.", true); showToastMessage(result.error ?? "Could not remove calendar events.", true);
@@ -279,22 +301,77 @@
await saveSyncSettings({ autoSyncWeekly: checked }); await saveSyncSettings({ autoSyncWeekly: checked });
} }
async function confirmDisconnect() { async function disconnectProvider(
if (isBusy || !modalProvider) return; provider: CalendarProvider,
const provider = modalProvider; label: string,
busy = { provider, phase: "disconnect" }; toastMessage?: string,
const label = calendarProviderLabel(provider); ) {
try {
const result = await disconnectCalendarProvider(provider); const result = await disconnectCalendarProvider(provider);
if (!result?.success) { if (!result?.success) {
showToastMessage(`Could not disconnect ${label} Calendar.`, true); showToastMessage(`Could not disconnect ${label} Calendar.`, true);
return; return false;
} }
setProviderStatus(provider, { connected: false, lastSyncAt: undefined }); setProviderStatus(provider, { connected: false, lastSyncAt: undefined });
showDisconnect = false;
menuOpen = false;
modalProvider = null; modalProvider = null;
showToastMessage(`Disconnected from ${label} Calendar.`); if (toastMessage) showToastMessage(toastMessage);
return true;
}
async function confirmDisconnect(deleteEvents: boolean) {
if (isBusy || !modalProvider) return;
const provider = modalProvider;
const label = calendarProviderLabel(provider);
menuOpen = false;
if (deleteEvents) {
showDisconnect = false;
disconnectOverlay = true;
busy = { provider, phase: "delete" };
syncProgress = {
phase: "preparing",
current: 0,
total: 1,
message: "Preparing removal…",
};
try {
const deleteResult = await deleteProviderEvents(provider);
if (!deleteResult.success) {
showToastMessage(deleteResult.error ?? "Could not remove calendar events.", true);
return;
}
busy = { provider, phase: "disconnect" };
syncProgress = {
phase: "preparing",
current: 0,
total: 1,
message: "Disconnecting account…",
};
const removed = deleteResult.deleted ?? 0;
const toastMessage =
removed > 0
? `Removed ${removed} event${removed === 1 ? "" : "s"} and disconnected from ${label} Calendar.`
: `Disconnected from ${label} Calendar.`;
await disconnectProvider(provider, label, toastMessage);
} catch (err) {
showToastMessage(err instanceof Error ? err.message : "Disconnect failed.", true);
} finally {
syncProgress = null;
busy = null;
disconnectOverlay = false;
}
return;
}
busy = { provider, phase: "disconnect" };
try {
const ok = await disconnectProvider(
provider,
label,
`Disconnected from ${label} Calendar.`,
);
if (ok) showDisconnect = false;
} catch (err) { } catch (err) {
showToastMessage(err instanceof Error ? err.message : "Disconnect failed.", true); showToastMessage(err instanceof Error ? err.message : "Disconnect failed.", true);
} finally { } finally {
@@ -327,6 +404,7 @@
if (themeHost instanceof HTMLElement) syncCalendarSyncTheme(themeHost); if (themeHost instanceof HTMLElement) syncCalendarSyncTheme(themeHost);
if (menuEl) syncCalendarSyncTheme(menuEl); if (menuEl) syncCalendarSyncTheme(menuEl);
if (modalEl) syncCalendarSyncTheme(modalEl); if (modalEl) syncCalendarSyncTheme(modalEl);
if (overlayEl) syncCalendarSyncTheme(overlayEl);
} }
$effect(() => { $effect(() => {
@@ -337,6 +415,20 @@
if (modalOpen && modalEl) syncHostTheme(); if (modalOpen && modalEl) syncHostTheme();
}); });
$effect(() => {
if (disconnectOverlay && overlayEl) syncHostTheme();
});
$effect(() => {
if (!disconnectOverlay) return;
const onBeforeUnload = (event: BeforeUnloadEvent) => {
event.preventDefault();
event.returnValue = "";
};
window.addEventListener("beforeunload", onBeforeUnload);
return () => window.removeEventListener("beforeunload", onBeforeUnload);
});
$effect(() => { $effect(() => {
if (!menuOpen || !triggerEl) return; if (!menuOpen || !triggerEl) return;
updateMenuPosition(); updateMenuPosition();
@@ -579,10 +671,10 @@
Disconnect {providerLabel} Calendar? Disconnect {providerLabel} Calendar?
</h2> </h2>
<p class="bsplus-cal-modal-body"> <p class="bsplus-cal-modal-body">
Stops BetterSEQTA+ from updating your calendar. Synced classes stay in {providerLabel} Calendar Disconnecting normally removes synced classes from {providerLabel} Calendar and signs you out.
until you delete them or connect again. Keep this tab open while that runs. You can also disconnect without deleting your events.
</p> </p>
<div class="bsplus-cal-modal-actions"> <div class="bsplus-cal-modal-actions bsplus-cal-modal-actions--disconnect">
<button <button
type="button" type="button"
class="bsplus-cal-btn bsplus-cal-btn--ghost" class="bsplus-cal-btn bsplus-cal-btn--ghost"
@@ -591,13 +683,21 @@
> >
Cancel Cancel
</button> </button>
<button
type="button"
class="bsplus-cal-btn bsplus-cal-btn--ghost"
disabled={modalBusy}
onclick={() => void confirmDisconnect(false)}
>
{modalBusy ? "Disconnecting…" : "Disconnect without deleting"}
</button>
<button <button
type="button" type="button"
class="bsplus-cal-btn bsplus-cal-btn--danger" class="bsplus-cal-btn bsplus-cal-btn--danger"
disabled={modalBusy} disabled={modalBusy}
onclick={() => void confirmDisconnect()} onclick={() => void confirmDisconnect(true)}
> >
{modalBusy ? "Disconnecting…" : "Disconnect account"} Disconnect & delete classes
</button> </button>
</div> </div>
{:else} {:else}
@@ -631,6 +731,43 @@
</div> </div>
{/if} {/if}
{#if disconnectOverlay}
<div
class="bsplus-cal-disconnect-overlay"
bind:this={overlayEl}
use:portalToBody
role="alertdialog"
aria-modal="true"
aria-labelledby="bsplus-cal-disconnect-title"
aria-describedby="bsplus-cal-disconnect-desc"
transition:fade={{ duration: 150 }}
>
<div class="bsplus-cal-disconnect-card">
<h2 id="bsplus-cal-disconnect-title" class="bsplus-cal-disconnect-title">
Do not close this tab
</h2>
<p id="bsplus-cal-disconnect-desc" class="bsplus-cal-disconnect-body">
Removing synced classes and disconnecting {providerLabel} Calendar. Closing SEQTA now may
leave events behind or interrupt sign-out.
</p>
<div
class="bsplus-cal-disconnect-progress"
role="progressbar"
aria-valuemin="0"
aria-valuemax="100"
aria-valuenow={overlayProgressPercent}
aria-label={overlayStatusText}
>
<span
class="bsplus-cal-disconnect-progress-fill"
style:width="{overlayProgressPercent}%"
></span>
</div>
<p class="bsplus-cal-disconnect-status">{overlayStatusText}</p>
</div>
</div>
{/if}
{#if toast} {#if toast}
<div <div
class="bsplus-cal-toast" class="bsplus-cal-toast"
@@ -1001,9 +1138,81 @@
.bsplus-cal-modal-actions { .bsplus-cal-modal-actions {
display: flex; display: flex;
justify-content: flex-end; justify-content: flex-end;
flex-wrap: wrap;
gap: 8px; gap: 8px;
} }
.bsplus-cal-modal-actions--disconnect {
justify-content: stretch;
}
.bsplus-cal-modal-actions--disconnect .bsplus-cal-btn {
flex: 1 1 auto;
min-width: fit-content;
}
.bsplus-cal-disconnect-overlay {
position: fixed;
inset: 0;
z-index: calc(var(--bsplus-cal-z-modal, 1300) + 1);
display: flex;
align-items: center;
justify-content: center;
padding: 24px;
background: rgba(0, 0, 0, 0.72);
backdrop-filter: blur(6px);
pointer-events: all;
}
.bsplus-cal-disconnect-card {
width: min(100%, 420px);
padding: 24px;
border-radius: 16px;
background: var(--bsplus-cal-surface, #fff);
color: var(--bsplus-cal-text, #111);
border: 1px solid color-mix(in srgb, var(--bsplus-cal-text, #111) 12%, transparent);
box-shadow: 0 24px 48px rgba(0, 0, 0, 0.35);
text-align: center;
}
.bsplus-cal-disconnect-title {
margin: 0 0 8px;
font-size: 20px;
font-weight: 700;
line-height: 1.3;
color: #dc2626;
}
.bsplus-cal-disconnect-body {
margin: 0 0 20px;
font-size: 14px;
line-height: 1.5;
color: color-mix(in srgb, var(--bsplus-cal-text, #111) 78%, transparent);
}
.bsplus-cal-disconnect-progress {
height: 8px;
margin: 0 0 10px;
border-radius: 999px;
overflow: hidden;
background: color-mix(in srgb, var(--bsplus-cal-text, #111) 10%, transparent);
}
.bsplus-cal-disconnect-progress-fill {
display: block;
height: 100%;
border-radius: inherit;
background: var(--bsplus-cal-accent, var(--better-main, #3b82f6));
transition: width 0.25s ease;
}
.bsplus-cal-disconnect-status {
margin: 0;
font-size: 13px;
font-weight: 600;
color: color-mix(in srgb, var(--bsplus-cal-text, #111) 72%, transparent);
}
.bsplus-cal-btn { .bsplus-cal-btn {
padding: 8px 14px; padding: 8px 14px;
border: none; border: none;
@@ -63,7 +63,12 @@ export function portalToBody(node: HTMLElement) {
} }
export function isCalendarSyncModalTarget(target: EventTarget | null): boolean { export function isCalendarSyncModalTarget(target: EventTarget | null): boolean {
return target instanceof Element && Boolean(target.closest(".bsplus-cal-modal-backdrop")); return (
target instanceof Element &&
Boolean(
target.closest(".bsplus-cal-modal-backdrop, .bsplus-cal-disconnect-overlay"),
)
);
} }
/** Sync extension theme (including dark mode) onto a calendar UI host or portaled menu. */ /** Sync extension theme (including dark mode) onto a calendar UI host or portaled menu. */
+17 -7
View File
@@ -13,7 +13,7 @@ import { eventManager } from "@/seqta/utils/listeners/EventManager";
import debounce from "@/seqta/utils/debounce"; import debounce from "@/seqta/utils/debounce";
// UI and theme management // UI and theme management
import { isSeqtaEngageExperience } from "@/seqta/utils/isSeqtaEngage"; import { isSeqtaEngageExperience, isSeqtaLoginPage } from "@/seqta/utils/isSeqtaEngage";
import RegisterClickListeners from "@/seqta/utils/listeners/ClickListeners"; import RegisterClickListeners from "@/seqta/utils/listeners/ClickListeners";
import { AddBetterSEQTAElements } from "@/seqta/ui/AddBetterSEQTAElements"; import { AddBetterSEQTAElements } from "@/seqta/ui/AddBetterSEQTAElements";
import { updateAllColors } from "@/seqta/ui/colors/Manager"; import { updateAllColors } from "@/seqta/ui/colors/Manager";
@@ -509,10 +509,8 @@ function CheckNoticeTextColour(notice: Element) {
noticeColourObserver.observe(notice, { childList: true, subtree: true }); noticeColourObserver.observe(notice, { childList: true, subtree: true });
} }
function watchForEngageLogin() { function watchForLoginDismiss() {
if (!document.querySelector(".login")) { if (!document.querySelector(".login")) return;
return;
}
const observer = new MutationObserver(() => { const observer = new MutationObserver(() => {
if (!document.querySelector(".login")) { if (!document.querySelector(".login")) {
observer.disconnect(); observer.disconnect();
@@ -570,7 +568,7 @@ export function tryLoad() {
const mode = await waitForEngageLoginOrContent(); const mode = await waitForEngageLoginOrContent();
if (mode === "login") { if (mode === "login") {
finishLoad(); finishLoad();
watchForEngageLogin(); watchForLoginDismiss();
return; return;
} }
if (mode === "timeout") { if (mode === "timeout") {
@@ -589,8 +587,15 @@ export function tryLoad() {
return; return;
} }
if (isSeqtaLoginPage()) {
finishLoad();
watchForLoginDismiss();
return;
}
waitForElm(".login").then(() => { waitForElm(".login").then(() => {
finishLoad(); finishLoad();
watchForLoginDismiss();
}); });
waitForElm(".day-container").then(() => { waitForElm(".day-container").then(() => {
@@ -702,6 +707,7 @@ export function init() {
if (settingsState.onoff) { if (settingsState.onoff) {
verboseInfo("[BetterSEQTA+] Enabled"); verboseInfo("[BetterSEQTA+] Enabled");
const onLogin = isSeqtaLoginPage();
if (settingsState.DarkMode) document.documentElement.classList.add("dark"); if (settingsState.DarkMode) document.documentElement.classList.add("dark");
if (settingsState.iconOnlySidebar) { if (settingsState.iconOnlySidebar) {
if (document.body) { if (document.body) {
@@ -713,11 +719,13 @@ export function init() {
} }
} }
if (!onLogin) {
document.querySelector(".legacy-root")?.classList.add("hidden"); document.querySelector(".legacy-root")?.classList.add("hidden");
}
// Learn only: hide native sidebar + mount Svelte replacement during loading. // Learn only: hide native sidebar + mount Svelte replacement during loading.
// Engage keeps its native React menu — never apply the pending hide class there. // Engage keeps its native React menu — never apply the pending hide class there.
if (!isSeqtaEngageExperience()) { if (!onLogin && !isSeqtaEngageExperience()) {
document.documentElement.classList.add("bsplus-custom-sidebar-pending"); document.documentElement.classList.add("bsplus-custom-sidebar-pending");
document.documentElement.classList.add("bsplus-custom-title-pending"); document.documentElement.classList.add("bsplus-custom-title-pending");
void import("@/seqta/ui/sidebar/mountCustomSidebar").then((mod) => { void import("@/seqta/ui/sidebar/mountCustomSidebar").then((mod) => {
@@ -742,7 +750,9 @@ export function init() {
window.addEventListener("hashchange", () => { window.addEventListener("hashchange", () => {
if (settingsState.adaptiveThemeColour) void updateAllColors(); if (settingsState.adaptiveThemeColour) void updateAllColors();
}); });
if (!onLogin) {
loading(); loading();
}
InjectCustomIcons(); InjectCustomIcons();
applyMenuItemVisibility(); applyMenuItemVisibility();
syncTimetableUrlMonitoring(); syncTimetableUrlMonitoring();
+2 -2
View File
@@ -1,7 +1,7 @@
import { mount, unmount } from "svelte"; import { mount, unmount } from "svelte";
import type { SettingsState } from "@/types/storage"; import type { SettingsState } from "@/types/storage";
import { settingsState } from "@/seqta/utils/listeners/SettingsState"; import { settingsState } from "@/seqta/utils/listeners/SettingsState";
import { isSeqtaEngageExperience } from "@/seqta/utils/isSeqtaEngage"; import { isSeqtaEngageExperience, isSeqtaLoginPage } from "@/seqta/utils/isSeqtaEngage";
import { waitForElm } from "@/seqta/utils/waitForElm"; import { waitForElm } from "@/seqta/utils/waitForElm";
import { waitForSeqtaMenu } from "@/seqta/utils/waitForSeqtaShell"; import { waitForSeqtaMenu } from "@/seqta/utils/waitForSeqtaShell";
import Sidebar from "./Sidebar.svelte"; import Sidebar from "./Sidebar.svelte";
@@ -199,7 +199,7 @@ function clearPendingClass() {
* and begin mounting the Svelte sidebar as soon as `#menu` exists. * and begin mounting the Svelte sidebar as soon as `#menu` exists.
*/ */
export function prepareCustomSidebarEarly() { export function prepareCustomSidebarEarly() {
if (isSeqtaEngageExperience()) return; if (isSeqtaEngageExperience() || isSeqtaLoginPage()) return;
if (!settingsState.onoff) return; if (!settingsState.onoff) return;
if (earlyPrepareStarted) return; if (earlyPrepareStarted) return;
+4 -4
View File
@@ -1,6 +1,6 @@
import { mount, unmount } from "svelte"; import { mount, unmount } from "svelte";
import { settingsState } from "@/seqta/utils/listeners/SettingsState"; import { settingsState } from "@/seqta/utils/listeners/SettingsState";
import { isSeqtaEngageExperience } from "@/seqta/utils/isSeqtaEngage"; import { isSeqtaEngageExperience, isSeqtaLoginPage } from "@/seqta/utils/isSeqtaEngage";
import { waitForSeqtaTitle } from "@/seqta/utils/waitForSeqtaShell"; import { waitForSeqtaTitle } from "@/seqta/utils/waitForSeqtaShell";
import TitleBar from "./TitleBar.svelte"; import TitleBar from "./TitleBar.svelte";
import { titleBarState } from "./titleBarState.svelte"; import { titleBarState } from "./titleBarState.svelte";
@@ -46,7 +46,7 @@ function isReady() {
/** finishLoad waits here so the overlay stays until the title bar is ready. */ /** finishLoad waits here so the overlay stays until the title bar is ready. */
export async function waitForCustomTitleBarReady(timeoutMs = 10000) { export async function waitForCustomTitleBarReady(timeoutMs = 10000) {
if (isSeqtaEngageExperience() || !settingsState.onoff) { if (isSeqtaEngageExperience() || isSeqtaLoginPage() || !settingsState.onoff) {
document.documentElement.classList.remove(PENDING_CLASS); document.documentElement.classList.remove(PENDING_CLASS);
return; return;
} }
@@ -85,7 +85,7 @@ function observeHost(host: HTMLElement) {
} }
export function prepareCustomTitleBarEarly() { export function prepareCustomTitleBarEarly() {
if (isSeqtaEngageExperience() || !settingsState.onoff || earlyPrepareStarted) { if (isSeqtaEngageExperience() || isSeqtaLoginPage() || !settingsState.onoff || earlyPrepareStarted) {
return; return;
} }
earlyPrepareStarted = true; earlyPrepareStarted = true;
@@ -94,7 +94,7 @@ export function prepareCustomTitleBarEarly() {
} }
export async function mountCustomTitleBar(): Promise<boolean> { export async function mountCustomTitleBar(): Promise<boolean> {
if (isSeqtaEngageExperience() || !settingsState.onoff) return false; if (isSeqtaEngageExperience() || isSeqtaLoginPage() || !settingsState.onoff) return false;
if (app && titleEl && document.getElementById(ROOT_ID)) { if (app && titleEl && document.getElementById(ROOT_ID)) {
observeHost(titleEl); observeHost(titleEl);
+5
View File
@@ -2,3 +2,8 @@
export function isSeqtaEngageExperience(): boolean { export function isSeqtaEngageExperience(): boolean {
return document.title.includes("SEQTA Engage"); return document.title.includes("SEQTA Engage");
} }
/** Unauthenticated SEQTA login shell (Learn + Engage). */
export function isSeqtaLoginPage(): boolean {
return document.querySelector(".login") !== null;
}