show TOTM popup until dismissed - forgotten commit

i forgot to commit this
basically just shows until dismissed even persistent over reloads so the user doesn't lose it the moment they navigate away or if they load the page and close it immediately
This commit is contained in:
2026-05-29 10:55:55 +09:30
parent 9f263c8c02
commit a23eda1162
4 changed files with 52 additions and 21 deletions
+36
View File
@@ -586,6 +586,41 @@ async function resetThemeOfTheMonthDisabledFor366Upgrade(
}
}
/** 3.7.0: Close no longer marks entries seen — clear legacy dismissal keys. */
const THEME_OF_THE_MONTH_RELOAD_VERSION = "3.7.0";
async function resetThemeOfTheMonthDismissalFor370Upgrade(
previousVersion: string,
): Promise<void> {
try {
const currRaw = browser.runtime.getManifest().version;
const prev = semver.coerce(previousVersion);
const curr = semver.coerce(currRaw);
if (
prev == null ||
curr == null ||
semver.lt(curr, THEME_OF_THE_MONTH_RELOAD_VERSION) ||
!semver.lt(prev, THEME_OF_THE_MONTH_RELOAD_VERSION)
) {
return;
}
await browser.storage.local.set({
themeOfTheMonthLastSeenId: undefined,
themeOfTheMonthDismissedMonth: undefined,
});
console.info(
`[BetterSEQTA+] Migration ${THEME_OF_THE_MONTH_RELOAD_VERSION}: Theme of the Month shows again until dismissed for the month (from ${previousVersion}).`,
);
} catch (e) {
console.warn(
"[BetterSEQTA+] Theme of the Month 3.7.0 dismissal migration failed:",
e,
);
}
}
browser.runtime.onInstalled.addListener(function (event) {
browser.storage.local.remove(["justupdated"]);
browser.storage.local.remove(["data"]);
@@ -597,6 +632,7 @@ browser.runtime.onInstalled.addListener(function (event) {
if (event.reason === "update" && event.previousVersion) {
void migrateGlobalSearchDefaultsFor365Upgrade(event.previousVersion);
void resetThemeOfTheMonthDisabledFor366Upgrade(event.previousVersion);
void resetThemeOfTheMonthDismissalFor370Upgrade(event.previousVersion);
}
});
@@ -45,10 +45,10 @@ export async function fetchThemeOfTheMonth(): Promise<ThemeOfTheMonthEntry | nul
}
}
/** True when we have a new monthly entry the user hasn't dismissed yet. */
/** True when the current month's entry should appear in the startup queue. */
export function shouldShowThemeOfTheMonth(entry: ThemeOfTheMonthEntry | null): boolean {
if (!entry || settingsState.themeOfTheMonthDisabled) return false;
return settingsState.themeOfTheMonthLastSeenId !== entry.id;
return settingsState.themeOfTheMonthDismissedMonth !== entry.month;
}
function escapeHTML(str: string): string {
@@ -108,18 +108,9 @@ async function resolvePopupHeroImageUrl(entry: ThemeOfTheMonthEntry): Promise<st
return fallback || null;
}
function closeThemeOfTheMonthCard(
card: HTMLElement,
onDismissed?: () => void,
markSeen = true,
) {
function closeThemeOfTheMonthCard(card: HTMLElement, onDismissed?: () => void) {
if (card.classList.contains("themeOfTheMonthCardClosing")) return;
if (markSeen) {
const entryId = card.dataset.entryId;
if (entryId) settingsState.themeOfTheMonthLastSeenId = entryId;
}
card.classList.add("themeOfTheMonthCardClosing");
window.setTimeout(() => {
card.remove();
@@ -165,7 +156,7 @@ export async function OpenThemeOfTheMonthPopup(
<div class="themeOfTheMonthCardConfirm" hidden>
<div class="themeOfTheMonthCardConfirmInner">
<h3>Don't show again?</h3>
<p>You can re-enable Theme of the Month from BetterSEQTA+ settings.</p>
<p>You won't see this month's announcement again until next month. Re-enable monthly popups in BetterSEQTA+ settings.</p>
<div class="themeOfTheMonthCardConfirmActions">
<button type="button" class="themeOfTheMonthCardConfirmCancel">Cancel</button>
<button type="button" class="themeOfTheMonthCardConfirmAccept">Don't show again</button>
@@ -175,14 +166,13 @@ export async function OpenThemeOfTheMonthPopup(
</aside>
`).firstChild as HTMLElement;
card.dataset.entryId = entry.id;
const autoCloseTimeout = window.setTimeout(() => {
closeThemeOfTheMonthCard(card, onDismissed);
}, 12000);
const dismiss = (markSeen = true) => {
const dismiss = () => {
window.clearTimeout(autoCloseTimeout);
closeThemeOfTheMonthCard(card, onDismissed, markSeen);
closeThemeOfTheMonthCard(card, onDismissed);
};
card.addEventListener("mouseenter", () => window.clearTimeout(autoCloseTimeout), { once: true });
@@ -216,7 +206,7 @@ export async function OpenThemeOfTheMonthPopup(
});
card.querySelector(".themeOfTheMonthCardConfirmAccept")?.addEventListener("click", () => {
settingsState.themeOfTheMonthDisabled = true;
settingsState.themeOfTheMonthDismissedMonth = entry.month;
dismiss();
});
@@ -225,7 +215,7 @@ export async function OpenThemeOfTheMonthPopup(
/**
* Dev helper: fetch the current month's entry and show the popup immediately,
* even if the user has already dismissed it this month.
* even if the user dismissed it for this calendar month.
*/
export async function showThemeOfTheMonthPopupNow(): Promise<void> {
const entry = await fetchThemeOfTheMonth();
@@ -236,7 +226,7 @@ export async function showThemeOfTheMonthPopupNow(): Promise<void> {
return;
}
settingsState.themeOfTheMonthLastSeenId = undefined;
settingsState.themeOfTheMonthDismissedMonth = undefined;
if (document.getElementById("whatsnewbk")) {
await closePopup();
+1 -1
View File
@@ -15,7 +15,7 @@ type QueueStep = (goNext: () => void) => void;
/**
* Runs startup modals in order: What's New (if the extension just updated),
* Theme of the Month (when a new monthly entry hasn't been seen), then shows
* Theme of the Month (when the user hasn't dismissed this calendar month), then shows
* the SEQTA Engage toast (once, non-blocking).
*/
export async function runStartupPopupQueue() {
+6 -1
View File
@@ -36,7 +36,12 @@ export interface SettingsState {
engageParentsAnnouncementShown?: boolean;
/** One-time announcement: BS Cloud automatic settings sync (last in startup popup queue). */
bsCloudAutoSyncAnnouncementShown?: boolean;
/** ID of the last Theme of the Month entry shown to the user (shows once per new entry). */
/**
* Calendar month (`YYYY-MM`) for which the user dismissed the Theme of the Month
* popup via "Don't show again" (not a normal Close).
*/
themeOfTheMonthDismissedMonth?: string;
/** @deprecated Migrated away; no longer read. */
themeOfTheMonthLastSeenId?: string;
/** Permanently disables Theme of the Month startup prompts. */
themeOfTheMonthDisabled?: boolean;