Skip to content

Commit a124b3e

Browse files
committed
Improve usage banner a lot
1 parent 12794da commit a124b3e

File tree

2 files changed

+43
-17
lines changed

2 files changed

+43
-17
lines changed

cli/src/components/usage-banner.tsx

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { useTheme } from '../hooks/use-theme'
1212
import { usageQueryKeys, useUsageQuery } from '../hooks/use-usage-query'
1313
import { WEBSITE_URL } from '../login/constants'
1414
import { useChatStore } from '../state/chat-store'
15-
import { formatResetTime } from '../utils/time-format'
15+
import { formatResetTime, formatResetTimeLong } from '../utils/time-format'
1616
import {
1717
getBannerColorLevel,
1818
generateLoadingBannerText,
@@ -118,48 +118,47 @@ export const UsageBanner = ({ showTime }: { showTime: number }) => {
118118
{/* Strong subscription section - only show if subscribed */}
119119
{hasSubscription && (
120120
<box style={{ flexDirection: 'column', marginBottom: 1 }}>
121-
<text style={{ fg: theme.foreground }}>
122-
{subscriptionData.displayName ?? 'Strong'} subscription
123-
{subscriptionInfo?.tier ? ` · $${subscriptionInfo.tier}/mo` : ''}
124-
{subscriptionInfo?.billingPeriodEnd
125-
? ` · Renews ${formatRenewalDate(subscriptionInfo.billingPeriodEnd)}`
126-
: ''}
127-
</text>
121+
<box style={{ flexDirection: 'row', gap: 1 }}>
122+
<text style={{ fg: theme.foreground }}>
123+
{subscriptionData.displayName ?? 'Strong'} subscription
124+
</text>
125+
{subscriptionInfo?.tier && (
126+
<text style={{ fg: theme.muted }}>${subscriptionInfo.tier}/mo</text>
127+
)}
128+
</box>
128129
{isSubscriptionLoading ? (
129130
<text style={{ fg: theme.muted }}>Loading subscription data...</text>
130131
) : rateLimit ? (
131132
<box style={{ flexDirection: 'column', gap: 0 }}>
132133
{/* Block progress - show if there's an active block */}
133134
{rateLimit.blockLimit != null && rateLimit.blockUsed != null && (
134135
<box style={{ flexDirection: 'row', alignItems: 'center', gap: 1 }}>
135-
<text style={{ fg: theme.muted }}>
136-
{subscriptionData.displayName ?? 'Strong'}:
137-
</text>
136+
<text style={{ fg: theme.muted }}>5h limit: </text>
138137
<ProgressBar
139138
value={Math.max(0, 100 - Math.round((rateLimit.blockUsed / rateLimit.blockLimit) * 100))}
140139
width={12}
141140
showPercentage={false}
142141
/>
143142
<text style={{ fg: theme.muted }}>
144-
{Math.round((rateLimit.blockUsed / rateLimit.blockLimit) * 100)}% used
143+
{Math.max(0, 100 - Math.round((rateLimit.blockUsed / rateLimit.blockLimit) * 100))}% remaining
145144
</text>
146145
{rateLimit.blockResetsAt && (
147146
<text style={{ fg: theme.muted }}>
148-
(resets in {formatResetTime(new Date(rateLimit.blockResetsAt))})
147+
· resets in {formatResetTime(new Date(rateLimit.blockResetsAt))}
149148
</text>
150149
)}
151150
</box>
152151
)}
153152
{/* Weekly progress */}
154153
<box style={{ flexDirection: 'row', alignItems: 'center', gap: 1 }}>
155-
<text style={{ fg: theme.muted }}>Week: </text>
154+
<text style={{ fg: theme.muted }}>Weekly limit:</text>
156155
<ProgressBar
157156
value={100 - rateLimit.weeklyPercentUsed}
158157
width={12}
159158
showPercentage={false}
160159
/>
161160
<text style={{ fg: theme.muted }}>
162-
{rateLimit.weeklyPercentUsed}% used · Resets {formatRenewalDate(rateLimit.weeklyResetsAt)}
161+
{100 - rateLimit.weeklyPercentUsed}% remaining · resets in {formatResetTimeLong(rateLimit.weeklyResetsAt)}
163162
</text>
164163
</box>
165164
</box>
@@ -177,14 +176,14 @@ export const UsageBanner = ({ showTime }: { showTime: number }) => {
177176
{/* Main stats row */}
178177
<box style={{ flexDirection: 'row', flexWrap: 'wrap', gap: 1 }}>
179178
<text style={{ fg: theme.muted }}>Session:</text>
180-
<text style={{ fg: theme.foreground }}>{sessionCreditsUsed.toLocaleString()}</text>
179+
<text style={{ fg: theme.foreground }}>{sessionCreditsUsed.toLocaleString()} credits</text>
181180
<text style={{ fg: theme.muted }}>·</text>
182181
<text style={{ fg: theme.muted }}>Remaining:</text>
183182
{isLoadingData ? (
184183
<text style={{ fg: theme.muted }}>...</text>
185184
) : (
186185
<text style={{ fg: theme.foreground }}>
187-
{activeData.remainingBalance?.toLocaleString() ?? '?'}
186+
{activeData.remainingBalance?.toLocaleString() ?? '?'} credits
188187
</text>
189188
)}
190189
{adCredits != null && adCredits > 0 && (

cli/src/utils/time-format.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,30 @@ export const formatResetTime = (resetDate: Date | null): string => {
1818
}
1919
return `${diffMins}m`
2020
}
21+
22+
/**
23+
* Format time until reset in human-readable form, including days
24+
* @param resetDate - The date when the quota/resource resets
25+
* @returns Human-readable string like "4d 7h" or "2h 30m"
26+
*/
27+
export const formatResetTimeLong = (resetDate: Date | string | null): string => {
28+
if (!resetDate) return ''
29+
const date = typeof resetDate === 'string' ? new Date(resetDate) : resetDate
30+
const now = new Date()
31+
const diffMs = date.getTime() - now.getTime()
32+
if (diffMs <= 0) return 'now'
33+
34+
const diffMins = Math.floor(diffMs / (1000 * 60))
35+
const diffHours = Math.floor(diffMins / 60)
36+
const diffDays = Math.floor(diffHours / 24)
37+
const remainingHours = diffHours % 24
38+
const remainingMins = diffMins % 60
39+
40+
if (diffDays > 0) {
41+
return `${diffDays}d ${remainingHours}h`
42+
}
43+
if (diffHours > 0) {
44+
return `${diffHours}h ${remainingMins}m`
45+
}
46+
return `${diffMins}m`
47+
}

0 commit comments

Comments
 (0)