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 | //! `g1t://` links. `g1t://acme/-/chat/dm/chn_1` opens that page on the |
| 2 | //! server: the site, when the window is on it, is told the path and moves | |
| 3 | //! without a reload; otherwise the window loads the page. A link that | |
| 4 | //! started the app is read on the way up; one that arrives while it runs | |
| 5 | //! comes through the deep-link plugin, from a second launch too. | |
| 6 | ||
| 7 | use tauri::{AppHandle, Emitter, Manager}; | |
| 8 | use tauri_plugin_deep_link::DeepLinkExt; | |
| 9 | use url::Url; | |
| 10 | ||
| 11 | use crate::{WINDOW, config, tray}; | |
| 12 | ||
| 13 | /// What the page listens for (bridge.js). | |
| 14 | pub const EVENT: &str = "g1t-navigate"; | |
| 15 | ||
| 16 | pub fn install(app: &AppHandle) { | |
| 17 | // Installers register the scheme; a build run from the source tree, | |
| 18 | // and an AppImage, need it done here. | |
| 19 | #[cfg(any(windows, target_os = "linux"))] | |
| 20 | let _ = app.deep_link().register_all(); | |
| 21 | let handle = app.clone(); | |
| 22 | app.deep_link().on_open_url(move |event| { | |
| 23 | for url in event.urls() { | |
| 24 | open(&handle, &url); | |
| 25 | } | |
| 26 | }); | |
| 27 | if let Ok(Some(urls)) = app.deep_link().get_current() { | |
| 28 | for url in urls { | |
| 29 | open(app, &url); | |
| 30 | } | |
| 31 | } | |
| 32 | } | |
| 33 | ||
| 34 | /// The site path a link names: `g1t://acme/-/chat?x` is `/acme/-/chat?x`. | |
| 35 | pub fn path_of(url: &Url) -> Option<String> { | |
| 36 | if url.scheme() != "g1t" { | |
| 37 | return None; | |
| 38 | } | |
| 39 | let mut path = match url.host_str() { | |
| 40 | Some(host) if !host.is_empty() => format!("/{host}{}", url.path()), | |
| 41 | _ => url.path().to_string(), | |
| 42 | }; | |
| 43 | if path.is_empty() || !path.starts_with('/') { | |
| 44 | path.insert(0, '/'); | |
| 45 | } | |
| 46 | if let Some(query) = url.query() { | |
| 47 | path.push('?'); | |
| 48 | path.push_str(query); | |
| 49 | } | |
| 50 | Some(path) | |
| 51 | } | |
| 52 | ||
| 53 | pub fn open(app: &AppHandle, url: &Url) { | |
| 54 | if let Some(path) = path_of(url) { | |
| 55 | go(app, &path); | |
| 56 | } | |
| 57 | } | |
| 58 | ||
| 59 | /// Takes the window to a path on the server. | |
| 60 | pub fn go(app: &AppHandle, path: &str) { | |
| 61 | tray::show(app); | |
| 62 | if config::on_site(app) { | |
| 63 | let _ = app.emit_to(WINDOW, EVENT, path.to_string()); | |
| 64 | return; | |
| 65 | } | |
| 66 | if let Some(window) = app.get_webview_window(WINDOW) { | |
| 67 | if let Ok(target) = config::server(app).join(path.trim_start_matches('/')) { | |
| 68 | let _ = window.navigate(target); | |
| 69 | } | |
| 70 | } | |
| 71 | } | |
| 72 | ||
| 73 | #[cfg(test)] | |
| 74 | mod tests { | |
| 75 | use super::path_of; | |
| 76 | use url::Url; | |
| 77 | ||
| 78 | #[test] | |
| 79 | fn a_link_names_a_site_path() { | |
| 80 | let path = |text: &str| path_of(&Url::parse(text).unwrap()); | |
| 81 | assert_eq!(path("g1t://acme/-/chat/dm/chn_1").as_deref(), Some("/acme/-/chat/dm/chn_1")); | |
| 82 | assert_eq!(path("g1t://acme/hello/pull/4?tab=files").as_deref(), Some("/acme/hello/pull/4?tab=files")); | |
| 83 | assert_eq!(path("g1t://notifications").as_deref(), Some("/notifications")); | |
| 84 | assert_eq!(path("https://g1t.sh/acme"), None); | |
| 85 | } | |
| 86 | } |