fix: resizing etc

This commit is contained in:
Brooklyn Nicholson 2026-04-09 00:46:35 -05:00
parent 54bd25ff4a
commit 8755b9dfc0
3 changed files with 36 additions and 28 deletions

View file

@ -1,6 +1,6 @@
import { describe, expect, it } from 'vitest' import { describe, expect, it } from 'vitest'
import { sameToolTrailGroup } from '../lib/text.js' import { fmtK, sameToolTrailGroup } from '../lib/text.js'
describe('sameToolTrailGroup', () => { describe('sameToolTrailGroup', () => {
it('matches bare check lines', () => { it('matches bare check lines', () => {
@ -18,3 +18,19 @@ describe('sameToolTrailGroup', () => {
expect(sameToolTrailGroup('🔍 searching', '🔍 searching extra ✓')).toBe(false) expect(sameToolTrailGroup('🔍 searching', '🔍 searching extra ✓')).toBe(false)
}) })
}) })
describe('fmtK', () => {
it('keeps small numbers plain', () => {
expect(fmtK(999)).toBe('999')
})
it('formats thousands as K', () => {
expect(fmtK(1000)).toBe('1K')
expect(fmtK(1500)).toBe('1.5K')
})
it('formats millions and billions', () => {
expect(fmtK(1_000_000)).toBe('1M')
expect(fmtK(1_000_000_000)).toBe('1B')
})
})

View file

@ -3,7 +3,7 @@ import { mkdtempSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs'
import { tmpdir } from 'node:os' import { tmpdir } from 'node:os'
import { join } from 'node:path' import { join } from 'node:path'
import { Box, Static, Text, useApp, useInput, useStdout } from 'ink' import { Box, Text, useApp, useInput, useStdout } from 'ink'
import { useCallback, useEffect, useRef, useState } from 'react' import { useCallback, useEffect, useRef, useState } from 'react'
import { ActivityLane } from './components/activityLane.js' import { ActivityLane } from './components/activityLane.js'
@ -250,7 +250,6 @@ export function App({ gw }: { gw: GatewayClient }) {
const [sid, setSid] = useState<string | null>(null) const [sid, setSid] = useState<string | null>(null)
const [theme, setTheme] = useState<Theme>(DEFAULT_THEME) const [theme, setTheme] = useState<Theme>(DEFAULT_THEME)
const [info, setInfo] = useState<SessionInfo | null>(null) const [info, setInfo] = useState<SessionInfo | null>(null)
const [introCollapsed, setIntroCollapsed] = useState(false)
const [thinking, setThinking] = useState(false) const [thinking, setThinking] = useState(false)
const [turnKey, setTurnKey] = useState(0) const [turnKey, setTurnKey] = useState(0)
const [activity, setActivity] = useState<ActivityItem[]>([]) const [activity, setActivity] = useState<ActivityItem[]>([])
@ -385,7 +384,6 @@ export function App({ gw }: { gw: GatewayClient }) {
setPastes([]) setPastes([])
setActivity([]) setActivity([])
setBgTasks(new Set()) setBgTasks(new Set())
setIntroCollapsed(false)
setUsage(ZERO) setUsage(ZERO)
lastStatusNoteRef.current = '' lastStatusNoteRef.current = ''
protocolWarnedRef.current = false protocolWarnedRef.current = false
@ -545,7 +543,6 @@ export function App({ gw }: { gw: GatewayClient }) {
inflightPasteIdsRef.current = payload.usedIds inflightPasteIdsRef.current = payload.usedIds
setLastUserMsg(text) setLastUserMsg(text)
setIntroCollapsed(true)
appendMessage({ role: 'user', text }) appendMessage({ role: 'user', text })
setBusy(true) setBusy(true)
setStatus('running…') setStatus('running…')
@ -1683,28 +1680,18 @@ export function App({ gw }: { gw: GatewayClient }) {
return ( return (
<Box flexDirection="column"> <Box flexDirection="column">
<Static items={historyItems}> {historyItems.map((m, i) => (
{(m, i) => (
<Box flexDirection="column" key={i} paddingX={1}> <Box flexDirection="column" key={i} paddingX={1}>
{m.kind === 'intro' && m.info ? ( {m.kind === 'intro' && m.info ? (
<Box flexDirection="column" paddingTop={1}> <Box flexDirection="column" paddingTop={1}>
{introCollapsed ? (
<Text color={theme.color.dim}>
{theme.brand.icon} {theme.brand.name} · {m.info.model.split('/').pop()}
</Text>
) : (
<>
<Banner t={theme} /> <Banner t={theme} />
<SessionPanel info={m.info} sid={sid} t={theme} /> <SessionPanel info={m.info} sid={sid} t={theme} />
</>
)}
</Box> </Box>
) : ( ) : (
<MessageLine cols={cols} compact={compact} msg={m} t={theme} /> <MessageLine cols={cols} compact={compact} msg={m} t={theme} />
)} )}
</Box> </Box>
)} ))}
</Static>
<Box flexDirection="column" paddingX={1}> <Box flexDirection="column" paddingX={1}>
{streaming && ( {streaming && (

View file

@ -80,7 +80,12 @@ export const estimateRows = (text: string, w: number, compact = false) => {
export const flat = (r: Record<string, string[]>) => Object.values(r).flat() export const flat = (r: Record<string, string[]>) => Object.values(r).flat()
export const fmtK = (n: number) => (n >= 1000 ? `${(n / 1000).toFixed(1)}k` : `${n}`) const COMPACT_NUMBER = new Intl.NumberFormat('en-US', {
maximumFractionDigits: 1,
notation: 'compact'
})
export const fmtK = (n: number) => COMPACT_NUMBER.format(n)
export const hasInterpolation = (s: string) => { export const hasInterpolation = (s: string) => {
INTERPOLATION_RE.lastIndex = 0 INTERPOLATION_RE.lastIndex = 0