Skip to content

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

g1t.sh
182 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.

The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.1// The settings window's work: show what the app has, and keep each change
2// the moment it is made. Everything it asks is a command in
3// src/bridge.rs, answered only to this window.
4(function () {
5 var SWITCHES = ["startHidden", "closeToTray", "notifications", "flash", "badge", "menuBar", "autoUpdate"];
6 var current = null;
7
8 function byId(id) {
9 return document.getElementById(id);
10 }
11
12 function invoke(command, args) {
13 var core = window.__TAURI__ && window.__TAURI__.core;
14 if (core && typeof core.invoke === "function") return core.invoke(command, args || {});
15 return Promise.reject(new Error("This page belongs inside the g1t desktop app."));
16 }
17
18 function fail(error) {
19 var box = byId("error");
20 box.textContent = typeof error === "string" ? error : (error && error.message) || "That could not be changed.";
21 box.hidden = false;
22 }
23
24 function hostOf(server) {
25 try {
26 return new URL(server).host;
27 } catch (error) {
28 return server;
29 }
30 }
31
32 // What changes between Windows, macOS and Linux.
33 function platform(name) {
34 byId("flash-label").textContent =
35 name === "macos" ? "Bounce the dock icon" : name === "windows" ? "Flash the taskbar icon" : "Ask for attention";
36 // macOS keeps its menu bar at the top of the screen, always there.
37 byId("menu-bar-row").hidden = name === "macos";
38 if (name === "macos") byId("zoom-note").textContent = "The View menu changes it too: ⌘+, ⌘− and ⌘0.";
39 else byId("zoom-note").textContent = "The View menu changes it too: Ctrl+=, Ctrl+− and Ctrl+0.";
40 }
41
42 function render(view) {
43 current = view;
44 byId("error").hidden = true;
45 byId("openAtLogin").checked = !!view.openAtLogin;
46 SWITCHES.forEach(function (key) {
47 byId(key).checked = !!view[key];
48 });
49 // Starting in the tray only means something when g1t starts at sign-in.
50 byId("startHidden").disabled = !view.openAtLogin;
51 byId("startHidden").closest(".setting").classList.toggle("off", !view.openAtLogin);
52 var zoom = byId("zoom");
53 zoom.value = String(view.zoom);
54 if (zoom.value === "") zoom.value = "1";
55 byId("version").textContent = "g1t " + view.version;
Checking for updates in the desktop app answers in its settings window, with a restart beside a downloaded version.56 if (!checking) updateStatus(view);
The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.57 byId("server").textContent = hostOf(view.server);
58 }
59
60 function settingsOf() {
61 var settings = {};
62 SWITCHES.forEach(function (key) {
63 settings[key] = byId(key).checked;
64 });
65 settings.zoom = Number(byId("zoom").value) || 1;
66 return settings;
67 }
68
69 function save() {
70 invoke("save_settings", { settings: settingsOf() }).then(render, function (error) {
71 fail(error);
72 if (current) render(current);
73 });
74 }
75
76 SWITCHES.forEach(function (key) {
77 byId(key).addEventListener("change", save);
78 });
79 byId("zoom").addEventListener("change", save);
80 byId("openAtLogin").addEventListener("change", function (event) {
81 invoke("set_open_at_login", { on: event.target.checked }).then(render, function (error) {
82 fail(error);
83 if (current) render(current);
84 });
85 });
86
Checking for updates in the desktop app answers in its settings window, with a restart beside a downloaded version.87 // Updates: where this copy stands, said in the window, so a check from
88 // the menu or the tray is answered here and cannot be missed.
89 var checking = false;
90
91 function when(ms) {
92 var date = new Date(ms);
93 var today = new Date().toDateString() === date.toDateString();
94 var time = date.toLocaleTimeString([], { hour: "numeric", minute: "2-digit" });
95 return today ? "today at " + time : date.toLocaleDateString([], { month: "short", day: "numeric" }) + " at " + time;
96 }
97
98 function ready(version) {
99 byId("update-status").textContent = "Version " + version + " is downloaded and installs when g1t restarts.";
100 byId("restart").hidden = false;
101 }
102
103 function updateStatus(view) {
104 if (view.updateReady) return ready(view.updateReady);
105 byId("restart").hidden = true;
106 byId("update-status").textContent = view.checkedAt
107 ? "Up to date. Last checked " + when(view.checkedAt) + "."
108 : view.autoUpdate
109 ? "Not checked yet since g1t started; it checks on its own shortly."
110 : "Checking on its own is off.";
111 }
112
113 function check() {
114 if (checking) return;
115 checking = true;
The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.116 var button = byId("check");
117 var status = byId("update-status");
118 button.disabled = true;
Checking for updates in the desktop app answers in its settings window, with a restart beside a downloaded version.119 status.textContent = "Checking, and downloading any new version…";
The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.120 invoke("check_for_updates")
121 .then(function (answer) {
Checking for updates in the desktop app answers in its settings window, with a restart beside a downloaded version.122 if (answer.indexOf("ready:") === 0) ready(answer.slice(6));
123 else status.textContent = "Up to date. Last checked " + when(Date.now()) + ".";
The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.124 })
125 .catch(function (error) {
Checking for updates in the desktop app answers in its settings window, with a restart beside a downloaded version.126 var text = typeof error === "string" ? error : "";
127 status.textContent = /sending request|connect|dns|timed out/i.test(text) || !text
128 ? "Could not reach g1t.sh to check. Check your connection and try again."
129 : "Could not check: " + text;
The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.130 })
131 .then(function () {
Checking for updates in the desktop app answers in its settings window, with a restart beside a downloaded version.132 checking = false;
The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.133 button.disabled = false;
134 });
Checking for updates in the desktop app answers in its settings window, with a restart beside a downloaded version.135 }
136
137 byId("check").addEventListener("click", check);
138 byId("restart").addEventListener("click", function () {
139 byId("restart").disabled = true;
140 byId("update-status").textContent = "Installing…";
141 invoke("restart_to_update").catch(function (error) {
142 byId("restart").disabled = false;
143 fail(error);
144 });
The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.145 });
146
Checking for updates in the desktop app answers in its settings window, with a restart beside a downloaded version.147 // The menu's or tray's "Check for updates…" with this window open, and a
148 // download finishing in the background (src/settings.rs).
149 var events = window.__TAURI__ && window.__TAURI__.event;
150 if (events && typeof events.listen === "function") {
151 events.listen("g1t-check-updates", check).catch(function () {});
152 events
153 .listen("g1t-update-ready", function (event) {
154 if (!checking && typeof event.payload === "string") ready(event.payload);
155 })
156 .catch(function () {});
157 }
158
The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.159 byId("change-server").addEventListener("click", function () {
160 invoke("change_server").catch(fail);
161 });
162
163 // Links out, in the system's browser (src/bridge.js does the same on the site).
164 document.addEventListener("click", function (event) {
165 var anchor = event.target && event.target.closest ? event.target.closest("a[href]") : null;
166 if (!anchor) return;
167 event.preventDefault();
168 invoke("open_url", { url: anchor.href }).catch(function () {});
169 });
170
171 invoke("get_settings")
172 .then(function (view) {
173 platform(view.platform);
174 render(view);
Checking for updates in the desktop app answers in its settings window, with a restart beside a downloaded version.175 // Opened by "Check for updates…" in a menu.
176 if (new URLSearchParams(location.search).has("check")) {
177 byId("updates-row").scrollIntoView({ block: "center" });
178 check();
179 }
The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.180 })
181 .catch(fail);
182})();