Skip to content

Commit

Permalink
Implement ConfirmCallback for InputComponent
Browse files Browse the repository at this point in the history
  • Loading branch information
TheRealLorenz committed Nov 3, 2023
1 parent 0568380 commit 73099ef
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 57 deletions.
2 changes: 1 addition & 1 deletion rq-cli/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ impl App {

handle_requests(req_rx, res_tx);

let responses = std::iter::repeat(ResponsePanel::default())
let responses = std::iter::repeat_with(ResponsePanel::default)
.take(http_file.requests.len())
.collect();

Expand Down
40 changes: 35 additions & 5 deletions rq-cli/src/components/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,39 @@ use super::BlockComponent;

const INPUT_KEYMAPS: &[(&str, &str); 2] = &[("Enter", "Confirm"), ("Esc", "Cancel")];

impl BlockComponent for Input {
type ConfirmCallback = Box<dyn Fn(&str) -> anyhow::Result<()>>;

#[derive(Default)]
pub struct InputComponent {
input: Input,
confirm_callback: Option<ConfirmCallback>,
}

impl InputComponent {
pub fn with_confirm_callback(self, confirm_callback: ConfirmCallback) -> Self {
Self {
confirm_callback: Some(confirm_callback),
..self
}
}
}

impl InputComponent {
pub fn confirm(&self) -> super::HandleResult {
if let Some(callback) = self.confirm_callback.as_ref() {
callback(self.input.value())?
}

Ok(super::HandleSuccess::Consumed)
}
}

impl BlockComponent for InputComponent {
fn on_event(&mut self, key_event: crossterm::event::KeyEvent) -> super::HandleResult {
match self.handle_event(&crossterm::event::Event::Key(key_event)) {
match self
.input
.handle_event(&crossterm::event::Event::Key(key_event))
{
Some(_) => Ok(super::HandleSuccess::Consumed),
None => Ok(super::HandleSuccess::Ignored),
}
Expand All @@ -24,7 +54,7 @@ impl BlockComponent for Input {
area: ratatui::prelude::Rect,
block: ratatui::widgets::Block,
) {
let p = Paragraph::new(self.value());
let p = Paragraph::new(self.input.value());
let [main_area, legend_area] = {
let x = Layout::default()
.direction(Direction::Vertical)
Expand All @@ -33,7 +63,7 @@ impl BlockComponent for Input {

[x[0], x[1]]
};
let scroll = self.visual_scroll(main_area.width as usize);
let scroll = self.input.visual_scroll(main_area.width as usize);
let legend = Legend::from(
INPUT_KEYMAPS
.iter()
Expand All @@ -47,7 +77,7 @@ impl BlockComponent for Input {

frame.set_cursor(
// Put cursor past the end of the input text
main_area.x + ((self.visual_cursor()).max(scroll) - scroll) as u16 + 1,
main_area.x + ((self.input.visual_cursor()).max(scroll) - scroll) as u16 + 1,
// Move one line down, from the border to the input line
main_area.y + 1,
)
Expand Down
91 changes: 40 additions & 51 deletions rq-cli/src/components/response_panel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ use ratatui::{
};
use rq_core::request::{Response, StatusCode};
use std::fmt::Write;
use tui_input::Input;

use super::{
input::InputComponent,
message_dialog::{Message, MessageDialog},
popup::Popup,
BlockComponent, HandleResult, HandleSuccess,
Expand All @@ -22,30 +22,19 @@ enum Content {
Empty,
}

#[derive(Clone, Default)]
enum SaveMode {
#[default]
All,
Body,
}

#[derive(Clone, Default)]
#[derive(Default)]
pub struct ResponsePanel {
content: Content,
scroll: u16,
last_input: Option<String>,
input_popup: Option<Popup<Input>>,
save_mode: SaveMode,
input_popup: Option<Popup<InputComponent>>,
}

impl From<Response> for ResponsePanel {
fn from(value: Response) -> Self {
Self {
content: Content::Response(value),
scroll: 0,
last_input: None,
input_popup: None,
save_mode: SaveMode::All,
}
}
}
Expand All @@ -59,32 +48,6 @@ impl ResponsePanel {
self.scroll = self.scroll.saturating_sub(1);
}

fn get_last_input(&self) -> Option<&str> {
self.last_input
.as_ref()
.and_then(|s| if s.is_empty() { None } else { Some(s.as_str()) })
}

fn save_to_file(&mut self) -> anyhow::Result<()> {
let path = self.get_last_input().ok_or(anyhow!("Empty filename"))?;

std::fs::write(path, self.to_string()?)?;

MessageDialog::push_message(Message::Info(format!("Response saved to {}", path)));

Ok(())
}

fn save_body_to_file(&mut self) -> anyhow::Result<()> {
let path = self.get_last_input().ok_or(anyhow!("Empty filename"))?;

std::fs::write(path, self.body()?)?;

MessageDialog::push_message(Message::Info(format!("Response body saved to {}", path)));

Ok(())
}

fn body(&self) -> anyhow::Result<String> {
match &self.content {
Content::Response(response) => Ok(response.body.clone()),
Expand Down Expand Up @@ -125,18 +88,12 @@ impl BlockComponent for ResponsePanel {

match key_event.code {
KeyCode::Enter => {
self.last_input = Some(input_popup.value().into());
input_popup.confirm()?;
self.input_popup = None;

match self.save_mode {
SaveMode::All => self.save_to_file()?,
SaveMode::Body => self.save_body_to_file()?,
}

return Ok(HandleSuccess::Consumed);
}
KeyCode::Esc => {
self.last_input = None;
self.input_popup = None;

return Ok(HandleSuccess::Consumed);
Expand All @@ -149,12 +106,44 @@ impl BlockComponent for ResponsePanel {
KeyCode::Down | KeyCode::Char('j') => self.scroll_down(),
KeyCode::Up | KeyCode::Char('k') => self.scroll_up(),
KeyCode::Char('s') => {
self.save_mode = SaveMode::Body;
self.input_popup = Some(Popup::new(Input::new("".into())));
self.input_popup = {
let body = self.body()?;

let input = InputComponent::default().with_confirm_callback(Box::new(
move |path: &str| {
std::fs::write(path, body.clone())?;

MessageDialog::push_message(Message::Info(format!(
"Response body saved to {}",
path
)));

Ok(())
},
));

Some(Popup::new(input))
}
}
KeyCode::Char('S') => {
self.save_mode = SaveMode::All;
self.input_popup = Some(Popup::new(Input::new("".into())));
self.input_popup = {
let request = self.to_string()?;

let input = InputComponent::default().with_confirm_callback(Box::new(
move |path: &str| {
std::fs::write(path, request.clone())?;

MessageDialog::push_message(Message::Info(format!(
"Response saved to {}",
path
)));

Ok(())
},
));

Some(Popup::new(input))
}
}
_ => return Ok(HandleSuccess::Ignored),
};
Expand Down

0 comments on commit 73099ef

Please sign in to comment.