Moving to Rust 1.87 introduced a clippy warning that `SendError<AppEvent>` was too large. In practice, the only thing we ever did when we got this error was log it (if the mspc channel is closed, then the app is likely shutting down or something, so there's not much to do...), so this finally motivated me to introduce `AppEventSender`, which wraps `std::sync::mpsc::Sender<AppEvent>` with a `send()` method that invokes `send()` on the underlying `Sender` and logs an `Err` if it gets one. This greatly simplifies the code, as many functions that previously returned `Result<(), SendError<AppEvent>>` now return `()`, so we don't have to propagate an `Err` all over the place that we don't really handle, anyway. This also makes it so we can upgrade to Rust 1.87 in CI.
66 lines
1.9 KiB
Rust
66 lines
1.9 KiB
Rust
use crossterm::event::KeyEvent;
|
|
use ratatui::buffer::Buffer;
|
|
use ratatui::layout::Rect;
|
|
use ratatui::widgets::WidgetRef;
|
|
|
|
use crate::app_event_sender::AppEventSender;
|
|
use crate::user_approval_widget::ApprovalRequest;
|
|
use crate::user_approval_widget::UserApprovalWidget;
|
|
|
|
use super::BottomPane;
|
|
use super::BottomPaneView;
|
|
|
|
/// Modal overlay asking the user to approve/deny a sequence of requests.
|
|
pub(crate) struct ApprovalModalView<'a> {
|
|
current: UserApprovalWidget<'a>,
|
|
queue: Vec<ApprovalRequest>,
|
|
app_event_tx: AppEventSender,
|
|
}
|
|
|
|
impl ApprovalModalView<'_> {
|
|
pub fn new(request: ApprovalRequest, app_event_tx: AppEventSender) -> Self {
|
|
Self {
|
|
current: UserApprovalWidget::new(request, app_event_tx.clone()),
|
|
queue: Vec::new(),
|
|
app_event_tx,
|
|
}
|
|
}
|
|
|
|
pub fn enqueue_request(&mut self, req: ApprovalRequest) {
|
|
self.queue.push(req);
|
|
}
|
|
|
|
/// Advance to next request if the current one is finished.
|
|
fn maybe_advance(&mut self) {
|
|
if self.current.is_complete() {
|
|
if let Some(req) = self.queue.pop() {
|
|
self.current = UserApprovalWidget::new(req, self.app_event_tx.clone());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'a> BottomPaneView<'a> for ApprovalModalView<'a> {
|
|
fn handle_key_event(&mut self, _pane: &mut BottomPane<'a>, key_event: KeyEvent) {
|
|
self.current.handle_key_event(key_event);
|
|
self.maybe_advance();
|
|
}
|
|
|
|
fn is_complete(&self) -> bool {
|
|
self.current.is_complete() && self.queue.is_empty()
|
|
}
|
|
|
|
fn calculate_required_height(&self, area: &Rect) -> u16 {
|
|
self.current.get_height(area)
|
|
}
|
|
|
|
fn render(&self, area: Rect, buf: &mut Buffer) {
|
|
(&self.current).render_ref(area, buf);
|
|
}
|
|
|
|
fn try_consume_approval_request(&mut self, req: ApprovalRequest) -> Option<ApprovalRequest> {
|
|
self.enqueue_request(req);
|
|
None
|
|
}
|
|
}
|