Skip to content
209 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 () {
The desktop app draws its own title bar, as Slack and Discord do, and the site can call the app again.5 var SWITCHES = ["startHidden", "closeToTray", "notifications", "flash", "badge", "systemTitleBar", "autoUpdate"];
The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.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";
The desktop app draws its own title bar, as Slack and Discord do, and the site can call the app again.36 // macOS keeps its menu bar at the top of the screen, whichever title bar the window has.
37 if (name === "macos") byId("system-title-bar-note").textContent = "In place of g1t's own, which sits under the window's buttons.";
The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.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);
The desktop app draws its own title bar, as Slack and Discord do, and the site can call the app again.52 // The title bar changes when g1t restarts.
53 byId("restart-row").hidden = !view.titleBarChanged;
The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.54 var zoom = byId("zoom");
55 zoom.value = String(view.zoom);
56 if (zoom.value === "") zoom.value = "1";
57 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.58 if (!checking) updateStatus(view);
The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.59 byId("server").textContent = hostOf(view.server);
60 }
61
62 function settingsOf() {
63 var settings = {};
64 SWITCHES.forEach(function (key) {
65 settings[key] = byId(key).checked;
66 });
67 settings.zoom = Number(byId("zoom").value) || 1;
68 return settings;
69 }
70
71 function save() {
72 invoke("save_settings", { settings: settingsOf() }).then(render, function (error) {
73 fail(error);
74 if (current) render(current);
75 });
76 }
77
78 SWITCHES.forEach(function (key) {
79 byId(key).addEventListener("change", save);
80 });
81 byId("zoom").addEventListener("change", save);
82 byId("openAtLogin").addEventListener("change", function (event) {
83 invoke("set_open_at_login", { on: event.target.checked }).then(render, function (error) {
84 fail(error);
85 if (current) render(current);
86 });
87 });
88
Checking for updates in the desktop app answers in its settings window, with a restart beside a downloaded version.89 // Updates: where this copy stands, said in the window, so a check from
90 // the menu or the tray is answered here and cannot be missed.
91 var checking = false;
92
93 function when(ms) {
94 var date = new Date(ms);
95 var today = new Date().toDateString() === date.toDateString();
96 var time = date.toLocaleTimeString([], { hour: "numeric", minute: "2-digit" });
97 return today ? "today at " + time : date.toLocaleDateString([], { month: "short", day: "numeric" }) + " at " + time;
98 }
99
100 function ready(version) {
101 byId("update-status").textContent = "Version " + version + " is downloaded and installs when g1t restarts.";
102 byId("restart").hidden = false;
103 }
104
105 function updateStatus(view) {
106 if (view.updateReady) return ready(view.updateReady);
107 byId("restart").hidden = true;
108 byId("update-status").textContent = view.checkedAt
109 ? "Up to date. Last checked " + when(view.checkedAt) + "."
110 : view.autoUpdate
111 ? "Not checked yet since g1t started; it checks on its own shortly."
112 : "Checking on its own is off.";
113 }
114
115 function check() {
116 if (checking) return;
117 checking = true;
The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.118 var button = byId("check");
119 var status = byId("update-status");
120 button.disabled = true;
Checking for updates in the desktop app answers in its settings window, with a restart beside a downloaded version.121 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.122 invoke("check_for_updates")
123 .then(function (answer) {
Checking for updates in the desktop app answers in its settings window, with a restart beside a downloaded version.124 if (answer.indexOf("ready:") === 0) ready(answer.slice(6));
125 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.126 })
127 .catch(function (error) {
Checking for updates in the desktop app answers in its settings window, with a restart beside a downloaded version.128 var text = typeof error === "string" ? error : "";
129 status.textContent = /sending request|connect|dns|timed out/i.test(text) || !text
130 ? "Could not reach g1t.sh to check. Check your connection and try again."
131 : "Could not check: " + text;
The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.132 })
133 .then(function () {
Checking for updates in the desktop app answers in its settings window, with a restart beside a downloaded version.134 checking = false;
The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.135 button.disabled = false;
136 });
Checking for updates in the desktop app answers in its settings window, with a restart beside a downloaded version.137 }
138
139 byId("check").addEventListener("click", check);
140 byId("restart").addEventListener("click", function () {
141 byId("restart").disabled = true;
142 byId("update-status").textContent = "Installing…";
143 invoke("restart_to_update").catch(function (error) {
144 byId("restart").disabled = false;
145 fail(error);
146 });
The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.147 });
148
Checking for updates in the desktop app answers in its settings window, with a restart beside a downloaded version.149 // The menu's or tray's "Check for updates…" with this window open, and a
150 // download finishing in the background (src/settings.rs).
151 var events = window.__TAURI__ && window.__TAURI__.event;
152 if (events && typeof events.listen === "function") {
153 events.listen("g1t-check-updates", check).catch(function () {});
154 events
155 .listen("g1t-update-ready", function (event) {
156 if (!checking && typeof event.payload === "string") ready(event.payload);
157 })
158 .catch(function () {});
159 }
160
The desktop app draws its own title bar, as Slack and Discord do, and the site can call the app again.161 byId("restart-app").addEventListener("click", function () {
162 byId("restart-app").disabled = true;
163 invoke("restart").catch(function (error) {
164 byId("restart-app").disabled = false;
165 fail(error);
166 });
167 });
168
The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.169 byId("change-server").addEventListener("click", function () {
170 invoke("change_server").catch(fail);
171 });
172
173 // Links out, in the system's browser (src/bridge.js does the same on the site).
174 document.addEventListener("click", function (event) {
175 var anchor = event.target && event.target.closest ? event.target.closest("a[href]") : null;
176 if (!anchor) return;
177 event.preventDefault();
178 invoke("open_url", { url: anchor.href }).catch(function () {});
179 });
180
Merge branch 'main' of github.com:flagon-io/g1t181 // g1t's own title bar, when the window has no system frame.
182 function frame(view) {
183 if (!view.customFrame) return;
184 if (view.platform === "macos") document.documentElement.classList.add("mac");
185 var bar = byId("titlebar");
186 bar.hidden = false;
187 document.body.classList.add("framed");
188 bar.addEventListener("mousedown", function (event) {
189 if (event.button !== 0 || event.target.closest("button")) return;
190 invoke("window_control", { action: "drag" }).catch(function () {});
191 });
192 byId("close-window").addEventListener("click", function () {
193 invoke("window_control", { action: "close" }).catch(function () {});
194 });
195 }
196
The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.197 invoke("get_settings")
198 .then(function (view) {
Merge branch 'main' of github.com:flagon-io/g1t199 frame(view);
The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.200 platform(view.platform);
201 render(view);
Checking for updates in the desktop app answers in its settings window, with a restart beside a downloaded version.202 // Opened by "Check for updates…" in a menu.
203 if (new URLSearchParams(location.search).has("check")) {
204 byId("updates-row").scrollIntoView({ block: "center" });
205 check();
206 }
The desktop app has settings of its own and a menu, and it is for using g1t, not browsing it.207 })
208 .catch(fail);
209})();

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