From 249d1c1b4a16eb12303dfe81392be984696a2bbf Mon Sep 17 00:00:00 2001 From: Aden Linday Date: Mon, 13 Apr 2026 19:39:57 +0930 Subject: [PATCH] feat: auto sync popoup --- src/css/injected.scss | 26 +++++++ .../OpenBsCloudAutoSyncAnnouncement.ts | 71 +++++++++++++++++++ src/seqta/utils/Openers/StartupPopupQueue.ts | 11 ++- src/types/storage.ts | 2 + 4 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 src/seqta/utils/Openers/OpenBsCloudAutoSyncAnnouncement.ts diff --git a/src/css/injected.scss b/src/css/injected.scss index 62a56537..9a92a4a3 100644 --- a/src/css/injected.scss +++ b/src/css/injected.scss @@ -3692,6 +3692,32 @@ div.day-empty { object-position: center; } +.whatsnewHeader.bsCloudAutoSyncAnnouncementHeader { + height: auto; + min-height: unset; +} +.whatsnewHeader.bsCloudAutoSyncAnnouncementHeader h1 { + line-height: 1.2; +} +.bsCloudAccent { + color: #059669; + font-weight: 700; +} +.dark .bsCloudAccent { + color: #34d399; +} +.whatsnewTextContainer .bsCloudAutoSyncSignupCallout { + margin: 1.5rem 0 0; + padding: 1.25rem 1rem 0; + border-top: 1px solid color-mix(in srgb, var(--text-primary) 12%, transparent); + font-size: clamp(1.35rem, 3.8vw, 1.85rem); + font-weight: 800; + line-height: 1.35; + letter-spacing: -0.02em; + text-align: center; + color: var(--text-primary); +} + .popup-media-fullscreenable { cursor: pointer; transition: opacity 0.2s ease-in-out, transform 0.2s ease-in-out; diff --git a/src/seqta/utils/Openers/OpenBsCloudAutoSyncAnnouncement.ts b/src/seqta/utils/Openers/OpenBsCloudAutoSyncAnnouncement.ts new file mode 100644 index 00000000..440e3ca0 --- /dev/null +++ b/src/seqta/utils/Openers/OpenBsCloudAutoSyncAnnouncement.ts @@ -0,0 +1,71 @@ +import stringToHTML from "../stringToHTML"; +import { settingsState } from "../listeners/SettingsState"; +import { openPopup } from "./PopupManager"; +import { attachPopupMediaFullscreen } from "./attachPopupMediaFullscreen"; + +/** Same hosting pattern as the What's New update video (GitHub raw). */ +const BS_CLOUD_DEMO_VIDEO_URL = + "https://raw.githubusercontent.com/BetterSEQTA/BetterSEQTA-Plus/main/src/resources/bsclouddemo.webm"; + +export function shouldShowBsCloudAutoSyncAnnouncement(): boolean { + return !settingsState.bsCloudAutoSyncAnnouncementShown; +} + +/** + * One-time announcement for BetterSEQTA Cloud automatic settings sync (after other startup popups). + * Video layout matches {@link OpenWhatsNewPopup} (`whatsnewImgContainer` / `whatsnewImg`). + */ +export function showBsCloudAutoSyncAnnouncement(onDismissed?: () => void) { + if (document.getElementById("whatsnewbk")) { + onDismissed?.(); + return; + } + if (!shouldShowBsCloudAutoSyncAnnouncement()) { + onDismissed?.(); + return; + } + + const header = stringToHTML( + /* html */ + `
+

BetterSEQTA Cloud

+
`, + ).firstChild as HTMLElement; + + const imageContainer = document.createElement("div"); + imageContainer.classList.add("whatsnewImgContainer"); + + const video = document.createElement("video"); + const source = document.createElement("source"); + source.setAttribute("src", BS_CLOUD_DEMO_VIDEO_URL); + source.setAttribute("type", "video/webm"); + video.autoplay = true; + video.muted = true; + video.loop = true; + video.appendChild(source); + video.classList.add("whatsnewImg"); + imageContainer.appendChild(video); + attachPopupMediaFullscreen(video); + + const text = stringToHTML(/* html */ ` +
+

+ BetterSEQTA Cloud can keep your BetterSEQTA+ settings backed up and in + sync across browsers. Optional automatic settings sync runs when you are signed in (passwords + and tokens are never included). +

+

+ Close this dialog when you are done. We will not show this announcement again. +

+

Sign up in BetterSEQTA settings

+
+ `).firstChild as HTMLElement; + + settingsState.bsCloudAutoSyncAnnouncementShown = true; + + openPopup({ + header, + content: [imageContainer, text], + afterClose: onDismissed, + }); +} diff --git a/src/seqta/utils/Openers/StartupPopupQueue.ts b/src/seqta/utils/Openers/StartupPopupQueue.ts index b29b9e6c..3b05e88b 100644 --- a/src/seqta/utils/Openers/StartupPopupQueue.ts +++ b/src/seqta/utils/Openers/StartupPopupQueue.ts @@ -8,12 +8,17 @@ import { shouldShowEngageParentsAnnouncement, showEngageParentsAnnouncement, } from "./OpenEngageParentsAnnouncement"; +import { + shouldShowBsCloudAutoSyncAnnouncement, + showBsCloudAutoSyncAnnouncement, +} from "./OpenBsCloudAutoSyncAnnouncement"; type QueueStep = (goNext: () => void) => void; /** * Runs startup modals in order: What's New (if the extension just updated), - * privacy statement (if required), then the SEQTA Engage announcement (once). + * privacy statement (if required), SEQTA Engage announcement (once), then BS Cloud + * auto-sync (once, last). */ export function runStartupPopupQueue() { const steps: QueueStep[] = []; @@ -30,6 +35,10 @@ export function runStartupPopupQueue() { steps.push((goNext) => showEngageParentsAnnouncement(goNext)); } + if (shouldShowBsCloudAutoSyncAnnouncement()) { + steps.push((goNext) => showBsCloudAutoSyncAnnouncement(goNext)); + } + function runNext() { const step = steps.shift(); if (step) step(runNext); diff --git a/src/types/storage.ts b/src/types/storage.ts index 5e72c618..adbaf8c9 100644 --- a/src/types/storage.ts +++ b/src/types/storage.ts @@ -34,6 +34,8 @@ export interface SettingsState { privacyStatementLastUpdated?: string; /** One-time announcement: SEQTA Engage support for parents (dismissed popup queue). */ engageParentsAnnouncementShown?: boolean; + /** One-time announcement: BS Cloud automatic settings sync (last in startup popup queue). */ + bsCloudAutoSyncAnnouncementShown?: boolean; timeFormat?: string; animations: boolean; defaultPage: string;