Skip to content

Commit 57bcf4c

Browse files
authored
Merge pull request #267 from RustCastLabs/events-opening
feat: add events opening
2 parents 85f2545 + cf05647 commit 57bcf4c

12 files changed

Lines changed: 213 additions & 6 deletions

File tree

Cargo.lock

Lines changed: 40 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ objc2 = "0.6.3"
2323
objc2-app-kit = { version = "0.3.2", features = ["NSImage"] }
2424
objc2-application-services = { version = "0.3.2", default-features = false, features = ["HIServices", "Processes"] }
2525
objc2-core-foundation = "0.3.2"
26-
objc2-foundation = { version = "0.3.2", features = ["NSString"] }
26+
objc2-event-kit = "0.3.2"
27+
objc2-foundation = { version = "0.3.2", features = ["NSDateFormatter", "NSFormatter", "NSString"] }
2728
objc2-service-management = "0.3.2"
2829
once_cell = "1.21.3"
2930
rand = "0.9.2"

src/app.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ pub enum Message {
101101
OpenFileDialogue(String),
102102
ReturnFocus,
103103
EscKeyPressed(Id),
104+
UpdateEvents,
104105
ClearSearchResults,
105106
WindowFocusChanged(Id, bool),
106107
ClearSearchQuery,
@@ -131,6 +132,7 @@ pub enum SetConfigFields {
131132
HapticFeedback(bool),
132133
ShowMenubarIcon(bool),
133134
SetPage(MainPage),
135+
SetEventDuration(String),
134136
Modes(Editable<(String, String)>),
135137
Aliases(Editable<(String, String)>),
136138
SearchDirs(Editable<String>),

src/app/apps.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,16 @@ impl PartialEq for App {
5959
}
6060

6161
impl App {
62+
pub fn new(name: String, icon: Option<Handle>, desc: String, command: AppCommand) -> Self {
63+
Self {
64+
ranking: 0,
65+
open_command: command,
66+
icons: icon,
67+
search_name: name.to_lowercase(),
68+
display_name: name,
69+
desc,
70+
}
71+
}
6272
/// A vec of all the emojis as App structs
6373
pub fn emoji_apps() -> Vec<App> {
6474
emojis::iter()

src/app/pages/settings.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ pub fn settings_page(config: Config) -> Element<'static, Message> {
175175
})
176176
.into(),
177177
radio(
178-
"Frequently Used",
178+
"Frequents",
179179
MainPage::FrequentlyUsed,
180180
Some(config.main_page),
181181
|page| Message::SetConfig(SetConfigFields::SetPage(page)),
@@ -185,6 +185,14 @@ pub fn settings_page(config: Config) -> Element<'static, Message> {
185185
move |_, _| settings_radio_button_style(&theme_clone.clone())
186186
})
187187
.into(),
188+
radio("Events", MainPage::Events, Some(config.main_page), |page| {
189+
Message::SetConfig(SetConfigFields::SetPage(page))
190+
})
191+
.style({
192+
let theme_clone = theme_clone.clone();
193+
move |_, _| settings_radio_button_style(&theme_clone.clone())
194+
})
195+
.into(),
188196
radio("Nothing", MainPage::Blank, Some(config.main_page), |page| {
189197
Message::SetConfig(SetConfigFields::SetPage(page))
190198
})
@@ -277,6 +285,23 @@ pub fn settings_page(config: Config) -> Element<'static, Message> {
277285
notice_item(theme.clone(), "What font rustcast should use"),
278286
]);
279287

