aboutsummaryrefslogtreecommitdiff
path: root/extensions/chrome-profile-bridge/index.ts
diff options
context:
space:
mode:
authorTJ Dong <122852285+tj-dong@users.noreply.github.com>2026-06-08 20:39:14 -0700
committerGitHub <noreply@github.com>2026-06-08 23:39:14 -0400
commitdce772f330db12a73e85297918882c0c4f28f030 (patch)
tree4999c5ade1242bcfefb3dc0c5bc2443b91fcdd70 /extensions/chrome-profile-bridge/index.ts
parent35bebbbb35d4f461ca6d3302294b45d5602eca13 (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.ts38
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];