fix(app): keep usage in context tooltip

This commit is contained in:
Michael Wu
2026-10-03 05:07:06 +09:00
parent 3d686cbba3
commit 90da599662
4 changed files with 46 additions and 12 deletions
@@ -3,6 +3,7 @@ import Svg, { Circle } from "react-native-svg";
import { StyleSheet, useUnistyles } from "react-native-unistyles";
import { useTranslation } from "react-i18next";
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
import { ContextWindowUsageTooltip } from "@/usage/context-window-section";
import { formatContextPercentage, formatTokenCount } from "./context-window-meter.utils";
interface ContextWindowMeterProps {
@@ -10,6 +11,8 @@ interface ContextWindowMeterProps {
usedTokens: number | null;
totalCostUsd?: number | null;
showPercentage?: boolean;
serverId?: string;
agentId?: string;
/** Reserve the meter footprint and show a loading ring while usage is pending. */
pending?: boolean;
/** Optional glyph envelope for icon-toolbar alignment. */
@@ -95,6 +98,8 @@ export function ContextWindowMeter({
usedTokens,
totalCostUsd,
showPercentage = false,
serverId,
agentId,
pending = false,
glyphSize,
}: ContextWindowMeterProps) {
@@ -104,13 +109,9 @@ export function ContextWindowMeter({
maxTokens !== null && usedTokens !== null ? getUsagePercentage(maxTokens, usedTokens) : null;
const geometry = getMeterGeometry(showPercentage, glyphSize);
// No usage yet: reserve the footprint with a track-only ring while a session is
// active so the real ring fades in without shifting siblings. Render nothing when
// no usage is expected.
// No context telemetry yet: reserve the meter footprint while it is pending.
if (percentage === null || maxTokens === null || usedTokens === null) {
if (!pending) {
return null;
}
if (!pending) return null;
return (
<View style={geometry.containerStyle}>
<Svg
@@ -206,6 +207,9 @@ export function ContextWindowMeter({
{t("contextWindow.sessionCost", { cost: formattedSessionCost })}
</Text>
) : null}
{serverId && agentId ? (
<ContextWindowUsageTooltip serverId={serverId} agentId={agentId} />
) : null}
</View>
</TooltipContent>
</Tooltip>
+1 -1
View File
@@ -289,7 +289,7 @@ function renderContextWindowMeter(
glyphSize: number,
): ReactElement | null {
const hasData = contextWindowMaxTokens !== null && contextWindowUsedTokens !== null;
if (!hasData && !pending && !showPercentage) {
if (!hasData && !pending) {
return null;
}
return (
+1 -5
View File
@@ -12,11 +12,7 @@ interface ResolvedBalance {
usedPct: number | null;
}
function resolveBalance(
balance: UsageBalance,
t: TFunction,
locale?: string,
): ResolvedBalance {
function resolveBalance(balance: UsageBalance, t: TFunction, locale?: string): ResolvedBalance {
const { used, remaining, limit, unit } = balance;
const format = (value: number) => formatAmount(value, unit, locale);
if (limit != null && limit > 0) {
@@ -0,0 +1,34 @@
import { View } from "react-native";
import { StyleSheet } from "react-native-unistyles";
import { UsageCard } from "./card";
import { useUsagePreferences } from "./display";
import { useAgentUsage } from "./queries";
/** The active agent's usage inside its context-window tooltip. */
export function ContextWindowUsageTooltip({
serverId,
agentId,
}: {
serverId: string;
agentId: string;
}) {
const { entry } = useAgentUsage(serverId, agentId);
const { display } = useUsagePreferences();
if (!entry) return null;
return (
<>
<View style={styles.divider} />
<UsageCard serverId={serverId} entry={entry} display={display} compact />
</>
);
}
const styles = StyleSheet.create((theme) => ({
divider: {
height: 1,
backgroundColor: theme.colors.borderAccent,
marginVertical: theme.spacing[2],
marginHorizontal: -theme.spacing[2],
},
}));