Skip to content
106 linesCodeBlameRaw
1//! The tray icon and its menu, and showing and hiding the window. Closing
2//! the window hides it, unless settings say closing quits; g1t keeps
3//! running for notifications, and the tray's Open, or the icon, brings it
4//! back. Quit is here too. The menu's rows are handled with the app
5//! menu's (menu.rs).
6
7use std::sync::OnceLock;
8
9use tauri::menu::{Menu, MenuItem, PredefinedMenuItem};
10use tauri::tray::{MouseButton, MouseButtonState, TrayIconBuilder, TrayIconEvent};
11use tauri::{AppHandle, Manager, Wry};
12
13use crate::{WINDOW, config, updates};
14
15pub const TRAY: &str = "g1t";
16
17/// The menu row that restarts into a downloaded update: off until one is.
18static RESTART: OnceLock<MenuItem<Wry>> = OnceLock::new();
19
20pub fn install(app: &AppHandle) -> tauri::Result<()> {
21 let open = MenuItem::with_id(app, "open", "Open g1t", true, None::<&str>)?;
22 let check = MenuItem::with_id(app, "check", "Check for updates…", true, None::<&str>)?;
23 let restart = MenuItem::with_id(app, "restart", "Restart to finish updating", false, None::<&str>)?;
24 let settings = MenuItem::with_id(app, "settings", "Settings…", true, None::<&str>)?;
25 let server = MenuItem::with_id(app, "server", "Use another g1t…", true, None::<&str>)?;
26 let quit = MenuItem::with_id(app, "quit", "Quit g1t", true, None::<&str>)?;
27 let menu = Menu::with_items(
28 app,
29 &[
30 &open,
31 &PredefinedMenuItem::separator(app)?,
32 &check,
33 &restart,
34 &PredefinedMenuItem::separator(app)?,
35 &settings,
36 &server,
37 &PredefinedMenuItem::separator(app)?,
38 &quit,
39 ],
40 )?;
41 let _ = RESTART.set(restart);
42 let mut tray = TrayIconBuilder::with_id(TRAY)
43 .menu(&menu)
44 .show_menu_on_left_click(false)
45 .tooltip("g1t")
46 .on_tray_icon_event(|tray, event| {
47 if let TrayIconEvent::Click { button: MouseButton::Left, button_state: MouseButtonState::Up, .. } = event {
48 show(tray.app_handle());
49 }
50 });
51 if let Some(icon) = app.default_window_icon() {
52 tray = tray.icon(icon.clone());
53 }
54 tray.build(app)?;
55 Ok(())
56}
57
58/// The update is downloaded: the menu says so, and offers the restart.
59pub fn update_ready(version: &str) {
60 if let Some(item) = RESTART.get() {
61 let _ = item.set_text(format!("Restart to update to {version}"));
62 let _ = item.set_enabled(true);
63 }
64}
65
66pub fn show(app: &AppHandle) {
67 if let Some(window) = app.get_webview_window(WINDOW) {
68 let _ = window.show();
69 let _ = window.unminimize();
70 let _ = window.set_focus();
71 }
72}
73
74/// The window was closed: it waits in the tray, or g1t quits, as settings say.
75pub fn close(app: &AppHandle) {
76 if config::settings(app).close_to_tray {
77 hide(app);
78 } else {
79 updates::quit(app);
80 }
81}
82
83pub fn hide(app: &AppHandle) {
84 if let Some(window) = app.get_webview_window(WINDOW) {
85 let _ = window.hide();
86 }
87}
88
89/// The address of the launcher page bundled with the app.
90pub fn launcher_url(query: &str) -> url::Url {
91 let base = if cfg!(windows) { "http://tauri.localhost/" } else { "tauri://localhost/" };
92 let mut url = url::Url::parse(base).expect("the launcher's address is a URL");
93 url.set_path("/index.html");
94 if !query.is_empty() {
95 url.set_query(Some(query));
96 }
97 url
98}
99
100/// Takes the window to the launcher: `change` to choose another server.
101pub fn launcher(app: &AppHandle, query: &str) {
102 if let Some(window) = app.get_webview_window(WINDOW) {
103 let _ = window.navigate(launcher_url(query));
104 show(app);
105 }
106}