diff options
| author | TJ Dong <122852285+tj-dong@users.noreply.github.com> | 2026-06-08 20:39:14 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-06-08 23:39:14 -0400 |
| commit | dce772f330db12a73e85297918882c0c4f28f030 (patch) | |
| tree | 4999c5ade1242bcfefb3dc0c5bc2443b91fcdd70 /extensions/chrome-profile-bridge/index.ts | |
| parent | 35bebbbb35d4f461ca6d3302294b45d5602eca13 (diff) | |
feat: show remaining auth time in Chrome Bridge status bar (#5)
* 0.15.36: richer chrome_snapshot + chrome_find/chrome_inspect (ported from foxfirecodes fork)
- chrome_snapshot returns a concise observation (layout, hints, actions, forms,
page map, query matches, diff) with mode/query/maxTextChars params
- new chrome_find (query -> ranked uids) and chrome_inspect (deep element context,
with page.inspect fallback)
- includeSnapshot on click/type/fill/key now embeds the formatted snapshot
- snapshot/inspect logic shipped as eval-free packaged snapshot_injected.js,
sharing window.__PI_CHROME_STATE__ (el- uid scheme) with existing input helpers
* feat: show remaining auth time in Chrome Bridge status bar
Before: ● Chrome Bridge
After: ● Chrome Bridge (14m)
● Chrome Bridge (indefinite)
Changes:
- authCountdownLabel() computes remaining minutes from chromeAuthorizedUntil
- updateChromeStatus appends the label to the status line
- startCountdownTicker() runs setInterval every 60s to refresh the display
while a timed authorization is active; no-ops for indefinite auth
- clearCountdownInterval() called in lockChromeControl and session_shutdown
so no interval leaks on revoke or reload
- scheduleAuthExpiry calls startCountdownTicker so the ticker starts
whenever authorization is granted or restored after /reload
---------
Co-authored-by: Tianren Dong <tianrendong.dtr@gmail.com>
Diffstat (limited to 'extensions/chrome-profile-bridge/index.ts')
| -rw-r--r-- | extensions/chrome-profile-bridge/index.ts | 38 |
1 files changed, 37 insertions, 1 deletions
diff --git a/extensions/chrome-profile-bridge/index.ts b/extensions/chrome-profile-bridge/index.ts index 424b9c1..51d8e26 100644 --- a/extensions/chrome-profile-bridge/index.ts +++ b/extensions/chrome-profile-bridge/index.ts @@ -702,6 +702,7 @@ export default function (pi: ExtensionAPI): void { }; let chromeToolsRegistered = false; let authExpiryTimer: NodeJS.Timeout | undefined; + let countdownInterval: NodeJS.Timeout | undefined; // Remembered so bridge sends can tag tabs with this session's group even when ctx isn't handy. let sessionCtx: ExtensionContext | undefined; @@ -711,6 +712,12 @@ export default function (pi: ExtensionAPI): void { authExpiryTimer = undefined; }; + const clearCountdownInterval = (): void => { + if (!countdownInterval) return; + clearInterval(countdownInterval); + countdownInterval = undefined; + }; + const activeToolNamesWithoutChrome = (): string[] => pi.getActiveTools().filter((name) => !CHROME_TOOL_NAME_SET.has(name)); const activateChromeTools = (): void => { @@ -724,6 +731,7 @@ export default function (pi: ExtensionAPI): void { const lockChromeControl = (): void => { clearAuthExpiryTimer(); + clearCountdownInterval(); chromeAuthorizedUntil = undefined; persistAuth(); deactivateChromeTools(); @@ -759,16 +767,42 @@ export default function (pi: ExtensionAPI): void { return `Pi Session: ${name || id || "unknown"}`; }; + const authCountdownLabel = (): string => { + if (chromeAuthorizedUntil === "indefinite") return " (indefinite)"; + if (typeof chromeAuthorizedUntil === "number") { + const remainingMs = chromeAuthorizedUntil - Date.now(); + if (remainingMs > 0) { + const mins = Math.ceil(remainingMs / 60_000); + return mins >= 1 ? ` (${mins}m)` : " (<1m)"; + } + } + return ""; + }; + const updateChromeStatus = (ctx: ExtensionContext): void => { if (chromeControlAuthorized()) { - ctx.ui.setStatus("chrome", ctx.ui.theme.fg("success", "●") + " Chrome Bridge"); + ctx.ui.setStatus("chrome", ctx.ui.theme.fg("success", "●") + " Chrome Bridge" + authCountdownLabel()); } else { ctx.ui.setStatus("chrome", undefined); } }; + // Ticks every 60 s while a timed authorization is active to keep the countdown current. + const startCountdownTicker = (ctx: ExtensionContext): void => { + clearCountdownInterval(); + if (chromeAuthorizedUntil === "indefinite" || typeof chromeAuthorizedUntil !== "number") return; + countdownInterval = setInterval(() => { + if (!chromeControlAuthorized()) { + clearCountdownInterval(); + return; + } + updateChromeStatus(ctx); + }, 60_000); + }; + const scheduleAuthExpiry = (ctx: ExtensionContext, until: number | "indefinite"): void => { clearAuthExpiryTimer(); + startCountdownTicker(ctx); if (until === "indefinite") return; authExpiryTimer = setTimeout(() => { if (chromeAuthorizedUntil !== until) return; @@ -816,12 +850,14 @@ export default function (pi: ExtensionAPI): void { if (chromeControlAuthorized()) { activateChromeTools(); if (typeof chromeAuthorizedUntil === "number") scheduleAuthExpiry(ctx, chromeAuthorizedUntil); + else if (chromeAuthorizedUntil === "indefinite") startCountdownTicker(ctx); } updateChromeStatus(ctx); }); pi.on("session_shutdown", () => { clearAuthExpiryTimer(); + clearCountdownInterval(); bridge.stop(); if (globalState[PI_CHROME_GLOBAL_KEY]?.token === instanceToken) { delete globalState[PI_CHROME_GLOBAL_KEY]; |
