mirror of
https://github.com/openai/codex.git
synced 2026-10-28 18:58:46 +00:00
Cache stable active-cell layout measurements (#38242)
## What changed - Reuse desired and rendered heights for active transcript cells that report a stable height. - Invalidate the cached layout when the cell identity, revision, width, render mode, or syntax theme changes, and when the active cell is removed. - Continue rebuilding display lines on every frame so animated content stays live, while dynamic-height cells bypass the persistent cache. ## Testing - Add rendering tests for height reuse, bottom-anchored overflow, cache invalidation, animated display lines, and dynamic-height cells. GitOrigin-RevId: 414cc4269bfb6b68105837c82e31787272d335a7
This commit is contained in:
@@ -1,12 +1,37 @@
|
||||
//! Transcript and active-cell bookkeeping for `ChatWidget`.
|
||||
|
||||
use super::HistoryCell;
|
||||
use super::HistoryRenderMode;
|
||||
use std::cell::Cell;
|
||||
|
||||
/// Identifies the render state that determines an active cell's viewport height.
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub(super) struct ActiveCellLayoutCacheKey {
|
||||
pub(super) cell_identity: usize,
|
||||
pub(super) revision: u64,
|
||||
pub(super) width: u16,
|
||||
pub(super) render_mode: HistoryRenderMode,
|
||||
pub(super) syntax_theme_revision: u64,
|
||||
}
|
||||
|
||||
/// Retains the active cell's semantic and actual wrapped heights independently.
|
||||
///
|
||||
/// History cells may override their desired height, so it cannot be substituted for the rendered
|
||||
/// row count used to keep overflowing content anchored to the bottom of the viewport.
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub(super) struct ActiveCellLayoutCache {
|
||||
pub(super) key: ActiveCellLayoutCacheKey,
|
||||
pub(super) desired_height: Option<u16>,
|
||||
pub(super) rendered_height: Option<usize>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub(super) struct TranscriptState {
|
||||
pub(super) active_cell: Option<Box<dyn HistoryCell>>,
|
||||
/// Monotonic-ish counter used to invalidate transcript overlay caching.
|
||||
pub(super) active_cell_revision: u64,
|
||||
/// One bounded entry shared by layout and paint across unchanged active-cell frames.
|
||||
pub(super) active_cell_layout: Cell<Option<ActiveCellLayoutCache>>,
|
||||
/// Raw markdown of the most recently completed agent response.
|
||||
pub(super) last_agent_markdown: Option<String>,
|
||||
pub(super) last_completed_agent_message: Option<(String, String)>,
|
||||
@@ -43,6 +68,16 @@ impl TranscriptState {
|
||||
// Wrapping avoids overflow; wraparound would require 2^64 bumps and at
|
||||
// worst causes a one-time cache-key collision.
|
||||
self.active_cell_revision = self.active_cell_revision.wrapping_add(1);
|
||||
self.active_cell_layout.set(None);
|
||||
}
|
||||
|
||||
/// Remove the active cell and invalidate its layout before its address can be reused.
|
||||
pub(super) fn take_active_cell(&mut self) -> Option<Box<dyn HistoryCell>> {
|
||||
let active_cell = self.active_cell.take();
|
||||
if active_cell.is_some() {
|
||||
self.active_cell_layout.set(None);
|
||||
}
|
||||
active_cell
|
||||
}
|
||||
|
||||
pub(super) fn record_agent_markdown(&mut self, markdown: String) {
|
||||
|
||||
Reference in New Issue
Block a user