Skip to content

Commit 5b09ef5

Browse files
nahharrisDavid Tadokoro
authored andcommitted
feat: make patchset apply action interactive and with feedback
The previous command introduced all the logic to handle the apply of a patchset into a target kernel tree. However, it lacked any interactiveness and feedback for the user. In this sense, add a button "apply" to the "Actions" tab of the "Patchset Details and Actions" screen, and make it run like the other actions, i.e., after the user toggles it by hitting (in this case) the `a` key, the `ENTER` key needs to be hit to actually run the action. Moreover, implement a new `PopUp` type, named `InfoPopUp`, and use it to display the result of the patchset apply action. [Maintainer edits] - Rephrase commit message - Switch order of "apply" button with "reviewed-by" - Implement and use `InfoPopUp` to notify user about result of patchset apply action Signed-off-by: OJarrisonn <[email protected]> Reviewed-by: David Tadokoro <[email protected]> Signed-off-by: David Tadokoro <[email protected]>
1 parent 6097135 commit 5b09ef5

File tree

6 files changed

+156
-6
lines changed

6 files changed

+156
-6
lines changed

src/app.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
use crate::{log_on_error, ui::popup::PopUp};
1+
use crate::{
2+
log_on_error,
3+
ui::popup::{info_popup::InfoPopUp, PopUp},
4+
};
25
use ansi_to_tui::IntoText;
36
use color_eyre::eyre::bail;
47
use config::Config;
@@ -241,6 +244,7 @@ impl App {
241244
patchset_actions: HashMap::from([
242245
(PatchsetAction::Bookmark, is_patchset_bookmarked),
243246
(PatchsetAction::ReplyWithReviewedBy, false),
247+
(PatchsetAction::Apply, false),
244248
]),
245249
reviewed_by,
246250
tested_by,
@@ -311,6 +315,28 @@ impl App {
311315
.reset_reply_with_reviewed_by_action();
312316
}
313317

318+
if let Some(true) = self
319+
.details_actions
320+
.as_ref()
321+
.unwrap()
322+
.patchset_actions
323+
.get(&PatchsetAction::Apply)
324+
{
325+
let popup = match self
326+
.details_actions
327+
.as_ref()
328+
.unwrap()
329+
.apply_patchset(&self.config)
330+
{
331+
Ok(msg) => InfoPopUp::generate_info_popup("Patchset Apply Success", &msg),
332+
Err(msg) => InfoPopUp::generate_info_popup("Patchset Apply Fail", &msg),
333+
};
334+
335+
self.popup = Some(popup);
336+
337+
self.details_actions.as_mut().unwrap().toggle_apply_action();
338+
}
339+
314340
Ok(())
315341
}
316342

src/app/screens/details_actions.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ const LAST_LINE_PADDING: usize = 10;
4747
pub enum PatchsetAction {
4848
Bookmark,
4949
ReplyWithReviewedBy,
50+
Apply,
5051
}
5152

5253
impl DetailsActions {
@@ -142,6 +143,10 @@ impl DetailsActions {
142143
}
143144
}
144145