288+
let theme_clone = theme.clone();
289+
let event_duration = settings_item_column([
290+
settings_hint_text(theme.clone(), "Set Event duration"),
291+
text_input("Event duration", &config.event_duration.to_string())
292+
.on_input(move |input: String| {
293+
Message::SetConfig(SetConfigFields::SetEventDuration(input))
294+
})
295+
.on_submit(Message::WriteConfig(false))
296+
.width(Length::Fill)
297+
.style(move |_, _| settings_text_input_item_style(&theme_clone))
298+
.into(),
299+
notice_item(
300+
theme.clone(),
301+
"How many minutes from now the events should be displayed",
302+
),
303+
]);
304+
280305
let theme_clone = theme.clone();
281306
let theme_clone_1 = theme.clone();
282307
let theme_clone_2 = theme.clone();
@@ -431,6 +456,7 @@ pub fn settings_page(config: Config) -> Element<'static, Message> {
431456
clear_on_enter.into(),
432457
show_icons.into(),
433458
font_family.into(),
459+
event_duration.into(),
434460
text_clr.into(),
435461
bg_clr.into(),
436462
settings_hint_text(theme.clone(), "Aliases"),

src/app/tile.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use crate::clipboard::ClipBoardContentType;
88
use crate::config::{Config, Shelly};
99
use crate::debounce::Debouncer;
1010
use crate::platform::default_app_paths;
11+
use crate::platform::macos::events::Event;
1112
use crate::platform::macos::launching::Shortcut;
1213

1314
use arboard::Clipboard;
@@ -173,6 +174,7 @@ pub struct Tile {
173174
emoji_apps: AppIndex,
174175
visible: bool,
175176
focused: bool,
177+
pub events: Vec<Event>,
176178
frontmost: Option<Retained<NSRunningApplication>>,
177179
pub config: Config,
178180
hotkeys: Hotkeys,
@@ -233,6 +235,7 @@ impl Tile {
233235
keyboard,
234236
Subscription::run(crate::platform::macos::urlscheme::url_stream),
235237
Subscription::run(handle_recipient),
238+
Subscription::run(reload_events),
236239
Subscription::run(handle_version_and_rankings),
237240
Subscription::run(handle_clipboard_history),
238241
Subscription::run(handle_file_search),
@@ -595,6 +598,15 @@ fn handle_recipient() -> impl futures::Stream<Item = Message> {
595598
})
596599
}
597600

