Skip to content

Commit 07854d1

Browse files
authored
fix(plugins): update subtitle fallback for session status in Claude and Codex plugins and fix about plugin text, replaced home icon with OpenUsage logo (#57)
- Changed subtitle display to show "No active session" when reset information is missing in both Claude and Codex plugins. - Added tests to verify the correct fallback behavior for session subtitles in plugin functionality.
1 parent cfeb157 commit 07854d1

8 files changed

Lines changed: 43 additions & 17 deletions

File tree

plugins/claude/plugin.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@
324324
value: data.five_hour.utilization,
325325
max: 100,
326326
unit: "percent",
327-
subtitle: resetIn ? "Resets in " + resetIn : null
327+
subtitle: resetIn ? "Resets in " + resetIn : "No active session"
328328
}))
329329
}
330330
if (data.seven_day && typeof data.seven_day.utilization === "number") {

plugins/claude/plugin.test.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,25 @@ describe("claude plugin", () => {
6666
expect(result.lines.find((line) => line.label === "Weekly")).toBeTruthy()
6767
})
6868

69+
it("shows fallback subtitle when resets_at is missing", async () => {
70+
const ctx = makeCtx()
71+
ctx.host.fs.readText = () =>
72+
JSON.stringify({ claudeAiOauth: { accessToken: "token", subscriptionType: "pro" } })
73+
ctx.host.fs.exists = () => true
74+
ctx.host.http.request.mockReturnValue({
75+
status: 200,
76+
bodyText: JSON.stringify({
77+
five_hour: { utilization: 0 },
78+
}),
79+
})
80+
81+
const plugin = await loadPlugin()
82+
const result = plugin.probe(ctx)
83+
const sessionLine = result.lines.find((line) => line.label === "Session")
84+
expect(sessionLine).toBeTruthy()
85+
expect(sessionLine.subtitle).toBe("No active session")
86+
})
87+
6988
it("throws token expired on 401", async () => {
7089
const ctx = makeCtx()
7190
ctx.host.fs.readText = () => JSON.stringify({ claudeAiOauth: { accessToken: "token" } })

plugins/codex/plugin.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@
188188
value: headerPrimary,
189189
max: 100,
190190
unit: "percent",
191-
subtitle: resetIn ? "Resets in " + resetIn : null
191+
subtitle: resetIn ? "Resets in " + resetIn : "No active session"
192192
}))
193193
}
194194
if (headerSecondary !== null) {
@@ -210,7 +210,7 @@
210210
value: data.rate_limit.primary_window.used_percent,
211211
max: 100,
212212
unit: "percent",
213-
subtitle: resetIn ? "Resets in " + resetIn : null
213+
subtitle: resetIn ? "Resets in " + resetIn : "No active session"
214214
}))
215215
}
216216
if (data.rate_limit.secondary_window && typeof data.rate_limit.secondary_window.used_percent === "number") {
@@ -243,9 +243,9 @@
243243
const creditsHeader = readNumber(creditsBalance)
244244
const creditsData = data.credits ? readNumber(data.credits.balance) : null
245245
if (creditsHeader !== null) {
246-
lines.push(ctx.line.progress({ label: "Credits", value: creditsHeader, max: 1000 }))
246+
lines.push(ctx.line.progress({ label: "Credits", value: creditsHeader, max: 1000, subtitle: "1,000 credits limit" }))
247247
} else if (creditsData !== null) {
248-
lines.push(ctx.line.progress({ label: "Credits", value: creditsData, max: 1000 }))
248+
lines.push(ctx.line.progress({ label: "Credits", value: creditsData, max: 1000, subtitle: "1,000 credits limit" }))
249249
}
250250

251251
let plan = null

plugins/codex/plugin.test.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ describe("codex plugin", () => {
129129
expect(result.lines.find((line) => line.label === "Credits")).toBeTruthy()
130130
})
131131

132-
it("skips reset lines when window lacks reset info", async () => {
132+
it("shows fallback subtitle when window lacks reset info", async () => {
133133
const ctx = makeCtx()
134134
ctx.host.fs.writeText("~/.codex/auth.json", JSON.stringify({
135135
tokens: { access_token: "token" },
@@ -146,8 +146,9 @@ describe("codex plugin", () => {
146146
})
147147
const plugin = await loadPlugin()
148148
const result = plugin.probe(ctx)
149-
expect(result.lines.find((line) => line.label === "Session")).toBeTruthy()
150-
expect(result.lines.every((line) => !line.subtitle)).toBe(true)
149+
const sessionLine = result.lines.find((line) => line.label === "Session")
150+
expect(sessionLine).toBeTruthy()
151+
expect(sessionLine.subtitle).toBe("No active session")
151152
})
152153

153154
it("uses reset_at when present for subtitles", async () => {

plugins/cursor/plugin.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,8 @@
244244
label: "On-demand",
245245
value: ctx.fmt.dollars(used),
246246
max: ctx.fmt.dollars(limit),
247-
unit: "dollars"
247+
unit: "dollars",
248+
subtitle: "$" + String(ctx.fmt.dollars(limit)) + " limit"
248249
}))
249250
}
250251
}

src/App.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -646,7 +646,7 @@ function App() {
646646
<div ref={containerRef} className="flex flex-col items-center p-6 pt-1.5 bg-transparent">
647647
<div className="tray-arrow" />
648648
<div
649-
className="bg-card rounded-xl overflow-hidden select-none w-full border shadow-lg"
649+
className="relative bg-card rounded-xl overflow-hidden select-none w-full border shadow-lg"
650650
style={maxPanelHeightPx ? { maxHeight: `${maxPanelHeightPx - ARROW_OVERHEAD_PX}px` } : undefined}
651651
>
652652
<div className="flex h-full min-h-0 flex-row">

src/components/about-dialog.tsx

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export function AboutDialog({ version, onClose }: AboutDialogProps) {
3333
useEffect(() => {
3434
const handleKeyDown = (e: KeyboardEvent) => {
3535
if (e.key === "Escape") {
36+
e.preventDefault();
3637
onClose();
3738
}
3839
};
@@ -60,7 +61,7 @@ export function AboutDialog({ version, onClose }: AboutDialogProps) {
6061

6162
return (
6263
<div
63-
className="fixed inset-0 z-50 flex items-center justify-center bg-black/50 backdrop-blur-sm"
64+
className="absolute inset-0 z-50 flex items-center justify-center bg-black/50 backdrop-blur-sm rounded-xl"
6465
onClick={handleBackdropClick}
6566
>
6667
<div className="bg-card rounded-lg border shadow-xl p-6 max-w-xs w-full mx-4 text-center animate-in fade-in zoom-in-95 duration-200">
@@ -81,10 +82,6 @@ export function AboutDialog({ version, onClose }: AboutDialogProps) {
8182
Built by{" "}
8283
<ExternalLink href="https://itsbyrob.in/x">Robin Ebers</ExternalLink>
8384
</p>
84-
<p>
85-
Tray icon can show up to 4 usage bars. Plugins may declare one
86-
primary progress metric.
87-
</p>
8885
<p>
8986
Open source on{" "}
9087
<ExternalLink href="https://github.com/robinebers/openusage">

src/components/side-nav.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
1-
import { Home, Settings } from "lucide-react"
1+
import { Settings } from "lucide-react"
2+
3+
function GaugeIcon({ className }: { className?: string }) {
4+
return (
5+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" className={className}>
6+
<path d="M12 2C17.5228 2 22 6.47715 22 12C22 17.5228 17.5228 22 12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2ZM12 4C7.58172 4 4 7.58172 4 12C4 16.4183 7.58172 20 12 20C16.4183 20 20 16.4183 20 12C20 7.58172 16.4183 4 12 4ZM15.8329 7.33748C16.0697 7.17128 16.3916 7.19926 16.5962 7.40381C16.8002 7.60784 16.8267 7.92955 16.6587 8.16418C14.479 11.2095 13.2796 12.8417 13.0607 13.0607C12.4749 13.6464 11.5251 13.6464 10.9393 13.0607C10.3536 12.4749 10.3536 11.5251 10.9393 10.9393C11.3126 10.5661 12.9438 9.36549 15.8329 7.33748ZM17.5 11C18.0523 11 18.5 11.4477 18.5 12C18.5 12.5523 18.0523 13 17.5 13C16.9477 13 16.5 12.5523 16.5 12C16.5 11.4477 16.9477 11 17.5 11ZM6.5 11C7.05228 11 7.5 11.4477 7.5 12C7.5 12.5523 7.05228 13 6.5 13C5.94772 13 5.5 12.5523 5.5 12C5.5 11.4477 5.94772 11 6.5 11ZM8.81802 7.40381C9.20854 7.79433 9.20854 8.4275 8.81802 8.81802C8.4275 9.20854 7.79433 9.20854 7.40381 8.81802C7.01328 8.4275 7.01328 7.79433 7.40381 7.40381C7.79433 7.01328 8.4275 7.01328 8.81802 7.40381ZM12 5.5C12.5523 5.5 13 5.94772 13 6.5C13 7.05228 12.5523 7.5 12 7.5C11.4477 7.5 11 7.05228 11 6.5C11 5.94772 11.4477 5.5 12 5.5Z" />
7+
</svg>
8+
)
9+
}
210
import { cn } from "@/lib/utils"
311
import { getRelativeLuminance } from "@/lib/color"
412
import { useDarkMode } from "@/hooks/use-dark-mode"
@@ -63,7 +71,7 @@ export function SideNav({ activeView, onViewChange, plugins }: SideNavProps) {
6371
onClick={() => onViewChange("home")}
6472
aria-label="Home"
6573
>
66-
<Home className="size-6" />
74+
<GaugeIcon className="size-6" />
6775
</NavButton>
6876

6977
{/* Plugin icons */}

0 commit comments

Comments
 (0)