146+
pub fn toggle_apply_action(&mut self) {
147+
self.toggle_action(PatchsetAction::Apply);
148+
}
149+
145150
pub fn reset_reply_with_reviewed_by_action(&mut self) {
146151
self.patches_to_reply = vec![false; self.patches_to_reply.len()];
147152
self.patchset_actions

src/handler/details_actions.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::time::Duration;
22

33
use crate::{
4-
app::{logging::Logger, screens::CurrentScreen, App},
4+
app::{screens::CurrentScreen, App},
55
ui::popup::{help::HelpPopUpBuilder, review_trailers::ReviewTrailersPopUp, PopUp},
66
utils,
77
};
@@ -67,10 +67,9 @@ pub fn handle_patchset_details<B: Backend>(
6767
app.set_current_screen(ps_da_clone);
6868
app.reset_details_actions();
6969
}
70-
KeyCode::Char('a') => match patchset_details_and_actions.apply_patchset(&app.config) {
71-
Ok(msg) => Logger::info(msg),
72-
Err(msg) => Logger::error(msg),
73-
},
70+
KeyCode::Char('a') => {
71+
patchset_details_and_actions.toggle_apply_action();
72+
}
7473
KeyCode::Char('j') | KeyCode::Down => {
7574
patchset_details_and_actions.preview_scroll_down(1);
7675
}

src/ui/details_actions.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ fn render_details_and_actions(f: &mut Frame, app: &App, details_chunk: Rect, act
134134
f.render_widget(patchset_details, details_chunk);
135135

136136
let patchset_actions = &patchset_details_and_actions.patchset_actions;
137+
// TODO: Create a function to produce new action lines
137138
let patchset_actions = vec![
138139
Line::from(vec![
139140
if *patchset_actions.get(&PatchsetAction::Bookmark).unwrap() {
@@ -150,6 +151,21 @@ fn render_details_and_actions(f: &mut Frame, app: &App, details_chunk: Rect, act
150151
),
151152
Span::styled("ookmark", Style::default().fg(Color::Cyan)),
152153
]),
154+
Line::from(vec![
155+
if *patchset_actions.get(&PatchsetAction::Apply).unwrap() {
156+
Span::styled("[x] ", Style::default().fg(Color::Green))
157+
} else {
158+
Span::styled("[ ] ", Style::default().fg(Color::Cyan))
159+
},
160+
Span::styled(
161+
"a",
162+
Style::default()
163+
.fg(Color::Cyan)
164+
.add_modifier(Modifier::UNDERLINED)
165+
.add_modifier(Modifier::BOLD),
166+
),
167+
Span::styled("pply", Style::default().fg(Color::Cyan)),
168+
]),
153169
Line::from(vec![
154170
if *patchset_details_and_actions
155171
.patches_to_reply

src/ui/popup.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::fmt::Debug;
33
use ratatui::{crossterm::event::KeyEvent, layout::Rect, Frame};
44

55
pub mod help;
6+
pub mod info_popup;
67
pub mod review_trailers;
78

89
/// A trait that represents a popup that can be rendered on top of a screen

src/ui/popup/info_popup.rs

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
use ratatui::{
2+
crossterm::event::KeyCode,
3+
layout::{Alignment, Rect},
4+
style::{Color, Modifier, Style},
5+
text::Line,
6+
widgets::{Block, BorderType, Borders, Clear, Paragraph, Wrap},
7+
};
8+
9+
use super::PopUp;
10+
11+
#[derive(Debug)]
12+
pub struct InfoPopUp {
13+
title: String,
14+
info: String,
15+
offset: (u16, u16),
16+
max_offset: (u16, u16),
17+
dimensions: (u16, u16),
18+
}
19+
20+
impl InfoPopUp {
21+
/// Generate a pop-up with a title and an arbitrary information.
22+
pub fn generate_info_popup(title: &str, info: &str) -> Box<dyn PopUp> {
23+
let mut lines = 0;
24+
let mut columns = 0;
25+
26+
for line in info.lines() {
27+
lines += 1;
28+
let line_len = line.len() as u16;
29+
if line_len > columns {
30+
columns = line_len;
31+
}
32+
}
33+
34+
let dimensions = (30, 50); // TODO: Calculate percentage based on the lines and screen size
35+
36+
Box::new(InfoPopUp {
37+
title: title.to_string(),
38+
info: info.to_string(),
39+
offset: (0, 0),
40+
max_offset: (lines, columns),
41+
dimensions,
42+
})
43+
}
44+
}
45+
46+
impl PopUp for InfoPopUp {
47+
fn dimensions(&self) -> (u16, u16) {
48+
self.dimensions
49+
}
50+
51+
/// Renders a centered overlaying pop-up with a title and an arbitrary info.
52+
fn render(&self, f: &mut ratatui::Frame, chunk: Rect) {
53+
let bold_blue = Style::default()
54+
.add_modifier(Modifier::BOLD)
55+
.fg(Color::Blue);
56+
let block = Block::default()
57+
.title(self.title.clone())
58+
.title_alignment(Alignment::Center)
59+
.title_style(bold_blue)
60+
.title_bottom(Line::styled("(ESC / q) Close", bold_blue))
61+
.borders(Borders::ALL)
62+
.border_type(BorderType::Double)
63+
.style(Style::default());
64+
65+
let pop_up = Paragraph::new(self.info.clone())
66+
.block(block)
67+
.alignment(Alignment::Left)
68+
.wrap(Wrap { trim: true })
69+
.scroll(self.offset);
70+
71+
f.render_widget(Clear, chunk);
72+
f.render_widget(pop_up, chunk);
73+
}
74+
75+
/// Handles simple one-char width navigation.
76+
fn handle(&mut self, key: ratatui::crossterm::event::KeyEvent) -> color_eyre::Result<()> {
77+
match key.code {
78+
KeyCode::Up | KeyCode::Char('k') => {
79+
if self.offset.0 > 0 {
80+
self.offset.0 -= 1;
81+
}
82+
}
83+
KeyCode::Down | KeyCode::Char('j') => {
84+
if self.offset.0 < self.max_offset.0 {
85+
self.offset.0 += 1;
86+
}
87+
}
88+
KeyCode::Left | KeyCode::Char('h') => {
89+
if self.offset.1 > 0 {
90+
self.offset.1 -= 1;
91+
}
92+
}
93+
KeyCode::Right | KeyCode::Char('l') => {
94+
if self.offset.1 < self.max_offset.1 {
95+
self.offset.1 += 1;
96+
}
97+
}
98+
_ => {}
99+
}
100+
101+
Ok(())
102+
}
103+
}

0 commit comments

Comments
 (0)