Skip to content

Commit 12794da

Browse files
committed
Remove bottom status bar for Strong subscription. Include subscription indicator in message footer
1 parent 07ba6f5 commit 12794da

File tree

3 files changed

+69
-73
lines changed

3 files changed

+69
-73
lines changed

cli/src/chat.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1461,8 +1461,6 @@ export const Chat = ({
14611461
isClaudeConnected={isClaudeOAuthActive}
14621462
isClaudeActive={isClaudeActive}
14631463
claudeQuota={claudeQuota}
1464-
hasSubscription={subscriptionData?.hasSubscription ?? false}
1465-
subscriptionRateLimit={subscriptionData?.rateLimit}
14661464
/>
14671465
</box>
14681466
</box>

cli/src/components/bottom-status-line.tsx

Lines changed: 5 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import { useTheme } from '../hooks/use-theme'
44
import { formatResetTime } from '../utils/time-format'
55

66
import type { ClaudeQuotaData } from '../hooks/use-claude-quota-query'
7-
import type { SubscriptionRateLimit } from '../hooks/use-subscription-query'
87

98
interface BottomStatusLineProps {
109
/** Whether Claude OAuth is connected */
@@ -13,10 +12,6 @@ interface BottomStatusLineProps {
1312
isClaudeActive: boolean
1413
/** Quota data from Anthropic API */
1514
claudeQuota?: ClaudeQuotaData | null
16-
/** Whether the user has an active Codebuff Strong subscription */
17-
hasSubscription: boolean
18-
/** Rate limit data for the subscription */
19-
subscriptionRateLimit?: SubscriptionRateLimit | null
2015
}
2116

2217
/**
@@ -27,8 +22,6 @@ export const BottomStatusLine: React.FC<BottomStatusLineProps> = ({
2722
isClaudeConnected,
2823
isClaudeActive,
2924
claudeQuota,
30-
hasSubscription,
31-
subscriptionRateLimit,
3225
}) => {
3326
const theme = useTheme()
3427

@@ -47,13 +40,8 @@ export const BottomStatusLine: React.FC<BottomStatusLineProps> = ({
4740
: claudeQuota.sevenDayResetsAt
4841
: null
4942

50-
// Show Claude when connected and not depleted (takes priority over Strong)
51-
const showClaude = isClaudeConnected && !isClaudeExhausted
52-
// Show Strong when subscribed AND (no Claude connected OR Claude depleted)
53-
const showStrong = hasSubscription && (!isClaudeConnected || isClaudeExhausted)
54-
55-
// Don't render if there's nothing to show
56-
if (!showClaude && !showStrong && !(isClaudeConnected && isClaudeExhausted)) {
43+
// Only show when Claude is connected
44+
if (!isClaudeConnected) {
5745
return null
5846
}
5947

@@ -64,28 +52,6 @@ export const BottomStatusLine: React.FC<BottomStatusLineProps> = ({
6452
? theme.success
6553
: theme.muted
6654

67-
// Subscription remaining percentage (based on weekly)
68-
const subscriptionRemaining = subscriptionRateLimit
69-
? 100 - subscriptionRateLimit.weeklyPercentUsed
70-
: null
71-
const isSubscriptionLimited = subscriptionRateLimit?.limited === true
72-
73-
// Get subscription reset time
74-
const subscriptionResetTime = subscriptionRateLimit
75-
? subscriptionRateLimit.reason === 'block_exhausted' && subscriptionRateLimit.blockResetsAt
76-
? new Date(subscriptionRateLimit.blockResetsAt)
77-
: subscriptionRateLimit.weeklyResetsAt
78-
? new Date(subscriptionRateLimit.weeklyResetsAt)
79-
: null
80-
: null
81-
82-
// Determine dot color for Strong: red if limited, green if has remaining credits, muted otherwise
83-
const strongDotColor = isSubscriptionLimited
84-
? theme.error
85-
: subscriptionRemaining !== null && subscriptionRemaining > 0
86-
? theme.success
87-
: theme.muted
88-
8955
return (
9056
<box
9157
style={{
@@ -96,8 +62,8 @@ export const BottomStatusLine: React.FC<BottomStatusLineProps> = ({
9662
gap: 2,
9763
}}
9864
>
99-
{/* Show Claude subscription when connected (even when depleted, to show reset time) */}
100-
{isClaudeConnected && !isClaudeExhausted && (
65+
{/* Show Claude subscription when connected and not depleted */}
66+
{!isClaudeExhausted && (
10167
<box
10268
style={{
10369
flexDirection: 'row',
@@ -114,7 +80,7 @@ export const BottomStatusLine: React.FC<BottomStatusLineProps> = ({
11480
)}
11581

11682
{/* Show Claude as depleted when exhausted */}
117-
{isClaudeConnected && isClaudeExhausted && (
83+
{isClaudeExhausted && (
11884
<box
11985
style={{
12086
flexDirection: 'row',
@@ -129,25 +95,6 @@ export const BottomStatusLine: React.FC<BottomStatusLineProps> = ({
12995
)}
13096
</box>
13197
)}
132-
133-
{/* Show Codebuff Strong when subscribed and Claude not healthy */}
134-
{showStrong && (
135-
<box
136-
style={{
137-
flexDirection: 'row',
138-
alignItems: 'center',
139-
gap: 0,
140-
}}
141-
>
142-
<text style={{ fg: strongDotColor }}></text>
143-
<text style={{ fg: theme.muted }}> Codebuff Strong</text>
144-
{isSubscriptionLimited && subscriptionResetTime ? (
145-
<text style={{ fg: theme.muted }}>{` · resets in ${formatResetTime(subscriptionResetTime)}`}</text>
146-
) : subscriptionRemaining !== null ? (
147-
<BatteryIndicator value={subscriptionRemaining} theme={theme} />
148-
) : null}
149-
</box>
150-
)}
15198
</box>
15299
)
153100
}

cli/src/components/message-footer.tsx

Lines changed: 64 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
import { SUBSCRIPTION_DISPLAY_NAME } from '@codebuff/common/constants/subscription-plans'
12
import { pluralize } from '@codebuff/common/util/string'
23
import { TextAttributes } from '@opentui/core'
34
import React, { useCallback, useMemo } from 'react'
45

56
import { CopyButton } from './copy-button'
67
import { ElapsedTimer } from './elapsed-timer'
78
import { FeedbackIconButton } from './feedback-icon-button'
9+
import { useSubscriptionQuery } from '../hooks/use-subscription-query'
810
import { useTheme } from '../hooks/use-theme'
911
import {
1012
useFeedbackStore,
@@ -157,19 +159,7 @@ export const MessageFooter: React.FC<MessageFooterProps> = ({
157159
if (typeof credits === 'number' && credits > 0) {
158160
footerItems.push({
159161
key: 'credits',
160-
node: (
161-
<text
162-
attributes={TextAttributes.DIM}
163-
style={{
164-
wrapMode: 'none',
165-
fg: theme.secondary,
166-
marginTop: 0,
167-
marginBottom: 0,
168-
}}
169-
>
170-
{pluralize(credits, 'credit')}
171-
</text>
172-
),
162+
node: <CreditsOrSubscriptionIndicator credits={credits} />,
173163
})
174164
}
175165
if (shouldRenderFeedbackButton) {
@@ -222,3 +212,64 @@ export const MessageFooter: React.FC<MessageFooterProps> = ({
222212
</box>
223213
)
224214
}
215+
216+
/**
217+
* Shows either subscription indicator or credits count based on subscription status.
218+
* If user has an active subscription with remaining block credits, shows "✓ Strong".
219+
* If block is < 15% remaining, also shows the percentage.
220+
* Otherwise, shows the regular credits count.
221+
*/
222+
const CreditsOrSubscriptionIndicator: React.FC<{ credits: number }> = ({ credits }) => {
223+
const theme = useTheme()
224+
const { data: subscriptionData } = useSubscriptionQuery({
225+
refetchInterval: false, // Don't poll, just use cached data
226+
refetchOnActivity: false,
227+
pauseWhenIdle: false,
228+
})
229+
230+
const hasActiveSubscription = subscriptionData?.hasSubscription === true
231+
const rateLimit = subscriptionData?.rateLimit
232+
const isLimited = rateLimit?.limited === true
233+
234+
// Calculate block remaining percentage
235+
const blockPercentRemaining = useMemo(() => {
236+
if (!rateLimit?.blockLimit || rateLimit.blockUsed == null) return null
237+
const remaining = rateLimit.blockLimit - rateLimit.blockUsed
238+
return Math.round((remaining / rateLimit.blockLimit) * 100)
239+
}, [rateLimit])
240+
241+
// Show subscription indicator if user has active subscription and block is not depleted
242+
const showSubscriptionIndicator = hasActiveSubscription && !isLimited && blockPercentRemaining !== null && blockPercentRemaining > 0
243+
244+
if (showSubscriptionIndicator) {
245+
const showPercentage = blockPercentRemaining < 20
246+
return (
247+
<text
248+
attributes={TextAttributes.DIM}
249+
style={{
250+
wrapMode: 'none',
251+
fg: theme.success,
252+
marginTop: 0,
253+
marginBottom: 0,
254+
}}
255+
>
256+
{showPercentage ? `✓ ${SUBSCRIPTION_DISPLAY_NAME} (${blockPercentRemaining}% left)` : `✓ ${SUBSCRIPTION_DISPLAY_NAME}`}
257+
</text>
258+
)
259+
}
260+
261+
// Default: show credits count
262+
return (
263+
<text
264+
attributes={TextAttributes.DIM}
265+
style={{
266+
wrapMode: 'none',
267+
fg: theme.secondary,
268+
marginTop: 0,
269+
marginBottom: 0,
270+
}}
271+
>
272+
{pluralize(credits, 'credit')}
273+
</text>
274+
)
275+
}

0 commit comments

Comments
 (0)