|
tui: theme repaцвет chat + bounded history + tail purge (Etap 4)
- apply_theme now re-renders already-drawn chat bubbles in the new palette: ChatPanel.refresh_content() rebuilds each visible item's rich renderable (the item renderers read get_active_theme(), already switched) and drops the per-widget Content/height caches so the next paint rebuilds instead of returning the old-theme cached Content. Theme switch / live preview no longer leaves the conversation in the previous palette (5.B1). - theme_picker live preview is debounced (~100 ms coalesce via set_timer): apply_theme now re-renders every bubble, so applying it on every highlight while scrolling the theme list would stutter — rapid moves collapse into one apply, with the freshest theme winning. Escape/cancel dismiss the pending timer so it cannot fire after a restore and re-apply the highlighted theme over the restored one (4.P2). - ChatModel.items is now bounded: a cap (visible window * 3) trims the oldest items off the front via a single _append/_trim path, so a long autonomous session no longer grows items without limit. The visible window is much smaller than the cap, so trimming only drops already-off-screen items and the truncation hint still reads correctly (3.P3). - stream_end purges empty assistant/thinking bubbles off the tail (while-pop) instead of a full-history list-comprehension copy — empty bubbles are created at the end of the turn, so O(tail) suffices (1.P1). Tests: apply_theme re-renders bubbles; theme picker debounces + escape cancels; chat_model cap trims front / cap=None keeps everything; stream_end keeps non-empty assistant + purges trailing empty thinking. Full suite: 946 passed, 1 skipped. |
|---|
|
|
| clients/terminal/tui/chat_model.py |
|---|
| clients/terminal/tui/screens/theme_picker.py |
|---|
| clients/terminal/tui/tui_app.py |
|---|
| clients/terminal/tui/widgets/chat_panel.py |
|---|
| tests/clients/test_chat_panel.py |
|---|
| tests/clients/test_tui_themes.py |
|---|