diff --git a/rq-cli/src/app.rs b/rq-cli/src/app.rs index 88e2cf3..08977bf 100644 --- a/rq-cli/src/app.rs +++ b/rq-cli/src/app.rs @@ -267,30 +267,8 @@ impl App { self.responses[self.request_menu.idx()].save_body(&file_name) } }, - Event::NewInput((content, typ)) => { - match typ { - crate::event::InputType::FileName(save_option) => { - self.input_popup = Some( - InputComponent::from(content.as_str()) - .with_cursor(0) - .with_confirm_callback(move |value| { - Event::emit(Event::InputConfirm); - Event::emit(Event::Save((value, save_option))); - }) - .popup(), - ); - } - crate::event::InputType::VarValue(name) => { - self.input_popup = Some( - InputComponent::from(content.as_str()) - .with_confirm_callback(move |value| { - Event::emit(Event::InputConfirm); - Event::emit(Event::UpdateVar((name.clone(), value))); - }) - .popup(), - ); - } - }; + Event::NewInput(builder) => { + self.input_popup = Some(builder.build().popup()); Ok(()) } Event::InputCancel => { diff --git a/rq-cli/src/components/input.rs b/rq-cli/src/components/input.rs index e950aa0..38e7751 100644 --- a/rq-cli/src/components/input.rs +++ b/rq-cli/src/components/input.rs @@ -6,6 +6,8 @@ use crate::event::Event; use super::BlockComponent; +pub mod builder; + type ConfirmCallback = Box; type CancelCallback = Box; @@ -26,21 +28,21 @@ impl Default for InputComponent { } impl InputComponent { - pub fn from(value: &str) -> Self { + fn from(value: &str) -> Self { Self { input: Input::from(value), ..Self::default() } } - pub fn with_cursor(self, cursor: usize) -> Self { + fn with_cursor(self, cursor: usize) -> Self { Self { input: self.input.with_cursor(cursor), ..self } } - pub fn with_confirm_callback(self, confirm_callback: F) -> Self + fn with_confirm_callback(self, confirm_callback: F) -> Self where F: Fn(String) + 'static, { @@ -50,7 +52,7 @@ impl InputComponent { } } - pub fn with_cancel_callback(self, cancel_callback: F) -> Self + fn with_cancel_callback(self, cancel_callback: F) -> Self where F: Fn() + 'static, { diff --git a/rq-cli/src/components/input/builder.rs b/rq-cli/src/components/input/builder.rs new file mode 100644 index 0000000..7d9d911 --- /dev/null +++ b/rq-cli/src/components/input/builder.rs @@ -0,0 +1,59 @@ +use crate::{components::response_panel::SaveOption, event::Event}; + +use super::InputComponent; + +pub struct InputBuilder { + content: String, + cursor: Option, + typ: InputType, +} + +pub enum InputType { + FileName(SaveOption), + VarValue(String), +} + +impl InputBuilder { + pub fn new(typ: InputType) -> Self { + Self { + content: String::new(), + cursor: None, + typ, + } + } + + pub fn with_content(self, content: String) -> Self { + Self { content, ..self } + } + + pub fn with_cursor(self, cursor: usize) -> Self { + Self { + cursor: Some(cursor), + ..self + } + } + + fn build_component(&self) -> InputComponent { + let input = InputComponent::from(&self.content); + + match self.cursor { + Some(i) => input.with_cursor(i), + None => input, + } + } + + pub fn build(self) -> InputComponent { + let input = self.build_component(); + + match self.typ { + InputType::FileName(save_option) => input.with_confirm_callback(move |value| { + Event::emit(Event::InputConfirm); + Event::emit(Event::Save((value, save_option))); + }), + InputType::VarValue(name) => input.with_confirm_callback(move |value| { + Event::emit(Event::InputConfirm); + Event::emit(Event::UpdateVar((name.clone(), value))); + }), + } + } +} diff --git a/rq-cli/src/components/response_panel.rs b/rq-cli/src/components/response_panel.rs index 5993079..712a8f1 100644 --- a/rq-cli/src/components/response_panel.rs +++ b/rq-cli/src/components/response_panel.rs @@ -9,12 +9,10 @@ use ratatui::{ use rq_core::request::{mime::Payload, Response, StatusCode}; use std::{fmt::Write, iter}; -use crate::{ - app::FocusState, - event::{Event, InputType}, -}; +use crate::{app::FocusState, event::Event}; use super::{ + input::builder::{InputBuilder, InputType}, message_dialog::{Message, MessageDialog}, BlockComponent, HandleResult, HandleSuccess, }; @@ -176,17 +174,19 @@ impl BlockComponent for ResponsePanel { KeyCode::Down | KeyCode::Char('j') => self.scroll_down(), KeyCode::Up | KeyCode::Char('k') => self.scroll_up(), KeyCode::Char('s') => { - Event::emit(Event::NewInput(( - self.extension().unwrap_or_default(), - InputType::FileName(SaveOption::Body), - ))); + Event::emit(Event::NewInput( + InputBuilder::new(InputType::FileName(SaveOption::Body)) + .with_content(self.extension().unwrap_or_default()) + .with_cursor(0), + )); } KeyCode::Char('S') => { - Event::emit(Event::NewInput(( - self.extension().unwrap_or_default(), - InputType::FileName(SaveOption::All), - ))); + Event::emit(Event::NewInput( + InputBuilder::new(InputType::FileName(SaveOption::All)) + .with_content(self.extension().unwrap_or_default()) + .with_cursor(0), + )); } KeyCode::Char('t') => { self.show_raw = !self.show_raw; diff --git a/rq-cli/src/components/variables/panel.rs b/rq-cli/src/components/variables/panel.rs index 5b9749e..28729a3 100644 --- a/rq-cli/src/components/variables/panel.rs +++ b/rq-cli/src/components/variables/panel.rs @@ -4,8 +4,12 @@ use crossterm::event::KeyCode; use rq_core::parser::variables::TemplateString; use crate::{ - components::{menu::Menu, BlockComponent, HandleSuccess}, - event::{Event, InputType}, + components::{ + input::builder::{InputBuilder, InputType}, + menu::Menu, + BlockComponent, HandleSuccess, + }, + event::Event, }; pub struct VarsPanel { @@ -17,10 +21,10 @@ impl VarsPanel { pub fn new(vars: HashMap) -> Self { let menu = Menu::new(vars.iter().map(|(k, v)| (k.clone(), v.clone())).collect()) .with_confirm_callback(|(name, value)| { - Event::emit(Event::NewInput(( - value.to_string(), - InputType::VarValue(name.clone()), - ))); + Event::emit(Event::NewInput( + InputBuilder::new(InputType::VarValue(name.clone())) + .with_content(value.to_string()), + )) }); Self { vars, menu } diff --git a/rq-cli/src/event.rs b/rq-cli/src/event.rs index 39a24ab..cb6c7fb 100644 --- a/rq-cli/src/event.rs +++ b/rq-cli/src/event.rs @@ -2,27 +2,31 @@ use std::{collections::VecDeque, sync::Mutex}; use once_cell::sync::Lazy; -use crate::{app::FocusState, components::response_panel::SaveOption}; +use crate::{ + app::FocusState, + components::{input::builder::InputBuilder, response_panel::SaveOption}, +}; static EVENT_QUEUE: Lazy>> = Lazy::new(|| Mutex::new(VecDeque::new())); pub enum Event { Focus(FocusState), Save((String, SaveOption)), - NewInput((String, InputType)), + NewInput(InputBuilder), + InputConfirm, InputCancel, + + // Request index in menu SendRequest(usize), + + // Name, value UpdateVar((String, String)), + Key(crossterm::event::KeyEvent), Other(crossterm::event::Event), } -pub enum InputType { - FileName(SaveOption), - VarValue(String), -} - impl Event { pub fn emit(event: Event) { EVENT_QUEUE.lock().unwrap().push_front(event);