Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions src/toad/frame_presentation.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

from agent_comms.nominal.declared_family import DeclaredFamily
from textual._paint_state import PaintState
from textual.geometry import Region
from textual.app import ScreenStackError, UnknownModeError
from textual import events
from textual.strip import Strip
Expand Down Expand Up @@ -537,8 +538,21 @@ def frame_moved(self) -> None:

def redraw(self) -> None:
"""A frame paints over the lines (paint_effects in render_line); the content they
show is unchanged, so it is not rendered again."""
self.repaint_lines()
show is unchanged, so it is not rendered again. Invalidate only the lines the
running effects actually paint; a one-row throbber or a two-row sidebar name
should not flush the styles cache of a 200-line conversation widget."""
if not self.effects:
return
region = self._effect_region()
if region is not None:
self._invalidate_lines(region)
self._repaint_required = True
else:
self.repaint_lines()

def _effect_region(self) -> Region | None:
"""The region the running effects paint, or None for the whole widget."""
return None


class EffectInContent:
Expand Down
7 changes: 7 additions & 0 deletions src/toad/widgets/conversation.py
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,13 @@ def on_mount(self) -> None:
def animation_visible(self) -> bool:
return super().animation_visible and self.query_ancestor(Window).has_focus

def _effect_region(self) -> Region | None:
cursor = self.query_ancestor(Conversation).navigation.cursor
visible = cursor.visible_region
if visible.height == 0:
return Region(0, 0, 1, 0)
return Region(0, visible.y - self.region.y, 1, visible.height)

def render_lines(self, crop: Region) -> list[Strip]:
colours = self.app.colours
strips = [colours.paint_mix(self.RAIL, Strip([Segment("▌")], cell_length=1))] * crop.height
Expand Down
Loading