Skip to content

Commit dd1c4ec

Browse files
authored
Merge pull request #119 from Mnem42/path_exclusions
Stuff
2 parents 19cc7c7 + 8028cd4 commit dd1c4ec

File tree

21 files changed

+1081
-595
lines changed

21 files changed

+1081
-595
lines changed

Cargo.lock

Lines changed: 309 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,14 @@ edition = "2024"
55

66
[target.'cfg(target_os = "windows")'.dependencies]
77
winreg = "0.52"
8-
windows = { version = "0.58", features = ["Win32_UI_WindowsAndMessaging", "Win32_Foundation", "Win32_Graphics_Gdi", "Win32_System_Com", "Win32_UI_Shell"] }
8+
windows = { version = "0.58", features = [
9+
"Win32_UI_WindowsAndMessaging",
10+
"Win32_Foundation",
11+
"Win32_Graphics_Gdi",
12+
"Win32_System_Com",
13+
"Win32_UI_Shell",
14+
"Win32_Globalization"
15+
]}
916

1017
[target.'cfg(target_os = "macos")'.dependencies]
1118
objc2 = "0.6.3"
@@ -36,6 +43,11 @@ tray-icon = "0.21.3"
3643
url = "2.5.8"
3744
tracing = "0.1.44"
3845
tracing-subscriber = "0.3.22"
46+
glob = "0.3.3"
47+
open = "5.3.3"
48+
regex = "1.12.2"
49+
lnk = "0.6.3"
50+
codepage = "0.1.2"
3951

4052
[package.metadata.bundle]
4153
name = "RustCast"

src/app.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
//! Main logic for the app
2+
23
use crate::commands::Function;
34
use iced::window::{self, Id, Settings};
45

src/app/apps.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ use crate::{
1313
app::{Message, Page, RUSTCAST_DESC_NAME},
1414
clipboard::ClipBoardContentType,
1515
commands::Function,
16+
cross_platform::get_img_handle,
1617
styles::{result_button_style, result_row_container_style},
17-
utils::handle_from_icns,
1818
};
1919