601+
fn reload_events() -> impl futures::Stream<Item = Message> {
602+
stream::channel(100, async |mut output| {
603+
loop {
604+
output.send(Message::UpdateEvents).await.ok();
605+
tokio::time::sleep(Duration::from_mins(2)).await;
606+
}
607+
})
608+
}
609+
598610
fn handle_version_and_rankings() -> impl futures::Stream<Item = Message> {
599611
stream::channel(100, async |mut output| {
600612
let current_version = format!("\"{}\"", option_env!("APP_VERSION").unwrap_or(""));

src/app/tile/elm.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use crate::app::tile::{AppIndex, Hotkeys};
2222
use crate::app::{DEFAULT_WINDOW_HEIGHT, ToApp, ToApps};
2323
use crate::config::Theme;
2424
use crate::debounce::Debouncer;
25+
use crate::platform::macos::events::Event;
2526
use crate::styles::{
2627
contents_style, glass_border, glass_surface, results_scrollbar_style, rustcast_text_input_style,
2728
};
@@ -38,6 +39,8 @@ pub fn new(hotkeys: Hotkeys, config: &Config) -> (Tile, Task<Message>) {
3839
let (id, open) = window::open(default_settings());
3940
info!("Opening window");
4041

42+
let events = Event::get_events(config.event_duration);
43+
4144
let open = open.discard().chain(window::run(id, |handle| {
4245
platform::window_config(&handle.window_handle().expect("Unable to get window handle"));
4346
transform_process_to_ui_element();
@@ -78,6 +81,7 @@ pub fn new(hotkeys: Hotkeys, config: &Config) -> (Tile, Task<Message>) {
7881
results: vec![],
7982
options,
8083
hotkeys,
84+
events,
8185
emoji_apps: AppIndex::from_apps(App::emoji_apps()),
8286
visible: true,
8387
frontmost: None,

src/app/tile/update.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ use crate::commands::Function;
3636
use crate::config::Config;
3737
use crate::config::MainPage;
3838
use crate::debounce::DebouncePolicy;
39+
use crate::platform::macos::events::Event;
3940
use crate::platform::macos::launching::Shortcut;
4041
use crate::platform::macos::launching::global_handler;
4142
use crate::platform::macos::{start_at_login, stop_at_login};
@@ -71,6 +72,11 @@ pub fn handle_update(tile: &mut Tile, message: Message) -> Task<Message> {
7172
}
7273
}
7374

75+
Message::UpdateEvents => {
76+
tile.events = Event::get_events(tile.config.event_duration);
77+
Task::none()
78+
}
79+
7480
Message::UriReceived(uri) => {
7581
let Ok(url) = Url::parse(&uri) else {
7682
return Task::none();
@@ -706,6 +712,15 @@ pub fn handle_update(tile: &mut Tile, message: Message) -> Task<Message> {
706712
SetConfigFields::Modes(Editable::Create((key, value))) => {
707713
final_config.modes.insert(key, value);
708714
}
715+
SetConfigFields::SetEventDuration(duration) => {
716+
if duration.trim().is_empty() {
717+
final_config.event_duration = 0;
718+
} else if let Ok(duration) = duration.parse::<u32>() {
719+
final_config.event_duration = duration;
720+
}
721+
722+
tile.events = Event::get_events(final_config.event_duration);
723+
}
709724
SetConfigFields::Modes(Editable::Delete((key, _))) => {
710725
final_config.modes.remove(&key);
711726
}
@@ -976,6 +991,7 @@ fn execute_query(tile: &mut Tile, id: Id) -> Task<Message> {
976991
if tile.page == Page::Main && tile.query_lc.is_empty() {
977992
tile.results = match tile.config.main_page {
978993
MainPage::FrequentlyUsed => tile.frequent_results(),
994+
MainPage::Events => tile.events.iter().map(|x| x.to_app()).collect(),
979995
MainPage::Blank => vec![],
980996
MainPage::Favourites => tile.options.get_favourites(),
981997
};

src/commands.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use crate::{
1919
pub enum Function {
2020
OpenApp(String),
2121
QuitApp(String),
22+
OpenRawUrl(String),
2223
QuitAllApps,
2324
RunShellCommand(String),
2425
OpenWebsite(String),
@@ -41,6 +42,19 @@ impl Function {
4142
));
4243
});
4344
}
45+
46+
Function::OpenRawUrl(url) => {
47+
let url = url.to_owned();
48+
thread::spawn(move || {
49+
NSWorkspace::new().openURL(
50+
&NSURL::URLWithString_relativeToURL(
51+
&objc2_foundation::NSString::from_str(&url),
52+
None,
53+
)
54+
.unwrap(),
55+
);
56+
});
57+
}
4458
Function::RunShellCommand(command) => {
4559
Command::new("sh").arg("-c").arg(command).spawn().ok();
4660
}

src/config.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ pub struct Config {
2020
pub toggle_hotkey: String,
2121
pub clipboard_hotkey: String,
2222
pub buffer_rules: Buffer,
23+
pub event_duration: u32,
2324
pub main_page: MainPage,
2425
pub start_at_login: bool,
2526
pub theme: Theme,
@@ -45,6 +46,7 @@ impl Default for Config {
4546
buffer_rules: Buffer::default(),
4647
theme: Theme::default(),
4748
start_at_login: true,
49+
event_duration: 60,
4850
placeholder: String::from("Time to be productive!"),
4951
search_url: "https://duckduckgo.com/search?q=%s".to_string(),
5052
cbhist: true,
@@ -66,16 +68,18 @@ impl Default for Config {
6668
pub enum MainPage {
6769
Favourites,
6870
FrequentlyUsed,
71+
Events,
6972
#[default]
7073
Blank,
7174
}
7275

7376
impl std::fmt::Display for MainPage {
7477
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
7578
f.write_str(match self {
76-
MainPage::Blank => "♥️ Rustcast",
79+
MainPage::Blank => "Rustcast",
7780
MainPage::Favourites => "Favourites",
7881
MainPage::FrequentlyUsed => "Frequently Used",
82+
MainPage::Events => "Events",
7983
})
8084
}
8185
}

0 commit comments

Comments
 (0)