Skip to content
157 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
Merge branch 'main' of github.com:flagon-io/g1t26use tauri::webview::WebviewBuilder;
27use tauri::{RunEvent, WebviewUrl, WindowEvent};
preparing for cloud work28use tauri_plugin_window_state::{StateFlags, WindowExt};
29
Merge branch 'main' into worktree-agent-a0d19db53ce9b29d830/// What the window keeps between launches: its size, place, and whether it
31/// was maximized or full screen; not its frame.
32const KEPT: StateFlags = StateFlags::all().difference(StateFlags::DECORATIONS);
33
preparing for cloud work34/// The one window's label.
35pub const WINDOW: &str = "main";
36
37fn main() {
38 tauri::Builder::default()
39 // A second launch (a g1t:// link, or the icon clicked again) goes to
40 // the app already running: the link reaches links.rs through the
41 // deep-link plugin, and the window comes forward.
42 .plugin(tauri_plugin_single_instance::init(|app, _args, _cwd| tray::show(app)))
43 .plugin(tauri_plugin_deep_link::init())
44 .plugin(tauri_plugin_notification::init())
45 .plugin(tauri_plugin_opener::init())
46 .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.47 // The window's size and place come back in setup, without the plugin
Merge branch 'main' into worktree-agent-a0d19db53ce9b29d848 // also showing it: at sign-in g1t may start in the tray. Whether it
49 // has the system's frame is the title bar setting's (frame.rs), never
50 // what an earlier run left: kept, it would put the frame back round
51 // g1t's own title bar.
52 .plugin(
53 tauri_plugin_window_state::Builder::new()
54 .with_state_flags(KEPT)
55 .skip_initial_state(WINDOW)
56 .with_denylist(&[settings::SETTINGS])
57 .build(),
58 )
The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.59 // Opening at sign-in, which settings turn on; the argument tells that start from someone's.
60 .plugin(tauri_plugin_autostart::init(tauri_plugin_autostart::MacosLauncher::LaunchAgent, Some(vec![settings::AT_LOGIN])))
preparing for cloud work61 .manage(config::State::default())
Merge branch 'main' of github.com:flagon-io/g1t62 .manage(frame::State::default())
preparing for cloud work63 .invoke_handler(tauri::generate_handler![
64 bridge::desktop_info,
65 bridge::notify,
66 bridge::set_badge,
67 bridge::open_url,
68 bridge::reachable,
69 bridge::set_server,
70 bridge::check_for_updates,
The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.71 bridge::open_settings,
72 bridge::get_settings,
73 bridge::save_settings,
74 bridge::set_open_at_login,
75 bridge::change_server,
Checking for updates in the desktop app answers in its settings window, with a restart beside a downloaded version.76 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.77 bridge::restart,
78 bridge::window_control,
79 bridge::window_menu,
Merge branch 'main' of github.com:flagon-io/g1t80 bridge::title_bar_page,
81 bridge::title_bar_current,
82 bridge::title_bar_act,
preparing for cloud work83 ])
The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.84 .on_menu_event(|app, event| menu::handle(app, event.id().as_ref()))
preparing for cloud work85 .setup(|app| {
86 let handle = app.handle().clone();
Merge branch 'main' into worktree-agent-a0d19db53ce9b29d887 config::note_dev_server(&handle);
preparing for cloud work88 config::load(&handle);
89 config::allow_site(&handle)?;
The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.90 let hidden = settings::starts_hidden(&handle);
91 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.92 let custom = frame::started(&handle);
Merge branch 'main' of github.com:flagon-io/g1t93 // The site's web view: the launcher first, which goes on to the server.
94 let site = WebviewBuilder::new(frame::SITE, WebviewUrl::App("index.html".into()))
95 .initialization_script(bridge::script(custom))
preparing for cloud work96 .on_navigation({
97 let handle = handle.clone();
98 move |url| navigation::allowed(&handle, url)
99 })
100 .on_page_load({
101 let handle = handle.clone();
102 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.103 });
Merge branch 'main' of github.com:flagon-io/g1t104 let builder = frame::main_window(app, custom)?;
The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.105 // macOS has one menu bar, the app's; elsewhere the menu is the window's own.
106 #[cfg(target_os = "macos")]
107 app.set_menu(menu::build(&handle)?)?;
108 #[cfg(not(target_os = "macos"))]
109 let builder = builder.menu(menu::build(&handle)?);
Merge branch 'main' of github.com:flagon-io/g1t110 let window = builder.build()?;
The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.111 // Opened at sign-in, g1t waits in the tray; otherwise the window comes up where it was.
Merge branch 'main' into worktree-agent-a0d19db53ce9b29d8112 let _ = window.restore_state(KEPT - StateFlags::VISIBLE);
Merge branch 'main' of github.com:flagon-io/g1t113 frame::fill(&window, custom, site)?;
114 frame::layout(&window);
The desktop app draws its own title bar, as Slack and Discord do, and the site can call the app again.115 #[cfg(not(target_os = "macos"))]
116 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.117 if !hidden {
118 let _ = window.show();
Merge branch 'main' of github.com:flagon-io/g1t119 if let Some(site) = frame::site(&handle) {
120 let _ = site.set_focus();
121 }
The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.122 }
Merge branch 'main' of github.com:flagon-io/g1t123 if let Some(site) = frame::site(&handle).filter(|_| prefs.zoom != 1.0) {
124 let _ = site.set_zoom(prefs.zoom);
The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.125 }
Merge branch 'main' of github.com:flagon-io/g1t126 // Closing the window keeps g1t running, for notifications, unless
127 // settings say it quits. A new size gives the bar and the site theirs.
preparing for cloud work128 window.on_window_event({
129 let handle = handle.clone();
Merge branch 'main' of github.com:flagon-io/g1t130 let window = window.clone();
131 move |event| match event {
132 WindowEvent::CloseRequested { api, .. } => {
preparing for cloud work133 api.prevent_close();
The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.134 tray::close(&handle);
preparing for cloud work135 }
Merge branch 'main' of github.com:flagon-io/g1t136 WindowEvent::Resized(_) | WindowEvent::ScaleFactorChanged { .. } => frame::layout(&window),
137 _ => {}
preparing for cloud work138 }
139 });
140 tray::install(&handle)?;
141 links::install(&handle);
142 updates::schedule(handle);
143 Ok(())
144 })
145 .build(tauri::generate_context!())
146 .expect("g1t could not start")
147 .run(|app, event| match event {
148 // The dock icon, clicked while the window is hidden.
149 #[cfg(target_os = "macos")]
150 RunEvent::Reopen { .. } => tray::show(app),
151 // No window open is not a reason to quit: the tray is still there.
152 RunEvent::ExitRequested { api, code: None, .. } => api.prevent_exit(),
153 _ => {
154 let _ = app;
155 }
156 });
157}

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