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 desktop bridge: what the site finds at `window.g1tDesktop`, run at |
| 2 | // the start of every page the window loads (bridge.rs puts it there). The | |
| 3 | // site's lib/notify-client.ts describes the contract from its side; when | |
| 4 | // the bridge is there, notifications go to the system, the badge to the | |
| 5 | // icon, links out to the browser, and g1t:// links arrive as `onNavigate`. | |
| 6 | // Each call is a command in bridge.rs, which only answers the server's | |
| 7 | // pages; on any other page the calls fail quietly. | |
| 8 | (function () { | |
| 9 | if (window.g1tDesktop) return; | |
| 10 | var VERSION = "__VERSION__"; | |
| 11 | var PLATFORM = "__PLATFORM__"; | |
| 12 | ||
| 13 | function invoke(command, args) { | |
| 14 | var core = window.__TAURI__ && window.__TAURI__.core; | |
| 15 | if (core && typeof core.invoke === "function") return core.invoke(command, args || {}); | |
| 16 | var internals = window.__TAURI_INTERNALS__; | |
| 17 | if (internals && typeof internals.invoke === "function") return internals.invoke(command, args || {}); | |
| 18 | return Promise.reject(new Error("g1t desktop: this page cannot reach the app")); | |
| 19 | } | |
| 20 | ||
| 21 | function quietly(promise) { | |
| 22 | promise.catch(function (error) { | |
| 23 | console.warn("g1t desktop:", error && error.message ? error.message : error); | |
| 24 | }); | |
| 25 | } | |
| 26 | ||
| 27 | var listeners = []; | |
| 28 | var listening = false; | |
| 29 | function listen() { | |
| 30 | if (listening) return; | |
| 31 | listening = true; | |
| 32 | var events = window.__TAURI__ && window.__TAURI__.event; | |
| 33 | if (!events || typeof events.listen !== "function") return; | |
| 34 | events | |
| 35 | .listen("g1t-navigate", function (event) { | |
| 36 | var href = event && event.payload; | |
| 37 | if (typeof href !== "string") return; | |
| 38 | listeners.slice().forEach(function (listener) { | |
| 39 | try { | |
| 40 | listener(href); | |
| 41 | } catch (error) { | |
| 42 | console.warn("g1t desktop: a navigate listener failed", error); | |
| 43 | } | |
| 44 | }); | |
| 45 | }) | |
| 46 | .catch(function () {}); | |
| 47 | } | |
| 48 | ||
| 49 | var bridge = { | |
| 50 | version: VERSION, | |
| 51 | platform: PLATFORM, | |
| 52 | // A native notification, for a message to the person while the window is behind another. | |
| 53 | notify: function (notification) { | |
| 54 | quietly(invoke("notify", { title: String(notification.title || "g1t"), body: String(notification.body || "") })); | |
| 55 | }, | |
| 56 | // What needs the person, on the icon and the tray; 0 clears it. | |
| 57 | setBadge: function (count) { | |
| 58 | quietly(invoke("set_badge", { count: Math.max(0, Math.floor(Number(count) || 0)) })); | |
| 59 | }, | |
| 60 | // A link to somewhere else, in the browser the system uses. | |
| 61 | openUrl: function (url) { | |
| 62 | quietly(invoke("open_url", { url: String(url) })); | |
| 63 | }, | |
| 64 | // g1t:// links, as site paths such as "/acme/-/chat/dm/chn_1". | |
| 65 | onNavigate: function (listener) { | |
| 66 | listeners.push(listener); | |
| 67 | listen(); | |
| 68 | return function () { | |
| 69 | var at = listeners.indexOf(listener); | |
| 70 | if (at >= 0) listeners.splice(at, 1); | |
| 71 | }; | |
| 72 | }, | |
| 73 | // Looks for an update now: "current", "ready:<version>", or rejects with why. | |
| 74 | checkForUpdates: function () { | |
| 75 | return invoke("check_for_updates"); | |
| 76 | }, | |
| 77 | }; | |
| 78 | Object.defineProperty(window, "g1tDesktop", { value: Object.freeze(bridge), writable: false, configurable: false }); | |
| 79 | ||
| 80 | // Links out. A link to another site opens in the system's browser, and | |
| 81 | // the window stays on g1t; a link that asks for a new tab, or a click | |
| 82 | // with Ctrl or Cmd held, goes on in this window, which has no tabs. | |
| 83 | function destination(href) { | |
| 84 | try { | |
| 85 | var url = new URL(href, location.href); | |
| 86 | return /^https?:$/.test(url.protocol) ? url : null; | |
| 87 | } catch (error) { | |
| 88 | return null; | |
| 89 | } | |
| 90 | } | |
| 91 | document.addEventListener( | |
| 92 | "click", | |
| 93 | function (event) { | |
| 94 | if (event.defaultPrevented || event.button !== 0) return; | |
| 95 | var anchor = event.target && event.target.closest ? event.target.closest("a[href]") : null; | |
| 96 | if (!anchor || anchor.hasAttribute("download")) return; | |
| 97 | var url = destination(anchor.getAttribute("href")); | |
| 98 | if (!url) return; | |
| 99 | if (url.origin !== location.origin) { | |
| 100 | event.preventDefault(); | |
| 101 | event.stopImmediatePropagation(); | |
| 102 | bridge.openUrl(url.href); | |
| 103 | } else if (anchor.target === "_blank" || event.metaKey || event.ctrlKey) { | |
| 104 | event.preventDefault(); | |
| 105 | event.stopImmediatePropagation(); | |
| 106 | location.assign(url.href); | |
| 107 | } | |
| 108 | }, | |
| 109 | true, | |
| 110 | ); | |
| 111 | var open = window.open; | |
| 112 | window.open = function (href, target, features) { | |
| 113 | var url = destination(href); | |
| 114 | if (url) { | |
| 115 | if (url.origin === location.origin) location.assign(url.href); | |
| 116 | else bridge.openUrl(url.href); | |
| 117 | return null; | |
| 118 | } | |
| 119 | return typeof open === "function" ? open.call(window, href, target, features) : null; | |
| 120 | }; | |
| 121 | })(); |