desktop tray: card as tall as its content, card and menu open from the tray icon's edge (never over the taskbar); menu permission files
This commit is contained in:
parent
6782ac6078
commit
da7ca48ab4
17 changed files with 185 additions and 26 deletions
|
|
@ -62,7 +62,7 @@ pub fn place(tray: Rect, work: Rect, card_w: f64, card_h: f64, gap: f64) -> (f64
|
|||
|
||||
/// Whether a card action word is one the card may send.
|
||||
pub fn valid_action(a: &str) -> bool {
|
||||
matches!(a, "hide" | "open" | "route" | "refresh" | "mute" | "quit" | "external" | "ready")
|
||||
matches!(a, "hide" | "open" | "route" | "refresh" | "mute" | "quit" | "external" | "ready" | "size")
|
||||
}
|
||||
|
||||
// ---- the last snapshot ----
|
||||
|
|
@ -123,6 +123,38 @@ mod window {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// The icon rectangle of the last show, so a size change keeps the card anchored to the icon.
|
||||
static LAST_ICON: Mutex<Option<Rect>> = Mutex::new(None);
|
||||
|
||||
/// Card height in CSS px (what the page measured), clamped; the window keeps WIDTH.
|
||||
fn height_px(h: f64) -> f64 { h.clamp(120.0, HEIGHT) }
|
||||
|
||||
/// Puts the card next to `tray` at its current height: its edge GAP from the icon, inside the work area.
|
||||
fn anchor<R: Runtime>(app: &AppHandle<R>, w: &tauri::WebviewWindow<R>, tray: Rect, css_h: f64) {
|
||||
let monitor = app.monitor_from_point(tray.x + tray.w / 2.0, tray.y + tray.h / 2.0).ok().flatten().or_else(|| w.primary_monitor().ok().flatten());
|
||||
if let Some(m) = monitor {
|
||||
let s = m.scale_factor();
|
||||
let wa = m.work_area();
|
||||
let work = Rect { x: wa.position.x as f64, y: wa.position.y as f64, w: wa.size.width as f64, h: wa.size.height as f64 };
|
||||
let _ = w.set_size(tauri::PhysicalSize::new((WIDTH * s).round() as u32, (css_h * s).round() as u32));
|
||||
let (x, y) = place(tray, work, WIDTH * s, css_h * s, GAP * s);
|
||||
let _ = w.set_position(PhysicalPosition::new(x as i32, y as i32));
|
||||
}
|
||||
}
|
||||
|
||||
/// The page measured its height: resize the window to it and keep it anchored (the bottom edge stays above a bottom
|
||||
/// taskbar, no empty band under the content).
|
||||
pub fn resize<R: Runtime>(app: &AppHandle<R>, css_h: f64) {
|
||||
let Some(w) = app.get_webview_window(LABEL) else { return };
|
||||
let h = height_px(css_h);
|
||||
if let Ok(mut c) = CURRENT_H.lock() { *c = h; }
|
||||
if let Some(tray) = LAST_ICON.lock().ok().and_then(|t| *t) {
|
||||
anchor(app, &w, tray, h);
|
||||
}
|
||||
}
|
||||
|
||||
static CURRENT_H: Mutex<f64> = Mutex::new(HEIGHT);
|
||||
|
||||
/// A left click on the tray icon: shows the card next to the icon, or hides it when it is open.
|
||||
pub fn toggle<R: Runtime>(app: &AppHandle<R>, tray: Rect) {
|
||||
let Some(w) = app.get_webview_window(LABEL) else { return };
|
||||
|
|
@ -134,14 +166,9 @@ mod window {
|
|||
if just_hidden() {
|
||||
return;
|
||||
}
|
||||
let monitor = app.monitor_from_point(tray.x + tray.w / 2.0, tray.y + tray.h / 2.0).ok().flatten().or_else(|| w.primary_monitor().ok().flatten());
|
||||
if let Some(m) = monitor {
|
||||
let s = m.scale_factor();
|
||||
let wa = m.work_area();
|
||||
let work = Rect { x: wa.position.x as f64, y: wa.position.y as f64, w: wa.size.width as f64, h: wa.size.height as f64 };
|
||||
let (x, y) = place(tray, work, WIDTH * s, HEIGHT * s, GAP * s);
|
||||
let _ = w.set_position(PhysicalPosition::new(x as i32, y as i32));
|
||||
}
|
||||
if let Ok(mut t) = LAST_ICON.lock() { *t = Some(tray); }
|
||||
let h = CURRENT_H.lock().map(|c| *c).unwrap_or(HEIGHT);
|
||||
anchor(app, &w, tray, h);
|
||||
let _ = w.show();
|
||||
let _ = w.set_focus();
|
||||
let _ = app.emit_to(LABEL, "card-shown", ());
|
||||
|
|
@ -158,4 +185,4 @@ mod window {
|
|||
}
|
||||
|
||||
#[cfg(desktop)]
|
||||
pub use window::{create, hide, toggle};
|
||||
pub use window::{create, hide, resize, toggle};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue