Skip to content

Commit

Permalink
refactor: hints are now controlled by its own component
Browse files Browse the repository at this point in the history
  • Loading branch information
wllfaria committed Jun 5, 2024
1 parent 68273d1 commit 4abb707
Show file tree
Hide file tree
Showing 8 changed files with 162 additions and 28 deletions.
2 changes: 1 addition & 1 deletion hac-client/src/pages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ pub mod collection_viewer;
pub mod confirm_popup;
pub mod error_popup;
pub mod input;
mod overlay;
pub mod overlay;
mod spinner;
pub mod terminal_too_small;
mod under_construction;
Expand Down
18 changes: 7 additions & 11 deletions hac-client/src/pages/collection_dashboard/collection_dashboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::pages::collection_dashboard::new_collection_form::{
};
use crate::pages::confirm_popup::ConfirmPopup;
use crate::pages::error_popup::ErrorPopup;
use crate::pages::overlay::draw_overlay;
use crate::pages::overlay::{draw_overlay, make_overlay};
use crate::pages::{Eventful, Renderable};

use std::ops::{Add, Div, Not, Sub};
Expand Down Expand Up @@ -342,9 +342,8 @@ impl<'a> CollectionDashboard<'a> {
frame.render_widget(hint, self.layout.hint_pane);
}

