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
106 changes: 106 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ iced = { version = "0.14.0", features = ["image", "tokio"] }
icns = "0.3.1"
image = "0.25.9"
libc = "0.2.180"
log = "0.4.29"
objc2 = "0.6.3"
objc2-app-kit = { version = "0.3.2", features = ["NSImage"] }
objc2-application-services = { version = "0.3.2", default-features = false, features = [
Expand All @@ -26,5 +27,6 @@ rayon = "1.11.0"
serde = { version = "1.0.228", features = ["derive"] }
tokio = { version = "1.48.0", features = ["full"] }
toml = "0.9.8"
tracing-subscriber = { version = "0.3.22", features = ["env-filter"] }
tray-icon = "0.21.3"
url = { version = "2.5.8", default-features = false }
2 changes: 2 additions & 0 deletions src/app/menubar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use std::io::Cursor;

use global_hotkey::hotkey::{Code, HotKey, Modifiers};
use image::{DynamicImage, ImageReader};
use log::info;
use tray_icon::{
Icon, TrayIcon, TrayIconBuilder,
menu::{
Expand Down Expand Up @@ -69,6 +70,7 @@ fn init_event_handler(sender: ExtSender, hotkey_id: u32) {
MenuEvent::set_event_handler(Some(move |x: MenuEvent| {
let sender = sender.clone();
let sender = sender.0.clone();
info!("Menubar event called: {}", x.id.0);
match x.id().0.as_str() {
"refresh_rustcast" => {
runtime.spawn(async move {
Expand Down
21 changes: 16 additions & 5 deletions src/app/tile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@ use iced::{
};
use iced::{event, window};

use log::info;
use objc2::rc::Retained;
use objc2_app_kit::NSRunningApplication;
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
use tray_icon::TrayIcon;

use std::fmt::Debug;
use std::fs;
use std::ops::Bound;
use std::time::Duration;
Expand Down Expand Up @@ -70,18 +72,23 @@ impl AppIndex {
/// This is the base window, and its a "Tile"
/// Its fields are:
/// - Theme ([`iced::Theme`])
/// - Focus "ID" (which element in the choices is currently selected)
/// - Query (String)
/// - Query Lowercase (String, but lowercase)
/// - Previous Query Lowercase (String)
/// - Results (Vec<[`App`]>) the results of the search
/// - Options (Vec<[`App`]>) the options to search through
/// - Options ([`AppIndex`]) the options to search through (is a BTreeMap wrapper)
/// - Emoji Apps ([`AppIndex`]) emojis that are considered as "apps"
/// - Visible (bool) whether the window is visible or not
/// - Focused (bool) whether the window is focused or not
/// - Frontmost ([`Option<Retained<NSRunningApplication>>`]) the frontmost application before the window was opened
/// - Config ([`Config`]) the app's config
/// - Open Hotkey ID (`u32`) the id of the hotkey that opens the window
/// - Hotkeys, storing the hotkey used for directly opening to the clipboard history page, and
/// opening the app
/// - Sender (The [`ExtSender`] that sends messages, used by the tray icon currently)
/// - Clipboard Content (`Vec<`[`ClipBoardContentType`]`>`) all of the cliboard contents
/// - Page ([`Page`]) the current page of the window (main or clipboard history)
/// - RustCast's height: to figure out which height to resize to
#[derive(Clone)]
pub struct Tile {
pub theme: iced::Theme,
Expand All @@ -95,7 +102,6 @@ pub struct Tile {
focused: bool,
frontmost: Option<Retained<NSRunningApplication>>,
pub config: Config,
/// The opening hotkey
hotkeys: Hotkeys,
clipboard_content: Vec<ClipBoardContentType>,
tray_icon: Option<TrayIcon>,
Expand All @@ -104,7 +110,7 @@ pub struct Tile {
pub height: f32,
}

#[derive(Clone)]
#[derive(Clone, Debug)]
pub struct Hotkeys {
pub toggle: HotKey,
pub clipboard_hotkey: HotKey,
Expand Down Expand Up @@ -285,6 +291,7 @@ fn handle_hot_reloading() -> impl futures::Stream<Item = Message> {
})
}

/// Helper fn for counting directories (since macos `.app`'s are directories) inside a directory
fn count_dirs_in_dir(dir: impl AsRef<Path>) -> usize {
// Read the directory; if it fails, treat as empty
let entries = match fs::read_dir(dir) {
Expand All @@ -298,11 +305,12 @@ fn count_dirs_in_dir(dir: impl AsRef<Path>) -> usize {
.count()
}

/// This is the subscription function that handles hotkeys for hiding / showing the window
/// 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
{
Expand Down Expand Up @@ -331,6 +339,7 @@ fn handle_clipboard_history() -> impl futures::Stream<Item = Message> {
if byte_rep != prev_byte_rep
&& let Some(content) = &byte_rep
{
info!("Adding item to cbhist");
output
.send(Message::ClipboardHistory(content.to_owned()))
.await
Expand All @@ -342,6 +351,7 @@ fn handle_clipboard_history() -> impl futures::Stream<Item = Message> {
})
}

/// Handles the rx / receiver for sending and receiving messages
fn handle_recipient() -> impl futures::Stream<Item = Message> {
stream::channel(100, async |mut output| {
let (sender, mut recipient) = channel(100);
Expand All @@ -353,6 +363,7 @@ 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
6 changes: 6 additions & 0 deletions src/app/tile/elm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use iced::{Alignment, Color, Length, Vector, window};
use iced::{Element, Task};
use iced::{Length::Fill, widget::text_input};

use log::info;
use rayon::slice::ParallelSliceMut;

use crate::app::DEFAULT_WINDOW_HEIGHT;
Expand All @@ -28,18 +29,23 @@ use crate::{
/// Initialise the base window
pub fn new(hotkey: HotKey, config: &Config) -> (Tile, Task<Message>) {
let (id, open) = window::open(default_settings());
info!("Opening window");

let open = open.discard().chain(window::run(id, |handle| {
platform::window_config(&handle.window_handle().expect("Unable to get window handle"));
transform_process_to_ui_element();
}));
info!("MacOS platform config applied");

let store_icons = config.theme.show_icons;

let mut options = get_installed_apps(store_icons);

options.extend(config.shells.iter().map(|x| x.to_app()));
info!("Loaded shell commands");

options.extend(App::basic_apps());
info!("Loaded basic apps / default apps");
options.par_sort_by_key(|x| x.name.len());
let options = AppIndex::from_apps(options);

Expand Down
5 changes: 5 additions & 0 deletions src/app/tile/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use iced::widget::operation;
use iced::widget::operation::AbsoluteOffset;
use iced::window;
use iced::window::Id;
use log::info;
use rayon::slice::ParallelSliceMut;

use crate::app::WINDOW_WIDTH;
Expand Down Expand Up @@ -160,6 +161,7 @@ pub fn handle_update(tile: &mut Tile, message: Message) -> Task<Message> {
}

Message::ResizeWindow(id, height) => {
info!("Resizing rustcast window");
tile.height = height;
window::resize(
id,
Expand Down Expand Up @@ -187,6 +189,7 @@ pub fn handle_update(tile: &mut Tile, message: Message) -> Task<Message> {
},

Message::ReloadConfig => {
info!("Reloading config");
let new_config: Config = match toml::from_str(
&fs::read_to_string(
std::env::var("HOME").unwrap_or("".to_owned())
Expand Down Expand Up @@ -280,13 +283,15 @@ pub fn handle_update(tile: &mut Tile, message: Message) -> Task<Message> {
}

Message::HideWindow(a) => {
info!("Hiding RustCast window");
tile.visible = false;
tile.focused = false;
tile.page = Page::Main;
Task::batch([window::close(a), Task::done(Message::ClearSearchResults)])
}

Message::ReturnFocus => {
info!("Restoring frontmost app");
tile.restore_frontmost();
Task::none()
}
Expand Down
Loading