Skip to content

Commit 83c7289

Browse files
authored
Merge pull request #210 from hriztam/recent-actions
added the recent actions feature when search bar is empty
2 parents 5d5f378 + 65f58c7 commit 83c7289

7 files changed

Lines changed: 110 additions & 45 deletions

File tree

docs/config.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,4 +66,3 @@ command = "echo "
6666
# icon_path is optional
6767
alias = "Variables 1" # the name that will be displayed in the results
6868
alias_lc = "var test" # the name used to search for it
69-

src/app.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ pub enum Message {
8383
UpdateAvailable,
8484
ResizeWindow(Id, f32),
8585
OpenWindow,
86+
OpenResult(u32),
8687
OpenToSettings,
8788
SearchQueryChanged(String, Id),
8889
KeyPressed(u32),

src/app/apps.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ impl App {
165165
theme: crate::config::Theme,
166166
id_num: u32,
167167
focussed_id: u32,
168+
on_press: Option<Message>,
168169
) -> iced::Element<'static, Message> {
169170
let focused = focussed_id == id_num;
170171

@@ -202,11 +203,11 @@ impl App {
202203
}
203204
row = row.push(container(text_block).width(Fill));
204205

205-
let msg = match self.open_command.clone() {
206+
let msg = on_press.or(match self.open_command.clone() {
206207
AppCommand::Function(func) => Some(Message::RunFunction(func)),
207208
AppCommand::Message(msg) => Some(msg),
208209
AppCommand::Display => None,
209-
};
210+
});
210211

211212
let theme_clone = theme.clone();
212213

src/app/pages/clipboard.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ pub fn clipboard_view(
6060
Column::from_iter(clipboard_content.iter().enumerate().map(|(i, content)| {
6161
content
6262
.to_app()
63-
.render(theme.clone(), i as u32, focussed_id)
63+
.render(theme.clone(), i as u32, focussed_id, None)
6464
}))
6565
.width(WINDOW_WIDTH / 3.),
6666
Direction::Vertical(Scrollbar::hidden()),

src/app/tile.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use log::{info, warn};
2727
use objc2::rc::Retained;
2828
use objc2_app_kit::NSRunningApplication;
2929
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
30+
use rayon::slice::ParallelSliceMut;
3031
use tokio::io::AsyncBufReadExt;
3132
use tray_icon::TrayIcon;
3233

@@ -71,6 +72,24 @@ impl AppIndex {
7172
app.ranking += 1;
7273
}
7374

75+
fn top_ranked(&self, limit: usize) -> Vec<App> {
76+
let mut ranked: Vec<App> = self
77+
.by_name
78+
.values()
79+
.filter(|app| app.ranking > 0)
80+
.cloned()
81+
.collect();
82+
83+
ranked.par_sort_by(|left, right| {
84+
right
85+
.ranking
86+
.cmp(&left.ranking)
87+
.then_with(|| left.display_name.cmp(&right.display_name))
88+
});
89+
ranked.truncate(limit);
90+
ranked
91+
}
92+
7493
fn empty() -> AppIndex {
7594
AppIndex {
7695
by_name: HashMap::new(),
@@ -261,6 +280,10 @@ impl Tile {
261280
self.results = results;
262281
}
263282

283+
pub fn frequent_results(&self) -> Vec<App> {
284+
self.options.top_ranked(5)
285+
}
286+
264287
/// Gets the frontmost application to focus later.
265288
pub fn capture_frontmost(&mut self) {
266289
use objc2_app_kit::NSWorkspace;

src/app/tile/elm.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,12 @@ pub fn view(tile: &Tile, wid: window::Id) -> Element<'_, Message> {
136136
Page::Settings => settings_page(tile.config.clone()),
137137
Page::FileSearch | Page::Main => container(Column::from_iter(
138138
tile.results.iter().enumerate().map(|(i, app)| {
139-
app.clone()
140-
.render(tile.config.theme.clone(), i as u32, tile.focus_id)
139+
app.clone().render(
140+
tile.config.theme.clone(),
141+
i as u32,
142+
tile.focus_id,
143+
Some(Message::OpenResult(i as u32)),
144+
)
141145
}),
142146
))
143147
.into(),
@@ -164,7 +168,11 @@ pub fn view(tile: &Tile, wid: window::Id) -> Element<'_, Message> {
164168
.height(height as u32);
165169

166170
let text = if tile.query_lc.is_empty() {
167-
tile.page.to_string()
171+
if tile.page == Page::Main {
172+
"Frequently used".to_string()
173+
} else {
174+
tile.page.to_string()
175+
}
168176
} else {
169177
match results_count {
170178
1 => "1 result found".to_string(),

src/app/tile/update.rs

Lines changed: 71 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,14 @@ pub fn handle_update(tile: &mut Tile, message: Message) -> Task<Message> {
4848
focus_this_app();
4949
tile.focused = true;
5050
tile.visible = true;
51-
Task::none()
51+
52+
if tile.page == Page::Main && tile.query_lc.is_empty() {
53+
window::latest()
54+
.map(|x| x.unwrap())
55+
.map(|id| Message::SearchQueryChanged(String::new(), id))
56+
} else {
57+
Task::none()
58+
}
5259
}
5360

5461
Message::UpdateAvailable => {
@@ -221,42 +228,8 @@ pub fn handle_update(tile: &mut Tile, message: Message) -> Task<Message> {
221228
)
222229
}
223230

224-
Message::OpenFocused => {
225-
info!("Open Focussed called");
226-
let results = if tile.page == Page::ClipboardHistory {
227-
tile.clipboard_content
228-
.iter()
229-
.map(|x| x.to_app().to_owned())
230-
.collect()
231-
} else {
232-
tile.results.clone()
233-
};
234-
match results.get(tile.focus_id as usize) {
235-
Some(App {
236-
search_name: name,
237-
open_command: AppCommand::Function(func),
238-
..
239-
}) => {
240-
info!("Updating ranking for: {name}");
241-
tile.options.update_ranking(name);
242-
Task::done(Message::RunFunction(func.to_owned()))
243-
}
244-
Some(App {
245-
search_name: name,
246-
open_command: AppCommand::Message(msg),
247-
..
248-
}) => {
249-
info!("Updating ranking for: {name}");
250-
tile.options.update_ranking(name);
251-
Task::done(msg.to_owned())
252-
}
253-
Some(App {
254-
open_command: AppCommand::Display,
255-
..
256-
}) => Task::done(Message::ReturnFocus),
257-
None => Task::none(),
258-
}
259-
}
231+
Message::OpenFocused => Task::done(Message::OpenResult(tile.focus_id)),
232+
Message::OpenResult(id) => open_result(tile, id as usize),
260233

261234
Message::ReloadConfig => {
262235
info!("Reloading config");
@@ -355,10 +328,19 @@ pub fn handle_update(tile: &mut Tile, message: Message) -> Task<Message> {
355328
_ => Task::none(),
356329
};
357330

331+
let refresh_empty_main_query = if tile.page == Page::Main {
332+
window::latest()
333+
.map(|x| x.unwrap())
334+
.map(|id| Message::SearchQueryChanged(String::new(), id))
335+
} else {
336+
Task::none()
337+
};
338+
358339
Task::batch([
359340
Task::done(Message::ClearSearchQuery),
360341
Task::done(Message::ClearSearchResults),
361342
task,
343+
refresh_empty_main_query,
362344
])
363345
}
364346

@@ -574,7 +556,7 @@ pub fn handle_update(tile: &mut Tile, message: Message) -> Task<Message> {
574556
let mut final_config = tile.config.clone();
575557
match config {
576558
SetConfigFields::ToggleHotkey(hk) => final_config.toggle_hotkey = hk,
577-
SetConfigFields::ClipboardHotkey(hk) => final_config.toggle_hotkey = hk,
559+
SetConfigFields::ClipboardHotkey(hk) => final_config.clipboard_hotkey = hk,
578560
SetConfigFields::Modes(Editable::Create((key, value))) => {
579561
final_config.modes.insert(key, value);
580562
}
@@ -724,6 +706,52 @@ fn zero_item_resize_task(id: Id) -> Task<Message> {
724706
Task::done(Message::ResizeWindow(id, DEFAULT_WINDOW_HEIGHT))
725707
}
726708

709+
fn resize_for_results_count(id: Id, count: usize) -> Task<Message> {
710+
if count == 0 {
711+
return zero_item_resize_task(id);
712+
}
713+
if count == 1 {
714+
return single_item_resize_task(id);
715+
}
716+
717+
let max_elem = min(5, count);
718+
Task::done(Message::ResizeWindow(
719+
id,
720+
((max_elem * 55) + 35 + DEFAULT_WINDOW_HEIGHT as usize) as f32,
721+
))
722+
}
723+
724+
fn open_result(tile: &mut Tile, id: usize) -> Task<Message> {
725+
let results = if tile.page == Page::ClipboardHistory {
726+
tile.clipboard_content
727+
.iter()
728+
.map(|x| x.to_app().to_owned())
729+
.collect()
730+
} else {
731+
tile.results.clone()
732+
};
733+
734+
let Some(app) = results.get(id).cloned() else {
735+
return Task::none();
736+
};
737+
738+
let search_name = app.search_name.clone();
739+
740+
match app.open_command {
741+
AppCommand::Function(func) => {
742+
info!("Updating ranking for: {search_name}");
743+
tile.options.update_ranking(&search_name);
744+
Task::done(Message::RunFunction(func))
745+
}
746+
AppCommand::Message(msg) => {
747+
info!("Updating ranking for: {search_name}");
748+
tile.options.update_ranking(&search_name);
749+
Task::done(msg)
750+
}
751+
AppCommand::Display => Task::done(Message::ReturnFocus),
752+
}
753+
}
754+
727755
/// Handling the lemon easter egg icon
728756
fn lemon_icon_handle() -> Option<Handle> {
729757
image::ImageReader::new(Cursor::new(include_bytes!("../../../docs/lemon.png")))
@@ -747,6 +775,11 @@ fn execute_query(tile: &mut Tile, id: Id) -> Task<Message> {
747775
_ => {}
748776
}
749777

778+
if tile.page == Page::Main && tile.query_lc.is_empty() {
779+
tile.results = tile.frequent_results();
780+
return resize_for_results_count(id, tile.results.len());
781+
}
782+
750783
if tile.query_lc.is_empty()
751784
|| (tile.query_lc.chars().count() < 2 && tile.page == Page::FileSearch)
752785
{

0 commit comments

Comments
 (0)