feat: implement Component trait for modular UI components and refactor TUI views to use it
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
//! - `mark_dirty()` di Tick hanya dipanggil jika ada event aktif atau spinner berjalan
|
||||
|
||||
use super::theme::Theme;
|
||||
use crate::components::Component;
|
||||
use ratatui::layout::Rect;
|
||||
use ratatui::style::{Color, Modifier, Style};
|
||||
use ratatui::text::{Line, Span};
|
||||
@@ -14,6 +15,9 @@ use ratatui::widgets::{Block, BorderType, Borders, Paragraph};
|
||||
use ratatui::Frame;
|
||||
use zesdex_domain::core::Role;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct ChatComponent;
|
||||
|
||||
const PREFIX_WIDTH: usize = 15;
|
||||
|
||||
fn role_accent_color(role: &Role) -> Color {
|
||||
@@ -160,14 +164,8 @@ fn render_one_message(
|
||||
lines
|
||||
}
|
||||
|
||||
/// Pre-render hook: update cache secara incremental.
|
||||
///
|
||||
/// Strategi:
|
||||
/// - Cache menyimpan jumlah pesan saat terakhir di-render (`cached_msg_count`)
|
||||
/// - Jika pesan bertambah → hanya render pesan BARU, append ke cache
|
||||
/// - Jika pesan berkurang (eviction) atau width berubah → full rebuild
|
||||
/// - Token count dihitung lazily hanya jika `token_count_dirty`
|
||||
pub fn pre_render_chat(state: &mut crate::state::AppStateRest) {
|
||||
impl Component for ChatComponent {
|
||||
fn pre_render(&mut self, state: &mut crate::state::AppStateRest) {
|
||||
let content_width = state.last_render_width.saturating_sub(PREFIX_WIDTH as u16 + 2);
|
||||
let msg_count = state.transcript_cache.messages.len();
|
||||
let cached_count = state.cached_msg_count;
|
||||
@@ -220,11 +218,7 @@ pub fn pre_render_chat(state: &mut crate::state::AppStateRest) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Render chat transcript.
|
||||
///
|
||||
/// TIDAK melakukan clone seluruh cache — hanya mengambil slice window
|
||||
/// yang visible (biasanya 30-50 baris) via reference langsung ke cache.
|
||||
pub fn draw_chat(frame: &mut Frame, area: Rect, state: &crate::state::AppStateRest) {
|
||||
fn draw(&mut self, frame: &mut Frame, area: Rect, state: &crate::state::AppStateRest) {
|
||||
let messages = &state.transcript_cache.messages;
|
||||
let scroll_offset = state.scroll.offset;
|
||||
let max_visible = (area.height as usize).saturating_sub(3);
|
||||
@@ -300,6 +294,7 @@ pub fn draw_chat(frame: &mut Frame, area: Rect, state: &crate::state::AppStateRe
|
||||
.style(Style::default().bg(Theme::BG));
|
||||
|
||||
frame.render_widget(paragraph, area);
|
||||
}
|
||||
}
|
||||
|
||||
fn split_spans_into_lines(spans: Vec<Span<'_>>) -> Vec<Line<'_>> {
|
||||
|
||||
Reference in New Issue
Block a user