refactor: tray panel
This commit is contained in:
@@ -1,18 +1,16 @@
|
||||
use std::ffi::CString;
|
||||
|
||||
use cocoa::appkit::NSWindowCollectionBehavior;
|
||||
use tauri::Manager;
|
||||
use tauri::{AppHandle, Manager, WebviewWindow};
|
||||
use tauri_nspanel::{
|
||||
block::ConcreteBlock,
|
||||
cocoa::{
|
||||
appkit::{NSMainMenuWindowLevel, NSView, NSWindow},
|
||||
appkit::{NSMainMenuWindowLevel, NSView, NSWindow, NSWindowCollectionBehavior},
|
||||
base::{id, nil},
|
||||
foundation::{NSPoint, NSRect},
|
||||
},
|
||||
objc::{class, msg_send, runtime::NO, sel, sel_impl},
|
||||
panel_delegate, ManagerExt, WebviewWindowExt,
|
||||
};
|
||||
use tauri_plugin_decorum::WebviewWindowExt as WebviewWindowExt2;
|
||||
|
||||
#[allow(non_upper_case_globals)]
|
||||
const NSWindowStyleMaskNonActivatingPanel: i32 = 1 << 7;
|
||||
@@ -23,14 +21,17 @@ pub fn swizzle_to_menubar_panel(app_handle: &tauri::AppHandle) {
|
||||
});
|
||||
|
||||
let window = app_handle.get_webview_window("panel").unwrap();
|
||||
window.make_transparent().unwrap();
|
||||
|
||||
let panel = window.to_panel().unwrap();
|
||||
|
||||
let handle = app_handle.clone();
|
||||
|
||||
panel_delegate.set_listener(Box::new(move |delegate_name: String| {
|
||||
if delegate_name.as_str() == "window_did_resign_key" {
|
||||
let _ = handle.emit("menubar_panel_did_resign_key", ());
|
||||
match delegate_name.as_str() {
|
||||
"window_did_resign_key" => {
|
||||
let _ = handle.emit("menubar_panel_did_resign_key", ());
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -47,12 +48,14 @@ pub fn swizzle_to_menubar_panel(app_handle: &tauri::AppHandle) {
|
||||
panel.set_delegate(panel_delegate);
|
||||
}
|
||||
|
||||
pub fn setup_menubar_panel_listeners(app_handle: &tauri::AppHandle) {
|
||||
pub fn setup_menubar_panel_listeners(app_handle: &AppHandle) {
|
||||
fn hide_menubar_panel(app_handle: &tauri::AppHandle) {
|
||||
if check_menubar_frontmost() {
|
||||
return;
|
||||
}
|
||||
|
||||
let panel = app_handle.get_webview_panel("panel").unwrap();
|
||||
|
||||
panel.order_out(None);
|
||||
}
|
||||
|
||||
@@ -79,19 +82,16 @@ pub fn setup_menubar_panel_listeners(app_handle: &tauri::AppHandle) {
|
||||
);
|
||||
}
|
||||
|
||||
pub fn update_menubar_appearance(app_handle: &tauri::AppHandle) {
|
||||
let window = app_handle.get_window("panel").unwrap();
|
||||
set_corner_radius(&window, 13.0);
|
||||
}
|
||||
|
||||
pub fn set_corner_radius(window: &tauri::Window, radius: f64) {
|
||||
pub fn set_corner_radius(window: &WebviewWindow, radius: f64) {
|
||||
let win: id = window.ns_window().unwrap() as _;
|
||||
|
||||
unsafe {
|
||||
let view: id = win.contentView();
|
||||
|
||||
view.wantsLayer();
|
||||
|
||||
let layer: id = view.layer();
|
||||
|
||||
let _: () = msg_send![layer, setCornerRadius: radius];
|
||||
}
|
||||
}
|
||||
@@ -138,7 +138,6 @@ pub fn position_menubar_panel(app_handle: &tauri::AppHandle, padding_top: f64) {
|
||||
|
||||
fn register_workspace_listener(name: String, callback: Box<dyn Fn()>) {
|
||||
let workspace: id = unsafe { msg_send![class!(NSWorkspace), sharedWorkspace] };
|
||||
|
||||
let notification_center: id = unsafe { msg_send![workspace, notificationCenter] };
|
||||
|
||||
let block = ConcreteBlock::new(move |_notif: id| {
|
||||
@@ -160,7 +159,6 @@ fn register_workspace_listener(name: String, callback: Box<dyn Fn()>) {
|
||||
|
||||
fn app_pid() -> i32 {
|
||||
let process_info: id = unsafe { msg_send![class!(NSProcessInfo), processInfo] };
|
||||
|
||||
let pid: i32 = unsafe { msg_send![process_info, processIdentifier] };
|
||||
|
||||
pid
|
||||
@@ -1,49 +0,0 @@
|
||||
use std::process::Command;
|
||||
|
||||
#[tauri::command]
|
||||
#[specta::specta]
|
||||
pub async fn show_in_folder(path: String) {
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
Command::new("explorer")
|
||||
.args(["/select,", &path]) // The comma after select is not a typo
|
||||
.spawn()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
use std::fs::metadata;
|
||||
use std::path::PathBuf;
|
||||
if path.contains(",") {
|
||||
// see https://gitlab.freedesktop.org/dbus/dbus/-/issues/76
|
||||
let new_path = match metadata(&path).unwrap().is_dir() {
|
||||
true => path,
|
||||
false => {
|
||||
let mut path2 = PathBuf::from(path);
|
||||
path2.pop();
|
||||
path2.into_os_string().into_string().unwrap()
|
||||
}
|
||||
};
|
||||
Command::new("xdg-open").arg(&new_path).spawn().unwrap();
|
||||
} else {
|
||||
Command::new("dbus-send")
|
||||
.args([
|
||||
"--session",
|
||||
"--dest=org.freedesktop.FileManager1",
|
||||
"--type=method_call",
|
||||
"/org/freedesktop/FileManager1",
|
||||
"org.freedesktop.FileManager1.ShowItems",
|
||||
format!("array:string:file://{path}").as_str(),
|
||||
"string:\"\"",
|
||||
])
|
||||
.spawn()
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
Command::new("open").args(["-R", &path]).spawn().unwrap();
|
||||
}
|
||||
}
|
||||
@@ -1,2 +1,3 @@
|
||||
pub mod folder;
|
||||
pub mod fns;
|
||||
pub mod tray;
|
||||
pub mod window;
|
||||
|
||||
65
src-tauri/src/commands/tray.rs
Normal file
65
src-tauri/src/commands/tray.rs
Normal file
@@ -0,0 +1,65 @@
|
||||
use std::path::PathBuf;
|
||||
use tauri::window::{Effect, EffectsBuilder};
|
||||
use tauri::{
|
||||
tray::{MouseButtonState, TrayIconEvent},
|
||||
WebviewWindowBuilder,
|
||||
};
|
||||
use tauri::{AppHandle, Manager, WebviewUrl};
|
||||
use tauri_nspanel::ManagerExt;
|
||||
|
||||
use super::fns::{
|
||||
position_menubar_panel, set_corner_radius, setup_menubar_panel_listeners,
|
||||
swizzle_to_menubar_panel,
|
||||
};
|
||||
|
||||
pub fn create_tray_panel(account: &str, app: &AppHandle) {
|
||||
let tray = app.tray_by_id("main").unwrap();
|
||||
|
||||
tray.on_tray_icon_event(|tray, event| {
|
||||
if let TrayIconEvent::Click { button_state, .. } = event {
|
||||
if button_state == MouseButtonState::Up {
|
||||
let app = tray.app_handle();
|
||||
let panel = app.get_webview_panel("panel").unwrap();
|
||||
|
||||
match panel.is_visible() {
|
||||
true => panel.order_out(None),
|
||||
false => {
|
||||
position_menubar_panel(app, 0.0);
|
||||
panel.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if let Some(window) = app.get_webview_window("panel") {
|
||||
let _ = window.destroy();
|
||||
};
|
||||
|
||||
let mut url = "/panel/".to_owned();
|
||||
url.push_str(account);
|
||||
|
||||
let window = WebviewWindowBuilder::new(app, "panel", WebviewUrl::App(PathBuf::from(url)))
|
||||
.title("Panel")
|
||||
.inner_size(350.0, 500.0)
|
||||
.fullscreen(false)
|
||||
.resizable(false)
|
||||
.visible(false)
|
||||
.decorations(false)
|
||||
.transparent(true)
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
let _ = window.set_effects(
|
||||
EffectsBuilder::new()
|
||||
.effect(Effect::Popover)
|
||||
.state(tauri::window::EffectState::FollowsWindowActiveState)
|
||||
.build(),
|
||||
);
|
||||
|
||||
set_corner_radius(&window, 13.0);
|
||||
|
||||
// Convert window to panel
|
||||
swizzle_to_menubar_panel(app);
|
||||
setup_menubar_panel_listeners(app);
|
||||
}
|
||||
@@ -9,6 +9,9 @@ extern crate cocoa;
|
||||
#[macro_use]
|
||||
extern crate objc;
|
||||
|
||||
use nostr_sdk::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use specta::Type;
|
||||
use std::sync::Mutex;
|
||||
use std::time::Duration;
|
||||
use std::{
|
||||
@@ -16,24 +19,10 @@ use std::{
|
||||
io::{self, BufRead},
|
||||
str::FromStr,
|
||||
};
|
||||
|
||||
use nostr_sdk::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use specta::Type;
|
||||
#[cfg(target_os = "macos")]
|
||||
use tauri::tray::{MouseButtonState, TrayIconEvent};
|
||||
use tauri::{path::BaseDirectory, Manager};
|
||||
use tauri_nspanel::ManagerExt;
|
||||
use tauri_plugin_decorum::WebviewWindowExt;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
use crate::fns::{
|
||||
position_menubar_panel, setup_menubar_panel_listeners, swizzle_to_menubar_panel,
|
||||
update_menubar_appearance,
|
||||
};
|
||||
|
||||
pub mod commands;
|
||||
pub mod fns;
|
||||
pub mod nostr;
|
||||
|
||||
#[derive(Serialize)]
|
||||
@@ -129,7 +118,6 @@ fn main() {
|
||||
nostr::event::event_to_bech32,
|
||||
nostr::event::user_to_bech32,
|
||||
nostr::event::unlisten,
|
||||
commands::folder::show_in_folder,
|
||||
commands::window::create_column,
|
||||
commands::window::close_column,
|
||||
commands::window::reposition_column,
|
||||
@@ -161,37 +149,6 @@ fn main() {
|
||||
#[cfg(target_os = "macos")]
|
||||
main_window.set_traffic_lights_inset(8.0, 16.0).unwrap();
|
||||
|
||||
// Create panel
|
||||
#[cfg(target_os = "macos")]
|
||||
swizzle_to_menubar_panel(app.handle());
|
||||
#[cfg(target_os = "macos")]
|
||||
update_menubar_appearance(app.handle());
|
||||
#[cfg(target_os = "macos")]
|
||||
setup_menubar_panel_listeners(app.handle());
|
||||
|
||||
// Setup tray icon
|
||||
#[cfg(target_os = "macos")]
|
||||
let tray = app.tray_by_id("tray_panel").unwrap();
|
||||
|
||||
// Handle tray icon event
|
||||
#[cfg(target_os = "macos")]
|
||||
tray.on_tray_icon_event(|tray, event| {
|
||||
if let TrayIconEvent::Click { button_state, .. } = event {
|
||||
if button_state == MouseButtonState::Up {
|
||||
let app = tray.app_handle();
|
||||
let panel = app.get_webview_panel("panel").unwrap();
|
||||
|
||||
match panel.is_visible() {
|
||||
true => panel.order_out(None),
|
||||
false => {
|
||||
position_menubar_panel(app, 0.0);
|
||||
panel.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Create data folder if not exist
|
||||
let home_dir = app.path().home_dir().unwrap();
|
||||
let _ = fs::create_dir_all(home_dir.join("Lume/"));
|
||||
|
||||
@@ -7,6 +7,7 @@ use std::time::Duration;
|
||||
use tauri::{EventTarget, Manager, State};
|
||||
use tauri_plugin_notification::NotificationExt;
|
||||
|
||||
use crate::commands::tray::create_tray_panel;
|
||||
use crate::nostr::event::RichEvent;
|
||||
use crate::nostr::internal::{get_user_settings, init_nip65};
|
||||
use crate::nostr::utils::parse_event;
|
||||
@@ -202,6 +203,10 @@ pub async fn load_account(
|
||||
// Connect to user's relay (NIP-65)
|
||||
init_nip65(client).await;
|
||||
|
||||
// Create tray (macOS)
|
||||
#[cfg(target_os = "macos")]
|
||||
create_tray_panel(npub, &handle);
|
||||
|
||||
// Get user's contact list
|
||||
if let Ok(contacts) = client.get_contact_list(None).await {
|
||||
*state.contact_list.lock().unwrap() = contacts
|
||||
|
||||
Reference in New Issue
Block a user