Show context usage beside compact mode selector
This commit is contained in:
@@ -190,6 +190,7 @@ function renderContextWindowMeter(
|
||||
contextWindowMaxTokens: number | null,
|
||||
contextWindowUsedTokens: number | null,
|
||||
totalCostUsd: number | null,
|
||||
showPercentage: boolean,
|
||||
): ReactElement | null {
|
||||
if (contextWindowMaxTokens === null || contextWindowUsedTokens === null) {
|
||||
return null;
|
||||
@@ -199,6 +200,7 @@ function renderContextWindowMeter(
|
||||
maxTokens={contextWindowMaxTokens}
|
||||
usedTokens={contextWindowUsedTokens}
|
||||
totalCostUsd={totalCostUsd}
|
||||
showPercentage={showPercentage}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -206,13 +208,13 @@ function renderContextWindowMeter(
|
||||
function resolveContextWindowPlacement(
|
||||
meter: ReactElement | null,
|
||||
isMobile: boolean,
|
||||
): { beforeVoiceContent: ReactNode; footerRight: ReactNode } {
|
||||
): { beforeVoiceContent: ReactNode; footerInlineContent: ReactNode } {
|
||||
if (isMobile) {
|
||||
return { beforeVoiceContent: null, footerRight: meter };
|
||||
return { beforeVoiceContent: null, footerInlineContent: meter };
|
||||
}
|
||||
return {
|
||||
beforeVoiceContent: <View style={styles.contextWindowMeterSlot}>{meter}</View>,
|
||||
footerRight: null,
|
||||
footerInlineContent: null,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -238,13 +240,18 @@ interface RenderAttachmentTrayArgs {
|
||||
handleRemoveAttachment: (index: number) => void;
|
||||
}
|
||||
|
||||
function renderComposerFooter(footer: ReactNode, footerRight: ReactNode): ReactElement | null {
|
||||
if (!footer && !footerRight) return null;
|
||||
function renderComposerFooter(
|
||||
footer: ReactNode,
|
||||
footerInlineContent: ReactNode,
|
||||
): ReactElement | null {
|
||||
if (!footer && !footerInlineContent) return null;
|
||||
return (
|
||||
<View style={styles.footer}>
|
||||
<View style={styles.footerContent}>
|
||||
<View style={styles.footerLeft}>{footer}</View>
|
||||
<View style={styles.footerRight}>{footerRight}</View>
|
||||
<View style={styles.footerLeft}>
|
||||
{footer}
|
||||
{footerInlineContent}
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
@@ -1468,10 +1475,11 @@ export function Composer({
|
||||
contextWindowMaxTokens,
|
||||
contextWindowUsedTokens,
|
||||
agentState.totalCostUsd,
|
||||
isMobile,
|
||||
),
|
||||
[contextWindowMaxTokens, contextWindowUsedTokens, agentState.totalCostUsd],
|
||||
[contextWindowMaxTokens, contextWindowUsedTokens, agentState.totalCostUsd, isMobile],
|
||||
);
|
||||
const { beforeVoiceContent, footerRight } = useMemo(
|
||||
const { beforeVoiceContent, footerInlineContent } = useMemo(
|
||||
() => resolveContextWindowPlacement(contextWindowMeter, isMobile),
|
||||
[contextWindowMeter, isMobile],
|
||||
);
|
||||
@@ -1718,7 +1726,7 @@ export function Composer({
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
{renderComposerFooter(footer, footerRight)}
|
||||
{renderComposerFooter(footer, footerInlineContent)}
|
||||
</Animated.View>
|
||||
);
|
||||
}
|
||||
@@ -1782,6 +1790,7 @@ const styles = StyleSheet.create((theme: Theme) => ({
|
||||
flexShrink: 1,
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
gap: theme.spacing[1],
|
||||
// On mobile, cancel the leading glyph's internal padding (chip paddingHorizontal)
|
||||
// so its icon aligns to the composer border before the footer inset is applied.
|
||||
marginLeft: {
|
||||
@@ -1789,17 +1798,6 @@ const styles = StyleSheet.create((theme: Theme) => ({
|
||||
md: 0,
|
||||
},
|
||||
},
|
||||
footerRight: {
|
||||
flexShrink: 0,
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
// On mobile, cancel the trailing glyph's internal inset (28px box around a 16px
|
||||
// ring) so its right edge aligns to the composer border before the footer inset.
|
||||
marginRight: {
|
||||
xs: -6,
|
||||
md: 0,
|
||||
},
|
||||
},
|
||||
messageInputContainer: {
|
||||
position: "relative",
|
||||
width: "100%",
|
||||
|
||||
Reference in New Issue
Block a user