Skip to content
168 linesCodeBlameRaw

Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.

The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.1//! The app's menu: File, Edit, View, Go, Window and Help, as a desktop app
2//! has. On macOS it is the menu bar at the top of the screen, with g1t's
3//! own menu first; on Windows and Linux it sits under the window's title,
4//! and settings can hide it. The tray's menu (tray.rs) shares its ids, and
5//! every menu event, from either, comes to `handle`.
6
7use tauri::menu::{AboutMetadata, Menu, MenuItem, PredefinedMenuItem, Submenu};
8use tauri::{AppHandle, Manager, Wry};
9use tauri_plugin_opener::OpenerExt;
10
11use crate::{WINDOW, links, settings, tray, updates};
12
13const DOCS: &str = "https://docs.g1t.sh/guides/desktop/";
14const STATUS: &str = "https://status.g1t.sh/";
15
16pub fn build(app: &AppHandle) -> tauri::Result<Menu<Wry>> {
17 let separator = || PredefinedMenuItem::separator(app);
18 let item = |id: &str, text: &str, accelerator: Option<&str>| MenuItem::with_id(app, id, text, true, accelerator);
19
20 let settings_item = item("settings", if cfg!(target_os = "macos") { "Settings…" } else { "Settings" }, Some("CmdOrCtrl+,"))?;
21 let check = item("check", "Check for updates…", None)?;
22 let server = item("server", "Use another g1t…", None)?;
23 let quit = item("quit", "Quit g1t", Some("CmdOrCtrl+Q"))?;
24
25 let edit = Submenu::with_items(
26 app,
27 "Edit",
28 true,
29 &[
30 &PredefinedMenuItem::undo(app, None)?,
31 &PredefinedMenuItem::redo(app, None)?,
32 &separator()?,
33 &PredefinedMenuItem::cut(app, None)?,
34 &PredefinedMenuItem::copy(app, None)?,
35 &PredefinedMenuItem::paste(app, None)?,
36 &PredefinedMenuItem::select_all(app, None)?,
37 ],
38 )?;
39 let view = Submenu::with_items(
40 app,
41 "View",
42 true,
43 &[
44 &item("reload", "Reload", Some("CmdOrCtrl+R"))?,
45 &separator()?,
46 &item("zoom-reset", "Actual size", Some("CmdOrCtrl+0"))?,
47 &item("zoom-in", "Zoom in", Some("CmdOrCtrl+="))?,
48 &item("zoom-out", "Zoom out", Some("CmdOrCtrl+-"))?,
49 &separator()?,
50 &PredefinedMenuItem::fullscreen(app, None)?,
51 ],
52 )?;
53 let go = Submenu::with_items(
54 app,
55 "Go",
56 true,
57 &[
58 &item("back", "Back", Some(if cfg!(target_os = "macos") { "Cmd+[" } else { "Alt+Left" }))?,
59 &item("forward", "Forward", Some(if cfg!(target_os = "macos") { "Cmd+]" } else { "Alt+Right" }))?,
60 &separator()?,
61 &item("home", "Home", None)?,
62 &item("notifications", "Notifications", None)?,
63 ],
64 )?;
65 let window = Submenu::with_items(
66 app,
67 "Window",
68 true,
69 &[&PredefinedMenuItem::minimize(app, None)?, &PredefinedMenuItem::maximize(app, None)?],
70 )?;
71 let help = Submenu::with_items(app, "Help", true, &[&item("docs", "Desktop app guide", None)?, &item("status", "g1t.sh status", None)?, &separator()?, &check])?;
72 // macOS keeps About in g1t's own menu; elsewhere it closes Help.
73 #[cfg(not(target_os = "macos"))]
74 {
75 help.append(&separator()?)?;
76 help.append(&PredefinedMenuItem::about(app, Some("About g1t"), Some(about()))?)?;
77 }
78
79 #[cfg(target_os = "macos")]
80 {
81 let g1t = Submenu::with_items(
82 app,
83 "g1t",
84 true,
85 &[
86 &PredefinedMenuItem::about(app, Some("About g1t"), Some(about()))?,
87 &separator()?,
88 &settings_item,
89 &server,
90 &separator()?,
91 &PredefinedMenuItem::services(app, None)?,
92 &separator()?,
93 &PredefinedMenuItem::hide(app, None)?,
94 &PredefinedMenuItem::hide_others(app, None)?,
95 &PredefinedMenuItem::show_all(app, None)?,
96 &separator()?,
97 &quit,
98 ],
99 )?;
100 let file = Submenu::with_items(app, "File", true, &[&PredefinedMenuItem::close_window(app, None)?])?;
101 Menu::with_items(app, &[&g1t, &file, &edit, &view, &go, &window, &help])
102 }
103 #[cfg(not(target_os = "macos"))]
104 {
105 let file = Submenu::with_items(
106 app,
107 "File",
108 true,
109 &[&settings_item, &server, &separator()?, &item("close", "Close window", Some("CmdOrCtrl+W"))?, &quit],
110 )?;
111 Menu::with_items(app, &[&file, &edit, &view, &go, &window, &help])
112 }
113}
114
115fn about() -> AboutMetadata<'static> {
116 AboutMetadata {
117 name: Some("g1t".into()),
118 version: Some(env!("CARGO_PKG_VERSION").into()),
119 copyright: Some("Flagon, Inc.".into()),
120 website: Some("https://g1t.sh".into()),
121 website_label: Some("g1t.sh".into()),
122 ..Default::default()
123 }
124}
125
126/// Runs the script on the main window's page.
127fn eval(app: &AppHandle, script: &str) {
128 if let Some(window) = app.get_webview_window(WINDOW) {
129 let _ = window.eval(script);
130 }
131}
132
133/// A menu row was chosen, from the app's menu or the tray's.
134pub fn handle(app: &AppHandle, id: &str) {
135 match id {
136 "open" => tray::show(app),
137 "settings" => settings::open(app),
138 "server" => tray::launcher(app, "change"),
139 "check" => {
140 let app = app.clone();
141 tauri::async_runtime::spawn(async move {
142 let _ = updates::check(&app, true).await;
143 });
144 }
145 "restart" => updates::restart(app),
146 "quit" => updates::quit(app),
147 "close" => tray::close(app),
148 "reload" => {
149 if let Some(window) = app.get_webview_window(WINDOW) {
150 let _ = window.reload();
151 }
152 }
153 "zoom-in" => settings::zoom(app, 1),
154 "zoom-out" => settings::zoom(app, -1),
155 "zoom-reset" => settings::zoom(app, 0),
156 "back" => eval(app, "history.back()"),
157 "forward" => eval(app, "history.forward()"),
158 "home" => links::go(app, "/"),
159 "notifications" => links::go(app, "/notifications"),
160 "docs" => {
161 let _ = app.opener().open_url(DOCS, None::<&str>);
162 }
163 "status" => {
164 let _ = app.opener().open_url(STATUS, None::<&str>);
165 }
166 _ => {}
167 }
168}