This commit is contained in:
Matthew Zeng
2026-01-22 09:40:18 -08:00
parent 5d5595ba04
commit 341cb5a8f8

View File

@@ -1,123 +0,0 @@
use crossterm::event::KeyCode;
use crossterm::event::KeyEvent;
use ratatui::buffer::Buffer;
use ratatui::layout::Constraint;
use ratatui::layout::Layout;
use ratatui::layout::Rect;
use ratatui::style::Stylize;
use ratatui::text::Line;
use ratatui::widgets::Block;
use ratatui::widgets::Paragraph;
use ratatui::widgets::Widget;
use textwrap::wrap;
use super::CancellationEvent;
use super::bottom_pane_view::BottomPaneView;
use crate::key_hint;
use crate::render::Insets;
use crate::render::RectExt as _;
use crate::style::user_message_style;
use crate::wrapping::word_wrap_lines;
pub(crate) struct AppLinkView {
title: String,
instructions: String,
url: String,
complete: bool,
}
impl AppLinkView {
pub(crate) fn new(title: String, instructions: String, url: String) -> Self {
Self {
title,
instructions,
url,
complete: false,
}
}
fn content_lines(&self, width: u16) -> Vec<Line<'static>> {
let usable_width = width.max(1) as usize;
let mut lines: Vec<Line<'static>> = Vec::new();
lines.push(Line::from(self.title.clone().bold()));
lines.push(Line::from(""));
let instructions = self.instructions.trim();
if !instructions.is_empty() {
for line in wrap(instructions, usable_width) {
lines.push(Line::from(line.into_owned()));
}
lines.push(Line::from(""));
}
lines.push(Line::from(vec!["Open:".dim()]));
let url_line = Line::from(vec![self.url.clone().cyan().underlined()]);
lines.extend(word_wrap_lines(vec![url_line], usable_width));
lines
}
}
impl BottomPaneView for AppLinkView {
fn handle_key_event(&mut self, key_event: KeyEvent) {
if let KeyEvent {
code: KeyCode::Esc, ..
} = key_event
{
self.on_ctrl_c();
}
}
fn on_ctrl_c(&mut self) -> CancellationEvent {
self.complete = true;
CancellationEvent::Handled
}
fn is_complete(&self) -> bool {
self.complete
}
}
impl crate::render::renderable::Renderable for AppLinkView {
fn desired_height(&self, width: u16) -> u16 {
let content_width = width.saturating_sub(4).max(1);
let content_lines = self.content_lines(content_width);
content_lines.len() as u16 + 3
}
fn render(&self, area: Rect, buf: &mut Buffer) {
if area.height == 0 || area.width == 0 {
return;
}
Block::default()
.style(user_message_style())
.render(area, buf);
let [content_area, hint_area] =
Layout::vertical([Constraint::Fill(1), Constraint::Length(1)]).areas(area);
let inner = content_area.inset(Insets::vh(1, 2));
let content_width = inner.width.max(1);
let lines = self.content_lines(content_width);
Paragraph::new(lines).render(inner, buf);
if hint_area.height > 0 {
let hint_area = Rect {
x: hint_area.x.saturating_add(2),
y: hint_area.y,
width: hint_area.width.saturating_sub(2),
height: hint_area.height,
};
hint_line().dim().render(hint_area, buf);
}
}
}
fn hint_line() -> Line<'static> {
Line::from(vec![
"Press ".into(),
key_hint::plain(KeyCode::Esc).into(),
" to close".into(),
])
}