Skip to content

Commit b5bbf98

Browse files
committed
search popup
1 parent ed849a3 commit b5bbf98

File tree

7 files changed

+250
-5
lines changed

7 files changed

+250
-5
lines changed

asyncgit/src/sync/logwalker.rs

+7
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,14 @@ bitflags! {
7474
}
7575
}
7676

77+
impl Default for FilterSearchOptions {
78+
fn default() -> Self {
79+
Self::all()
80+
}
81+
}
82+
7783
///
84+
#[derive(Default)]
7885
pub struct LogFilterSearch {
7986
///
8087
pub matcher: fuzzy_matcher::skim::SkimMatcherV2,

src/app.rs

+17-4
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ use crate::{
88
ConfirmComponent, CreateBranchComponent, DrawableComponent,
99
ExternalEditorComponent, FetchComponent, FileRevlogComponent,
1010
FuzzyFindPopup, FuzzyFinderTarget, HelpComponent,
11-
InspectCommitComponent, MsgComponent, OptionsPopupComponent,
12-
PullComponent, PushComponent, PushTagsComponent,
13-
RenameBranchComponent, ResetPopupComponent,
14-
RevisionFilesPopup, StashMsgComponent,
11+
InspectCommitComponent, LogSearchPopupComponent,
12+
MsgComponent, OptionsPopupComponent, PullComponent,
13+
PushComponent, PushTagsComponent, RenameBranchComponent,
14+
ResetPopupComponent, RevisionFilesPopup, StashMsgComponent,
1515
SubmodulesListComponent, TagCommitComponent,
1616
TagListComponent,
1717
},
@@ -74,6 +74,7 @@ pub struct App {
7474
external_editor_popup: ExternalEditorComponent,
7575
revision_files_popup: RevisionFilesPopup,
7676
fuzzy_find_popup: FuzzyFindPopup,
77+
log_search_popup: LogSearchPopupComponent,
7778
push_popup: PushComponent,
7879
push_tags_popup: PushTagsComponent,
7980
pull_popup: PullComponent,
@@ -271,6 +272,11 @@ impl App {
271272
theme.clone(),
272273
key_config.clone(),
273274
),
275+
log_search_popup: LogSearchPopupComponent::new(
276+
&queue,
277+
theme.clone(),
278+
key_config.clone(),
279+
),
274280
fuzzy_find_popup: FuzzyFindPopup::new(
275281
&queue,
276282
theme.clone(),
@@ -580,6 +586,7 @@ impl App {
580586
accessors!(
581587
self,
582588
[
589+
log_search_popup,
583590
fuzzy_find_popup,
584591
msg,
585592
reset,
@@ -632,6 +639,7 @@ impl App {
632639
rename_branch_popup,
633640
revision_files_popup,
634641
fuzzy_find_popup,
642+
log_search_popup,
635643
push_popup,
636644
push_tags_popup,
637645
pull_popup,
@@ -895,6 +903,11 @@ impl App {
895903
flags
896904
.insert(NeedsUpdate::ALL | NeedsUpdate::COMMANDS);
897905
}
906+
InternalEvent::OpenLogSearchPopup => {
907+
self.log_search_popup.open()?;
908+
flags
909+
.insert(NeedsUpdate::ALL | NeedsUpdate::COMMANDS);
910+
}
898911
InternalEvent::OptionSwitched(o) => {
899912
match o {
900913
AppOption::StatusShowUntracked => {

src/components/log_search_popup.rs

+219
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
#![allow(dead_code)]
2+
3+
use super::{
4+
visibility_blocking, CommandBlocking, CommandInfo, Component,
5+
DrawableComponent, EventState, TextInputComponent,
6+
};
7+
use crate::{
8+
keys::{key_match, SharedKeyConfig},
9+
queue::Queue,
10+
strings::{self},
11+
ui::{self, style::SharedTheme},
12+
};
13+
use anyhow::Result;
14+
use asyncgit::sync::FilterSearchOptions;
15+
use crossterm::event::Event;
16+
use ratatui::{
17+
backend::Backend,
18+
layout::{
19+
Alignment, Constraint, Direction, Layout, Margin, Rect,
20+
},
21+
style::Style,
22+
text::{Line, Span},
23+
widgets::{Block, Borders, Clear, Paragraph},
24+
Frame,
25+
};
26+
27+
pub struct LogSearchPopupComponent {
28+
queue: Queue,
29+
visible: bool,
30+
key_config: SharedKeyConfig,
31+
find_text: TextInputComponent,
32+
options: FilterSearchOptions,
33+
theme: SharedTheme,
34+
}
35+
36+
impl LogSearchPopupComponent {
37+
///
38+
pub fn new(
39+
queue: &Queue,
40+
theme: SharedTheme,
41+
key_config: SharedKeyConfig,
42+
) -> Self {
43+
let mut find_text = TextInputComponent::new(
44+
theme.clone(),
45+
key_config.clone(),
46+
"",
47+
"search text",
48+
false,
49+
);
50+
find_text.embed();
51+
52+
Self {
53+
queue: queue.clone(),
54+
visible: false,
55+
key_config,
56+
options: FilterSearchOptions::default(),
57+
theme,
58+
find_text,
59+
}
60+
}
61+
62+
pub fn open(&mut self) -> Result<()> {
63+
self.show()?;
64+
self.find_text.show()?;
65+
self.find_text.set_text(String::new());
66+
67+
Ok(())
68+
}
69+
70+
fn execute_search(&mut self) {
71+
self.hide();
72+
}
73+
74+
fn get_text(&self) -> Vec<Line> {
75+
let mut txt: Vec<Line> = Vec::with_capacity(2);
76+
77+
let x_message =
78+
if self.options.contains(FilterSearchOptions::MESSAGE) {
79+
"X"
80+
} else {
81+
" "
82+
};
83+
84+
txt.push(Line::from(vec![Span::styled(
85+
format!("[{x_message}] message",),
86+
Style::default(),
87+
)]));
88+
89+
txt
90+
}
91+
}
92+
93+
impl DrawableComponent for LogSearchPopupComponent {
94+
fn draw<B: Backend>(
95+
&self,
96+
f: &mut Frame<B>,
97+
area: Rect,
98+
) -> Result<()> {
99+
if self.is_visible() {
100+
const SIZE: (u16, u16) = (60, 8);
101+
let area =
102+
ui::centered_rect_absolute(SIZE.0, SIZE.1, area);
103+
104+
f.render_widget(Clear, area);
105+
f.render_widget(
106+
Block::default()
107+
.borders(Borders::all())
108+
.style(self.theme.title(true))
109+
.title(Span::styled(
110+
strings::POPUP_TITLE_LOG_SEARCH,
111+
self.theme.title(true),
112+
)),
113+
area,
114+
);
115+
116+
let chunks = Layout::default()
117+
.direction(Direction::Vertical)
118+
.constraints(
119+
[
120+
Constraint::Length(1),
121+
Constraint::Percentage(100),
122+
]
123+
.as_ref(),
124+
)
125+
.split(area.inner(&Margin {
126+
horizontal: 1,
127+
vertical: 1,
128+
}));
129+
130+
self.find_text.draw(f, chunks[0])?;
131+
132+
f.render_widget(
133+
Paragraph::new(self.get_text())
134+
.block(
135+
Block::default()
136+
.borders(Borders::TOP)
137+
.border_style(self.theme.block(true)),
138+
)
139+
.alignment(Alignment::Left),
140+
chunks[1],
141+
);
142+
}
143+
144+
Ok(())
145+
}
146+
}
147+
148+
impl Component for LogSearchPopupComponent {
149+
fn commands(
150+
&self,
151+
out: &mut Vec<CommandInfo>,
152+
force_all: bool,
153+
) -> CommandBlocking {
154+
if self.is_visible() || force_all {
155+
out.push(
156+
CommandInfo::new(
157+
strings::commands::close_popup(&self.key_config),
158+
true,
159+
true,
160+
)
161+
.order(1),
162+
);
163+
out.push(
164+
CommandInfo::new(
165+
strings::commands::navigate_tree(
166+
&self.key_config,
167+
),
168+
true,
169+
true,
170+
)
171+
.order(1),
172+
);
173+
out.push(CommandInfo::new(
174+
strings::commands::confirm_action(&self.key_config),
175+
true,
176+
self.visible,
177+
));
178+
}
179+
180+
visibility_blocking(self)
181+
}
182+
183+
fn event(
184+
&mut self,
185+
event: &crossterm::event::Event,
186+
) -> Result<EventState> {
187+
if self.is_visible() {
188+
if let Event::Key(key) = &event {
189+
if key_match(key, self.key_config.keys.exit_popup) {
190+
self.hide();
191+
} else if key_match(key, self.key_config.keys.enter) {
192+
self.execute_search();
193+
}
194+
}
195+
196+
if self.find_text.event(event)?.is_consumed() {
197+
return Ok(EventState::Consumed);
198+
}
199+
200+
return Ok(EventState::Consumed);
201+
}
202+
203+
Ok(EventState::NotConsumed)
204+
}
205+
206+
fn is_visible(&self) -> bool {
207+
self.visible
208+
}
209+
210+
fn hide(&mut self) {
211+
self.visible = false;
212+
}
213+
214+
fn show(&mut self) -> Result<()> {
215+
self.visible = true;
216+
217+
Ok(())
218+
}
219+
}

src/components/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ mod file_revlog;
1515
mod fuzzy_find_popup;
1616
mod help;
1717
mod inspect_commit;
18+
mod log_search_popup;
1819
mod msg;
1920
mod options_popup;
2021
mod pull;
@@ -51,6 +52,7 @@ pub use file_revlog::{FileRevOpen, FileRevlogComponent};
5152
pub use fuzzy_find_popup::FuzzyFindPopup;
5253
pub use help::HelpComponent;
5354
pub use inspect_commit::{InspectCommitComponent, InspectCommitOpen};
55+
pub use log_search_popup::LogSearchPopupComponent;
5456
pub use msg::MsgComponent;
5557
pub use options_popup::{AppOption, OptionsPopupComponent};
5658
pub use pull::PullComponent;

src/queue.rs

+2
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ pub enum InternalEvent {
113113
///
114114
OpenFuzzyFinder(Vec<String>, FuzzyFinderTarget),
115115
///
116+
OpenLogSearchPopup,
117+
///
116118
FuzzyFinderChanged(usize, String, FuzzyFinderTarget),
117119
///
118120
FetchRemotes,

src/strings.rs

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ pub static PUSH_TAGS_STATES_DONE: &str = "done";
2929

3030
pub static POPUP_TITLE_SUBMODULES: &str = "Submodules";
3131
pub static POPUP_TITLE_FUZZY_FIND: &str = "Fuzzy Finder";
32+
pub static POPUP_TITLE_LOG_SEARCH: &str = "Search";
3233

3334
pub static POPUP_FAIL_COPY: &str = "Failed to copy text";
3435
pub static POPUP_SUCCESS_COPY: &str = "Copied Text";

src/tabs/revlog.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,8 @@ impl Component for Revlog {
431431
);
432432
} else if key_match(k, self.key_config.keys.log_find)
433433
{
434-
self.find();
434+
self.queue
435+
.push(InternalEvent::OpenLogSearchPopup);
435436
return Ok(EventState::Consumed);
436437
} else if key_match(
437438
k,

0 commit comments

Comments
 (0)