Skip to content

Commit

Permalink
wip: header edit form without key handling
Browse files Browse the repository at this point in the history
  • Loading branch information
wllfaria committed Jun 8, 2024
1 parent 1151fe7 commit 446d4f7
Show file tree
Hide file tree
Showing 15 changed files with 225 additions and 70 deletions.
12 changes: 0 additions & 12 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 9 additions & 12 deletions hac-client/src/pages/collection_viewer/request_editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,31 +253,28 @@ impl Eventful for RequestEditor<'_> {
);

if let KeyCode::Tab = key_event.code {
let mut store = self.collection_store.borrow_mut();
if store.has_overlay() {
store.pop_overlay();
return Ok(None);
}
let store = self.collection_store.borrow_mut();
if self.curr_tab.eq(&ReqEditorTabs::Body)
&& self.body_editor.mode().eq(&EditorMode::Insert)
{
return Ok(None);
}
self.curr_tab = self.curr_tab.next();
if !store.has_overlay() {
self.curr_tab = self.curr_tab.next();
}
drop(store);
}

if let KeyCode::BackTab = key_event.code {
let mut store = self.collection_store.borrow_mut();
if store.has_overlay() {
store.pop_overlay();
return Ok(None);
}
let store = self.collection_store.borrow_mut();
if self.curr_tab.eq(&ReqEditorTabs::Body)
&& self.body_editor.mode().eq(&EditorMode::Insert)
{
return Ok(None);
}
self.curr_tab = self.curr_tab.prev();
if !store.has_overlay() {
self.curr_tab = self.curr_tab.prev();
}
}