fn draw_help_popup(&self, size: Rect, frame: &mut Frame) {
frame.render_widget(Clear, size);
draw_overlay(self.colors, size, "助ける", frame);
fn draw_help_popup(&self, frame: &mut Frame) {
make_overlay(self.colors, self.colors.primary.background, 0.2, frame);

let lines = vec![
Line::from(vec![
Expand Down Expand Up @@ -391,13 +390,10 @@ impl<'a> CollectionDashboard<'a> {
Line::from("press any key to go back".fg(self.colors.normal.magenta)).centered(),
];

frame.render_widget(Clear, self.layout.help_popup);
frame.render_widget(
Paragraph::new(lines).wrap(Wrap { trim: true }).block(
Block::default()
.padding(Padding::new(2, 2, 1, 1))
.bg(self.colors.primary.background),
),
Paragraph::new(lines)
.wrap(Wrap { trim: true })
.block(Block::default().padding(Padding::new(2, 2, 1, 1))),
self.layout.help_popup,
);
}
Expand Down Expand Up @@ -537,7 +533,7 @@ impl Renderable for CollectionDashboard<'_> {
PaneFocus::Error => self.draw_error_popup(frame),
PaneFocus::Form => self.draw_form_popup(size, frame),
PaneFocus::Filter => self.draw_filter_prompt(frame),
PaneFocus::Help => self.draw_help_popup(size, frame),
PaneFocus::Help => self.draw_help_popup(frame),
PaneFocus::Prompt => self.draw_delete_prompt(frame),
PaneFocus::List => self.draw_hint_text(frame),
}
Expand Down
10 changes: 2 additions & 8 deletions hac-client/src/pages/collection_viewer/collection_viewer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ impl<'cv> CollectionViewer<'cv> {
config,
collection_store.clone(),
layout.req_editor,
layout.hint_pane,
),
response_viewer: ResponseViewer::new(
colors,
Expand Down Expand Up @@ -664,18 +665,11 @@ impl Renderable for CollectionViewer<'_> {

self.drain_responses_channel();

self.sidebar.draw(frame, self.layout.sidebar)?;
self.response_viewer
.draw(frame, self.layout.response_preview)?;
self.request_editor.draw(frame, self.layout.req_editor)?;
self.request_uri.draw(frame, self.layout.req_uri)?;
self.sidebar.draw(frame, self.layout.sidebar)?;

match self.collection_store.borrow().get_focused_pane() {
PaneFocus::ReqUri => self.draw_req_uri_hint(frame),
PaneFocus::Sidebar => self.draw_sidebar_hint(frame),
PaneFocus::Preview => self.draw_preview_hint(frame),
PaneFocus::Editor => self.draw_editor_hint(frame),
}

match self.curr_overlay {
Overlays::CreateRequest => self.draw_create_request_form(frame),
Expand Down
4 changes: 4 additions & 0 deletions hac-client/src/pages/collection_viewer/request_editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ pub struct RequestEditor<'re> {

layout: ReqEditorLayout,
curr_tab: ReqEditorTabs,
hint_size: Rect,
}

impl<'re> RequestEditor<'re> {
Expand All @@ -109,6 +110,7 @@ impl<'re> RequestEditor<'re> {
config: &'re hac_config::Config,
collection_store: Rc<RefCell<CollectionStore>>,
size: Rect,
hint_size: Rect,
) -> Self {
let curr_tab = collection_store
.borrow()
Expand All @@ -133,11 +135,13 @@ impl<'re> RequestEditor<'re> {
colors,
collection_store.clone(),
layout.content_pane,
hint_size,
),
auth_editor: AuthEditor::new(colors),
layout,
curr_tab,
collection_store,
hint_size,
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
use hac_core::collection::types::HeaderMap;

use crate::pages::{collection_viewer::collection_store::CollectionStore, Eventful, Renderable};

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 ratatui::layout::{Constraint, Direction, Layout, Rect};
use ratatui::style::{Style, Stylize};
use ratatui::widgets::{Paragraph, Scrollbar, ScrollbarOrientation, ScrollbarState};
Expand Down Expand Up @@ -34,13 +33,15 @@ pub struct HeadersEditor<'he> {
row_height: u16,
amount_on_view: usize,
layout: HeadersEditorLayout,
hint_size: Rect,
}

impl<'he> HeadersEditor<'he> {
pub fn new(
colors: &'he hac_colors::colors::Colors,
collection_store: Rc<RefCell<CollectionStore>>,
size: Rect,
hint_size: Rect,
) -> Self {
let row_height = 2;
let layout = build_layout(size, row_height);
Expand All @@ -52,6 +53,7 @@ impl<'he> HeadersEditor<'he> {
row_height,
amount_on_view: layout.content_size.height.div(row_height).into(),
layout,
hint_size,
}
}

Expand Down Expand Up @@ -81,6 +83,17 @@ impl<'he> HeadersEditor<'he> {
frame.render_widget(value, row[2]);
frame.render_widget(Paragraph::new(checkbox).fg(decor_fg).centered(), row[3]);
}

fn draw_hint(&self, frame: &mut Frame) {
let hint = match self.hint_size.width {
w if w.le(&100) => "[j/k -> move down/up] [enter -> select] [space -> enable/disable] [? -> help]",
_ => "[j/k -> move down/up] [enter -> select] [space -> enable/disable] [d -> delete] [? -> help]",
};
frame.render_widget(
Paragraph::new(hint).fg(self.colors.bright.black).centered(),
self.hint_size,
);
}
}

impl Renderable for HeadersEditor<'_> {
Expand Down Expand Up @@ -110,6 +123,7 @@ impl Renderable for HeadersEditor<'_> {
.constraints([
Constraint::Length(2),
Constraint::Fill(1),
Constraint::Length(1),
Constraint::Fill(1),
Constraint::Length(1),
Constraint::Length(7),
Expand All @@ -125,7 +139,7 @@ impl Renderable for HeadersEditor<'_> {
// > Header-Name Header-Value [x]
// Header-Name Header-Value [x]
//
.filter(|(idx, _)| idx.ne(&3))
.filter(|(idx, _)| idx.ne(&2) && idx.ne(&4))
.map(|(_, rect)| *rect)
.collect::<Vec<_>>()
})
Expand All @@ -147,6 +161,8 @@ impl Renderable for HeadersEditor<'_> {
frame.render_widget(title_value, self.layout.value_header_size);
frame.render_widget(title_enabled, self.layout.enabled_header_size);

self.draw_hint(frame);

Ok(())
}

Expand All @@ -163,23 +179,42 @@ impl Eventful for HeadersEditor<'_> {
return Ok(Some(HeadersEditorEvent::Quit));
}

let Some(req) = self.collection_store.borrow().get_selected_request() else {
let Some(request) = self.collection_store.borrow_mut().get_selected_request() else {
return Ok(None);
};

let Some(ref headers) = req.read().unwrap().headers else {
let mut request = request.write().unwrap();
let Some(headers) = request.headers.as_mut() else {
return Ok(None);
};

let total_headers = headers.len();

tracing::debug!("handling key event on headers editor");

match key_event.code {
KeyCode::Char('j') => {
self.selected_row = usize::min(self.selected_row.add(1), total_headers.sub(1))
}
KeyCode::Char('k') => {
self.selected_row = self.selected_row.saturating_sub(1);
}
KeyCode::Char('?') => todo!(),
KeyCode::Char(' ') => {
if headers.is_empty() {
return Ok(None);
}

let header = match headers.get_mut(self.selected_row) {
Some(header) => header,
None => {
tracing::error!("tried to disable a non-existing header");
anyhow::bail!("tried to disable a non-existing header");
}
};

header.enabled = !header.enabled;
}
_ => {}
}

Expand Down
35 changes: 34 additions & 1 deletion hac-client/src/pages/overlay.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
use ratatui::{layout::Rect, style::Stylize, text::Line, widgets::Paragraph, Frame};
use ratatui::buffer::Cell;
use ratatui::layout::Rect;
use ratatui::style::{Color, Stylize};
use ratatui::text::Line;
use ratatui::widgets::Paragraph;
use ratatui::Frame;

use crate::utils::blend_colors_multiply;

/// draws a fullscreen overlay with the given fill text, many pages uses this to display
/// "floating" information
Expand All @@ -12,3 +19,29 @@ pub fn draw_overlay(colors: &hac_colors::Colors, size: Rect, fill_text: &str, fr

frame.render_widget(overlay, size);
}

pub fn make_overlay(colors: &hac_colors::Colors, color: Color, alpha: f32, frame: &mut Frame) {
let buffer = frame.buffer_mut();

let cells = buffer.content();

let new_cells = cells
.iter()
.map(|cell| {
let cell_fg = cell.style().fg.unwrap_or(colors.normal.white);
let cell_bg = cell.style().bg.unwrap_or(colors.primary.background);

let new_fg = blend_colors_multiply(cell_fg, color, alpha);
let new_bg = blend_colors_multiply(cell_bg, color, alpha);

let mut new_cell = Cell::default();
new_cell.set_fg(new_fg);
new_cell.set_bg(new_bg);
new_cell.set_symbol(cell.symbol());

new_cell
})
.collect::<Vec<_>>();

buffer.content = new_cells;
}
1 change: 0 additions & 1 deletion hac-client/src/pages/spinner.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use std::ops::Add;

use rand::Rng;

use ratatui::buffer::Buffer;
use ratatui::layout::Rect;
use ratatui::style::Style;
Expand Down
75 changes: 74 additions & 1 deletion hac-client/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use hac_core::syntax::highlighter::HIGHLIGHTER;

use std::ops::Add;

use ratatui::style::Stylize;
use ratatui::style::{Color, Stylize};
use ratatui::text::{Line, Span};
use tree_sitter::Tree;

Expand Down Expand Up @@ -144,3 +144,76 @@ pub fn build_syntax_highlighted_lines(

styled_lines
}

/// will try to apply a blending using multiply to two colors, based on a given alpha.
///
/// It will apply the background over the foreground so we get a middleground color. This
/// is done by using `alpha blending`, which is done by the given formula:
///
/// component = alpha * original component + (1.0 - alpha) * overlay component
///
/// eg:
///
/// ```rust
/// blend_colors_multiply(Color::Rgb(255, 255, 25), Color::Rgb(0, 0, 0), 0.5);
/// ```
///
/// will give you
///
/// ```rust
/// Color::Rgb(128, 128, 128);
/// ```
pub fn blend_colors_multiply(original: Color, overlay: Color, alpha: f32) -> Color {
let blend_component = |fg, bg| (alpha * fg as f32 + (1.0 - alpha) * bg as f32) as u8;

let Some(foreground) = color_to_rgb(original) else {
return original;
};

let Some(background) = color_to_rgb(overlay) else {
return original;
};

let r = blend_component(foreground.0, background.0);
let g = blend_component(foreground.1, background.1);
let b = blend_component(foreground.2, background.2);

Color::Rgb(r, g, b)
}

fn color_to_rgb(color: Color) -> Option<(u8, u8, u8)> {
match color {
Color::Rgb(r, g, b) => Some((r, g, b)),
Color::Indexed(color) => ansi_to_rgb(color),
_ => None,
}
}

fn ansi_to_rgb(val: u8) -> Option<(u8, u8, u8)> {
let rgb_table: [(u8, u8, u8); 16] = [
(0, 0, 0), // Black
(128, 0, 0), // Red
(0, 128, 0), // Green
(128, 128, 0), // Yellow
(0, 0, 128), // Blue
(128, 0, 128), // Magenta
(0, 128, 128), // Cyan
(192, 192, 192), // White
(128, 128, 128), // Bright Black (Gray)
(255, 0, 0), // Bright Red
(0, 255, 0), // Bright Green
(255, 255, 0), // Bright Yellow
(0, 0, 255), // Bright Blue
(255, 0, 255), // Bright Magenta
(0, 255, 255), // Bright Cyan
(255, 255, 255), // Bright White
];

if val < 16 {
Some(rgb_table[val as usize])
} else {
// techinically as we use ratatui colors, we shouldn't ever have another
// value here, but since we techinically can, we handle it
None
}
}

0 comments on commit 4abb707

Please sign in to comment.