fix(tui): stop registering one resize listener per transcript row (#43562)
This commit is contained in:
@@ -121,7 +121,14 @@ const TRANSCRIPT_BACKFILL_CHUNK = 60
|
||||
type PendingAction = "steer" | "queue" | "cancel"
|
||||
|
||||
const context = createContext<{
|
||||
/** Content width: terminal width minus vertical tabs, sidebar, and padding. */
|
||||
width: number
|
||||
/**
|
||||
* Shared reactive terminal size. Transcript-row components must read this
|
||||
* instead of calling useTerminalDimensions(), which registers one renderer
|
||||
* resize listener per mounted component and grows with transcript length.
|
||||
*/
|
||||
terminal: { width: number; height: number }
|
||||
sessionID: string
|
||||
thinkingMode: () => ThinkingMode
|
||||
showThinking: () => boolean
|
||||
@@ -1124,12 +1131,25 @@ export function Session(props: { verticalTabsWidth: number }) {
|
||||
),
|
||||
)
|
||||
|
||||
// Memoized per axis so width readers do not re-run on height-only resizes
|
||||
// (dimensions() is one object signal with identity equality) and vice versa.
|
||||
const terminalWidth = createMemo(() => dimensions().width)
|
||||
const terminalHeight = createMemo(() => dimensions().height)
|
||||
|
||||
return (
|
||||
<context.Provider
|
||||
value={{
|
||||
get width() {
|
||||
return contentWidth()
|
||||
},
|
||||
terminal: {
|
||||
get width() {
|
||||
return terminalWidth()
|
||||
},
|
||||
get height() {
|
||||
return terminalHeight()
|
||||
},
|
||||
},
|
||||
sessionID: route.sessionID,
|
||||
thinkingMode,
|
||||
showThinking,
|
||||
@@ -1805,7 +1825,6 @@ function AssistantFooter(props: { message: SessionMessageAssistant }) {
|
||||
const ctx = use()
|
||||
const data = useData()
|
||||
const local = useLocal()
|
||||
const dimensions = useTerminalDimensions()
|
||||
const theme = useTheme("elevated")
|
||||
const model = createMemo(
|
||||
() =>
|
||||
@@ -1829,10 +1848,10 @@ function AssistantFooter(props: { message: SessionMessageAssistant }) {
|
||||
<span style={{ fg: props.message.error ? theme.text.subdued : local.agent.color(props.message.agent) }}>
|
||||
{Locale.titlecase(props.message.agent)}
|
||||
</span>
|
||||
<Show when={dimensions().width >= 28}>
|
||||
<Show when={ctx.terminal.width >= 28}>
|
||||
<span style={{ fg: theme.text.subdued }}> · {model()}</span>
|
||||
</Show>
|
||||
<Show when={duration() && (dimensions().width < 28 || dimensions().width >= 36)}>
|
||||
<Show when={duration() && (ctx.terminal.width < 28 || ctx.terminal.width >= 36)}>
|
||||
<span style={{ fg: theme.text.subdued }}> · {Locale.duration(duration())}</span>
|
||||
</Show>
|
||||
<Show when={interrupted()}>
|
||||
@@ -2521,9 +2540,8 @@ function ToolImages(props: { parts: readonly SessionMessageAssistantTool[] }) {
|
||||
function SessionImages(props: { images: readonly { uri: string }[]; paddingLeft?: number }) {
|
||||
const ctx = use()
|
||||
const dialog = useDialog()
|
||||
const dimensions = useTerminalDimensions()
|
||||
const images = createMemo(() => (ctx.config.session?.image_preview ? props.images : []))
|
||||
const height = createMemo(() => Math.max(4, Math.min(8, Math.floor(dimensions().height / 4))))
|
||||
const height = createMemo(() => Math.max(4, Math.min(8, Math.floor(ctx.terminal.height / 4))))
|
||||
const visible = createMemo(() => images().slice(0, 3))
|
||||
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user