match self.curr_tab {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::ops::{Div, Sub};
use std::{cell::RefCell, ops::Add, rc::Rc};

use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
use hac_core::collection::types::HeaderMap;
use hac_core::collection::header_map::HeaderMap;
use rand::Rng;
use ratatui::layout::{Constraint, Direction, Layout, Rect};
use ratatui::style::{Style, Stylize};
Expand All @@ -18,7 +18,7 @@ use ratatui::Frame;
use super::headers_editor_delete_prompt::{
HeadersEditorDeletePrompt, HeadersEditorDeletePromptEvent,
};
use super::headers_editor_form::HeadersEditorForm;
use super::headers_editor_form::{HeadersEditorForm, HeadersEditorFormEvent};

#[derive(Debug)]
pub enum HeadersEditorEvent {
Expand Down Expand Up @@ -156,7 +156,7 @@ impl<'he> HeadersEditor<'he> {
.map(|l| Line::from(l.into_iter().collect::<Vec<_>>()))
.collect();

let mut logo = LOGO_ASCII[1];
let mut logo = LOGO_ASCII[self.logo_idx];
let size = frame.size();
let logo_size = logo.len();
// we are adding 2 spaces for the gap between the logo and the text
Expand Down Expand Up @@ -210,7 +210,7 @@ impl<'he> HeadersEditor<'he> {
self.delete_prompt.draw(frame, frame.size())?;
}
CollectionViewerOverlay::HeadersForm(header_idx) => {
self.header_form.update(header_idx);
self.header_form.update(header_idx)?;
self.header_form.draw(frame, frame.size())?;
}
_ => {}
Expand Down Expand Up @@ -335,6 +335,14 @@ impl Eventful for HeadersEditor<'_> {
return Ok(None);
}

if let CollectionViewerOverlay::HeadersForm(_) = overlay {
match self.header_form.handle_key_event(key_event)? {
Some(HeadersEditorFormEvent::FinishEdit) => {}
None => {}
}
return Ok(None);
}

if let (KeyCode::Char('c'), KeyModifiers::CONTROL) = (key_event.code, key_event.modifiers) {
return Ok(Some(HeadersEditorEvent::Quit));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::ops::{Add, Div, Sub};
use std::ops::{Add, Div};

use crate::ascii::LOGO_ASCII;
use crate::pages::{overlay::make_overlay, Eventful, Renderable};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,61 +1,166 @@
use std::{cell::RefCell, rc::Rc};
use crate::ascii::LOGO_ASCII;
use crate::pages::collection_viewer::collection_store::CollectionStore;
use crate::pages::collection_viewer::collection_viewer::CollectionViewerOverlay;
use crate::pages::input::Input;
use crate::pages::overlay::make_overlay;
use crate::pages::{Eventful, Renderable};

use crate::pages::{
collection_viewer::collection_store::CollectionStore, overlay::make_overlay, Eventful,
Renderable,
};
use std::cell::RefCell;
use std::ops::{Add, Div};
use std::rc::Rc;

use crossterm::event::KeyEvent;
use ratatui::{layout::Rect, Frame};
use crossterm::event::{KeyCode, KeyEvent};
use rand::Rng;
use ratatui::layout::Rect;
use ratatui::style::Stylize;
use ratatui::text::Line;
use ratatui::widgets::{Block, Paragraph};
use ratatui::Frame;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum HeadersEditorFormEvent {
FinishEdit,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum HeadersEditorFormInput {
Name,
Value,
}

impl HeadersEditorFormInput {
fn next(&self) -> Self {
match self {
HeadersEditorFormInput::Name => HeadersEditorFormInput::Value,
HeadersEditorFormInput::Value => HeadersEditorFormInput::Name,
}
}
}

#[derive(Debug)]
pub struct HeadersEditorForm<'hef> {
colors: &'hef hac_colors::Colors,
collection_store: Rc<RefCell<CollectionStore>>,
header_idx: usize,
name: String,
value: String,
logo_idx: usize,
focused_input: HeadersEditorFormInput,
}

impl<'hef> HeadersEditorForm<'hef> {
pub fn new(
colors: &'hef hac_colors::Colors,
collection_store: Rc<RefCell<CollectionStore>>,
) -> HeadersEditorForm {
let logo_idx = rand::thread_rng().gen_range(0..LOGO_ASCII.len());

HeadersEditorForm {
colors,
header_idx: 0,
collection_store,
name: Default::default(),
value: Default::default(),
logo_idx,
focused_input: HeadersEditorFormInput::Name,
}
}

pub fn update(&mut self, header_idx: usize) {
pub fn update(&mut self, header_idx: usize) -> anyhow::Result<()> {
self.header_idx = header_idx;
}
}

impl Renderable for HeadersEditorForm<'_> {
fn draw(&mut self, frame: &mut Frame, size: Rect) -> anyhow::Result<()> {
make_overlay(self.colors, self.colors.normal.black, 0.0, frame);

let store = self.collection_store.borrow_mut();
let Some(request) = store.get_selected_request() else {
tracing::error!("trying to edit a header without a selected request");
anyhow::bail!("trying to edit a header without a selected request");
};

let request = request.read().unwrap();
let Some(ref header) = request.headers else {
tracing::error!("trying to edit a header that don't exist");
let Some(ref headers) = request.headers else {
anyhow::bail!("trying to edit a header that don't exist");
};

let CollectionViewerOverlay::HeadersForm(idx) = store.peek_overlay() else {
anyhow::bail!("tried to display the header form without the proper overlay set");
};

let header = headers
.get(idx)
.expect("selected a non-existing header to edit");

self.name = header.pair.0.to_string();
self.value = header.pair.1.to_string();

Ok(())
}
}

impl Renderable for HeadersEditorForm<'_> {
#[tracing::instrument(skip_all, err)]
fn draw(&mut self, frame: &mut Frame, _: Rect) -> anyhow::Result<()> {
make_overlay(self.colors, self.colors.normal.black, 0.1, frame);

let size = frame.size();

let mut logo = LOGO_ASCII[self.logo_idx];
let mut logo_size = logo.len() as u16;

let total_size = logo_size.add(11).add(2);
let mut size = Rect::new(
size.width.div(2).saturating_sub(25),
size.height
.div(2)
.saturating_sub(logo_size.div(2))
.saturating_sub(5),
50,
logo_size.add(11),
);

if total_size.ge(&frame.size().height) {
logo = &[];
logo_size = 0;
size.height = 11;
size.y = size.height.div(2).saturating_sub(5);
}

let name_input = Input::new(self.colors, "Name".into());
let value_input = Input::new(self.colors, "Value".into());
let hint = Paragraph::new(
"Press enter to confirm, press esc to cancel".fg(self.colors.bright.black),
)
.centered();

//frame.render_widget(Par, area);
if !logo.is_empty() {
let logo = logo
.iter()
.map(|line| Line::from(line.fg(self.colors.normal.red)).centered())
.collect::<Vec<_>>();

let logo_size = Rect::new(size.x, size.y, size.width, logo_size);
frame.render_widget(Paragraph::new(logo), logo_size);
}

let name_size = Rect::new(size.x, size.y.add(logo_size).add(1), size.width, 3);
let value_size = Rect::new(size.x, name_size.y.add(4), size.width, 3);
let hint_size = Rect::new(size.x, value_size.y.add(4), size.width, 1);

frame.render_stateful_widget(name_input, name_size, &mut self.name);
frame.render_stateful_widget(value_input, value_size, &mut self.value);
frame.render_widget(hint, hint_size);

match self.focused_input {
HeadersEditorFormInput::Name => {
frame.set_cursor(
name_size.x.add(self.name.len().add(1) as u16),
name_size.y.add(1),
);
}
HeadersEditorFormInput::Value => {
frame.set_cursor(
value_size.x.add(self.value.len().add(1) as u16),
value_size.y.add(1),
);
}
}

Ok(())
}
Expand All @@ -65,6 +170,21 @@ impl Eventful for HeadersEditorForm<'_> {
type Result = HeadersEditorFormEvent;

fn handle_key_event(&mut self, key_event: KeyEvent) -> anyhow::Result<Option<Self::Result>> {
tracing::debug!("{}", self.name);
match key_event.code {
KeyCode::Tab => self.focused_input = self.focused_input.next(),
KeyCode::BackTab => self.focused_input = self.focused_input.next(),
KeyCode::Backspace => match self.focused_input {
HeadersEditorFormInput::Name => _ = self.name.pop(),
HeadersEditorFormInput::Value => _ = self.value.pop(),
},
KeyCode::Char(c) => match self.focused_input {
HeadersEditorFormInput::Name => self.name.push(c),
HeadersEditorFormInput::Value => self.value.push(c),
},
_ => {}
};

Ok(Some(HeadersEditorFormEvent::FinishEdit))
}
}
Loading

0 comments on commit 446d4f7

Please sign in to comment.