2020
/// This tells each "App" what to do when it is clicked, whether it is a function, a message, or a display
@@ -73,7 +73,7 @@ impl App {
7373
App {
7474
open_command: AppCommand::Function(Function::Quit),
7575
desc: RUSTCAST_DESC_NAME.to_string(),
76-
icons: handle_from_icns(Path::new(
76+
icons: get_img_handle(Path::new(
7777
"/Applications/Rustcast.app/Contents/Resources/icon.icns",
7878
)),
7979
name: "Quit RustCast".to_string(),
@@ -82,7 +82,7 @@ impl App {
8282
App {
8383
open_command: AppCommand::Function(Function::OpenPrefPane),
8484
desc: RUSTCAST_DESC_NAME.to_string(),
85-
icons: handle_from_icns(Path::new(
85+
icons: get_img_handle(Path::new(
8686
"/Applications/Rustcast.app/Contents/Resources/icon.icns",
8787
)),
8888
name: "Open RustCast Preferences".to_string(),
@@ -91,7 +91,7 @@ impl App {
9191
App {
9292
open_command: AppCommand::Message(Message::SwitchToPage(Page::EmojiSearch)),
9393
desc: RUSTCAST_DESC_NAME.to_string(),
94-
icons: handle_from_icns(Path::new(
94+
icons: get_img_handle(Path::new(
9595
"/Applications/Rustcast.app/Contents/Resources/icon.icns",
9696
)),
9797
name: "Search for an Emoji".to_string(),
@@ -100,7 +100,7 @@ impl App {
100100
App {
101101
open_command: AppCommand::Message(Message::SwitchToPage(Page::ClipboardHistory)),
102102
desc: RUSTCAST_DESC_NAME.to_string(),
103-
icons: handle_from_icns(Path::new(
103+
icons: get_img_handle(Path::new(
104104
"/Applications/Rustcast.app/Contents/Resources/icon.icns",
105105
)),
106106
name: "Clipboard History".to_string(),
@@ -109,7 +109,7 @@ impl App {
109109
App {
110110
open_command: AppCommand::Message(Message::ReloadConfig),
111111
desc: RUSTCAST_DESC_NAME.to_string(),
112-
icons: handle_from_icns(Path::new(
112+
icons: get_img_handle(Path::new(
113113
"/Applications/Rustcast.app/Contents/Resources/icon.icns",
114114
)),
115115
name: "Reload RustCast".to_string(),
@@ -118,7 +118,7 @@ impl App {
118118
App {
119119
open_command: AppCommand::Display,
120120
desc: RUSTCAST_DESC_NAME.to_string(),
121-
icons: handle_from_icns(Path::new(
121+
icons: get_img_handle(Path::new(
122122
"/Applications/Rustcast.app/Contents/Resources/icon.icns",
123123
)),
124124
name: format!("Current RustCast Version: {app_version}"),
@@ -129,7 +129,7 @@ impl App {
129129
"/System/Library/CoreServices/Finder.app".to_string(),
130130
)),
131131
desc: "Application".to_string(),
132-
icons: handle_from_icns(Path::new(
132+
icons: get_img_handle(Path::new(
133133
"/System/Library/CoreServices/Finder.app/Contents/Resources/Finder.icns",
134134
)),
135135
name: "Finder".to_string(),

src/app/menubar.rs

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,10 @@ use tray_icon::{
1313

1414
use crate::{
1515
app::{Message, tile::ExtSender},
16-
cross_platform::{open_settings, open_url},
16+
cross_platform::open_settings,
1717
};
1818

19-
const DISCORD_LINK: &str = "https://discord.gg/bDfNYPbnC5";
20-
21-
use tokio::runtime::Runtime;
22-
23-
/// This create a new menubar icon for the app
19+
/// This creates a new menubar icon for the app
2420
pub fn menu_icon(hotkey: HotKey, sender: ExtSender) -> TrayIcon {
2521
let builder = TrayIconBuilder::new();
2622

@@ -96,7 +92,9 @@ fn init_event_handler(sender: ExtSender, hotkey_id: u32) {
9692
.spawn(async move { sender.clone().try_send(Message::HideTrayIcon).unwrap() });
9793
}
9894
"open_issue_page" => {
99-
open_url("https://github.com/unsecretised/rustcast/issues/new");
95+
if let Err(e) = open::that("https://github.com/unsecretised/rustcast/issues/new") {
96+
tracing::error!("Error opening url: {}", e)
97+
}
10098
}
10199
"show_rustcast" => {
102100
runtime.spawn(async move {
@@ -106,17 +104,20 @@ fn init_event_handler(sender: ExtSender, hotkey_id: u32) {
106104
.unwrap();
107105
});
108106
}
109-
"open_discord" => {
110-
open_url(DISCORD_LINK);
111-
}
112107
"open_help_page" => {
113-
open_url("https://github.com/unsecretised/rustcast/discussions/new?category=q-a");
108+
if let Err(e) = open::that(
109+
"https://github.com/unsecretised/rustcast/discussions/new?category=q-a",
110+
) {
111+
tracing::error!("Error opening url: {}", e)
112+
}
114113
}
115114
"open_preferences" => {
116115
open_settings();
117116
}
118117
"open_github_page" => {
119-
open_url("https://github.com/unsecretised/rustcast");
118+
if let Err(e) = open::that("https://github.com/unsecretised/rustcast") {
119+
tracing::error!("Error opening url: {}", e)
120+
}
120121
}
121122
_ => {}
122123
}

src/app/tile.rs

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -235,19 +235,30 @@ impl Tile {
235235
}
236236

237237
// Unused, keeping it for now
238-
pub fn capture_frontmost(&mut self) {
239-
#[cfg(target_os = "macos")]
240-
{
241-
use objc2_app_kit::NSWorkspace;
238+
// pub fn capture_frontmost(&mut self) {
239+
// #[cfg(target_os = "macos")]
240+
// {
241+
// use objc2_app_kit::NSWorkspace;
242242

243-
let ws = NSWorkspace::sharedWorkspace();
244-
self.frontmost = ws.frontmostApplication();
245-
};
243+
// let ws = NSWorkspace::sharedWorkspace();
244+
// self.frontmost = ws.frontmostApplication();
245+
// };
246246

247-
#[cfg(target_os = "windows")]
248-
{
249-
self.frontmost = Some(unsafe { GetForegroundWindow() });
250-
}
247+
// #[cfg(target_os = "windows")]
248+
// {
249+
// use windows::Win32::UI::WindowsAndMessaging::GetForegroundWindow;
250+
251+
// self.frontmost = Some(unsafe { GetForegroundWindow() });
252+
// }
253+
// }
254+
255+
/// Gets the frontmost application to focus later.
256+
#[cfg(target_os = "macos")]
257+
pub fn capture_frontmost(&mut self) {
258+
use objc2_app_kit::NSWorkspace;
259+
260+
let ws = NSWorkspace::sharedWorkspace();
261+
self.frontmost = ws.frontmostApplication();
251262
}
252263

253264
/// Restores the frontmost application.

src/app/tile/elm.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@ use iced::{Length::Fill, widget::text_input};
1212

1313
use rayon::slice::ParallelSliceMut;
1414

15+
#[cfg(target_os = "windows")]
16+
use crate::app;
1517
use crate::app::WINDOW_WIDTH;
1618
use crate::app::pages::clipboard::clipboard_view;
1719
use crate::app::pages::emoji::emoji_page;
1820
use crate::app::tile::AppIndex;
19-
use crate::utils::get_installed_apps;
21+
use crate::utils::index_installed_apps;
2022
use crate::config::Theme;
2123
use crate::styles::{contents_style, rustcast_text_input_style, tint, with_alpha};
2224
use crate::{
@@ -67,7 +69,7 @@ pub fn new(hotkey: HotKey, config: &Config) -> (Tile, Task<Message>) {
6769
let (id, open) = window::open(settings);
6870

6971
#[cfg(target_os = "windows")]
70-
let open: Task<iced::window::Id> = open.discard();
72+
let open: Task<app::Message> = open.discard();
7173

7274
#[cfg(target_os = "macos")]
7375
let open = open.discard().chain(window::run(id, |handle| {
@@ -76,7 +78,14 @@ pub fn new(hotkey: HotKey, config: &Config) -> (Tile, Task<Message>) {
7678
Message::OpenWindow
7779
}));
7880

79-
let mut options: Vec<App> = get_installed_apps(config);
81+
let options = index_installed_apps(config);
82+
83+
if let Err(ref e) = options {
84+
tracing::error!("Error indexing apps: {e}")
85+
}
86+
87+
// Still try to load the rest
88+
let mut options = options.unwrap_or_default();
8089

8190
options.extend(config.shells.iter().map(|x| x.to_app()));
8291
options.extend(App::basic_apps());

src/app/tile/update.rs

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,25 +25,22 @@ use crate::app::menubar::menu_icon;
2525
use crate::app::tile::AppIndex;
2626
use crate::app::{Message, Page, tile::Tile};
2727

28-
#[cfg(target_os = "windows")]
29-
use crate::utils::get_config_installation_dir;
30-
3128
use crate::calculator::Expr;
3229
use crate::clipboard::ClipBoardContentType;
3330
use crate::commands::Function;
3431
use crate::config::Config;
3532
use crate::unit_conversion;
36-
use crate::utils::get_installed_apps;
33+
use crate::utils::index_installed_apps;
3734

38-
use crate::utils::is_valid_url;
3935
#[cfg(target_os = "macos")]
4036
use crate::{
4137
cross_platform::macos::focus_this_app,
4238
cross_platform::macos::haptics::{HapticPattern, perform_haptic},
4339
};
4440

4541
pub fn handle_update(tile: &mut Tile, message: Message) -> Task<Message> {
46-
tracing::debug!("Handling update (message: {:?})", message);
42+
tracing::trace!("Handling update (message: {:?})", message);
43+
4744
match message {
4845
Message::OpenWindow => {
4946
#[cfg(target_os = "macos")]
@@ -189,20 +186,20 @@ pub fn handle_update(tile: &mut Tile, message: Message) -> Task<Message> {
189186
Ok(a) => a,
190187
Err(_) => return Task::none(),
191188
};
189+
let mut options = Vec::new();
192190

193-
let mut new_options: Vec<App> = default_app_paths()
194-
.par_iter()
195-
.map(|path| get_installed_apps(path, new_config.theme.show_icons))
196-
.flatten()
197-
.collect();
191+
match index_installed_apps(&new_config) {
192+
Ok(x) => options.extend(x),
193+
Err(e) => tracing::error!("Error indexing apps: {e}")
194+
}
198195

199-
new_options.extend(new_config.shells.iter().map(|x| x.to_app()));
200-
new_options.extend(App::basic_apps());
201-
new_options.par_sort_by_key(|x| x.name.len());
196+
options.extend(new_config.shells.iter().map(|x| x.to_app()));
197+
options.extend(App::basic_apps());
198+
options.par_sort_by_key(|x| x.name.len());
202199

203200
tile.theme = new_config.theme.to_owned().into();
204201
tile.config = new_config;
205-
tile.options = AppIndex::from_apps(new_options);
202+
tile.options = AppIndex::from_apps(options);
206203
Task::none()
207204
}
208205

@@ -310,6 +307,7 @@ pub fn handle_update(tile: &mut Tile, message: Message) -> Task<Message> {
310307
tile.results = vec![];
311308
Task::none()
312309
}
310+
313311
Message::WindowFocusChanged(wid, focused) => {
314312
tile.focused = focused;
315313
if !focused {
@@ -332,7 +330,7 @@ pub fn handle_update(tile: &mut Tile, message: Message) -> Task<Message> {
332330
}
333331

334332
tile.query_lc = input.trim().to_lowercase();
335-
tile.query = input;
333+
tile.query = input.clone();
336334
let prev_size = tile.results.len();
337335
if tile.query_lc.is_empty() && tile.page != Page::ClipboardHistory {
338336
tile.results = vec![];
@@ -430,7 +428,7 @@ pub fn handle_update(tile: &mut Tile, message: Message) -> Task<Message> {
430428
}
431429
})
432430
.collect();
433-
} else if tile.results.is_empty() && is_valid_url(&tile.query) {
431+
} else if tile.results.is_empty() && url::Url::parse(&input).is_ok() {
434432
tile.results.push(App {
435433
open_command: AppCommand::Function(Function::OpenWebsite(tile.query.clone())),
436434
desc: "Web Browsing".to_string(),

src/commands.rs

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -75,23 +75,15 @@ impl Function {
7575
);
7676
}
7777

78-
#[cfg(target_os = "macos")]
7978
Function::OpenWebsite(url) => {
8079
let open_url = if url.starts_with("http") {
8180
url.to_owned()
8281
} else {
8382
format!("https://{}", url)
8483
};
8584

86-
thread::spawn(move || {
87-
NSWorkspace::new().openURL(
88-
&NSURL::URLWithString_relativeToURL(
89-
&objc2_foundation::NSString::from_str(&open_url),
90-
None,
91-
)
92-
.unwrap(),
93-
);
94-
});
85+
// Should never get here without it being validated first
86+
open::that(open_url).unwrap();
9587
}
9688

9789
Function::Calculate(expr) => {
@@ -110,8 +102,8 @@ impl Function {
110102
}
111103
},
112104

105+
#[cfg(target_os = "macos")]
113106
Function::OpenPrefPane => {
114-
#[cfg(target_os = "macos")]
115107
thread::spawn(move || {
116108
NSWorkspace::new().openURL(&NSURL::fileURLWithPath(
117109
&objc2_foundation::NSString::from_str(
@@ -123,6 +115,10 @@ impl Function {
123115
}
124116

125117
Function::Quit => std::process::exit(0),
118+
f => {
119+
// TODO: something in the UI to show this
120+
tracing::error!("The function {:?} is unimplemented for this platform", f);
121+
}
126122
}
127123
}
128124
}

0 commit comments

Comments
 (0)