use std::sync::Arc;
use parking_lot::Mutex;
use ratatui::{
Frame,
layout::{Alignment, Direction, Layout},
style::{Modifier, Style},
text::{Line, Span},
widgets::{Block, BorderType, Borders, Clear, Paragraph},
};
use super::{CONSTRAINT_BUTTONS, CONSTRAINT_POPUP};
use crate::{
app_data::ContainerName,
config::{AppColors, Keymap},
ui::{
DeleteButton, GuiState,
gui_state::{BoxLocation, Region},
},
};
use super::popup;
pub fn draw(
colors: AppColors,
f: &mut Frame,
gui_state: &Arc<Mutex<GuiState>>,
keymap: &Keymap,
name: &ContainerName,
) {
let block = Block::default()
.title(" Confirm Delete ")
.border_type(BorderType::Rounded)
.style(
Style::default()
.bg(colors.popup_delete.background)
.fg(colors.popup_delete.text),
)
.title_alignment(Alignment::Center)
.borders(Borders::ALL);
let confirm = Line::from(vec![
Span::from("Are you sure you want to delete container: "),
Span::styled(
name.get(),
Style::default()
.fg(colors.popup_delete.text_highlight)
.bg(colors.popup_delete.background)
.add_modifier(Modifier::BOLD),
),
]);
let yes_text = if keymap.delete_confirm == Keymap::new().delete_confirm {
"( y ) yes".to_owned()
} else if let Some(secondary) = keymap.delete_confirm.1 {
format!("( {} | {} ) yes", keymap.delete_confirm.0, secondary)
} else {
format!("( {} ) yes", keymap.delete_confirm.0)
};
let no_text = if keymap.delete_deny == Keymap::new().delete_deny {
"( n ) no".to_owned()
} else if let Some(secondary) = keymap.delete_deny.1 {
format!("( {} | {} ) no", keymap.delete_deny.0, secondary)
} else {
format!("( {} ) no", keymap.delete_deny.0)
};
let max_line_width = u16::try_from(confirm.width()).unwrap_or(64) + 12;
let lines = 8;
let confirm_para = Paragraph::new(confirm).alignment(Alignment::Center);
let button_block = || {
Block::default()
.border_type(BorderType::Rounded)
.borders(Borders::ALL)
.style(Style::default().bg(colors.popup_delete.background))
};
let yes_para = Paragraph::new(yes_text)
.alignment(Alignment::Center)
.block(button_block());
let no_para = Paragraph::new(no_text)
.alignment(Alignment::Center)
.block(button_block());
let area = popup::draw(
lines,
max_line_width.into(),
f.area(),
BoxLocation::MiddleCentre,
);
let split_popup = Layout::default()
.direction(Direction::Vertical)
.constraints(CONSTRAINT_POPUP)
.split(area);
let split_buttons = Layout::default()
.direction(Direction::Horizontal)
.constraints(CONSTRAINT_BUTTONS)
.split(split_popup[3]);
let no_area = split_buttons[1];
let yes_area = split_buttons[3];
f.render_widget(Clear, area);
f.render_widget(block, area);
f.render_widget(confirm_para, split_popup[1]);
f.render_widget(no_para, no_area);
f.render_widget(yes_para, yes_area);
gui_state
.lock()
.update_region_map(Region::Delete(DeleteButton::Cancel), no_area);
gui_state
.lock()
.update_region_map(Region::Delete(DeleteButton::Confirm), yes_area);
}
#[cfg(test)]
#[allow(clippy::unwrap_used)]
mod tests {
use crossterm::event::KeyCode;
use insta::assert_snapshot;
use ratatui::style::{Color, Modifier};
use crate::{
app_data::ContainerName,
config::{AppColors, Keymap},
ui::draw_blocks::tests::{get_result, test_setup},
};
#[test]
fn test_draw_blocks_delete() {
let mut setup = test_setup(82, 10, true, true);
let colors = setup.app_data.lock().config.app_colors;
let keymap = &setup.app_data.lock().config.keymap;
setup
.terminal
.draw(|f| {
super::draw(
colors,
f,
&setup.gui_state,
keymap,
&ContainerName::from("container_1"),
);
})
.unwrap();
assert_snapshot!(setup.terminal.backend());
for (row_index, result_row) in get_result(&setup) {
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
match (row_index, result_cell_index) {
(0 | 9, _) | (1..=8, 0..=7 | 74..=81) => {
assert_eq!(result_cell.bg, Color::Reset);
assert_eq!(result_cell.fg, Color::Reset);
}
(3, 57..=67) => {
assert_eq!(result_cell.bg, Color::White);
assert_eq!(result_cell.fg, Color::Red);
assert_eq!(result_cell.modifier, Modifier::BOLD);
}
_ => {
assert_eq!(result_cell.bg, Color::White);
assert_eq!(result_cell.fg, Color::Black);
}
}
}
}
}
#[test]
fn test_draw_blocks_delete_long_name() {
let mut setup = test_setup(106, 10, true, true);
let name = ContainerName::from("container_1_container_1_container_1");
setup.app_data.lock().containers.items[0].name = name.clone();
let colors = setup.app_data.lock().config.app_colors;
let keymap = &setup.app_data.lock().config.keymap;
setup
.terminal
.draw(|f| {
super::draw(colors, f, &setup.gui_state, keymap, &name);
})
.unwrap();
assert_snapshot!(setup.terminal.backend());
for (row_index, result_row) in get_result(&setup) {
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
match (row_index, result_cell_index) {
(0 | 9, _) | (1..=8, 0..=7 | 98..=106) => {
assert_eq!(result_cell.bg, Color::Reset);
assert_eq!(result_cell.fg, Color::Reset);
}
(3, 57..=91) => {
assert_eq!(result_cell.bg, Color::White);
assert_eq!(result_cell.fg, Color::Red);
assert_eq!(result_cell.modifier, Modifier::BOLD);
}
_ => {
assert_eq!(result_cell.bg, Color::White);
assert_eq!(result_cell.fg, Color::Black);
}
}
}
}
}
#[test]
fn test_draw_blocks_delete_custom_colors() {
let mut setup = test_setup(82, 10, true, true);
let mut colors = AppColors::new();
colors.popup_delete.background = Color::Black;
colors.popup_delete.text = Color::Yellow;
colors.popup_delete.text_highlight = Color::Green;
setup
.terminal
.draw(|f| {
super::draw(
colors,
f,
&setup.gui_state,
&Keymap::new(),
&ContainerName::from("container_1"),
);
})
.unwrap();
assert_snapshot!(setup.terminal.backend());
for (row_index, result_row) in get_result(&setup) {
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
match (row_index, result_cell_index) {
(0 | 9, _) | (1..=8, 0..=7 | 74..=81) => {
assert_eq!(result_cell.bg, Color::Reset);
assert_eq!(result_cell.fg, Color::Reset);
}
(3, 57..=67) => {
assert_eq!(result_cell.bg, Color::Black);
assert_eq!(result_cell.fg, Color::Green);
assert_eq!(result_cell.modifier, Modifier::BOLD);
}
_ => {
assert_eq!(result_cell.bg, Color::Black);
assert_eq!(result_cell.fg, Color::Yellow);
}
}
}
}
}
#[test]
fn test_draw_blocks_delete_custom_keymap_one_definition() {
let mut setup = test_setup(82, 10, true, true);
let mut keymap = Keymap::new();
keymap.delete_confirm = (KeyCode::F(10), None);
keymap.delete_deny = (KeyCode::End, None);
setup
.terminal
.draw(|f| {
super::draw(
AppColors::new(),
f,
&setup.gui_state,
&keymap,
&ContainerName::from("container_1"),
);
})
.unwrap();
assert_snapshot!(setup.terminal.backend());
}
#[test]
fn test_draw_blocks_delete_custom_keymap_two_definition() {
let mut setup = test_setup(82, 10, true, true);
let mut keymap = Keymap::new();
keymap.delete_confirm = (KeyCode::F(10), Some(KeyCode::Char('L')));
keymap.delete_deny = (KeyCode::End, Some(KeyCode::Up));
setup
.terminal
.draw(|f| {
super::draw(
AppColors::new(),
f,
&setup.gui_state,
&keymap,
&ContainerName::from("container_1"),
);
})
.unwrap();
assert_snapshot!(setup.terminal.backend());
}
#[test]
fn test_draw_blocks_delete_custom_keymap_one_two_definition() {
let mut setup = test_setup(82, 10, true, true);
let mut keymap = Keymap::new();
keymap.delete_confirm = (KeyCode::F(10), None);
keymap.delete_deny = (KeyCode::End, Some(KeyCode::Up));
setup
.terminal
.draw(|f| {
super::draw(
AppColors::new(),
f,
&setup.gui_state,
&keymap,
&ContainerName::from("container_1"),
);
})
.unwrap();
assert_snapshot!(setup.terminal.backend());
}
}