Skip to content
145 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.

preparing for cloud work1//! The g1t desktop app: g1t.sh, or a g1t of your own, in a window of its
2//! own. The window loads the live site, so every change to g1t reaches it
3//! the moment it is deployed and nothing here needs a new build for it;
4//! only what is native lives in this program: notifications from the
The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.5//! system, a badge on the icon, a tray, a menu, `g1t://` links, the server
6//! to use, the app's own settings, and updates that install themselves
7//! (docs.g1t.sh/guides/desktop/).
preparing for cloud work8//!
9//! The site finds the app at `window.g1tDesktop` (bridge.js), the one
10//! contract between the two; what the page asks of it is answered by the
11//! commands in bridge.rs, each of which checks that the page asking is the
12//! configured server's.
13#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
14
15mod badge;
16mod bridge;
17mod config;
The desktop app draws its own title bar, as Slack and Discord do, and the site can call the app again.18mod frame;
preparing for cloud work19mod links;
The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.20mod menu;
preparing for cloud work21mod navigation;
The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.22mod settings;
preparing for cloud work23mod tray;
24mod updates;
25
26use tauri::{RunEvent, WebviewUrl, WebviewWindowBuilder, WindowEvent};
27use tauri_plugin_window_state::{StateFlags, WindowExt};
28
Merge branch 'main' into worktree-agent-a0d19db53ce9b29d829/// What the window keeps between launches: its size, place, and whether it
30/// was maximized or full screen; not its frame.
31const KEPT: StateFlags = StateFlags::all().difference(StateFlags::DECORATIONS);
32
preparing for cloud work33/// The one window's label.
34pub const WINDOW: &str = "main";
35
36fn main() {
37 tauri::Builder::default()
38 // A second launch (a g1t:// link, or the icon clicked again) goes to
39 // the app already running: the link reaches links.rs through the
40 // deep-link plugin, and the window comes forward.
41 .plugin(tauri_plugin_single_instance::init(|app, _args, _cwd| tray::show(app)))
42 .plugin(tauri_plugin_deep_link::init())
43 .plugin(tauri_plugin_notification::init())
44 .plugin(tauri_plugin_opener::init())
45 .plugin(tauri_plugin_updater::Builder::new().build())
The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.46 // The window's size and place come back in setup, without the plugin
Merge branch 'main' into worktree-agent-a0d19db53ce9b29d847 // also showing it: at sign-in g1t may start in the tray. Whether it
48 // has the system's frame is the title bar setting's (frame.rs), never
49 // what an earlier run left: kept, it would put the frame back round
50 // g1t's own title bar.
51 .plugin(
52 tauri_plugin_window_state::Builder::new()
53 .with_state_flags(KEPT)
54 .skip_initial_state(WINDOW)
55 .with_denylist(&[settings::SETTINGS])
56 .build(),
57 )
The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.58 // Opening at sign-in, which settings turn on; the argument tells that start from someone's.
59 .plugin(tauri_plugin_autostart::init(tauri_plugin_autostart::MacosLauncher::LaunchAgent, Some(vec![settings::AT_LOGIN])))
preparing for cloud work60 .manage(config::State::default())
61 .invoke_handler(tauri::generate_handler![
62 bridge::desktop_info,
63 bridge::notify,
64 bridge::set_badge,
65 bridge::open_url,
66 bridge::reachable,
67 bridge::set_server,
68 bridge::check_for_updates,
The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.69 bridge::open_settings,
70 bridge::get_settings,
71 bridge::save_settings,
72 bridge::set_open_at_login,
73 bridge::change_server,
Checking for updates in the desktop app answers in its settings window, with a restart beside a downloaded version.74 bridge::restart_to_update,
The desktop app draws its own title bar, as Slack and Discord do, and the site can call the app again.75 bridge::restart,
76 bridge::window_control,
77 bridge::window_menu,
preparing for cloud work78 ])
The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.79 .on_menu_event(|app, event| menu::handle(app, event.id().as_ref()))
preparing for cloud work80 .setup(|app| {
81 let handle = app.handle().clone();
Merge branch 'main' into worktree-agent-a0d19db53ce9b29d882 config::note_dev_server(&handle);
preparing for cloud work83 config::load(&handle);
84 config::allow_site(&handle)?;
The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.85 let hidden = settings::starts_hidden(&handle);
86 let prefs = config::settings(&handle);
The desktop app draws its own title bar, as Slack and Discord do, and the site can call the app again.87 let custom = frame::started(&handle);
The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.88 let builder = WebviewWindowBuilder::new(app, WINDOW, WebviewUrl::App("index.html".into()))
preparing for cloud work89 .title("g1t")
90 .inner_size(1280.0, 840.0)
91 .min_inner_size(720.0, 480.0)
The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.92 .visible(false)
The desktop app draws its own title bar, as Slack and Discord do, and the site can call the app again.93 .initialization_script(bridge::script(WINDOW, custom))
preparing for cloud work94 .on_navigation({
95 let handle = handle.clone();
96 move |url| navigation::allowed(&handle, url)
97 })
98 .on_page_load({
99 let handle = handle.clone();
100 move |_webview, payload| config::at(&handle, payload.url().clone())
The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.101 });
102 // macOS has one menu bar, the app's; elsewhere the menu is the window's own.
103 #[cfg(target_os = "macos")]
104 app.set_menu(menu::build(&handle)?)?;
105 #[cfg(not(target_os = "macos"))]
106 let builder = builder.menu(menu::build(&handle)?);
The desktop app draws its own title bar, as Slack and Discord do, and the site can call the app again.107 let window = frame::style(builder, custom).build()?;
The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.108 // Opened at sign-in, g1t waits in the tray; otherwise the window comes up where it was.
Merge branch 'main' into worktree-agent-a0d19db53ce9b29d8109 let _ = window.restore_state(KEPT - StateFlags::VISIBLE);
The desktop app draws its own title bar, as Slack and Discord do, and the site can call the app again.110 #[cfg(not(target_os = "macos"))]
111 frame::menu_bar(&window, custom);
The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.112 if !hidden {
113 let _ = window.show();
114 }
115 if prefs.zoom != 1.0 {
116 let _ = window.set_zoom(prefs.zoom);
117 }
118 // Closing the window keeps g1t running, for notifications, unless settings say it quits.
preparing for cloud work119 window.on_window_event({
120 let handle = handle.clone();
121 move |event| {
122 if let WindowEvent::CloseRequested { api, .. } = event {
123 api.prevent_close();
The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.124 tray::close(&handle);
preparing for cloud work125 }
126 }
127 });
128 tray::install(&handle)?;
129 links::install(&handle);
130 updates::schedule(handle);
131 Ok(())
132 })
133 .build(tauri::generate_context!())
134 .expect("g1t could not start")
135 .run(|app, event| match event {
136 // The dock icon, clicked while the window is hidden.
137 #[cfg(target_os = "macos")]
138 RunEvent::Reopen { .. } => tray::show(app),
139 // No window open is not a reason to quit: the tray is still there.
140 RunEvent::ExitRequested { api, code: None, .. } => api.prevent_exit(),
141 _ => {
142 let _ = app;
143 }
144 });
145}

This file's history is long; its oldest lines are credited to the oldest commit read.