Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::app::apps::{App, AppCommand, ICNS_ICON};
use crate::commands::Function;
use crate::config::{Config, MainPage, Shelly};
use crate::debounce::DebouncePolicy;
use crate::platform::macos::launching::Shortcut;
use crate::utils::icns_data_to_handle;
use crate::{app::tile::ExtSender, clipboard::ClipBoardContentType};
use iced::time::Duration;
Expand Down Expand Up @@ -90,7 +91,7 @@ pub enum Message {
OpenResult(u32),
OpenToSettings,
SearchQueryChanged(String, Id),
KeyPressed(u32),
KeyPressed(Shortcut),
FocusTextInput(Move),
HideWindow(Id),
RunFunction(Function),
Expand Down
34 changes: 17 additions & 17 deletions src/app/menubar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use std::{collections::HashMap, io::Cursor};

use global_hotkey::hotkey::{Code, HotKey, Modifiers};
use global_hotkey::hotkey::{Code, Modifiers};
use image::{DynamicImage, ImageReader};
use log::info;
use tray_icon::{
Expand All @@ -16,6 +16,7 @@ use tray_icon::{
use crate::{
app::{Message, tile::ExtSender},
config::Config,
platform::macos::launching::Shortcut,
utils::open_url,
};

Expand All @@ -39,14 +40,15 @@ pub fn menu_icon(config: Config, sender: ExtSender) -> TrayIcon {
}

pub fn menu_builder(config: Config, sender: ExtSender, update_item: bool) -> Menu {
let hotkey = config.toggle_hotkey.parse::<HotKey>().ok();
let shortcut =
Shortcut::parse(&config.toggle_hotkey).unwrap_or(Shortcut::parse("opt+space").unwrap());

let mut modes = config.modes;
if !modes.contains_key("default") {
modes.insert("Default".to_string(), "default".to_string());
}

init_event_handler(sender, hotkey.map(|x| x.id));
init_event_handler(sender, shortcut);

Menu::with_items(&[
&MenuItem::with_id(
Expand All @@ -64,7 +66,7 @@ pub fn menu_builder(config: Config, sender: ExtSender, update_item: bool) -> Men
&open_github_item(),
&PredefinedMenuItem::separator(),
&refresh_item(),
&open_item(hotkey),
&open_item(),
&mode_item(modes),
&PredefinedMenuItem::separator(),
&open_issue_item(),
Expand All @@ -86,10 +88,12 @@ fn get_image() -> DynamicImage {
.unwrap()
}

fn init_event_handler(sender: ExtSender, hotkey_id: Option<u32>) {
fn init_event_handler(sender: ExtSender, shortcut: Shortcut) {
let runtime = Runtime::new().unwrap();
let shortcut = shortcut.clone();

MenuEvent::set_event_handler(Some(move |x: MenuEvent| {
let shortcut = shortcut.clone();
let sender = sender.clone();
let sender = sender.0.clone();
info!("Menubar event called: {}", x.id.0);
Expand All @@ -107,11 +111,12 @@ fn init_event_handler(sender: ExtSender, hotkey_id: Option<u32>) {
open_url("https://github.com/RustCastLabs/rustcast/issues/new");
}
"show_rustcast" => {
if let Some(hk) = hotkey_id {
runtime.spawn(async move {
sender.clone().try_send(Message::KeyPressed(hk)).unwrap();
});
}
runtime.spawn(async move {
sender
.clone()
.try_send(Message::KeyPressed(shortcut.clone()))
.unwrap();
});
}
"update" => {
open_url("https://github.com/RustCastLabs/rustcast/releases/latest");
Expand Down Expand Up @@ -178,13 +183,8 @@ fn mode_item(modes: HashMap<String, String>) -> Submenu {
Submenu::with_items("Modes", true, &items).unwrap()
}

fn open_item(hotkey: Option<HotKey>) -> MenuItem {
MenuItem::with_id(
"show_rustcast",
"Toggle View",
true,
hotkey.map(|hk| Accelerator::new(Some(hk.mods), hk.key)),
)
fn open_item() -> MenuItem {
MenuItem::with_id("show_rustcast", "Toggle View", true, None)
}

fn open_github_item() -> MenuItem {
Expand Down
4 changes: 2 additions & 2 deletions src/app/pages/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ pub fn settings_page(config: Config) -> Element<'static, Message> {
.width(Length::Fill)
.style(move |_, _| settings_text_input_item_style(&hotkey_theme))
.into(),
notice_item(theme.clone(), "Requires a restart"),
notice_item(theme.clone(), "Use \"+\" as a seperator"),
]);

let cb_theme = theme.clone();
Expand All @@ -56,7 +56,7 @@ pub fn settings_page(config: Config) -> Element<'static, Message> {
.width(Length::Fill)
.style(move |_, _| settings_text_input_item_style(&cb_theme))
.into(),
notice_item(theme.clone(), "Requires a restart"),
notice_item(theme.clone(), "Use \"+\" as a seperator"),
]);

let placeholder_theme = theme.clone();
Expand Down
54 changes: 16 additions & 38 deletions src/app/tile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,12 @@ pub mod update;
use crate::app::apps::App;
use crate::app::{ArrowKey, Message, Move, Page};
use crate::clipboard::ClipBoardContentType;
use crate::config::Config;
use crate::config::{Config, Shelly};
use crate::debounce::Debouncer;
use crate::platform::default_app_paths;
use crate::platform::macos::launching::Shortcut;

use arboard::Clipboard;
use global_hotkey::hotkey::HotKey;
use global_hotkey::{GlobalHotKeyEvent, HotKeyState};

use iced::futures::SinkExt;
use iced::futures::channel::mpsc::{Sender, channel};
Expand Down Expand Up @@ -190,9 +189,9 @@ pub struct Tile {
/// Stores the toggle [`HotKey`] and the Clipboard [`HotKey`]
#[derive(Clone, Debug)]
pub struct Hotkeys {
pub toggle: HotKey,
pub clipboard_hotkey: HotKey,
pub shells: HashMap<u32, String>,
pub toggle: Shortcut,
pub clipboard_hotkey: Shortcut,
pub shells: HashMap<Shortcut, Shelly>,
}

impl Tile {
Expand Down Expand Up @@ -229,7 +228,6 @@ impl Tile {
_ => None,
});
Subscription::batch([
Subscription::run(handle_hotkeys),
Subscription::run(handle_hot_reloading),
keyboard,
Subscription::run(handle_recipient),
Expand All @@ -241,37 +239,34 @@ impl Tile {
if let keyboard::Event::KeyPressed { key, modifiers, .. } = event {
match key {
keyboard::Key::Named(Named::ArrowUp) => {
return Some(Message::ChangeFocus(ArrowKey::Up, 1));
Some(Message::ChangeFocus(ArrowKey::Up, 1))
}
keyboard::Key::Named(Named::ArrowLeft) => {
return Some(Message::ChangeFocus(ArrowKey::Left, 1));
Some(Message::ChangeFocus(ArrowKey::Left, 1))
}
keyboard::Key::Named(Named::ArrowRight) => {
return Some(Message::ChangeFocus(ArrowKey::Right, 1));
Some(Message::ChangeFocus(ArrowKey::Right, 1))
}
keyboard::Key::Named(Named::ArrowDown) => {
return Some(Message::ChangeFocus(ArrowKey::Down, 1));
Some(Message::ChangeFocus(ArrowKey::Down, 1))
}
keyboard::Key::Character(chr) => {
if modifiers.command() && chr.to_string() == "r" {
return Some(Message::ReloadConfig);
Some(Message::ReloadConfig)
} else if chr.to_string() == "p" && modifiers.control() {
return Some(Message::ChangeFocus(ArrowKey::Up, 1));
Some(Message::ChangeFocus(ArrowKey::Up, 1))
} else if chr.to_string() == "n" && modifiers.control() {
return Some(Message::ChangeFocus(ArrowKey::Down, 1));
Some(Message::ChangeFocus(ArrowKey::Down, 1))
} else {
return Some(Message::FocusTextInput(Move::Forwards(
chr.to_string(),
)));
Some(Message::FocusTextInput(Move::Forwards(chr.to_string())))
}
}
keyboard::Key::Named(Named::Enter) => return Some(Message::OpenFocused),
keyboard::Key::Named(Named::Enter) => Some(Message::OpenFocused),
keyboard::Key::Named(Named::Backspace) => {
return Some(Message::FocusTextInput(Move::Back));
Some(Message::FocusTextInput(Move::Back))
}
_ => {}
_ => None,
}
None
} else {
None
}
Expand Down Expand Up @@ -337,22 +332,6 @@ impl Tile {
}
}

/// This is the subscription function that handles hotkeys, e.g. for hiding / showing the window
fn handle_hotkeys() -> impl futures::Stream<Item = Message> {
stream::channel(100, async |mut output| {
let receiver = GlobalHotKeyEvent::receiver();
loop {
info!("Hotkey received");
if let Ok(event) = receiver.recv()
&& event.state == HotKeyState::Pressed
{
output.try_send(Message::KeyPressed(event.id)).unwrap();
}
tokio::time::sleep(Duration::from_millis(100)).await;
}
})
}

/// This is the subscription function that handles the change in clipboard history
fn handle_clipboard_history() -> impl futures::Stream<Item = Message> {
stream::channel(100, async |mut output| {
Expand Down Expand Up @@ -602,7 +581,6 @@ fn handle_recipient() -> impl futures::Stream<Item = Message> {
let abcd = recipient
.try_recv()
.map(async |msg| {
info!("Sending a message");
output.send(msg).await.unwrap();
})
.ok();
Expand Down
23 changes: 2 additions & 21 deletions src/app/tile/elm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
use std::collections::HashMap;
use std::fs;

use global_hotkey::hotkey::HotKey;
use iced::border::Radius;
use iced::widget::scrollable::{Anchor, Direction, Scrollbar};
use iced::widget::text::LineHeight;
Expand Down Expand Up @@ -35,7 +34,7 @@ use crate::{
};

/// Initialise the base window
pub fn new(hotkey: HotKey, config: &Config) -> (Tile, Task<Message>) {
pub fn new(hotkeys: Hotkeys, config: &Config) -> (Tile, Task<Message>) {
let (id, open) = window::open(default_settings());
info!("Opening window");

Expand All @@ -60,24 +59,6 @@ pub fn new(hotkey: HotKey, config: &Config) -> (Tile, Task<Message>) {
options.par_sort_by_key(|x| x.display_name.len());
let options = AppIndex::from_apps(options);

let mut shells_map = HashMap::new();
for shell in &config.shells {
if let Some(hk_str) = &shell.hotkey
&& let Ok(hk) = hk_str.parse::<HotKey>()
{
shells_map.insert(hk.id, shell.command.clone());
}
}

let hotkeys = Hotkeys {
toggle: hotkey,
clipboard_hotkey: config
.clipboard_hotkey
.parse()
.unwrap_or("SUPER+SHIFT+C".parse().unwrap()),
shells: shells_map,
};

let home = std::env::var("HOME").unwrap_or("/".to_string());

let ranking = toml::from_str(
Expand All @@ -94,8 +75,8 @@ pub fn new(hotkey: HotKey, config: &Config) -> (Tile, Task<Message>) {
focus_id: 0,
results: vec![],
options,
emoji_apps: AppIndex::from_apps(App::emoji_apps()),
hotkeys,
emoji_apps: AppIndex::from_apps(App::emoji_apps()),
visible: true,
frontmost: None,
focused: false,
Expand Down
49 changes: 43 additions & 6 deletions src/app/tile/update.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! This handles the update logic for the tile (AKA rustcast's main window)
use std::cmp::min;
use std::collections::HashMap;
use std::fs;
use std::io::Cursor;
use std::thread;
Expand Down Expand Up @@ -34,6 +35,8 @@ use crate::commands::Function;
use crate::config::Config;
use crate::config::MainPage;
use crate::debounce::DebouncePolicy;
use crate::platform::macos::launching::Shortcut;
use crate::platform::macos::launching::global_handler;
use crate::platform::macos::{start_at_login, stop_at_login};
use crate::quit::get_open_apps;
use crate::unit_conversion;
Expand Down Expand Up @@ -91,6 +94,7 @@ pub fn handle_update(tile: &mut Tile, message: Message) -> Task<Message> {

Message::SetSender(sender) => {
tile.sender = Some(sender.clone());
global_handler(sender.clone());
if tile.config.show_trayicon {
tile.tray_icon = Some(menu_icon(tile.config.clone(), sender));
}
Expand Down Expand Up @@ -274,6 +278,24 @@ pub fn handle_update(tile: &mut Tile, message: Message) -> Task<Message> {
Err(_) => return Task::none(),
};

if let Ok(hotkey) = Shortcut::parse(&new_config.clipboard_hotkey) {
tile.hotkeys.clipboard_hotkey = hotkey
}

if let Ok(hotkey) = Shortcut::parse(&new_config.toggle_hotkey) {
tile.hotkeys.toggle = hotkey
}

let mut shell_map = HashMap::new();

for shell in &new_config.shells {
if let Some(hotkey) = shell.hotkey.clone().and_then(|x| Shortcut::parse(&x).ok()) {
shell_map.insert(hotkey, shell.clone());
}
}

tile.hotkeys.shells = shell_map;

let update_apps_task = if tile.config.shells != new_config.shells {
info!("App Update required");
Task::done(Message::UpdateApps)
Expand Down Expand Up @@ -303,17 +325,20 @@ pub fn handle_update(tile: &mut Tile, message: Message) -> Task<Message> {
Task::batch([Task::done(Message::LoadRanking), update_apps_task])
}

Message::KeyPressed(hk_id) => {
if let Some(cmd) = tile.hotkeys.shells.get(&hk_id) {
return Task::done(Message::RunFunction(Function::RunShellCommand(cmd.clone())));
Message::KeyPressed(shortcut) => {
if let Some(cmd) = tile.hotkeys.shells.get(&shortcut) {
return Task::done(Message::RunFunction(Function::RunShellCommand(
cmd.command.clone(),
)));
}

let is_clipboard_hotkey = tile.hotkeys.clipboard_hotkey.id == hk_id;
let is_open_hotkey = hk_id == tile.hotkeys.toggle.id;
let is_clipboard_hotkey = shortcut == tile.hotkeys.clipboard_hotkey;
let is_open_hotkey = shortcut == tile.hotkeys.toggle;

let clipboard_page_task = if is_clipboard_hotkey {
info!("Switching to clipboard page");
Task::done(Message::SwitchToPage(Page::ClipboardHistory))
} else if is_open_hotkey {
info!("Switching to main page");
Task::done(Message::SwitchToPage(Page::Main))
} else {
Task::none()
Expand Down Expand Up @@ -485,6 +510,18 @@ pub fn handle_update(tile: &mut Tile, message: Message) -> Task<Message> {
new_options.par_sort_by_key(|x| x.display_name.len());
tile.options = AppIndex::from_apps(new_options);

let mut shell_map = HashMap::new();

for shell in &tile.config.shells {
if let Some(has_hk) = &shell.hotkey
&& let Some(hotkey) = Shortcut::parse(has_hk).ok()
{
shell_map.insert(hotkey, shell.clone());
}
}

tile.hotkeys.shells = shell_map;

Task::none()
}

Expand Down
Loading
Loading