Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor modals #42

Merged
merged 3 commits into from
Feb 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion tori/src/app/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ impl<'a> App<'a> {
crossterm_event = channel.crossterm_rx.recv() => {
if let Some(ev) = crossterm_event {
let mut state = state.lock().await;
match handle_event(&mut state, ev) {
match handle_event(&mut state, channel.tx.clone(), ev) {
Ok(Some(a)) => channel.tx.send(a).expect("Failed to send action"),
Ok(None) => {}
Err(e) => state.notify_err(e.to_string()),
Expand Down
49 changes: 31 additions & 18 deletions tori/src/app/modal/confirmation_modal.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::{get_modal_chunk, Message, Modal};
use super::{get_modal_chunk, Modal};

use crossterm::event::{Event, KeyCode};
use tui::{
Expand All @@ -8,39 +8,56 @@ use tui::{
widgets::{Block, BorderType, Borders, Clear, Paragraph, Widget},
};

use crate::error::Result;
use crate::{
error::Result,
events::{channel::Tx, Action},
};

/// A confirmation modal box that asks for user yes/no input
#[derive(Debug, Default)]
pub struct ConfirmationModal {
pub struct ConfirmationModal<C> {
title: String,
style: Style,
on_yes: Option<C>,
}

impl ConfirmationModal {
impl<C> ConfirmationModal<C> {
pub fn new(title: &str) -> Self {
Self {
title: format!("\n{} (y/n)", title),
style: Style::default().fg(Color::LightBlue),
on_yes: None,
}
}
}

impl Modal for ConfirmationModal {
fn apply_style(&mut self, style: Style) {
pub fn style(mut self, style: Style) -> Self {
self.style = style;
self
}

fn handle_event(&mut self, event: Event) -> Result<Message> {
pub fn on_yes(mut self, action: C) -> Self {
self.on_yes = Some(action);
self
}
}

impl<C> Modal for ConfirmationModal<C>
where
C: FnOnce() -> Action + Send + Sync,
{
fn handle_event(&mut self, tx: Tx, event: Event) -> Result<Option<Action>> {
use KeyCode::*;
if let Event::Key(event) = event {
return match event.code {
Backspace | Esc | Char('q') | Char('n') | Char('N') => Ok(Message::Quit),
Enter | Char('y') | Char('Y') => Ok(Message::Commit("y".into())),
_ => Ok(Message::Nothing),
};
return Ok(match event.code {
Backspace | Esc | Char('q') | Char('n') | Char('N') => Some(Action::CloseModal),
Enter | Char('y') | Char('Y') => {
tx.send(Action::CloseModal);
self.on_yes.take().map(|f| f())
}
_ => None,
});
}
Ok(Message::Nothing)
Ok(None)
}

fn render(&self, area: Rect, buf: &mut Buffer) {
Expand All @@ -60,8 +77,4 @@ impl Modal for ConfirmationModal {
Clear.render(chunk, buf);
paragraph.render(chunk, buf);
}

fn mode(&self) -> ! {
todo!()
}
}
28 changes: 13 additions & 15 deletions tori/src/app/modal/help_modal.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
use super::{get_modal_chunk, Message, Modal};
use super::Modal;

use crossterm::event::Event;
use tui::{
layout::{Alignment, Constraint},
prelude::*,
style::{Color, Style},
text::{Line, Span},
widgets::{Block, BorderType, Borders, Clear, Paragraph, Row, Table, Widget},
prelude::*,
};
use unicode_width::UnicodeWidthStr;

use crate::{
config::{shortcuts::InputStr, Config},
error::Result,
events::Command,
events::{channel::Tx, Action, Command},
};

/// A modal box that asks for user input
Expand Down Expand Up @@ -60,19 +60,21 @@ impl HelpModal {
}

impl Modal for HelpModal {
fn apply_style(&mut self, _style: Style) {}

fn handle_event(&mut self, event: Event) -> Result<Message> {
fn handle_event(&mut self, tx: Tx, event: Event) -> Result<Option<Action>> {
if let Event::Key(_) = event {
return Ok(Message::Quit);
return Ok(Some(Action::CloseModal));
}
Ok(Message::Nothing)
Ok(None)
}

fn render(&self, area: Rect, buf: &mut Buffer) {
let mut chunk = get_modal_chunk(area);
chunk.y = 3;
chunk.height = area.height.saturating_sub(6);
let width = (area.width / 2).max(70).min(area.width);
let mut chunk = Rect {
x: area.width.saturating_sub(width) / 2,
width,
y: 3,
height: area.height.saturating_sub(6),
};

let block = Block::default()
.title(" Help ")
Expand Down Expand Up @@ -100,8 +102,4 @@ impl Modal for HelpModal {
chunk.height -= 3;
table.render(chunk, buf);
}

fn mode(&self) -> ! {
todo!()
}
}
24 changes: 8 additions & 16 deletions tori/src/app/modal/hotkey_modal.rs
Original file line number Diff line number Diff line change
@@ -1,37 +1,33 @@
use crate::{
config::shortcuts::InputStr,
error::Result,
events::{channel::Tx, Action},
};
use crossterm::event::Event as CrosstermEvent;
use crossterm::event::{Event, KeyCode};
use tui::{
layout::Alignment,
prelude::*,
style::{Color, Style},
widgets::{Block, BorderType, Borders, Clear, Paragraph, Widget},
prelude::*,
};

use super::Modal;

///////////////////////////////
// HotkeyModal //
///////////////////////////////
/// Shows what keys the user is pressing
#[derive(Debug, Default)]
pub struct HotkeyModal {
text: String,
}

impl Modal for HotkeyModal {
fn apply_style(&mut self, _style: Style) {}

fn handle_event(&mut self, event: CrosstermEvent) -> Result<super::Message> {
if let CrosstermEvent::Key(key) = event {
if let crossterm::event::KeyCode::Esc = key.code {
return Ok(super::Message::Quit);
fn handle_event(&mut self, tx: Tx, event: Event) -> Result<Option<Action>> {
if let Event::Key(key) = event {
if let KeyCode::Esc = key.code {
return Ok(Some(Action::CloseModal));
}
self.text = InputStr::from(key).0;
}
Ok(super::Message::Nothing)
Ok(None)
}

fn render(&self, area: Rect, buf: &mut Buffer) {
Expand All @@ -53,8 +49,4 @@ impl Modal for HotkeyModal {
Clear.render(chunk, buf);
paragraph.render(chunk, buf);
}

fn mode(&self) -> ! {
todo!()
}
}
Loading
Loading