finishing touches
This commit is contained in:
@@ -50,6 +50,7 @@ const ANTHROPIC_CACHE_TTL_MS = 30 * 60 * 1000;
|
||||
const REFRESH_MS = 5 * 60 * 1000;
|
||||
const PROVIDER_ORDER: ProviderName[] = ["anthropic", "codex", "gemini", "opencode-go"];
|
||||
const SHORTCUT_TOGGLE = "ctrl+alt+b";
|
||||
const SHORTCUT_BAR_STYLE = "ctrl+alt+t";
|
||||
const showToggleState = async (ctx: ExtensionContext, next: boolean, refresh: () => Promise<void>) => {
|
||||
if (!next) {
|
||||
ctx.ui.setWidget("sub-bar-local", undefined);
|
||||
@@ -174,12 +175,14 @@ function pushCodexWindow(windows: RateWindow[], label: string, window?: CodexRat
|
||||
});
|
||||
}
|
||||
|
||||
function barForPercent(theme: Theme, usedPercent: number, width = 8): string {
|
||||
function barForPercent(theme: Theme, usedPercent: number, width = 8, style: "thin" | "thick" = "thick"): string {
|
||||
const safeWidth = Math.max(1, width);
|
||||
const filled = Math.round((clampPercent(usedPercent) / 100) * safeWidth);
|
||||
const empty = Math.max(0, safeWidth - filled);
|
||||
const color = usedPercent >= 85 ? "error" : usedPercent >= 60 ? "warning" : "success";
|
||||
return `${theme.fg(color, "─".repeat(filled))}${theme.fg("dim", "─".repeat(empty))}`;
|
||||
const filledChar = style === "thin" ? "─" : "█";
|
||||
const emptyChar = style === "thin" ? "─" : "░";
|
||||
return `${theme.fg(color, filledChar.repeat(filled))}${theme.fg("dim", emptyChar.repeat(empty))}`;
|
||||
}
|
||||
|
||||
function padToWidth(text: string, width: number): string {
|
||||
@@ -206,6 +209,7 @@ function formatUsageTwoLines(
|
||||
usage: UsageSnapshot,
|
||||
width: number,
|
||||
statusNote?: string,
|
||||
barStyle: "thin" | "thick" = "thick",
|
||||
): { top: string; bottom?: string } {
|
||||
const provider = theme.bold(theme.fg("accent", usage.displayName));
|
||||
if (usage.error && usage.windows.length === 0) {
|
||||
@@ -247,7 +251,7 @@ function formatUsageTwoLines(
|
||||
const bottomCols = usage.windows.map((window, index) => {
|
||||
const colWidth = colWidths[index] ?? 1;
|
||||
const pct = clampPercent(window.usedPercent);
|
||||
return barForPercent(theme, pct, colWidth);
|
||||
return barForPercent(theme, pct, colWidth, barStyle);
|
||||
});
|
||||
|
||||
let top = prefix + topCols.join(gap);
|
||||
@@ -289,12 +293,7 @@ async function fetchAnthropicUsage(): Promise<UsageSnapshot> {
|
||||
if (data.seven_day?.utilization !== undefined) {
|
||||
windows.push({ label: "Week", usedPercent: clampPercent(data.seven_day.utilization), resetAt: data.seven_day.resets_at });
|
||||
}
|
||||
if (data.extra_usage?.is_enabled && data.extra_usage.utilization !== undefined) {
|
||||
const used = data.extra_usage.used_credits ?? 0;
|
||||
const limit = data.extra_usage.monthly_limit;
|
||||
const label = limit && limit > 0 ? `Extra ${used}/${limit}` : `Extra ${used}`;
|
||||
windows.push({ label, usedPercent: clampPercent(data.extra_usage.utilization) });
|
||||
}
|
||||
// hide Anthropic extra_usage window for now (it is confusing/noisy for premium users)
|
||||
if (windows.length === 0) throw new Error("no anthropic usage windows");
|
||||
|
||||
const now = Date.now();
|
||||
@@ -468,6 +467,7 @@ export default function createSubBarLocal(pi: ExtensionAPI) {
|
||||
let lastCtx: ExtensionContext | undefined;
|
||||
let activeProvider: ProviderName | "auto" = "auto";
|
||||
let widgetEnabled = true;
|
||||
let barStyle: "thin" | "thick" = "thick";
|
||||
let refreshTimer: NodeJS.Timeout | undefined;
|
||||
let anthropicRetryAfter = 0;
|
||||
const cache: Partial<Record<ProviderName, ProviderCache>> = {};
|
||||
@@ -515,7 +515,7 @@ export default function createSubBarLocal(pi: ExtensionAPI) {
|
||||
: cooldown
|
||||
? `usage endpoint limited, retry in ${cooldown}`
|
||||
: undefined;
|
||||
const lines = formatUsageTwoLines(theme, snapshot, safeWidth, statusNote);
|
||||
const lines = formatUsageTwoLines(theme, snapshot, safeWidth, statusNote, barStyle);
|
||||
const output = [topDivider, lines.top];
|
||||
if (lines.bottom) output.push(lines.bottom);
|
||||
return output;
|
||||
@@ -648,6 +648,32 @@ export default function createSubBarLocal(pi: ExtensionAPI) {
|
||||
},
|
||||
});
|
||||
|
||||
pi.registerCommand("sub:bars", {
|
||||
description: "Set sub bar style (thin|thick|toggle)",
|
||||
handler: async (args, ctx) => {
|
||||
const raw = String(args ?? "").trim().toLowerCase();
|
||||
if (!raw || raw === "toggle") {
|
||||
barStyle = barStyle === "thin" ? "thick" : "thin";
|
||||
} else if (raw === "thin" || raw === "thick") {
|
||||
barStyle = raw;
|
||||
} else {
|
||||
ctx.ui.notify("invalid style. use: thin|thick|toggle", "warning");
|
||||
return;
|
||||
}
|
||||
ctx.ui.notify(`sub bar style: ${barStyle}`, "info");
|
||||
render(ctx);
|
||||
},
|
||||
});
|
||||
|
||||
pi.registerShortcut(SHORTCUT_BAR_STYLE as import("@mariozechner/pi-tui").KeyId, {
|
||||
description: "Toggle sub bar bar style",
|
||||
handler: async (ctx) => {
|
||||
barStyle = barStyle === "thin" ? "thick" : "thin";
|
||||
ctx.ui.notify(`sub bar style: ${barStyle}`, "info");
|
||||
render(ctx);
|
||||
},
|
||||
});
|
||||
|
||||
pi.on("session_start", async (_event, ctx) => {
|
||||
lastCtx = ctx;
|
||||
if (!ctx.hasUI) return;
|
||||
@@ -660,11 +686,7 @@ export default function createSubBarLocal(pi: ExtensionAPI) {
|
||||
if (!ctx.hasUI) return;
|
||||
render(ctx);
|
||||
if (activeProvider === "auto") {
|
||||
if (getSelectedProvider(ctx) === "anthropic") {
|
||||
render(ctx);
|
||||
} else {
|
||||
await refreshCurrent(ctx, false);
|
||||
}
|
||||
await refreshCurrent(ctx, false);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user