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 work | 1 | //! 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 | |
| Merge remote-tracking branch 'origin/claude/cool-newton-7nm8r9' into claude/cool-newton-7nm8r9 | 5 | //! system, a badge on the icon, a tray, a menu, `g1t://` links, the server |
| Merge the desktop app's runner: it starts with the app for the signed-in person, sandboxed by default and running nothing where no sandbox is available yet, registers through the site, keeps itself up to date, and says everywhere what it is doing, why it is not, and how to fix it. | 6 | //! to use, the app's own settings, updates that install themselves, and a |
| 7 | //! self-hosted runner for the signed-in person (runner/mod.rs) | |
| Merge remote-tracking branch 'origin/claude/cool-newton-7nm8r9' into claude/cool-newton-7nm8r9 | 8 | //! (docs.g1t.sh/guides/desktop/). |
| preparing for cloud work | 9 | //! |
| 10 | //! The site finds the app at `window.g1tDesktop` (bridge.js), the one | |
| 11 | //! contract between the two; what the page asks of it is answered by the | |
| 12 | //! commands in bridge.rs, each of which checks that the page asking is the | |
| 13 | //! configured server's. | |
| 14 | #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] | |
| 15 | ||
| 16 | mod badge; | |
| 17 | mod bridge; | |
| 18 | mod config; | |
| Merge branch 'worktree-agent-a6b141eb3a7e9cf01' | 19 | mod devtools; |
| Merge remote-tracking branch 'origin/claude/cool-newton-7nm8r9' into claude/cool-newton-7nm8r9 | 20 | mod frame; |
| preparing for cloud work | 21 | mod links; |
| Merge remote-tracking branch 'origin/claude/cool-newton-7nm8r9' into claude/cool-newton-7nm8r9 | 22 | mod menu; |
| preparing for cloud work | 23 | mod navigation; |
| Merge the desktop app's runner: it starts with the app for the signed-in person, sandboxed by default and running nothing where no sandbox is available yet, registers through the site, keeps itself up to date, and says everywhere what it is doing, why it is not, and how to fix it. | 24 | mod runner; |
| Merge remote-tracking branch 'origin/claude/cool-newton-7nm8r9' into claude/cool-newton-7nm8r9 | 25 | mod settings; |
| preparing for cloud work | 26 | mod tray; |
| 27 | mod updates; | |
| 28 | ||
| Merge branch 'main' into rm-agents | 29 | use tauri::webview::{PageLoadEvent, WebviewBuilder}; |
| Merge remote-tracking branch 'origin/claude/cool-newton-7nm8r9' into claude/cool-newton-7nm8r9 | 30 | use tauri::{RunEvent, WebviewUrl, WindowEvent}; |
| preparing for cloud work | 31 | use tauri_plugin_window_state::{StateFlags, WindowExt}; |
| 32 | ||
| Merge remote-tracking branch 'origin/claude/cool-newton-7nm8r9' into claude/cool-newton-7nm8r9 | 33 | /// What the window keeps between launches: its size, place, and whether it |
| 34 | /// was maximized or full screen; not its frame. | |
| 35 | const KEPT: StateFlags = StateFlags::all().difference(StateFlags::DECORATIONS); | |
| 36 | ||
| preparing for cloud work | 37 | /// The one window's label. |
| 38 | pub const WINDOW: &str = "main"; | |
| 39 | ||
| 40 | fn main() { | |
| 41 | tauri::Builder::default() | |
| 42 | // A second launch (a g1t:// link, or the icon clicked again) goes to | |
| 43 | // the app already running: the link reaches links.rs through the | |
| 44 | // deep-link plugin, and the window comes forward. | |
| 45 | .plugin(tauri_plugin_single_instance::init(|app, _args, _cwd| tray::show(app))) | |
| 46 | .plugin(tauri_plugin_deep_link::init()) | |
| 47 | .plugin(tauri_plugin_notification::init()) | |
| 48 | .plugin(tauri_plugin_opener::init()) | |
| 49 | .plugin(tauri_plugin_updater::Builder::new().build()) | |
| Merge remote-tracking branch 'origin/claude/cool-newton-7nm8r9' into claude/cool-newton-7nm8r9 | 50 | // The window's size and place come back in setup, without the plugin |
| 51 | // also showing it: at sign-in g1t may start in the tray. Whether it | |
| 52 | // has the system's frame is the title bar setting's (frame.rs), never | |
| 53 | // what an earlier run left: kept, it would put the frame back round | |
| 54 | // g1t's own title bar. | |
| 55 | .plugin( | |
| 56 | tauri_plugin_window_state::Builder::new() | |
| 57 | .with_state_flags(KEPT) | |
| 58 | .skip_initial_state(WINDOW) | |
| 59 | .with_denylist(&[settings::SETTINGS]) | |
| 60 | .build(), | |
| 61 | ) | |
| 62 | // Opening at sign-in, which settings turn on; the argument tells that start from someone's. | |
| 63 | .plugin(tauri_plugin_autostart::init(tauri_plugin_autostart::MacosLauncher::LaunchAgent, Some(vec![settings::AT_LOGIN]))) | |
| preparing for cloud work | 64 | .manage(config::State::default()) |
| Merge remote-tracking branch 'origin/claude/cool-newton-7nm8r9' into claude/cool-newton-7nm8r9 | 65 | .manage(frame::State::default()) |
| Merge the desktop app's runner: it starts with the app for the signed-in person, sandboxed by default and running nothing where no sandbox is available yet, registers through the site, keeps itself up to date, and says everywhere what it is doing, why it is not, and how to fix it. | 66 | .manage(runner::Shared::default()) |
| preparing for cloud work | 67 | .invoke_handler(tauri::generate_handler![ |
| 68 | bridge::desktop_info, | |
| 69 | bridge::notify, | |
| 70 | bridge::set_badge, | |
| 71 | bridge::open_url, | |
| 72 | bridge::reachable, | |
| 73 | bridge::set_server, | |
| 74 | bridge::check_for_updates, | |
| Merge remote-tracking branch 'origin/claude/cool-newton-7nm8r9' into claude/cool-newton-7nm8r9 | 75 | bridge::open_settings, |
| 76 | bridge::get_settings, | |
| 77 | bridge::save_settings, | |
| 78 | bridge::set_open_at_login, | |
| 79 | bridge::change_server, | |
| 80 | bridge::restart_to_update, | |
| 81 | bridge::restart, | |
| 82 | bridge::window_control, | |
| 83 | bridge::window_menu, | |
| 84 | bridge::title_bar_page, | |
| 85 | bridge::title_bar_current, | |
| 86 | bridge::title_bar_act, | |
| Merge the desktop app's runner: it starts with the app for the signed-in person, sandboxed by default and running nothing where no sandbox is available yet, registers through the site, keeps itself up to date, and says everywhere what it is doing, why it is not, and how to fix it. | 87 | bridge::runner_status, |
| 88 | bridge::runner_offer, | |
| 89 | bridge::runner_register, | |
| 90 | bridge::runner_control, | |
| Merge branch 'main' into rm-agents | 91 | bridge::site_ready, |
| Merge branch 'worktree-agent-a6b141eb3a7e9cf01' | 92 | bridge::open_devtools, |
| preparing for cloud work | 93 | ]) |
| Merge remote-tracking branch 'origin/claude/cool-newton-7nm8r9' into claude/cool-newton-7nm8r9 | 94 | .on_menu_event(|app, event| menu::handle(app, event.id().as_ref())) |
| preparing for cloud work | 95 | .setup(|app| { |
| 96 | let handle = app.handle().clone(); | |
| Merge remote-tracking branch 'origin/claude/cool-newton-7nm8r9' into claude/cool-newton-7nm8r9 | 97 | config::note_dev_server(&handle); |
| preparing for cloud work | 98 | config::load(&handle); |
| 99 | config::allow_site(&handle)?; | |
| Merge remote-tracking branch 'origin/claude/cool-newton-7nm8r9' into claude/cool-newton-7nm8r9 | 100 | let hidden = settings::starts_hidden(&handle); |
| 101 | let prefs = config::settings(&handle); | |
| 102 | let custom = frame::started(&handle); | |
| 103 | // The site's web view: the launcher first, which goes on to the server. | |
| 104 | let site = WebviewBuilder::new(frame::SITE, WebviewUrl::App("index.html".into())) | |
| 105 | .initialization_script(bridge::script(custom)) | |
| Merge branch 'worktree-agent-a6b141eb3a7e9cf01' | 106 | // The web inspector, as the Developer tools setting has it now (devtools.rs). |
| 107 | .devtools(devtools::started(&handle)) | |
| preparing for cloud work | 108 | .on_navigation({ |
| 109 | let handle = handle.clone(); | |
| 110 | move |url| navigation::allowed(&handle, url) | |
| 111 | }) | |
| 112 | .on_page_load({ | |
| 113 | let handle = handle.clone(); | |
| Merge branch 'main' into rm-agents | 114 | move |_webview, payload| config::at(&handle, payload.url().clone(), matches!(payload.event(), PageLoadEvent::Started)) |
| Merge remote-tracking branch 'origin/claude/cool-newton-7nm8r9' into claude/cool-newton-7nm8r9 | 115 | }); |
| 116 | let builder = frame::main_window(app, custom)?; | |
| 117 | // macOS has one menu bar, the app's; elsewhere the menu is the window's own. | |
| 118 | #[cfg(target_os = "macos")] | |
| 119 | app.set_menu(menu::build(&handle)?)?; | |
| 120 | #[cfg(not(target_os = "macos"))] | |
| 121 | let builder = builder.menu(menu::build(&handle)?); | |
| 122 | let window = builder.build()?; | |
| 123 | // Opened at sign-in, g1t waits in the tray; otherwise the window comes up where it was. | |
| 124 | let _ = window.restore_state(KEPT - StateFlags::VISIBLE); | |
| 125 | frame::fill(&window, custom, site)?; | |
| 126 | frame::layout(&window); | |
| 127 | #[cfg(not(target_os = "macos"))] | |
| 128 | frame::menu_bar(&window, custom); | |
| 129 | if !hidden { | |
| 130 | let _ = window.show(); | |
| 131 | if let Some(site) = frame::site(&handle) { | |
| 132 | let _ = site.set_focus(); | |
| 133 | } | |
| 134 | } | |
| 135 | if let Some(site) = frame::site(&handle).filter(|_| prefs.zoom != 1.0) { | |
| 136 | let _ = site.set_zoom(prefs.zoom); | |
| 137 | } | |
| 138 | // Closing the window keeps g1t running, for notifications, unless | |
| 139 | // settings say it quits. A new size gives the bar and the site theirs. | |
| preparing for cloud work | 140 | window.on_window_event({ |
| 141 | let handle = handle.clone(); | |
| Merge remote-tracking branch 'origin/claude/cool-newton-7nm8r9' into claude/cool-newton-7nm8r9 | 142 | let window = window.clone(); |
| 143 | move |event| match event { | |
| 144 | WindowEvent::CloseRequested { api, .. } => { | |
| preparing for cloud work | 145 | api.prevent_close(); |
| Merge remote-tracking branch 'origin/claude/cool-newton-7nm8r9' into claude/cool-newton-7nm8r9 | 146 | tray::close(&handle); |
| preparing for cloud work | 147 | } |
| Merge remote-tracking branch 'origin/claude/cool-newton-7nm8r9' into claude/cool-newton-7nm8r9 | 148 | WindowEvent::Resized(_) | WindowEvent::ScaleFactorChanged { .. } => frame::layout(&window), |
| 149 | _ => {} | |
| preparing for cloud work | 150 | } |
| 151 | }); | |
| 152 | tray::install(&handle)?; | |
| 153 | links::install(&handle); | |
| Merge the desktop app's runner: it starts with the app for the signed-in person, sandboxed by default and running nothing where no sandbox is available yet, registers through the site, keeps itself up to date, and says everywhere what it is doing, why it is not, and how to fix it. | 154 | updates::schedule(handle.clone()); |
| 155 | // The runner starts on a thread of its own, a few seconds after the window. | |
| 156 | runner::install(&handle); | |
| preparing for cloud work | 157 | Ok(()) |
| 158 | }) | |
| 159 | .build(tauri::generate_context!()) | |
| 160 | .expect("g1t could not start") | |
| 161 | .run(|app, event| match event { | |
| 162 | // The dock icon, clicked while the window is hidden. | |
| 163 | #[cfg(target_os = "macos")] | |
| 164 | RunEvent::Reopen { .. } => tray::show(app), | |
| 165 | // No window open is not a reason to quit: the tray is still there. | |
| 166 | RunEvent::ExitRequested { api, code: None, .. } => api.prevent_exit(), | |
| Merge the desktop app's runner: it starts with the app for the signed-in person, sandboxed by default and running nothing where no sandbox is available yet, registers through the site, keeps itself up to date, and says everywhere what it is doing, why it is not, and how to fix it. | 167 | // However g1t ends, the runner it started ends with it. |
| 168 | RunEvent::Exit => runner::shutdown(app), | |
| preparing for cloud work | 169 | _ => { |
| 170 | let _ = app; | |
| 171 | } | |
| 172 | }); | |
| 173 | } |
This file's history is long; its oldest lines are credited to the oldest commit read.