haiku.rag/haiku_rag_slim/haiku/rag/chat/widgets/context_modal.py
2026-02-20 16:37:16 +02:00

95 lines
2.5 KiB
Python

from textual.app import ComposeResult
from textual.binding import Binding
from textual.containers import Horizontal, Vertical, VerticalScroll
from textual.screen import ModalScreen
from textual.widgets import Button, Markdown, Static
class ContextModal(ModalScreen):
"""Modal screen for viewing session Q&A history."""
BINDINGS = [
Binding("escape", "cancel", "Close", show=False),
Binding("ctrl+o", "cancel", "Close", show=False),
]
CSS = """
ContextModal {
align: center middle;
background: rgba(0, 0, 0, 0.5);
}
#context-container {
width: 70;
height: auto;
max-height: 32;
background: $surface;
border: tall $primary;
padding: 1 2;
}
#context-header {
height: auto;
margin-bottom: 1;
}
#context-description {
height: auto;
margin-bottom: 1;
color: $text-muted;
}
#context-content {
height: 1fr;
max-height: 16;
scrollbar-gutter: stable;
}
#button-row {
height: auto;
margin-top: 1;
align: right middle;
}
#button-row Button {
margin-left: 1;
min-width: 10;
}
"""
def __init__(self, qa_history: list | None = None) -> None:
super().__init__()
self._qa_history = qa_history or []
def compose(self) -> ComposeResult:
with Vertical(id="context-container"):
yield Static("[bold]Session Context[/bold]", id="context-header")
yield Static(
"Questions and answers from this session.",
id="context-description",
)
with VerticalScroll(id="context-content"):
yield Markdown(self._get_content())
with Horizontal(id="button-row"):
yield Button("Close", id="cancel-btn", variant="primary")
def _get_content(self) -> str:
if not self._qa_history:
return "*No questions asked yet.*"
parts = []
for entry in self._qa_history:
q = getattr(entry, "question", str(entry))
a = getattr(entry, "answer", "")
parts.append(f"**Q:** {q}\n\n**A:** {a}")
return "\n\n---\n\n".join(parts)
def on_button_pressed(self, event: Button.Pressed) -> None:
"""Handle button presses."""
if event.button.id == "cancel-btn":
self.action_cancel()
def action_cancel(self) -> None:
"""Cancel and close."""
self.app.pop_screen()