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.
| Merge remote-tracking branch 'origin/claude/cool-newton-7nm8r9' into claude/cool-newton-7nm8r9 | 1 | // The title bar's work: draw what the page under it reports, and send its |
| 2 | // buttons to the app (src/bridge.rs: title_bar_current, title_bar_act, | |
| 3 | // window_control, window_menu). A click here hands the keyboard back to | |
| 4 | // the page, so typing goes on where it was. | |
| 5 | (function () { | |
| 6 | var core = window.__TAURI__ && window.__TAURI__.core; | |
| 7 | var events = window.__TAURI__ && window.__TAURI__.event; | |
| 8 | function invoke(command, args) { | |
| 9 | if (core && typeof core.invoke === "function") return core.invoke(command, args || {}); | |
| 10 | return Promise.reject(new Error("the title bar cannot reach the app")); | |
| 11 | } | |
| 12 | function quietly(promise) { | |
| 13 | promise.catch(function () {}); | |
| 14 | } | |
| 15 | function act(action) { | |
| 16 | quietly(invoke("title_bar_act", { action: action })); | |
| 17 | } | |
| 18 | function control(action) { | |
| 19 | return invoke("window_control", { action: action }); | |
| 20 | } | |
| 21 | ||
| 22 | var ua = navigator.userAgent; | |
| 23 | var MAC = /Macintosh|Mac OS X/.test(ua) && !/Windows/.test(ua); | |
| 24 | if (MAC) document.documentElement.classList.add("mac"); | |
| 25 | ||
| 26 | function svg(body) { | |
| 27 | return ( | |
| 28 | '<svg viewBox="0 0 16 16" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">' + | |
| 29 | body + | |
| 30 | "</svg>" | |
| 31 | ); | |
| 32 | } | |
| 33 | // Drawn here, from lines and boxes, as each system draws its own. | |
| 34 | var ICONS = { | |
| 35 | menu: svg('<line x1="3" y1="4.5" x2="13" y2="4.5"/><line x1="3" y1="8" x2="13" y2="8"/><line x1="3" y1="11.5" x2="13" y2="11.5"/>'), | |
| 36 | back: svg('<polyline points="9.5,3.5 5,8 9.5,12.5"/><line x1="5" y1="8" x2="13" y2="8"/>'), | |
| 37 | forward: svg('<polyline points="6.5,3.5 11,8 6.5,12.5"/><line x1="3" y1="8" x2="11" y2="8"/>'), | |
| 38 | search: svg('<circle cx="7" cy="7" r="4"/><line x1="10" y1="10" x2="13" y2="13"/>'), | |
| The desktop app's settings are a button in its title bar. A Settings button sits at the right of the bar, before the window's own buttons (and at its end on macOS), so the runner and the rest are a click away instead of only in the File menu, the tray or the account menu. | 39 | settings: svg('<line x1="2.5" y1="4.5" x2="13.5" y2="4.5"/><line x1="2.5" y1="11.5" x2="13.5" y2="11.5"/><circle cx="10" cy="4.5" r="1.75" fill="var(--bg)"/><circle cx="6" cy="11.5" r="1.75" fill="var(--bg)"/>'), |
| Merge remote-tracking branch 'origin/claude/cool-newton-7nm8r9' into claude/cool-newton-7nm8r9 | 40 | minimize: svg('<line x1="3.5" y1="8" x2="12.5" y2="8"/>'), |
| 41 | maximize: svg('<rect x="3.5" y="3.5" width="9" height="9" rx="1"/>'), | |
| 42 | restore: svg('<rect x="3.5" y="5.5" width="7" height="7" rx="1"/><path d="M5.5 5.5V4.5a1 1 0 0 1 1-1h5a1 1 0 0 1 1 1v5a1 1 0 0 1-1 1h-1"/>'), | |
| 43 | close: svg('<line x1="4" y1="4" x2="12" y2="12"/><line x1="12" y1="4" x2="4" y2="12"/>'), | |
| 44 | }; | |
| 45 | ||
| 46 | function button(kind, label, icon, onClick) { | |
| 47 | var b = document.createElement("button"); | |
| 48 | b.type = "button"; | |
| 49 | b.tabIndex = -1; | |
| 50 | b.className = kind; | |
| 51 | b.setAttribute("aria-label", label); | |
| 52 | b.title = label; | |
| 53 | if (icon) b.innerHTML = ICONS[icon]; | |
| 54 | b.addEventListener("click", function (event) { | |
| 55 | event.stopPropagation(); | |
| 56 | onClick(b); | |
| 57 | }); | |
| 58 | return b; | |
| 59 | } | |
| 60 | ||
| 61 | var bar = document.getElementById("bar"); | |
| 62 | var left = document.getElementById("left"); | |
| 63 | var middle = document.getElementById("middle"); | |
| 64 | var right = document.getElementById("right"); | |
| 65 | ||
| 66 | if (!MAC) { | |
| 67 | left.append( | |
| 68 | button("icon", "Menu", "menu", function (b) { | |
| 69 | var box = b.getBoundingClientRect(); | |
| 70 | quietly(invoke("window_menu", { x: box.left, y: box.bottom })); | |
| 71 | }), | |
| 72 | ); | |
| 73 | } | |
| 74 | var back = button("icon", "Back", "back", function () { | |
| 75 | act("back"); | |
| 76 | }); | |
| 77 | var forward = button("icon", "Forward", "forward", function () { | |
| 78 | act("forward"); | |
| 79 | }); | |
| 80 | left.append(back, forward); | |
| 81 | ||
| Merge branch 'main' into rm-agents | 82 | // The runner, as a dot right beside the settings: its colour says what |
| 83 | // it is doing, live, and a wide window says it in words too. A click | |
| 84 | // opens its menu, which the site draws under the dot (or, with no page | |
| 85 | // of the site's to draw it, the Runner window). The words are the app's | |
| 86 | // (diagnosis.rs chip). | |
| 87 | var chip = button("chip", "Runner", null, function (b) { | |
| 88 | var box = b.getBoundingClientRect(); | |
| 89 | var width = document.documentElement.clientWidth || window.innerWidth || 1; | |
| 90 | // Where the dot's right edge is, as a share of the bar, so the menu | |
| 91 | // lines up under it whatever the site's zoom. | |
| 92 | quietly(invoke("title_bar_act", { action: "runner", at: box.right / width })); | |
| The desktop app is 0.3.4, and the runner has a window of its own. Beside the title bar's Settings button a chip says what the runner is doing, live, with a dot in its colour (Runner running, Running a job, Running 2 jobs, Runner starting, Runner updating, Runner stopped, Runner offline, Runner needs you), as Docker Desktop shows its engine; in a narrow window only the dot shows. It opens the Runner window, as the tray's runner row now does: at its top what the whole runner is doing, with what it is running, its version and workspace, and its own Stop or Start; then each kind of job's card as before; then its setup (running jobs here at all, how jobs run, the workspace, the computer with Check for runner updates and View on g1t); and its log, open and following along as it is written. Settings keeps the runner as one line, what it is doing with Open runner, and each window saves only its own settings over what the app has now, so neither undoes the other's. The chip's words are diagnosis.rs's, the Runner window is made off the main thread as Settings now is, and it has a capability of its own with only the commands it uses; the title bar may now ask the runner's status. Two things fixed on the way: a settings row hidden until it applies, Restart to change the title bar, showed all the time, since its row's display beat the hidden attribute; and in a narrow window the title bar's buttons ran over the search, which now shrinks instead. The desktop guide describes the chip, the Runner window and where each runner setting now is. | 93 | }); |
| 94 | chip.hidden = true; | |
| Merge branch 'main' into rm-agents | 95 | chip.setAttribute("aria-haspopup", "dialog"); |
| 96 | chip.setAttribute("aria-expanded", "false"); | |
| The desktop app is 0.3.4, and the runner has a window of its own. Beside the title bar's Settings button a chip says what the runner is doing, live, with a dot in its colour (Runner running, Running a job, Running 2 jobs, Runner starting, Runner updating, Runner stopped, Runner offline, Runner needs you), as Docker Desktop shows its engine; in a narrow window only the dot shows. It opens the Runner window, as the tray's runner row now does: at its top what the whole runner is doing, with what it is running, its version and workspace, and its own Stop or Start; then each kind of job's card as before; then its setup (running jobs here at all, how jobs run, the workspace, the computer with Check for runner updates and View on g1t); and its log, open and following along as it is written. Settings keeps the runner as one line, what it is doing with Open runner, and each window saves only its own settings over what the app has now, so neither undoes the other's. The chip's words are diagnosis.rs's, the Runner window is made off the main thread as Settings now is, and it has a capability of its own with only the commands it uses; the title bar may now ask the runner's status. Two things fixed on the way: a settings row hidden until it applies, Restart to change the title bar, showed all the time, since its row's display beat the hidden attribute; and in a narrow window the title bar's buttons ran over the search, which now shrinks instead. The desktop guide describes the chip, the Runner window and where each runner setting now is. | 97 | var chipDot = document.createElement("span"); |
| 98 | chipDot.className = "chip-dot"; | |
| 99 | var chipText = document.createElement("span"); | |
| 100 | chipText.className = "chip-text"; | |
| 101 | chip.append(chipDot, chipText); | |
| 102 | function drawChip(said) { | |
| 103 | if (!said || !said.label) return; | |
| 104 | chip.hidden = false; | |
| 105 | chip.dataset.tone = said.tone; | |
| 106 | chipText.textContent = said.label; | |
| Merge branch 'main' into rm-agents | 107 | chip.setAttribute("aria-label", /runner/i.test(said.label) ? said.label : "Runner: " + said.label); |
| 108 | chip.title = said.label; | |
| The desktop app is 0.3.4, and the runner has a window of its own. Beside the title bar's Settings button a chip says what the runner is doing, live, with a dot in its colour (Runner running, Running a job, Running 2 jobs, Runner starting, Runner updating, Runner stopped, Runner offline, Runner needs you), as Docker Desktop shows its engine; in a narrow window only the dot shows. It opens the Runner window, as the tray's runner row now does: at its top what the whole runner is doing, with what it is running, its version and workspace, and its own Stop or Start; then each kind of job's card as before; then its setup (running jobs here at all, how jobs run, the workspace, the computer with Check for runner updates and View on g1t); and its log, open and following along as it is written. Settings keeps the runner as one line, what it is doing with Open runner, and each window saves only its own settings over what the app has now, so neither undoes the other's. The chip's words are diagnosis.rs's, the Runner window is made off the main thread as Settings now is, and it has a capability of its own with only the commands it uses; the title bar may now ask the runner's status. Two things fixed on the way: a settings row hidden until it applies, Restart to change the title bar, showed all the time, since its row's display beat the hidden attribute; and in a narrow window the title bar's buttons ran over the search, which now shrinks instead. The desktop guide describes the chip, the Runner window and where each runner setting now is. | 109 | } |
| 110 | // The app's settings, at the right of the bar, before the window's | |
| 111 | // buttons: where they are found without the menu. | |
| The desktop app's settings are a button in its title bar. A Settings button sits at the right of the bar, before the window's own buttons (and at its end on macOS), so the runner and the rest are a click away instead of only in the File menu, the tray or the account menu. | 112 | right.append( |
| The desktop app is 0.3.4, and the runner has a window of its own. Beside the title bar's Settings button a chip says what the runner is doing, live, with a dot in its colour (Runner running, Running a job, Running 2 jobs, Runner starting, Runner updating, Runner stopped, Runner offline, Runner needs you), as Docker Desktop shows its engine; in a narrow window only the dot shows. It opens the Runner window, as the tray's runner row now does: at its top what the whole runner is doing, with what it is running, its version and workspace, and its own Stop or Start; then each kind of job's card as before; then its setup (running jobs here at all, how jobs run, the workspace, the computer with Check for runner updates and View on g1t); and its log, open and following along as it is written. Settings keeps the runner as one line, what it is doing with Open runner, and each window saves only its own settings over what the app has now, so neither undoes the other's. The chip's words are diagnosis.rs's, the Runner window is made off the main thread as Settings now is, and it has a capability of its own with only the commands it uses; the title bar may now ask the runner's status. Two things fixed on the way: a settings row hidden until it applies, Restart to change the title bar, showed all the time, since its row's display beat the hidden attribute; and in a narrow window the title bar's buttons ran over the search, which now shrinks instead. The desktop guide describes the chip, the Runner window and where each runner setting now is. | 113 | chip, |
| The desktop app's settings are a button in its title bar. A Settings button sits at the right of the bar, before the window's own buttons (and at its end on macOS), so the runner and the rest are a click away instead of only in the File menu, the tray or the account menu. | 114 | button("icon", "Settings", "settings", function () { |
| 115 | act("settings"); | |
| 116 | }), | |
| 117 | ); | |
| 118 | ||
| Merge remote-tracking branch 'origin/claude/cool-newton-7nm8r9' into claude/cool-newton-7nm8r9 | 119 | var maximize = null; |
| 120 | function drawMaximized(maximized) { | |
| 121 | if (!maximize) return; | |
| 122 | maximize.innerHTML = maximized ? ICONS.restore : ICONS.maximize; | |
| 123 | maximize.setAttribute("aria-label", maximized ? "Restore" : "Maximize"); | |
| 124 | maximize.title = maximized ? "Restore" : "Maximize"; | |
| 125 | } | |
| 126 | // The window's buttons, at the right as Windows and Linux put them; macOS has its own. | |
| 127 | if (!MAC) { | |
| 128 | maximize = button("caption", "Maximize", "maximize", function () { | |
| 129 | control("maximize").then(drawMaximized, function () {}); | |
| 130 | }); | |
| 131 | right.append( | |
| 132 | button("caption", "Minimize", "minimize", function () { | |
| 133 | quietly(control("minimize")); | |
| 134 | }), | |
| 135 | maximize, | |
| 136 | button("caption close", "Close", "close", function () { | |
| 137 | quietly(control("close")); | |
| 138 | }), | |
| 139 | ); | |
| 140 | var resizing = 0; | |
| 141 | window.addEventListener("resize", function () { | |
| 142 | clearTimeout(resizing); | |
| 143 | resizing = setTimeout(function () { | |
| 144 | control("maximized").then(drawMaximized, function () {}); | |
| 145 | }, 120); | |
| 146 | }); | |
| 147 | control("maximized").then(drawMaximized, function () {}); | |
| 148 | } | |
| 149 | ||
| 150 | // Dragging the bar moves the window; a double click maximizes it, as a system's title bar does. | |
| 151 | bar.addEventListener("mousedown", function (event) { | |
| 152 | if (event.button !== 0 || event.target.closest("button")) return; | |
| 153 | if (event.detail === 2) { | |
| 154 | control("maximize").then(drawMaximized, function () {}); | |
| 155 | return; | |
| 156 | } | |
| 157 | quietly(control("drag")); | |
| 158 | }); | |
| 159 | // The keyboard belongs to the page: a click here gives it back. | |
| 160 | window.addEventListener("mouseup", function () { | |
| 161 | act("focus"); | |
| 162 | }); | |
| 163 | ||
| 164 | var title = document.createElement("span"); | |
| 165 | title.className = "title"; | |
| 166 | var pill = button("search", "Search", "search", function () { | |
| 167 | act("search"); | |
| 168 | }); | |
| 169 | var pillText = document.createElement("span"); | |
| 170 | pill.append(pillText); | |
| 171 | ||
| 172 | function setColors(colors) { | |
| 173 | var root = document.documentElement.style; | |
| 174 | if (!colors) return; | |
| 175 | var shade = colors.dark ? "237, 237, 239" : "15, 15, 17"; | |
| 176 | root.setProperty("--bg", colors.background); | |
| 177 | root.setProperty("--fg", colors.foreground); | |
| 178 | root.setProperty("--muted", colors.muted); | |
| 179 | root.setProperty("--accent", colors.accent); | |
| 180 | root.setProperty("--hover", "rgba(" + shade + ", " + (colors.dark ? 0.1 : 0.07) + ")"); | |
| 181 | root.setProperty("--pill", "rgba(" + shade + ", " + (colors.dark ? 0.09 : 0.05) + ")"); | |
| 182 | root.setProperty("--pill-hover", "rgba(" + shade + ", " + (colors.dark ? 0.14 : 0.09) + ")"); | |
| 183 | root.setProperty("--pill-edge", "rgba(" + shade + ", " + (colors.dark ? 0.08 : 0.1) + ")"); | |
| 184 | document.documentElement.style.colorScheme = colors.dark ? "dark" : "light"; | |
| 185 | } | |
| 186 | ||
| 187 | function draw(page) { | |
| 188 | if (!page) return; | |
| 189 | middle.textContent = ""; | |
| 190 | if (page.search) { | |
| 191 | pillText.textContent = page.search; | |
| 192 | pill.setAttribute("aria-label", page.search); | |
| 193 | pill.removeAttribute("title"); | |
| 194 | middle.append(pill); | |
| 195 | } else { | |
| 196 | title.textContent = page.title || "g1t"; | |
| 197 | middle.append(title); | |
| 198 | } | |
| Merge branch 'main' into rm-agents | 199 | chip.setAttribute("aria-expanded", page.runnerMenu ? "true" : "false"); |
| Merge remote-tracking branch 'origin/claude/cool-newton-7nm8r9' into claude/cool-newton-7nm8r9 | 200 | back.disabled = page.canGoBack === false; |
| 201 | forward.disabled = page.canGoForward === false; | |
| 202 | setColors(page.colors); | |
| 203 | } | |
| 204 | ||
| 205 | if (events && typeof events.listen === "function") { | |
| 206 | events | |
| 207 | .listen("g1t-title-bar", function (event) { | |
| 208 | draw(event.payload); | |
| 209 | }) | |
| 210 | .catch(function () {}); | |
| 211 | } | |
| 212 | invoke("title_bar_current").then(draw, function () {}); | |
| The desktop app is 0.3.4, and the runner has a window of its own. Beside the title bar's Settings button a chip says what the runner is doing, live, with a dot in its colour (Runner running, Running a job, Running 2 jobs, Runner starting, Runner updating, Runner stopped, Runner offline, Runner needs you), as Docker Desktop shows its engine; in a narrow window only the dot shows. It opens the Runner window, as the tray's runner row now does: at its top what the whole runner is doing, with what it is running, its version and workspace, and its own Stop or Start; then each kind of job's card as before; then its setup (running jobs here at all, how jobs run, the workspace, the computer with Check for runner updates and View on g1t); and its log, open and following along as it is written. Settings keeps the runner as one line, what it is doing with Open runner, and each window saves only its own settings over what the app has now, so neither undoes the other's. The chip's words are diagnosis.rs's, the Runner window is made off the main thread as Settings now is, and it has a capability of its own with only the commands it uses; the title bar may now ask the runner's status. Two things fixed on the way: a settings row hidden until it applies, Restart to change the title bar, showed all the time, since its row's display beat the hidden attribute; and in a narrow window the title bar's buttons ran over the search, which now shrinks instead. The desktop guide describes the chip, the Runner window and where each runner setting now is. | 213 | if (events && typeof events.listen === "function") { |
| 214 | events | |
| 215 | .listen("g1t-runner-status", function (event) { | |
| 216 | drawChip(event.payload); | |
| 217 | }) | |
| 218 | .catch(function () {}); | |
| 219 | } | |
| 220 | invoke("runner_status").then(function (view) { | |
| 221 | drawChip(view && view.chip); | |
| 222 | }, function () {}); | |
| Merge remote-tracking branch 'origin/claude/cool-newton-7nm8r9' into claude/cool-newton-7nm8r9 | 223 | })(); |
This file's history is long; its oldest lines are credited to the oldest commit read.