300 files+5140−4543204 files not counted0/300 viewed
| 25 | 25 | These are the files to upload to Stripe and similar services. The site serves | |
| 26 | 26 | its own copies from `apps/web/public` and `apps/docs/public`. | |
| 27 | 27 | ||
| 28 | − | | File | Size | Use | | |
| 29 | − | | --- | --- | --- | | |
| 30 | − | | `icon-512.png` | 512×512, dark square | Stripe branding icon (square, at least 128px), Slack, GitHub app avatars | | |
| 31 | − | | `icon-1024.png` | 1024×1024, dark square | App stores and anywhere asking for a large square icon | | |
| 32 | − | | `icon-transparent-1024.png` | 1024×1024, transparent | Placing the icon on a dark surface of your own | | |
| 33 | − | | `logo-on-dark.png` | 1056×642, dark background | Stripe branding logo (wide), docs and decks on dark | | |
| 34 | − | | `logo-on-light.png` | 1056×642, white background | Invoices, receipts and anywhere the background is light | | |
| 28 | + | | File | Size | Use | | |
| 29 | + | | --------------------------- | -------------------------- | ------------------------------------------------------------------------ | | |
| 30 | + | | `icon-512.png` | 512×512, dark square | Stripe branding icon (square, at least 128px), Slack, GitHub app avatars | | |
| 31 | + | | `icon-1024.png` | 1024×1024, dark square | App stores and anywhere asking for a large square icon | | |
| 32 | + | | `icon-transparent-1024.png` | 1024×1024, transparent | Placing the icon on a dark surface of your own | | |
| 33 | + | | `logo-on-dark.png` | 1056×642, dark background | Stripe branding logo (wide), docs and decks on dark | | |
| 34 | + | | `logo-on-light.png` | 1056×642, white background | Invoices, receipts and anywhere the background is light | | |
| 35 | 35 | ||
| 36 | 36 | ## Sources | |
| 37 | 37 | ||
| 38 | 38 | `svg/` holds the source of every file above and of the site's favicons: | |
| 39 | 39 | ||
| 40 | − | | File | What it is | | |
| 41 | − | | --- | --- | | |
| 42 | − | | `svg/mark.svg` | The icon, the pixel 1, centred in a transparent square, for dark backgrounds (also `packages/theme/mark.svg`) | | |
| 43 | − | | `svg/mark-on-light.svg` | The icon on transparent, for light backgrounds | | |
| 44 | − | | `svg/mark-small.svg` | The 16px cut: each cell 2px, no gap | | |
| 45 | − | | `svg/icon-square.svg` | The icon on a full-bleed dark square, 1024 box on 100-unit cells (`icon-512.png`, `icon-1024.png`) | | |
| 46 | − | | `svg/icon-rounded.svg` | The icon on a rounded dark tile, the 256px cut (`brand/g1t-mark.*`) | | |
| 47 | − | | `svg/icon-padded.svg` | The icon with room for a circle crop, the 512px cut (`icon-512.png` in the apps; `apple-touch-icon.png` and `icon-192.png` are cut the same way at their own sizes) | | |
| 48 | − | | `svg/favicon.svg` | The 16px cut with no tile, coloured for a light or dark browser (`favicon.svg` in the apps and `packages/theme`) | | |
| 49 | − | | `svg/logo.svg`, `svg/logo-on-light.svg` | The wordmark, transparent and cropped to its ink, for dark and light backgrounds | | |
| 50 | − | | `svg/logo-dark-bg.svg`, `svg/logo-light-bg.svg` | The wordmark with padding and a background, on 40px cells | | |
| 40 | + | | File | What it is | | |
| 41 | + | | ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | |
| 42 | + | | `svg/mark.svg` | The icon, the pixel 1, centred in a transparent square, for dark backgrounds (also `packages/theme/mark.svg`) | | |
| 43 | + | | `svg/mark-on-light.svg` | The icon on transparent, for light backgrounds | | |
| 44 | + | | `svg/mark-small.svg` | The 16px cut: each cell 2px, no gap | | |
| 45 | + | | `svg/icon-square.svg` | The icon on a full-bleed dark square, 1024 box on 100-unit cells (`icon-512.png`, `icon-1024.png`) | | |
| 46 | + | | `svg/icon-rounded.svg` | The icon on a rounded dark tile, the 256px cut (`brand/g1t-mark.*`) | | |
| 47 | + | | `svg/icon-padded.svg` | The icon with room for a circle crop, the 512px cut (`icon-512.png` in the apps; `apple-touch-icon.png` and `icon-192.png` are cut the same way at their own sizes) | | |
| 48 | + | | `svg/favicon.svg` | The 16px cut with no tile, coloured for a light or dark browser (`favicon.svg` in the apps and `packages/theme`) | | |
| 49 | + | | `svg/logo.svg`, `svg/logo-on-light.svg` | The wordmark, transparent and cropped to its ink, for dark and light backgrounds | | |
| 50 | + | | `svg/logo-dark-bg.svg`, `svg/logo-light-bg.svg` | The wordmark with padding and a background, on 40px cells | | |
| 51 | 51 | ||
| 52 | 52 | `favicon.ico` in the apps holds the 16, 32 and 48px cuts of the icon on a | |
| 53 | 53 | rounded dark tile. The pixels are squares, so no file needs a font. |
| 70 | 70 | environment: | |
| 71 | 71 | name: production | |
| 72 | 72 | deployment: false | |
| 73 | − | timeout-minutes: 60 # the most g1t's own machines run a job | |
| 73 | + | timeout-minutes: 60 # the most g1t's own machines run a job | |
| 74 | 74 | steps: | |
| 75 | 75 | - uses: actions/checkout@v5 | |
| 76 | 76 | # rust: the toolchain; desktop: the app's Cargo.lock's crates.io and | |
| ⋯ | |||
| 174 | 174 | environment: | |
| 175 | 175 | name: production | |
| 176 | 176 | deployment: false | |
| 177 | − | timeout-minutes: 60 # the most g1t's own machines run a job | |
| 177 | + | timeout-minutes: 60 # the most g1t's own machines run a job | |
| 178 | 178 | steps: | |
| 179 | 179 | - uses: actions/checkout@v5 | |
| 180 | 180 | - name: Cache keys | |
| 7 | 7 | .react-router/ | |
| 8 | 8 | *.lock | |
| 9 | 9 | package-lock.json | |
| 10 | + | # Test fixtures: kept byte for byte as they were captured. | |
| 11 | + | **/fixtures/ | |
| 12 | + | *.fixtures.json | |
| 13 | + | *_fixtures.json | |
| 14 | + | # Prettier's MDX printer changes this page again on every run. | |
| 15 | + | apps/docs/src/content/docs/guides/self-hosted-runners.mdx | |
| 16 | + | # Generated, and checked against their generator by tests. | |
| 17 | + | apps/docs/src/content/docs/reference/cli.md | |
| 18 | + | apps/docs/src/data/openapi.json | |
| 19 | + | **/worker-configuration.d.ts | |
| 20 | + | # Tables the deploy tool's tests read row by row (scripts/deploy/deploy.test.mjs). | |
| 21 | + | apps/docs/src/content/docs/architecture/services.md | |
| 22 | + | apps/docs/src/content/docs/guides/self-hosting-architecture.md | |
| 23 | + | # TypeScript mirrors that Rust tests read line by line (crates/contracts: datasets.rs, scopes.rs). | |
| 24 | + | packages/contracts/src/datasets.ts | |
| 25 | + | packages/contracts/src/scopes.ts |
| 1 | 1 | { | |
| 2 | − | "printWidth": 160 | |
| 2 | + | "printWidth": 160, | |
| 3 | + | "overrides": [ | |
| 4 | + | { | |
| 5 | + | "files": "*.jsonc", | |
| 6 | + | "options": { | |
| 7 | + | "trailingComma": "none" | |
| 8 | + | } | |
| 9 | + | } | |
| 10 | + | ] | |
| 3 | 11 | } |
| 1 | 1 | { | |
| 2 | − | "editor.formatOnSave": true | |
| 2 | + | "editor.formatOnSave": true | |
| 3 | 3 | } |
| 10 | 10 | A pull request that changes what someone can do, see or call changes the | |
| 11 | 11 | docs in the same pull request: | |
| 12 | 12 | ||
| 13 | − | | If you change | Update | | |
| 14 | − | | --- | --- | | |
| 15 | − | | Something a person does on g1t.sh | The guide for it in `apps/docs/src/content/docs/guides/` | | |
| 16 | − | | An API route, a field, or an MCP tool | `apps/api/src/operations.rs` descriptions (they feed the OpenAPI document and the API reference), the example and notes for it in `apps/api/src/reference.json`, `reference/mcp.md`, and any guide that shows the call. Then refresh the docs' copy of the OpenAPI document with `G1T_WRITE_OPENAPI=1 cargo test -p g1t-api openapi`; `cargo test` fails until you do. | | |
| 17 | − | | What coding agents are told about g1t | `guides/bring-your-own-agent.mdx`, `guides/claude-code-plugin.md`, the plugin's skills in `plugins/claude-code/`, and `apps/web/public/llms.txt` | | |
| 18 | − | | The Claude Code plugin's files (`plugins/claude-code/`, except `test/`) | Its version, the same in `.claude-plugin/plugin.json` and `.claude-plugin/marketplace.json`: Claude Code updates an installed plugin only when it changes. On main, `plugins-release.yml` publishes it to `flagon-io/g1t-plugins`, and refuses a changed plugin with a version already published. Never commit to g1t-plugins itself. | | |
| 19 | − | | Settings, limits or prices | The page that names them, and the table it is in | | |
| 20 | − | | A new feature | A section in the guide that owns it, linked from the docs home if it is a new task | | |
| 21 | − | | How g1t is put together: a service, a binding, a store, an event route, the path of a request | Its page in the docs' Architecture section (`apps/docs/src/content/docs/architecture/`), and its diagram in `apps/docs/src/diagrams/architecture.ts`. [How g1t ships](https://docs.g1t.sh/architecture/shipping/#keeping-this-section-true) says which page covers what. | | |
| 13 | + | | If you change | Update | | |
| 14 | + | | --------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | |
| 15 | + | | Something a person does on g1t.sh | The guide for it in `apps/docs/src/content/docs/guides/` | | |
| 16 | + | | An API route, a field, or an MCP tool | `apps/api/src/operations.rs` descriptions (they feed the OpenAPI document and the API reference), the example and notes for it in `apps/api/src/reference.json`, `reference/mcp.md`, and any guide that shows the call. Then refresh the docs' copy of the OpenAPI document with `G1T_WRITE_OPENAPI=1 cargo test -p g1t-api openapi`; `cargo test` fails until you do. | | |
| 17 | + | | What coding agents are told about g1t | `guides/bring-your-own-agent.mdx`, `guides/claude-code-plugin.md`, the plugin's skills in `plugins/claude-code/`, and `apps/web/public/llms.txt` | | |
| 18 | + | | The Claude Code plugin's files (`plugins/claude-code/`, except `test/`) | Its version, the same in `.claude-plugin/plugin.json` and `.claude-plugin/marketplace.json`: Claude Code updates an installed plugin only when it changes. On main, `plugins-release.yml` publishes it to `flagon-io/g1t-plugins`, and refuses a changed plugin with a version already published. Never commit to g1t-plugins itself. | | |
| 19 | + | | Settings, limits or prices | The page that names them, and the table it is in | | |
| 20 | + | | A new feature | A section in the guide that owns it, linked from the docs home if it is a new task | | |
| 21 | + | | How g1t is put together: a service, a binding, a store, an event route, the path of a request | Its page in the docs' Architecture section (`apps/docs/src/content/docs/architecture/`), and its diagram in `apps/docs/src/diagrams/architecture.ts`. [How g1t ships](https://docs.g1t.sh/architecture/shipping/#keeping-this-section-true) says which page covers what. | | |
| 22 | 22 | ||
| 23 | 23 | The style, in short: plain sentences, second person, no marketing words, | |
| 24 | 24 | sentence-case headings, a numbered list for steps, a table for options, and | |
| ⋯ | |||
| 200 | 200 | its cache is keyed by that digest (`zigbuild` from `ci-cache.mjs keys`) | |
| 201 | 201 | rather than by this machine's `rustc`. | |
| 202 | 202 | ||
| 203 | − | | Entry | Key | Saved by | Restored by | | |
| 204 | − | | --- | --- | --- | --- | | |
| 205 | − | | npm's downloads | `npm-full-<os>-<package-lock.json>` | Caches (`npm`) | every npm install | | |
| 206 | − | | Crates and their index | `cargo-crates-<os>-<deps>` | CI Rust (`cargo fetch` of the whole lockfile) | Deploy, the runner release | | |
| 207 | − | | The test build | `cargo-test-<os>-<rust>-<deps>` | CI Rust | CI Rust on pull requests | | |
| 208 | − | | Workers' builds | `cargo-workers-<os>-<rust>-<group>-<deps>` | Deploy | Deploy | | |
| 209 | − | | The runner's image build | `runner-musl-<os>-<rust>-<deps>` | Deploy | Deploy | | |
| 210 | − | | worker-build and its tools | `worker-build-…`, `worker-build-tools-…` | Deploy | Deploy | | |
| 211 | − | | Compiled crates | sccache's, one per crate | every Rust job | every Rust job | | |
| 212 | − | | The desktop app's check | `desktop-check-<os>-<rust>-<desktop deps>` | CI desktop | CI desktop on pull requests | | |
| 213 | − | | apt for Tauri | `apt-tauri-<os>-<scripts/apt-install.sh>` | CI desktop | the desktop release | | |
| 214 | − | | The runner release | `runner-release-<os>-<target>-<rust>-<deps>`, zig | Caches (`runner`) | the runner release | | |
| 215 | − | | The desktop release | `desktop-release-linux-…`, `desktop-release-windows-…`, `xwin-…`, `apt-tauri-windows-…` | Caches (`desktop-linux`, `desktop-windows`) | the desktop release | | |
| 216 | − | | The CLI release | `cli-release-<os>-<zigbuild>-<deps>` (`target/zig`, every platform) | Caches (`cli`), built whole | the CLI release | | |
| 203 | + | | Entry | Key | Saved by | Restored by | | |
| 204 | + | | -------------------------- | --------------------------------------------------------------------------------------- | --------------------------------------------- | --------------------------- | | |
| 205 | + | | npm's downloads | `npm-full-<os>-<package-lock.json>` | Caches (`npm`) | every npm install | | |
| 206 | + | | Crates and their index | `cargo-crates-<os>-<deps>` | CI Rust (`cargo fetch` of the whole lockfile) | Deploy, the runner release | | |
| 207 | + | | The test build | `cargo-test-<os>-<rust>-<deps>` | CI Rust | CI Rust on pull requests | | |
| 208 | + | | Workers' builds | `cargo-workers-<os>-<rust>-<group>-<deps>` | Deploy | Deploy | | |
| 209 | + | | The runner's image build | `runner-musl-<os>-<rust>-<deps>` | Deploy | Deploy | | |
| 210 | + | | worker-build and its tools | `worker-build-…`, `worker-build-tools-…` | Deploy | Deploy | | |
| 211 | + | | Compiled crates | sccache's, one per crate | every Rust job | every Rust job | | |
| 212 | + | | The desktop app's check | `desktop-check-<os>-<rust>-<desktop deps>` | CI desktop | CI desktop on pull requests | | |
| 213 | + | | apt for Tauri | `apt-tauri-<os>-<scripts/apt-install.sh>` | CI desktop | the desktop release | | |
| 214 | + | | The runner release | `runner-release-<os>-<target>-<rust>-<deps>`, zig | Caches (`runner`) | the runner release | | |
| 215 | + | | The desktop release | `desktop-release-linux-…`, `desktop-release-windows-…`, `xwin-…`, `apt-tauri-windows-…` | Caches (`desktop-linux`, `desktop-windows`) | the desktop release | | |
| 216 | + | | The CLI release | `cli-release-<os>-<zigbuild>-<deps>` (`target/zig`, every platform) | Caches (`cli`), built whole | the CLI release | | |
| 217 | 217 | ||
| 218 | 218 | To see whether a change helped, read a run's cache steps: `Cache restored | |
| 219 | 219 | from key` names the entry (the key itself is a hit; another is a start), | |
| 119 | 119 | ||
| 120 | 120 | ## Layout | |
| 121 | 121 | ||
| 122 | − | | Path | What it is | Language | | |
| 123 | − | | --- | --- | --- | | |
| 124 | − | | `apps/web` | The site: server-rendered React on a Worker. Holds no data. | TypeScript | | |
| 125 | − | | `apps/docs` | The documentation site, with the API explorer. | TypeScript | | |
| 126 | − | | `apps/api` | REST API and MCP server. | Rust | | |
| 127 | − | | `apps/desktop` | The desktop app (Tauri), with a runner inside. | Rust, TypeScript | | |
| 128 | − | | `apps/mobile` | The phone app (Expo). | TypeScript | | |
| 129 | − | | `apps/status` | The status page at `status.g1t.sh`. | TypeScript | | |
| 130 | − | | `apps/sudo` | g1t's own staff console. | TypeScript | | |
| 131 | − | | `services/identity` | Accounts, workspaces, sessions, keys, tokens and invites. | Rust | | |
| 132 | − | | `services/repos` | Repository registry, contents, forks, diffs, landing, git over HTTPS. | Rust | | |
| 133 | − | | `services/work` | Work items, pull requests, reviews, check runs, agent sessions, claims and the merge queue. | Rust | | |
| 134 | − | | `services/events` | The event bus and its log. | Rust | | |
| 135 | − | | `services/search` | Site-wide search and Explore. | Rust | | |
| 136 | − | | `services/billing` | Usage, the price book, limits, invoices and payments. | Rust | | |
| 137 | − | | `services/actions` | Workflows, runs, caches and self-hosted runners. | Rust | | |
| 138 | − | | `services/security` | Push protection findings, history scanning and dependency updates. | Rust | | |
| 139 | − | | `services/integrations` | AI providers, Ask, alerts, trackers and the GitHub App. | Rust | | |
| 140 | − | | `services/webhooks` | Webhook deliveries. | Rust | | |
| 141 | − | | `services/packages` | The package registries and container images. | Rust | | |
| 142 | − | | `services/runner` | Starts sandboxes for workflow jobs, builds and the merge queue. | TypeScript | | |
| 143 | − | | `services/projects` | Projects: what a workspace builds and runs, and where its code lives. | TypeScript | | |
| 144 | − | | `services/deployments` | Builds, previews and production on `g1t.page`. | TypeScript | | |
| 145 | − | | `services/pages` | Serves every app deployed on `g1t.page`, and custom domains. | TypeScript | | |
| 146 | − | | `services/telemetry` | Observability: OpenTelemetry ingest, logs, traces, metrics and errors. | TypeScript | | |
| 147 | − | | `services/chat` | Channels, direct messages, threads and their live sockets. | TypeScript | | |
| 148 | − | | `services/artifacts` | Docs: their spaces, sharing and live editing. | TypeScript | | |
| 149 | − | | `services/notify` | Notifications: each person's feed, live counts and browser push. | TypeScript | | |
| 150 | − | | `services/og` | Social cards at `og.g1t.sh`: a PNG per page, showing only what anyone may see. | TypeScript | | |
| 151 | − | | `crates/g1t` | The `g1t` command line. | Rust | | |
| 152 | − | | `crates/runner` | The program inside a sandbox, and the self-hosted runner: runs a workflow job or a build and reports back. | Rust | | |
| 153 | − | | `crates/contracts` | Types and service interfaces for the Rust services. | Rust | | |
| 154 | − | | `crates/kit` | Plumbing shared by Rust services on Workers. | Rust | | |
| 155 | − | | `crates/rules` | The rules engine for rulesets on branches and tags. | Rust | | |
| 156 | − | | `crates/blobstore` | Object storage: R2 on Cloudflare, any S3-compatible store self-hosted. | Rust | | |
| 157 | − | | `crates/actions` | Reads workflows and evaluates their expressions. | Rust | | |
| 158 | − | | `crates/scan` | Secret and lockfile scanning, shared by services. | Rust | | |
| 159 | − | | `crates/secrets` | Secrets at rest and signatures. | Rust | | |
| 160 | − | | `crates/sshd` | Git over SSH, bridged to Cloudflare Artifacts. Not deployed. | Rust | | |
| 161 | − | | `packages/contracts` | The same interfaces for TypeScript callers. | TypeScript | | |
| 162 | − | | `packages/theme` | Design tokens and the logo, shared by the site and the docs. | CSS | | |
| 163 | − | | `plugins/claude-code` | g1t's Claude Code plugin: hooks, skills and commands, published to `flagon-io/g1t-plugins` on every change. | JavaScript | | |
| 164 | − | | `plugins/codex` | Codex plugin: MCP server and work coordination skill, published to `flagon-io/g1t-plugins`. | JSON / Markdown | | |
| 165 | − | | `plugins/other-harnesses` | The AGENTS.md snippet for Codex, Cursor and other harnesses. | Markdown | | |
| 166 | − | | `deploy` | `stack.jsonc`, every deployable part and its resources; `self-host`, the Docker Compose version. | JSON, Docker Compose | | |
| 122 | + | | Path | What it is | Language | | |
| 123 | + | | ------------------------- | ----------------------------------------------------------------------------------------------------------- | -------------------- | | |
| 124 | + | | `apps/web` | The site: server-rendered React on a Worker. Holds no data. | TypeScript | | |
| 125 | + | | `apps/docs` | The documentation site, with the API explorer. | TypeScript | | |
| 126 | + | | `apps/api` | REST API and MCP server. | Rust | | |
| 127 | + | | `apps/desktop` | The desktop app (Tauri), with a runner inside. | Rust, TypeScript | | |
| 128 | + | | `apps/mobile` | The phone app (Expo). | TypeScript | | |
| 129 | + | | `apps/status` | The status page at `status.g1t.sh`. | TypeScript | | |
| 130 | + | | `apps/sudo` | g1t's own staff console. | TypeScript | | |
| 131 | + | | `services/identity` | Accounts, workspaces, sessions, keys, tokens and invites. | Rust | | |
| 132 | + | | `services/repos` | Repository registry, contents, forks, diffs, landing, git over HTTPS. | Rust | | |
| 133 | + | | `services/work` | Work items, pull requests, reviews, check runs, agent sessions, claims and the merge queue. | Rust | | |
| 134 | + | | `services/events` | The event bus and its log. | Rust | | |
| 135 | + | | `services/search` | Site-wide search and Explore. | Rust | | |
| 136 | + | | `services/billing` | Usage, the price book, limits, invoices and payments. | Rust | | |
| 137 | + | | `services/actions` | Workflows, runs, caches and self-hosted runners. | Rust | | |
| 138 | + | | `services/security` | Push protection findings, history scanning and dependency updates. | Rust | | |
| 139 | + | | `services/integrations` | AI providers, Ask, alerts, trackers and the GitHub App. | Rust | | |
| 140 | + | | `services/webhooks` | Webhook deliveries. | Rust | | |
| 141 | + | | `services/packages` | The package registries and container images. | Rust | | |
| 142 | + | | `services/runner` | Starts sandboxes for workflow jobs, builds and the merge queue. | TypeScript | | |
| 143 | + | | `services/projects` | Projects: what a workspace builds and runs, and where its code lives. | TypeScript | | |
| 144 | + | | `services/deployments` | Builds, previews and production on `g1t.page`. | TypeScript | | |
| 145 | + | | `services/pages` | Serves every app deployed on `g1t.page`, and custom domains. | TypeScript | | |
| 146 | + | | `services/telemetry` | Observability: OpenTelemetry ingest, logs, traces, metrics and errors. | TypeScript | | |
| 147 | + | | `services/chat` | Channels, direct messages, threads and their live sockets. | TypeScript | | |
| 148 | + | | `services/artifacts` | Docs: their spaces, sharing and live editing. | TypeScript | | |
| 149 | + | | `services/notify` | Notifications: each person's feed, live counts and browser push. | TypeScript | | |
| 150 | + | | `services/og` | Social cards at `og.g1t.sh`: a PNG per page, showing only what anyone may see. | TypeScript | | |
| 151 | + | | `crates/g1t` | The `g1t` command line. | Rust | | |
| 152 | + | | `crates/runner` | The program inside a sandbox, and the self-hosted runner: runs a workflow job or a build and reports back. | Rust | | |
| 153 | + | | `crates/contracts` | Types and service interfaces for the Rust services. | Rust | | |
| 154 | + | | `crates/kit` | Plumbing shared by Rust services on Workers. | Rust | | |
| 155 | + | | `crates/rules` | The rules engine for rulesets on branches and tags. | Rust | | |
| 156 | + | | `crates/blobstore` | Object storage: R2 on Cloudflare, any S3-compatible store self-hosted. | Rust | | |
| 157 | + | | `crates/actions` | Reads workflows and evaluates their expressions. | Rust | | |
| 158 | + | | `crates/scan` | Secret and lockfile scanning, shared by services. | Rust | | |
| 159 | + | | `crates/secrets` | Secrets at rest and signatures. | Rust | | |
| 160 | + | | `crates/sshd` | Git over SSH, bridged to Cloudflare Artifacts. Not deployed. | Rust | | |
| 161 | + | | `packages/contracts` | The same interfaces for TypeScript callers. | TypeScript | | |
| 162 | + | | `packages/theme` | Design tokens and the logo, shared by the site and the docs. | CSS | | |
| 163 | + | | `plugins/claude-code` | g1t's Claude Code plugin: hooks, skills and commands, published to `flagon-io/g1t-plugins` on every change. | JavaScript | | |
| 164 | + | | `plugins/codex` | Codex plugin: MCP server and work coordination skill, published to `flagon-io/g1t-plugins`. | JSON / Markdown | | |
| 165 | + | | `plugins/other-harnesses` | The AGENTS.md snippet for Codex, Cursor and other harnesses. | Markdown | | |
| 166 | + | | `deploy` | `stack.jsonc`, every deployable part and its resources; `self-host`, the Docker Compose version. | JSON, Docker Compose | | |
| 167 | 167 | ||
| 168 | 168 | Each service is its own Worker, and each one that keeps data has its own | |
| 169 | 169 | database. They call each other through service bindings and react to each | |
| ⋯ | |||
| 207 | 207 | ||
| 208 | 208 | 1. Create the resources each part needs: D1 databases, queues, KV | |
| 209 | 209 | namespaces, R2 buckets and the Cloudflare Artifacts namespace (`npx wrangler d1 | |
| 210 | − | create <name>`, `npx wrangler queues create <name>`, and so on), and set | |
| 210 | + | create <name>`, `npx wrangler queues create <name>`, and so on), and set | |
| 211 | 211 | each part's secrets. `deploy/stack.jsonc` lists them all. | |
| 212 | 212 | 2. Put your own `account_id`, database ids and hostnames in each | |
| 213 | 213 | `wrangler.jsonc`. | |
| 35 | 35 | ||
| 36 | 36 | ## Inputs | |
| 37 | 37 | ||
| 38 | − | | Input | Default | | | |
| 39 | − | | --- | --- | --- | | |
| 40 | − | | `project` | The repository's one project with Deployments on | The project's slug. Needed when the repository has several. | | |
| 41 | − | | `root-dir` | The project's setting | Where the project is in the checkout. | | |
| 42 | − | | `build-command` | The project's setting, else what the build finds | What builds it. | | |
| 43 | − | | `output-dir` | The project's setting, else the folder the framework writes, else the first of `dist`, `build`, `out`, `public`, `_site`, `.output/public` | The folder a static build writes. | | |
| 44 | − | | `build-as` | The project's setting, else `auto` | What it is built as: `auto`, `static`, `workers` or `docker`. A container is built with the `docker` on the job's `PATH`. | | |
| 45 | − | | `dockerfile` | The project's setting, else `Dockerfile` or `Containerfile` | The Dockerfile a container is built from, relative to the project. | | |
| 46 | − | | `sha` | The run's commit | The commit this is a build of, for its `g1t / deploy` check. | | |
| 47 | − | | `token` | `${{ github.token }}` | The job's own token. It needs `deployments: write`; any other token is refused. | | |
| 38 | + | | Input | Default | | | |
| 39 | + | | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------- | | |
| 40 | + | | `project` | The repository's one project with Deployments on | The project's slug. Needed when the repository has several. | | |
| 41 | + | | `root-dir` | The project's setting | Where the project is in the checkout. | | |
| 42 | + | | `build-command` | The project's setting, else what the build finds | What builds it. | | |
| 43 | + | | `output-dir` | The project's setting, else the folder the framework writes, else the first of `dist`, `build`, `out`, `public`, `_site`, `.output/public` | The folder a static build writes. | | |
| 44 | + | | `build-as` | The project's setting, else `auto` | What it is built as: `auto`, `static`, `workers` or `docker`. A container is built with the `docker` on the job's `PATH`. | | |
| 45 | + | | `dockerfile` | The project's setting, else `Dockerfile` or `Containerfile` | The Dockerfile a container is built from, relative to the project. | | |
| 46 | + | | `sha` | The run's commit | The commit this is a build of, for its `g1t / deploy` check. | | |
| 47 | + | | `token` | `${{ github.token }}` | The job's own token. It needs `deployments: write`; any other token is refused. | | |
| 48 | 48 | ||
| 49 | 49 | ## Outputs | |
| 50 | 50 | ||
| 51 | − | | Output | | | |
| 52 | − | | --- | --- | | |
| 53 | − | | `url` | Where the app is served. | | |
| 54 | − | | `deployment-id` | The build's id, `dpl_…`. | | |
| 55 | − | | `kind` | `production` or `preview`. | | |
| 51 | + | | Output | | | |
| 52 | + | | --------------- | -------------------------- | | |
| 53 | + | | `url` | Where the app is served. | | |
| 54 | + | | `deployment-id` | The build's id, `dpl_…`. | | |
| 55 | + | | `kind` | `production` or `preview`. | | |
| 56 | 56 | ||
| 57 | 57 | ## How it works | |
| 58 | 58 |
| 19 | 19 | ||
| 20 | 20 | ## Inputs | |
| 21 | 21 | ||
| 22 | − | | Input | Default | | | |
| 23 | − | | --- | --- | --- | | |
| 24 | − | | `root-dir` | The checkout | Where the project is in the checkout. | | |
| 25 | − | | `build-command` | None | A build command of your own, as `g1t/deploy` takes it. | | |
| 26 | − | | `output-dir` | None | An output folder of your own, as `g1t/deploy` takes it. | | |
| 27 | − | | `build-as` | `auto` | What it is built as: `auto`, `static`, `workers` or `docker` (Container), as `g1t/deploy` takes it. | | |
| 28 | − | | `dockerfile` | None | A Dockerfile's path of your own, as `g1t/deploy` takes it. | | |
| 22 | + | | Input | Default | | | |
| 23 | + | | --------------- | ------------ | --------------------------------------------------------------------------------------------------- | | |
| 24 | + | | `root-dir` | The checkout | Where the project is in the checkout. | | |
| 25 | + | | `build-command` | None | A build command of your own, as `g1t/deploy` takes it. | | |
| 26 | + | | `output-dir` | None | An output folder of your own, as `g1t/deploy` takes it. | | |
| 27 | + | | `build-as` | `auto` | What it is built as: `auto`, `static`, `workers` or `docker` (Container), as `g1t/deploy` takes it. | | |
| 28 | + | | `dockerfile` | None | A Dockerfile's path of your own, as `g1t/deploy` takes it. | | |
| 29 | 29 | ||
| 30 | 30 | ## Outputs | |
| 31 | 31 | ||
| 32 | − | | Output | | | |
| 33 | − | | --- | --- | | |
| 34 | − | | `kind` | `workers` (a `wrangler.jsonc`, `wrangler.json` or `wrangler.toml`, a framework's Cloudflare adapter, or a Node.js server run as a Worker), `static` (a site a build writes), `html` (the files as they are), `container` (a server that is not run as a Worker, a framework set up to need a server, or a `Dockerfile` with nothing else to serve) or `none` (nothing to serve). | | |
| 35 | − | | `framework` | The framework it is built with, from the table below; `node` for a Node.js server run as a Worker; for a container without one, `dockerfile`, or the server g1t writes a Dockerfile for (`node`, `django`, `flask`, `fastapi`, `python`, `go`, `rails`, `rack`, `laravel`, `php`). Empty when there is none. | | |
| 36 | − | | `dockerfile` | A container's own Dockerfile, relative to the project. Empty when g1t writes one, and for anything that is not a container. | | |
| 37 | − | | `port` | The port a container listens on: its Dockerfile's `EXPOSE`, else `8080`. | | |
| 38 | − | | `entry` | For a Node.js server run as a Worker, the file that starts it, relative to the project. Empty for anything else. | | |
| 39 | − | | `install` | How dependencies are installed, from the lockfile: `npm ci`, `pnpm install --frozen-lockfile`, and so on, and `bundle install` for Jekyll. Empty when there is nothing to install. | | |
| 40 | − | | `build` | What builds it: your command, the package's `build` script (`npm run build`), the framework's own command, or `wrangler deploy --dry-run` for Workers. Empty when nothing does. | | |
| 41 | − | | `output-dir` | The folder served, relative to the project (`.` for the project itself): yours, a Workers project's assets directory, the folder the framework writes, or the first of `dist`, `build`, `out`, `public`, `_site`, `.output/public` that exists. Empty when a build has yet to write it, as for a Cloudflare adapter's Worker. | | |
| 32 | + | | Output | | | |
| 33 | + | | ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | |
| 34 | + | | `kind` | `workers` (a `wrangler.jsonc`, `wrangler.json` or `wrangler.toml`, a framework's Cloudflare adapter, or a Node.js server run as a Worker), `static` (a site a build writes), `html` (the files as they are), `container` (a server that is not run as a Worker, a framework set up to need a server, or a `Dockerfile` with nothing else to serve) or `none` (nothing to serve). | | |
| 35 | + | | `framework` | The framework it is built with, from the table below; `node` for a Node.js server run as a Worker; for a container without one, `dockerfile`, or the server g1t writes a Dockerfile for (`node`, `django`, `flask`, `fastapi`, `python`, `go`, `rails`, `rack`, `laravel`, `php`). Empty when there is none. | | |
| 36 | + | | `dockerfile` | A container's own Dockerfile, relative to the project. Empty when g1t writes one, and for anything that is not a container. | | |
| 37 | + | | `port` | The port a container listens on: its Dockerfile's `EXPOSE`, else `8080`. | | |
| 38 | + | | `entry` | For a Node.js server run as a Worker, the file that starts it, relative to the project. Empty for anything else. | | |
| 39 | + | | `install` | How dependencies are installed, from the lockfile: `npm ci`, `pnpm install --frozen-lockfile`, and so on, and `bundle install` for Jekyll. Empty when there is nothing to install. | | |
| 40 | + | | `build` | What builds it: your command, the package's `build` script (`npm run build`), the framework's own command, or `wrangler deploy --dry-run` for Workers. Empty when nothing does. | | |
| 41 | + | | `output-dir` | The folder served, relative to the project (`.` for the project itself): yours, a Workers project's assets directory, the folder the framework writes, or the first of `dist`, `build`, `out`, `public`, `_site`, `.output/public` that exists. Empty when a build has yet to write it, as for a Cloudflare adapter's Worker. | | |
| 42 | 42 | ||
| 43 | 43 | When `kind` is `none`, the step's log says what to change or add, such as | |
| 44 | 44 | a `Dockerfile`. [Docker deployments](https://docs.g1t.sh/guides/deployments/#docker-deployments) | |
| ⋯ | |||
| 46 | 46 | ||
| 47 | 47 | ## Frameworks | |
| 48 | 48 | ||
| 49 | − | | `framework` | Found by | Serves | | |
| 50 | − | | --- | --- | --- | | |
| 51 | − | | `vite`, `vite-react`, `vite-vue`, `vite-svelte`, `vite-solid`, `vite-preact` | `vite`, and the framework's Vite plugin | `dist`, or `build.outDir` | | |
| 52 | − | | `astro` | `astro` | `dist`, or `outDir`; a Worker with `@astrojs/cloudflare` | | |
| 53 | − | | `nextjs` | `next` | `out` with `output: 'export'`; a Worker with `@opennextjs/cloudflare` and a `wrangler.jsonc` | | |
| 54 | − | | `sveltekit` | `@sveltejs/kit` | `build` with `adapter-static`; a Worker with `adapter-cloudflare` | | |
| 55 | − | | `nuxt` | `nuxt` | `.output/public`, from `nuxi generate` | | |
| 56 | − | | `react-router`, `remix` | `@react-router/dev`, `@remix-run/dev` | `build/client` with `ssr: false` | | |
| 57 | − | | `gatsby` | `gatsby` | `public` | | |
| 58 | − | | `docusaurus` | `@docusaurus/core` | `build` | | |
| 59 | − | | `eleventy` | `@11ty/eleventy` | `_site` | | |
| 60 | − | | `angular` | `@angular/core` and `angular.json` | `dist/<project>/browser` | | |
| 61 | − | | `create-react-app` | `react-scripts` | `build` | | |
| 62 | − | | `hugo` | `hugo.toml`, or Hugo's `config.toml` | `public` | | |
| 63 | − | | `jekyll` | `_config.yml` and a `Gemfile` | `_site` | | |
| 64 | − | | `mdbook` | `book.toml` | `book` | | |
| 49 | + | | `framework` | Found by | Serves | | |
| 50 | + | | ---------------------------------------------------------------------------- | --------------------------------------- | -------------------------------------------------------------------------------------------- | | |
| 51 | + | | `vite`, `vite-react`, `vite-vue`, `vite-svelte`, `vite-solid`, `vite-preact` | `vite`, and the framework's Vite plugin | `dist`, or `build.outDir` | | |
| 52 | + | | `astro` | `astro` | `dist`, or `outDir`; a Worker with `@astrojs/cloudflare` | | |
| 53 | + | | `nextjs` | `next` | `out` with `output: 'export'`; a Worker with `@opennextjs/cloudflare` and a `wrangler.jsonc` | | |
| 54 | + | | `sveltekit` | `@sveltejs/kit` | `build` with `adapter-static`; a Worker with `adapter-cloudflare` | | |
| 55 | + | | `nuxt` | `nuxt` | `.output/public`, from `nuxi generate` | | |
| 56 | + | | `react-router`, `remix` | `@react-router/dev`, `@remix-run/dev` | `build/client` with `ssr: false` | | |
| 57 | + | | `gatsby` | `gatsby` | `public` | | |
| 58 | + | | `docusaurus` | `@docusaurus/core` | `build` | | |
| 59 | + | | `eleventy` | `@11ty/eleventy` | `_site` | | |
| 60 | + | | `angular` | `@angular/core` and `angular.json` | `dist/<project>/browser` | | |
| 61 | + | | `create-react-app` | `react-scripts` | `build` | | |
| 62 | + | | `hugo` | `hugo.toml`, or Hugo's `config.toml` | `public` | | |
| 63 | + | | `jekyll` | `_config.yml` and a `Gemfile` | `_site` | | |
| 64 | + | | `mdbook` | `book.toml` | `book` | | |
| 65 | 65 | ||
| 66 | 66 | [What deploys](https://docs.g1t.sh/guides/deployments/#frameworks) has | |
| 67 | 67 | each one's build command. Your `build-command` and `output-dir` win over | |
Binary or large file; its contents are not shown.
| 1 | 1 | { | |
| 2 | − | "$schema": "../../node_modules/wrangler/config-schema.json", | |
| 3 | − | "name": "g1t-api", | |
| 4 | − | "account_id": "1e6f2cffa3f445920836e8ebe446bb58", | |
| 5 | − | "compatibility_date": "2026-09-26", | |
| 6 | − | "placement": { "mode": "off" }, | |
| 7 | − | "main": "build/index.js", | |
| 8 | − | "build": { "command": "node ../../scripts/build-rust-worker.mjs" }, | |
| 9 | − | "workers_dev": false, | |
| 10 | − | // One Worker, two hostnames: REST on api, MCP on mcp. Both are thin | |
| 11 | − | // adapters over the same operations. | |
| 12 | − | "routes": [ | |
| 13 | − | { "pattern": "api.g1t.sh", "custom_domain": true }, | |
| 14 | − | { "pattern": "mcp.g1t.sh", "custom_domain": true } | |
| 15 | − | ], | |
| 16 | − | "services": [ | |
| 17 | − | { "binding": "IDENTITY", "service": "g1t-identity" }, | |
| 18 | − | { "binding": "REPOS", "service": "g1t-repos" }, | |
| 19 | − | { "binding": "WORK", "service": "g1t-work" }, | |
| 20 | − | { "binding": "EVENTS", "service": "g1t-events" }, | |
| 21 | − | { "binding": "RUNNER", "service": "g1t-runner" }, | |
| 22 | − | { "binding": "BILLING", "service": "g1t-billing" }, | |
| 23 | − | { "binding": "INTEGRATIONS", "service": "g1t-integrations" }, | |
| 24 | − | { "binding": "WEBHOOKS", "service": "g1t-webhooks" }, | |
| 25 | − | { "binding": "ACTIONS", "service": "g1t-actions" }, | |
| 26 | − | // Builds of deployments report through here. | |
| 27 | − | { "binding": "DEPLOYMENTS", "service": "g1t-deployments" }, | |
| 28 | − | // Observability: a project's requests, logs, traces, errors and | |
| 29 | − | // metrics, and OTLP sent to /otlp/v1/{traces,logs,metrics}. | |
| 30 | − | { "binding": "TELEMETRY", "service": "g1t-telemetry" }, | |
| 31 | − | { "binding": "SEARCH", "service": "g1t-search" }, | |
| 32 | − | // Secret and dependency alerts: list_security_alerts and dismissing them. | |
| 33 | − | { "binding": "SECURITY", "service": "g1t-security" }, | |
| 34 | − | // A person's pinned projects: list_pinned_projects and changing them. | |
| 35 | − | { "binding": "PROJECTS", "service": "g1t-projects" }, | |
| 36 | − | // Packages: list_packages, their settings, deleting and restoring them. | |
| 37 | − | { "binding": "PACKAGES", "service": "g1t-packages" }, | |
| 38 | − | // Artifacts (folios): the artifact tool and /workspaces/{ws}/artifacts. | |
| 39 | − | { "binding": "ARTIFACTS", "service": "g1t-artifacts" } | |
| 40 | − | ], | |
| 41 | − | // GitHub Actions artifacts older runners kept, in chunks, with KV's own | |
| 42 | − | // expiry, read until it passes (and cache | |
| 43 | − | // entries saved before the cache moved to R2, until they expire). | |
| 44 | − | "kv_namespaces": [{ "binding": "BLOBS", "id": "16a4232cb746418db53782aa068be693" }], | |
| 45 | − | // actions/cache entries (`c/`) and artifacts (`a/`), uploaded in parts. The actions | |
| 46 | − | // service lists them and decides what is kept (services/actions/src/cache.rs). | |
| 47 | − | "r2_buckets": [{ "binding": "ACTIONS_CACHE", "bucket_name": "g1t-actions-cache" }], | |
| 48 | − | // REST and MCP requests (src/limits.rs): per token, or per address | |
| 49 | − | // without one. Ids and limits: RATE_LIMITS in packages/contracts. | |
| 50 | − | "ratelimits": [ | |
| 51 | − | { "name": "API_ANONYMOUS_LIMIT", "namespace_id": "4401", "simple": { "limit": 60, "period": 60 } }, | |
| 52 | − | { "name": "API_TOKEN_LIMIT", "namespace_id": "4402", "simple": { "limit": 1000, "period": 60 } } | |
| 53 | − | ], | |
| 54 | − | // Logs of a tenth of requests: agents call it constantly. | |
| 55 | − | "observability": { "enabled": true, "head_sampling_rate": 0.1 } | |
| 2 | + | "$schema": "../../node_modules/wrangler/config-schema.json", | |
| 3 | + | "name": "g1t-api", | |
| 4 | + | "account_id": "1e6f2cffa3f445920836e8ebe446bb58", | |
| 5 | + | "compatibility_date": "2026-09-26", | |
| 6 | + | "placement": { "mode": "off" }, | |
| 7 | + | "main": "build/index.js", | |
| 8 | + | "build": { "command": "node ../../scripts/build-rust-worker.mjs" }, | |
| 9 | + | "workers_dev": false, | |
| 10 | + | // One Worker, two hostnames: REST on api, MCP on mcp. Both are thin | |
| 11 | + | // adapters over the same operations. | |
| 12 | + | "routes": [ | |
| 13 | + | { "pattern": "api.g1t.sh", "custom_domain": true }, | |
| 14 | + | { "pattern": "mcp.g1t.sh", "custom_domain": true } | |
| 15 | + | ], | |
| 16 | + | "services": [ | |
| 17 | + | { "binding": "IDENTITY", "service": "g1t-identity" }, | |
| 18 | + | { "binding": "REPOS", "service": "g1t-repos" }, | |
| 19 | + | { "binding": "WORK", "service": "g1t-work" }, | |
| 20 | + | { "binding": "EVENTS", "service": "g1t-events" }, | |
| 21 | + | { "binding": "RUNNER", "service": "g1t-runner" }, | |
| 22 | + | { "binding": "BILLING", "service": "g1t-billing" }, | |
| 23 | + | { "binding": "INTEGRATIONS", "service": "g1t-integrations" }, | |
| 24 | + | { "binding": "WEBHOOKS", "service": "g1t-webhooks" }, | |
| 25 | + | { "binding": "ACTIONS", "service": "g1t-actions" }, | |
| 26 | + | // Builds of deployments report through here. | |
| 27 | + | { "binding": "DEPLOYMENTS", "service": "g1t-deployments" }, | |
| 28 | + | // Observability: a project's requests, logs, traces, errors and | |
| 29 | + | // metrics, and OTLP sent to /otlp/v1/{traces,logs,metrics}. | |
| 30 | + | { "binding": "TELEMETRY", "service": "g1t-telemetry" }, | |
| 31 | + | { "binding": "SEARCH", "service": "g1t-search" }, | |
| 32 | + | // Secret and dependency alerts: list_security_alerts and dismissing them. | |
| 33 | + | { "binding": "SECURITY", "service": "g1t-security" }, | |
| 34 | + | // A person's pinned projects: list_pinned_projects and changing them. | |
| 35 | + | { "binding": "PROJECTS", "service": "g1t-projects" }, | |
| 36 | + | // Packages: list_packages, their settings, deleting and restoring them. | |
| 37 | + | { "binding": "PACKAGES", "service": "g1t-packages" }, | |
| 38 | + | // Artifacts (folios): the artifact tool and /workspaces/{ws}/artifacts. | |
| 39 | + | { "binding": "ARTIFACTS", "service": "g1t-artifacts" } | |
| 40 | + | ], | |
| 41 | + | // GitHub Actions artifacts older runners kept, in chunks, with KV's own | |
| 42 | + | // expiry, read until it passes (and cache | |
| 43 | + | // entries saved before the cache moved to R2, until they expire). | |
| 44 | + | "kv_namespaces": [{ "binding": "BLOBS", "id": "16a4232cb746418db53782aa068be693" }], | |
| 45 | + | // actions/cache entries (`c/`) and artifacts (`a/`), uploaded in parts. The actions | |
| 46 | + | // service lists them and decides what is kept (services/actions/src/cache.rs). | |
| 47 | + | "r2_buckets": [{ "binding": "ACTIONS_CACHE", "bucket_name": "g1t-actions-cache" }], | |
| 48 | + | // REST and MCP requests (src/limits.rs): per token, or per address | |
| 49 | + | // without one. Ids and limits: RATE_LIMITS in packages/contracts. | |
| 50 | + | "ratelimits": [ | |
| 51 | + | { "name": "API_ANONYMOUS_LIMIT", "namespace_id": "4401", "simple": { "limit": 60, "period": 60 } }, | |
| 52 | + | { "name": "API_TOKEN_LIMIT", "namespace_id": "4402", "simple": { "limit": 1000, "period": 60 } } | |
| 53 | + | ], | |
| 54 | + | // Logs of a tenth of requests: agents call it constantly. | |
| 55 | + | "observability": { "enabled": true, "head_sampling_rate": 0.1 } | |
| 56 | 56 | } |
| 6 | 6 | what you see. It is also where another g1t is chosen (?change). | |
| 7 | 7 | --> | |
| 8 | 8 | <html lang="en"> | |
| 9 | − | <head> | |
| 10 | − | <meta charset="utf-8" /> | |
| 11 | − | <meta name="viewport" content="width=device-width, initial-scale=1" /> | |
| 12 | − | <meta name="color-scheme" content="dark" /> | |
| 13 | − | <title>g1t</title> | |
| 14 | − | <link rel="stylesheet" href="launcher.css" /> | |
| 15 | − | </head> | |
| 16 | − | <body> | |
| 17 | − | <main> | |
| 18 | − | <svg class="mark" viewBox="0 0 256 256" shape-rendering="crispEdges" aria-hidden="true"> | |
| 19 | − | <rect width="256" height="256" rx="56" shape-rendering="geometricPrecision" fill="#0f0f11" /> | |
| 20 | − | <rect x="118" y="43" width="20" height="20" fill="#b6a8ff" /> | |
| 21 | − | <rect x="93" y="68" width="20" height="20" fill="#b6a8ff" /> | |
| 22 | − | <rect x="118" y="68" width="20" height="20" fill="#b6a8ff" /> | |
| 23 | − | <rect x="68" y="93" width="20" height="20" fill="#b6a8ff" /> | |
| 24 | − | <rect x="118" y="93" width="20" height="20" fill="#b6a8ff" /> | |
| 25 | − | <rect x="118" y="118" width="20" height="20" fill="#b6a8ff" /> | |
| 26 | − | <rect x="118" y="143" width="20" height="20" fill="#b6a8ff" /> | |
| 27 | − | <rect x="118" y="168" width="20" height="20" fill="#b6a8ff" /> | |
| 28 | − | <rect x="68" y="193" width="20" height="20" fill="#b6a8ff" /> | |
| 29 | − | <rect x="93" y="193" width="20" height="20" fill="#b6a8ff" /> | |
| 30 | − | <rect x="118" y="193" width="20" height="20" fill="#b6a8ff" /> | |
| 31 | − | <rect x="143" y="193" width="20" height="20" fill="#b6a8ff" /> | |
| 32 | − | <rect x="168" y="193" width="20" height="20" fill="#b6a8ff" /> | |
| 33 | − | </svg> | |
| 9 | + | <head> | |
| 10 | + | <meta charset="utf-8" /> | |
| 11 | + | <meta name="viewport" content="width=device-width, initial-scale=1" /> | |
| 12 | + | <meta name="color-scheme" content="dark" /> | |
| 13 | + | <title>g1t</title> | |
| 14 | + | <link rel="stylesheet" href="launcher.css" /> | |
| 15 | + | </head> | |
| 16 | + | <body> | |
| 17 | + | <main> | |
| 18 | + | <svg class="mark" viewBox="0 0 256 256" shape-rendering="crispEdges" aria-hidden="true"> | |
| 19 | + | <rect width="256" height="256" rx="56" shape-rendering="geometricPrecision" fill="#0f0f11" /> | |
| 20 | + | <rect x="118" y="43" width="20" height="20" fill="#b6a8ff" /> | |
| 21 | + | <rect x="93" y="68" width="20" height="20" fill="#b6a8ff" /> | |
| 22 | + | <rect x="118" y="68" width="20" height="20" fill="#b6a8ff" /> | |
| 23 | + | <rect x="68" y="93" width="20" height="20" fill="#b6a8ff" /> | |
| 24 | + | <rect x="118" y="93" width="20" height="20" fill="#b6a8ff" /> | |
| 25 | + | <rect x="118" y="118" width="20" height="20" fill="#b6a8ff" /> | |
| 26 | + | <rect x="118" y="143" width="20" height="20" fill="#b6a8ff" /> | |
| 27 | + | <rect x="118" y="168" width="20" height="20" fill="#b6a8ff" /> | |
| 28 | + | <rect x="68" y="193" width="20" height="20" fill="#b6a8ff" /> | |
| 29 | + | <rect x="93" y="193" width="20" height="20" fill="#b6a8ff" /> | |
| 30 | + | <rect x="118" y="193" width="20" height="20" fill="#b6a8ff" /> | |
| 31 | + | <rect x="143" y="193" width="20" height="20" fill="#b6a8ff" /> | |
| 32 | + | <rect x="168" y="193" width="20" height="20" fill="#b6a8ff" /> | |
| 33 | + | </svg> | |
| 34 | 34 | ||
| 35 | − | <section id="connecting" hidden> | |
| 36 | − | <p class="status"><span class="pulse"></span><span id="connecting-text">Connecting to g1t…</span></p> | |
| 37 | − | </section> | |
| 35 | + | <section id="connecting" hidden> | |
| 36 | + | <p class="status"><span class="pulse"></span><span id="connecting-text">Connecting to g1t…</span></p> | |
| 37 | + | </section> | |
| 38 | 38 | ||
| 39 | − | <section id="offline" hidden> | |
| 40 | − | <h1 id="offline-title">Can't reach g1t.sh</h1> | |
| 41 | − | <p class="muted">Check your connection, then try again. If g1t.sh itself is down, its status page says so.</p> | |
| 42 | − | <div class="row"> | |
| 43 | − | <button id="retry" type="button" class="primary">Try again</button> | |
| 44 | − | <button id="change" type="button">Use another g1t…</button> | |
| 45 | − | </div> | |
| 46 | − | <p class="muted small"><a id="status-link" href="https://status.g1t.sh/">status.g1t.sh</a></p> | |
| 47 | − | </section> | |
| 39 | + | <section id="offline" hidden> | |
| 40 | + | <h1 id="offline-title">Can't reach g1t.sh</h1> | |
| 41 | + | <p class="muted">Check your connection, then try again. If g1t.sh itself is down, its status page says so.</p> | |
| 42 | + | <div class="row"> | |
| 43 | + | <button id="retry" type="button" class="primary">Try again</button> | |
| 44 | + | <button id="change" type="button">Use another g1t…</button> | |
| 45 | + | </div> | |
| 46 | + | <p class="muted small"><a id="status-link" href="https://status.g1t.sh/">status.g1t.sh</a></p> | |
| 47 | + | </section> | |
| 48 | 48 | ||
| 49 | − | <section id="choose" hidden> | |
| 50 | − | <h1>Which g1t?</h1> | |
| 51 | − | <p class="muted">g1t.sh unless you run g1t yourself. Enter your g1t's address to use it instead; the app keeps it.</p> | |
| 52 | − | <form id="server-form"> | |
| 53 | − | <label for="server">Address</label> | |
| 54 | − | <input id="server" name="server" type="url" inputmode="url" autocomplete="off" spellcheck="false" placeholder="https://g1t.example.com" /> | |
| 55 | − | <p id="server-error" class="error" hidden></p> | |
| 56 | − | <div class="row"> | |
| 57 | − | <button type="submit" class="primary">Use this g1t</button> | |
| 58 | − | <button id="use-default" type="button">Use g1t.sh</button> | |
| 59 | − | </div> | |
| 60 | − | </form> | |
| 61 | − | </section> | |
| 49 | + | <section id="choose" hidden> | |
| 50 | + | <h1>Which g1t?</h1> | |
| 51 | + | <p class="muted">g1t.sh unless you run g1t yourself. Enter your g1t's address to use it instead; the app keeps it.</p> | |
| 52 | + | <form id="server-form"> | |
| 53 | + | <label for="server">Address</label> | |
| 54 | + | <input id="server" name="server" type="url" inputmode="url" autocomplete="off" spellcheck="false" placeholder="https://g1t.example.com" /> | |
| 55 | + | <p id="server-error" class="error" hidden></p> | |
| 56 | + | <div class="row"> | |
| 57 | + | <button type="submit" class="primary">Use this g1t</button> | |
| 58 | + | <button id="use-default" type="button">Use g1t.sh</button> | |
| 59 | + | </div> | |
| 60 | + | </form> | |
| 61 | + | </section> | |
| 62 | 62 | ||
| 63 | − | <p class="version muted small" id="version"></p> | |
| 64 | − | </main> | |
| 65 | − | <script src="launcher.js"></script> | |
| 66 | − | </body> | |
| 63 | + | <p class="version muted small" id="version"></p> | |
| 64 | + | </main> | |
| 65 | + | <script src="launcher.js"></script> | |
| 66 | + | </body> | |
| 67 | 67 | </html> |
| 1 | 1 | /* The launcher, in the site's colours (packages/theme/tokens.css): a very | |
| 2 | 2 | dark gray and lavender, the mark centred, one short message. */ | |
| 3 | 3 | :root { | |
| 4 | − | --bg: #0f0f11; | |
| 5 | − | --fg: #ededf0; | |
| 6 | − | --muted: #9a9aa6; | |
| 7 | − | --line: #26262c; | |
| 8 | − | --surface: #17171b; | |
| 9 | − | --accent: #b6a8ff; | |
| 10 | − | --accent-ink: #15112e; | |
| 11 | − | --error: #ff8a8a; | |
| 12 | − | color-scheme: dark; | |
| 4 | + | --bg: #0f0f11; | |
| 5 | + | --fg: #ededf0; | |
| 6 | + | --muted: #9a9aa6; | |
| 7 | + | --line: #26262c; | |
| 8 | + | --surface: #17171b; | |
| 9 | + | --accent: #b6a8ff; | |
| 10 | + | --accent-ink: #15112e; | |
| 11 | + | --error: #ff8a8a; | |
| 12 | + | color-scheme: dark; | |
| 13 | 13 | } | |
| 14 | 14 | * { | |
| 15 | − | box-sizing: border-box; | |
| 15 | + | box-sizing: border-box; | |
| 16 | 16 | } | |
| 17 | 17 | html, | |
| 18 | 18 | body { | |
| 19 | − | height: 100%; | |
| 20 | − | margin: 0; | |
| 19 | + | height: 100%; | |
| 20 | + | margin: 0; | |
| 21 | 21 | } | |
| 22 | 22 | body { | |
| 23 | − | background: var(--bg); | |
| 24 | − | color: var(--fg); | |
| 25 | − | font: 15px/1.5 system-ui, "Segoe UI", Roboto, "Helvetica Neue", sans-serif; | |
| 26 | − | -webkit-font-smoothing: antialiased; | |
| 27 | − | display: grid; | |
| 28 | − | place-items: center; | |
| 29 | − | user-select: none; | |
| 30 | − | cursor: default; | |
| 23 | + | background: var(--bg); | |
| 24 | + | color: var(--fg); | |
| 25 | + | font: | |
| 26 | + | 15px/1.5 system-ui, | |
| 27 | + | "Segoe UI", | |
| 28 | + | Roboto, | |
| 29 | + | "Helvetica Neue", | |
| 30 | + | sans-serif; | |
| 31 | + | -webkit-font-smoothing: antialiased; | |
| 32 | + | display: grid; | |
| 33 | + | place-items: center; | |
| 34 | + | user-select: none; | |
| 35 | + | cursor: default; | |
| 31 | 36 | } | |
| 32 | 37 | main { | |
| 33 | − | width: min(26rem, calc(100vw - 2rem)); | |
| 34 | − | text-align: center; | |
| 38 | + | width: min(26rem, calc(100vw - 2rem)); | |
| 39 | + | text-align: center; | |
| 35 | 40 | } | |
| 36 | 41 | .mark { | |
| 37 | − | width: 72px; | |
| 38 | − | height: 72px; | |
| 39 | − | display: block; | |
| 40 | − | margin: 0 auto 1.5rem; | |
| 41 | − | border-radius: 16px; | |
| 42 | − | box-shadow: 0 0 0 1px var(--line); | |
| 42 | + | width: 72px; | |
| 43 | + | height: 72px; | |
| 44 | + | display: block; | |
| 45 | + | margin: 0 auto 1.5rem; | |
| 46 | + | border-radius: 16px; | |
| 47 | + | box-shadow: 0 0 0 1px var(--line); | |
| 43 | 48 | } | |
| 44 | 49 | h1 { | |
| 45 | − | font-size: 1.125rem; | |
| 46 | − | font-weight: 600; | |
| 47 | − | margin: 0 0 0.5rem; | |
| 50 | + | font-size: 1.125rem; | |
| 51 | + | font-weight: 600; | |
| 52 | + | margin: 0 0 0.5rem; | |
| 48 | 53 | } | |
| 49 | 54 | p { | |
| 50 | − | margin: 0 0 1rem; | |
| 55 | + | margin: 0 0 1rem; | |
| 51 | 56 | } | |
| 52 | 57 | .muted { | |
| 53 | − | color: var(--muted); | |
| 58 | + | color: var(--muted); | |
| 54 | 59 | } | |
| 55 | 60 | .small { | |
| 56 | − | font-size: 0.8125rem; | |
| 61 | + | font-size: 0.8125rem; | |
| 57 | 62 | } | |
| 58 | 63 | .error { | |
| 59 | − | color: var(--error); | |
| 60 | − | font-size: 0.875rem; | |
| 61 | − | text-align: left; | |
| 64 | + | color: var(--error); | |
| 65 | + | font-size: 0.875rem; | |
| 66 | + | text-align: left; | |
| 62 | 67 | } | |
| 63 | 68 | .status { | |
| 64 | − | display: inline-flex; | |
| 65 | − | align-items: center; | |
| 66 | − | gap: 0.625rem; | |
| 67 | − | color: var(--muted); | |
| 69 | + | display: inline-flex; | |
| 70 | + | align-items: center; | |
| 71 | + | gap: 0.625rem; | |
| 72 | + | color: var(--muted); | |
| 68 | 73 | } | |
| 69 | 74 | .pulse { | |
| 70 | − | width: 8px; | |
| 71 | − | height: 8px; | |
| 72 | − | border-radius: 50%; | |
| 73 | − | background: var(--accent); | |
| 74 | − | animation: pulse 1.4s ease-in-out infinite; | |
| 75 | + | width: 8px; | |
| 76 | + | height: 8px; | |
| 77 | + | border-radius: 50%; | |
| 78 | + | background: var(--accent); | |
| 79 | + | animation: pulse 1.4s ease-in-out infinite; | |
| 75 | 80 | } | |
| 76 | 81 | @keyframes pulse { | |
| 77 | − | 0%, | |
| 78 | − | 100% { | |
| 79 | − | opacity: 0.35; | |
| 80 | − | transform: scale(0.85); | |
| 81 | − | } | |
| 82 | − | 50% { | |
| 83 | − | opacity: 1; | |
| 84 | − | transform: scale(1); | |
| 85 | − | } | |
| 82 | + | 0%, | |
| 83 | + | 100% { | |
| 84 | + | opacity: 0.35; | |
| 85 | + | transform: scale(0.85); | |
| 86 | + | } | |
| 87 | + | 50% { | |
| 88 | + | opacity: 1; | |
| 89 | + | transform: scale(1); | |
| 90 | + | } | |
| 86 | 91 | } | |
| 87 | 92 | @media (prefers-reduced-motion: reduce) { | |
| 88 | − | .pulse { | |
| 89 | − | animation: none; | |
| 90 | − | } | |
| 93 | + | .pulse { | |
| 94 | + | animation: none; | |
| 95 | + | } | |
| 91 | 96 | } | |
| 92 | 97 | .row { | |
| 93 | − | display: flex; | |
| 94 | − | gap: 0.5rem; | |
| 95 | − | justify-content: center; | |
| 96 | − | flex-wrap: wrap; | |
| 97 | − | margin-bottom: 1rem; | |
| 98 | + | display: flex; | |
| 99 | + | gap: 0.5rem; | |
| 100 | + | justify-content: center; | |
| 101 | + | flex-wrap: wrap; | |
| 102 | + | margin-bottom: 1rem; | |
| 98 | 103 | } | |
| 99 | 104 | button { | |
| 100 | − | font: inherit; | |
| 101 | − | font-size: 0.875rem; | |
| 102 | − | font-weight: 500; | |
| 103 | − | padding: 0.5rem 0.875rem; | |
| 104 | − | border-radius: 8px; | |
| 105 | − | border: 1px solid var(--line); | |
| 106 | − | background: var(--surface); | |
| 107 | − | color: var(--fg); | |
| 108 | − | cursor: default; | |
| 105 | + | font: inherit; | |
| 106 | + | font-size: 0.875rem; | |
| 107 | + | font-weight: 500; | |
| 108 | + | padding: 0.5rem 0.875rem; | |
| 109 | + | border-radius: 8px; | |
| 110 | + | border: 1px solid var(--line); | |
| 111 | + | background: var(--surface); | |
| 112 | + | color: var(--fg); | |
| 113 | + | cursor: default; | |
| 109 | 114 | } | |
| 110 | 115 | button:hover { | |
| 111 | − | border-color: #3a3a44; | |
| 116 | + | border-color: #3a3a44; | |
| 112 | 117 | } | |
| 113 | 118 | button:focus-visible, | |
| 114 | 119 | input:focus-visible { | |
| 115 | − | outline: 2px solid var(--accent); | |
| 116 | − | outline-offset: 2px; | |
| 120 | + | outline: 2px solid var(--accent); | |
| 121 | + | outline-offset: 2px; | |
| 117 | 122 | } | |
| 118 | 123 | button.primary { | |
| 119 | − | background: var(--accent); | |
| 120 | − | border-color: var(--accent); | |
| 121 | − | color: var(--accent-ink); | |
| 124 | + | background: var(--accent); | |
| 125 | + | border-color: var(--accent); | |
| 126 | + | color: var(--accent-ink); | |
| 122 | 127 | } | |
| 123 | 128 | button.primary:hover { | |
| 124 | − | filter: brightness(1.06); | |
| 129 | + | filter: brightness(1.06); | |
| 125 | 130 | } | |
| 126 | 131 | form { | |
| 127 | − | text-align: left; | |
| 132 | + | text-align: left; | |
| 128 | 133 | } | |
| 129 | 134 | label { | |
| 130 | − | display: block; | |
| 131 | − | font-size: 0.8125rem; | |
| 132 | − | color: var(--muted); | |
| 133 | − | margin-bottom: 0.25rem; | |
| 135 | + | display: block; | |
| 136 | + | font-size: 0.8125rem; | |
| 137 | + | color: var(--muted); | |
| 138 | + | margin-bottom: 0.25rem; | |
| 134 | 139 | } | |
| 135 | 140 | input { | |
| 136 | − | font: inherit; | |
| 137 | − | width: 100%; | |
| 138 | − | padding: 0.5rem 0.625rem; | |
| 139 | − | border-radius: 8px; | |
| 140 | − | border: 1px solid var(--line); | |
| 141 | − | background: var(--surface); | |
| 142 | − | color: var(--fg); | |
| 143 | − | margin-bottom: 0.75rem; | |
| 144 | − | user-select: text; | |
| 141 | + | font: inherit; | |
| 142 | + | width: 100%; | |
| 143 | + | padding: 0.5rem 0.625rem; | |
| 144 | + | border-radius: 8px; | |
| 145 | + | border: 1px solid var(--line); | |
| 146 | + | background: var(--surface); | |
| 147 | + | color: var(--fg); | |
| 148 | + | margin-bottom: 0.75rem; | |
| 149 | + | user-select: text; | |
| 145 | 150 | } | |
| 146 | 151 | a { | |
| 147 | − | color: var(--muted); | |
| 148 | − | text-decoration: underline; | |
| 149 | − | text-underline-offset: 3px; | |
| 152 | + | color: var(--muted); | |
| 153 | + | text-decoration: underline; | |
| 154 | + | text-underline-offset: 3px; | |
| 150 | 155 | } | |
| 151 | 156 | a:hover { | |
| 152 | − | color: var(--fg); | |
| 157 | + | color: var(--fg); | |
| 153 | 158 | } | |
| 154 | 159 | .version { | |
| 155 | − | margin-top: 2.5rem; | |
| 156 | − | margin-bottom: 0; | |
| 157 | − | font-variant-numeric: tabular-nums; | |
| 160 | + | margin-top: 2.5rem; | |
| 161 | + | margin-bottom: 0; | |
| 162 | + | font-variant-numeric: tabular-nums; | |
| 158 | 163 | } |
| 10 | 10 | (src/runner/diagnosis.rs). | |
| 11 | 11 | --> | |
| 12 | 12 | <html lang="en"> | |
| 13 | − | <head> | |
| 14 | − | <meta charset="utf-8" /> | |
| 15 | − | <meta name="viewport" content="width=device-width, initial-scale=1" /> | |
| 16 | − | <meta name="color-scheme" content="dark" /> | |
| 17 | − | <title>g1t runner</title> | |
| 18 | − | <link rel="stylesheet" href="settings.css" /> | |
| 19 | − | </head> | |
| 20 | − | <body> | |
| 21 | − | <!-- Its title bar, when g1t draws its own (src/frame.rs): drag it to move the window. --> | |
| 22 | − | <header class="titlebar" id="titlebar" hidden> | |
| 23 | − | <span>Runner</span> | |
| 24 | − | <button type="button" id="close-window" class="caption" aria-label="Close" title="Close" tabindex="-1"> | |
| 25 | − | <svg viewBox="0 0 16 16" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" aria-hidden="true"> | |
| 26 | − | <line x1="4" y1="4" x2="12" y2="12" /> | |
| 27 | − | <line x1="12" y1="4" x2="4" y2="12" /> | |
| 28 | − | </svg> | |
| 29 | − | </button> | |
| 30 | − | </header> | |
| 31 | − | <div class="page"> | |
| 32 | − | <main> | |
| 33 | − | <h1>Runner</h1> | |
| 34 | − | <p class="muted lede">Your workspace's <code>runs-on: self-hosted</code> jobs run on this computer while g1t is open, at no cost.</p> | |
| 13 | + | <head> | |
| 14 | + | <meta charset="utf-8" /> | |
| 15 | + | <meta name="viewport" content="width=device-width, initial-scale=1" /> | |
| 16 | + | <meta name="color-scheme" content="dark" /> | |
| 17 | + | <title>g1t runner</title> | |
| 18 | + | <link rel="stylesheet" href="settings.css" /> | |
| 19 | + | </head> | |
| 20 | + | <body> | |
| 21 | + | <!-- Its title bar, when g1t draws its own (src/frame.rs): drag it to move the window. --> | |
| 22 | + | <header class="titlebar" id="titlebar" hidden> | |
| 23 | + | <span>Runner</span> | |
| 24 | + | <button type="button" id="close-window" class="caption" aria-label="Close" title="Close" tabindex="-1"> | |
| 25 | + | <svg viewBox="0 0 16 16" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" aria-hidden="true"> | |
| 26 | + | <line x1="4" y1="4" x2="12" y2="12" /> | |
| 27 | + | <line x1="12" y1="4" x2="4" y2="12" /> | |
| 28 | + | </svg> | |
| 29 | + | </button> | |
| 30 | + | </header> | |
| 31 | + | <div class="page"> | |
| 32 | + | <main> | |
| 33 | + | <h1>Runner</h1> | |
| 34 | + | <p class="muted lede">Your workspace's <code>runs-on: self-hosted</code> jobs run on this computer while g1t is open, at no cost.</p> | |
| 35 | 35 | ||
| 36 | − | <!-- What the whole runner is doing, as the title bar's chip says it, with its Start or Stop. --> | |
| 37 | − | <div class="engine" id="engine"> | |
| 38 | − | <span class="dot" id="engine-dot" aria-hidden="true"></span> | |
| 39 | − | <span class="engine-text"> | |
| 40 | − | <strong id="engine-label" role="status" aria-live="polite">Runner</strong> | |
| 41 | − | <span class="muted" id="engine-sub"> </span> | |
| 42 | − | </span> | |
| 43 | − | <button type="button" id="engine-toggle" hidden>Stop</button> | |
| 44 | − | </div> | |
| 36 | + | <!-- What the whole runner is doing, as the title bar's chip says it, with its Start or Stop. --> | |
| 37 | + | <div class="engine" id="engine"> | |
| 38 | + | <span class="dot" id="engine-dot" aria-hidden="true"></span> | |
| 39 | + | <span class="engine-text"> | |
| 40 | + | <strong id="engine-label" role="status" aria-live="polite">Runner</strong> | |
| 41 | + | <span class="muted" id="engine-sub"> </span> | |
| 42 | + | </span> | |
| 43 | + | <button type="button" id="engine-toggle" hidden>Stop</button> | |
| 44 | + | </div> | |
| 45 | 45 | ||
| 46 | − | <section aria-labelledby="kinds-heading" id="runner-section"> | |
| 47 | − | <h2 id="kinds-heading" class="visually-hidden">Jobs</h2> | |
| 48 | − | <!-- | |
| 46 | + | <section aria-labelledby="kinds-heading" id="runner-section"> | |
| 47 | + | <h2 id="kinds-heading" class="visually-hidden">Jobs</h2> | |
| 48 | + | <!-- | |
| 49 | 49 | What affects the whole runner (signed out, no workspace, turned off, | |
| 50 | 50 | the sandbox down): why, and how to fix it (src/runner/diagnosis.rs). | |
| 51 | 51 | Hidden when the cards below say it all. | |
| 52 | 52 | --> | |
| 53 | − | <div class="diagnosis" id="runner-diagnosis" role="status" aria-live="polite" hidden> | |
| 54 | − | <span class="dot" id="runner-dot" aria-hidden="true"></span> | |
| 55 | − | <span class="diagnosis-text"> | |
| 56 | − | <strong id="runner-title">Runner</strong> | |
| 57 | − | <span class="muted" id="runner-cause"></span> | |
| 58 | − | <span id="runner-fix"></span> | |
| 59 | − | <span class="buttons" id="runner-actions"></span> | |
| 60 | − | </span> | |
| 61 | − | </div> | |
| 62 | − | <!-- Sandboxed: each kind of job it runs, a card of its own, started and stopped on its own. --> | |
| 63 | − | <div class="kinds" id="runner-kinds" role="list" aria-label="Kinds of job this computer runs" hidden></div> | |
| 64 | − | </section> | |
| 53 | + | <div class="diagnosis" id="runner-diagnosis" role="status" aria-live="polite" hidden> | |
| 54 | + | <span class="dot" id="runner-dot" aria-hidden="true"></span> | |
| 55 | + | <span class="diagnosis-text"> | |
| 56 | + | <strong id="runner-title">Runner</strong> | |
| 57 | + | <span class="muted" id="runner-cause"></span> | |
| 58 | + | <span id="runner-fix"></span> | |
| 59 | + | <span class="buttons" id="runner-actions"></span> | |
| 60 | + | </span> | |
| 61 | + | </div> | |
| 62 | + | <!-- Sandboxed: each kind of job it runs, a card of its own, started and stopped on its own. --> | |
| 63 | + | <div class="kinds" id="runner-kinds" role="list" aria-label="Kinds of job this computer runs" hidden></div> | |
| 64 | + | </section> | |
| 65 | 65 | ||
| 66 | − | <section aria-labelledby="setup-heading"> | |
| 67 | − | <h2 id="setup-heading">Setup</h2> | |
| 68 | − | <label class="setting"> | |
| 69 | − | <span | |
| 70 | − | ><strong>Run jobs on this computer while g1t is open</strong | |
| 71 | − | ><span class="muted">Off, nothing runs here until you turn it on again.</span></span | |
| 72 | − | > | |
| 73 | − | <input type="checkbox" role="switch" id="runner" /> | |
| 74 | − | </label> | |
| 75 | − | <label class="setting"> | |
| 76 | − | <span><strong>How jobs run</strong><span class="muted" id="runner-backend-note"> </span></span> | |
| 77 | − | <select id="runnerBackend"> | |
| 78 | − | <option value="sandboxed">Sandboxed (recommended)</option> | |
| 79 | − | <option value="docker">In Docker</option> | |
| 80 | − | <option value="host">Directly on this computer</option> | |
| 81 | − | </select> | |
| 82 | − | </label> | |
| 83 | − | <label class="setting"> | |
| 84 | − | <span><strong>Workspace</strong><span class="muted" id="runner-workspace-note">The workspace whose jobs it runs. Only a workspace's owners can add runners to it.</span></span> | |
| 85 | − | <select id="runnerWorkspace"></select> | |
| 86 | − | </label> | |
| 87 | − | <div class="setting"> | |
| 88 | − | <span><strong id="runner-machine">This computer</strong><span class="muted" id="runner-version"> </span></span> | |
| 89 | − | <span class="buttons" | |
| 90 | − | ><button type="button" id="runner-check" hidden>Check for runner updates</button | |
| 91 | − | ><button type="button" id="runner-view">View on g1t</button></span | |
| 92 | − | > | |
| 93 | − | </div> | |
| 94 | − | </section> | |
| 66 | + | <section aria-labelledby="setup-heading"> | |
| 67 | + | <h2 id="setup-heading">Setup</h2> | |
| 68 | + | <label class="setting"> | |
| 69 | + | <span | |
| 70 | + | ><strong>Run jobs on this computer while g1t is open</strong><span class="muted">Off, nothing runs here until you turn it on again.</span></span | |
| 71 | + | > | |
| 72 | + | <input type="checkbox" role="switch" id="runner" /> | |
| 73 | + | </label> | |
| 74 | + | <label class="setting"> | |
| 75 | + | <span><strong>How jobs run</strong><span class="muted" id="runner-backend-note"> </span></span> | |
| 76 | + | <select id="runnerBackend"> | |
| 77 | + | <option value="sandboxed">Sandboxed (recommended)</option> | |
| 78 | + | <option value="docker">In Docker</option> | |
| 79 | + | <option value="host">Directly on this computer</option> | |
| 80 | + | </select> | |
| 81 | + | </label> | |
| 82 | + | <label class="setting"> | |
| 83 | + | <span | |
| 84 | + | ><strong>Workspace</strong | |
| 85 | + | ><span class="muted" id="runner-workspace-note">The workspace whose jobs it runs. Only a workspace's owners can add runners to it.</span></span | |
| 86 | + | > | |
| 87 | + | <select id="runnerWorkspace"></select> | |
| 88 | + | </label> | |
| 89 | + | <div class="setting"> | |
| 90 | + | <span><strong id="runner-machine">This computer</strong><span class="muted" id="runner-version"> </span></span> | |
| 91 | + | <span class="buttons" | |
| 92 | + | ><button type="button" id="runner-check" hidden>Check for runner updates</button><button type="button" id="runner-view">View on g1t</button></span | |
| 93 | + | > | |
| 94 | + | </div> | |
| 95 | + | </section> | |
| 95 | 96 | ||
| 96 | − | <section aria-labelledby="log-heading"> | |
| 97 | − | <h2 id="log-heading">Log</h2> | |
| 98 | − | <pre class="live-log" id="runner-log" tabindex="0" aria-label="The runner's recent log">Nothing yet.</pre> | |
| 99 | − | <p class="buttons"><button type="button" id="runner-open-log">Open the whole log</button></p> | |
| 100 | − | </section> | |
| 97 | + | <section aria-labelledby="log-heading"> | |
| 98 | + | <h2 id="log-heading">Log</h2> | |
| 99 | + | <pre class="live-log" id="runner-log" tabindex="0" aria-label="The runner's recent log">Nothing yet.</pre> | |
| 100 | + | <p class="buttons"><button type="button" id="runner-open-log">Open the whole log</button></p> | |
| 101 | + | </section> | |
| 101 | 102 | ||
| 102 | − | <p class="error" id="error" role="alert" hidden></p> | |
| 103 | − | <p class="muted small foot"><a href="https://docs.g1t.sh/guides/desktop/#the-runner">About the runner</a></p> | |
| 104 | − | </main> | |
| 105 | − | </div> | |
| 106 | − | <script src="busy.js"></script> | |
| 107 | − | <script src="runner.js"></script> | |
| 108 | − | </body> | |
| 103 | + | <p class="error" id="error" role="alert" hidden></p> | |
| 104 | + | <p class="muted small foot"><a href="https://docs.g1t.sh/guides/desktop/#the-runner">About the runner</a></p> | |
| 105 | + | </main> | |
| 106 | + | </div> | |
| 107 | + | <script src="busy.js"></script> | |
| 108 | + | <script src="runner.js"></script> | |
| 109 | + | </body> | |
| 109 | 110 | </html> |
| 51 | 51 | function runnerStatus(runner) { | |
| 52 | 52 | var d = runner.diagnosis; | |
| 53 | 53 | var update = d.update || {}; | |
| 54 | − | return JSON.stringify([d.code, d.tone, d.title, d.cause, runner.chip.label, runner.enabled, runner.paused, update.checking, update.checked_at, update.ready]); | |
| 54 | + | return JSON.stringify([ | |
| 55 | + | d.code, | |
| 56 | + | d.tone, | |
| 57 | + | d.title, | |
| 58 | + | d.cause, | |
| 59 | + | runner.chip.label, | |
| 60 | + | runner.enabled, | |
| 61 | + | runner.paused, | |
| 62 | + | update.checking, | |
| 63 | + | update.checked_at, | |
| 64 | + | update.ready, | |
| 65 | + | ]); | |
| 55 | 66 | } | |
| 56 | 67 | ||
| 57 | 68 | // One kind of job's, with the whole runner's. | |
| ⋯ | |||
| 74 | 85 | if (action.id === "choose_workspace") return byId("runnerWorkspace").focus(); | |
| 75 | 86 | if (action.id === "choose_backend") return byId("runnerBackend").focus(); | |
| 76 | 87 | if (action.confirm && !window.confirm(action.confirm)) return; | |
| 77 | − | busy.run(button, key, status, !!action.waits, function () { | |
| 78 | − | return invoke("runner_control", { action: action.id }); | |
| 79 | − | }, fail).then(function (done) { | |
| 80 | − | if (!done || action.id.indexOf("copy_") !== 0) return; | |
| 81 | − | button.textContent = "Copied"; | |
| 82 | − | setTimeout(function () { | |
| 83 | − | button.textContent = action.label; | |
| 84 | − | }, 2000); | |
| 85 | − | }); | |
| 88 | + | busy | |
| 89 | + | .run( | |
| 90 | + | button, | |
| 91 | + | key, | |
| 92 | + | status, | |
| 93 | + | !!action.waits, | |
| 94 | + | function () { | |
| 95 | + | return invoke("runner_control", { action: action.id }); | |
| 96 | + | }, | |
| 97 | + | fail, | |
| 98 | + | ) | |
| 99 | + | .then(function (done) { | |
| 100 | + | if (!done || action.id.indexOf("copy_") !== 0) return; | |
| 101 | + | button.textContent = "Copied"; | |
| 102 | + | setTimeout(function () { | |
| 103 | + | button.textContent = action.label; | |
| 104 | + | }, 2000); | |
| 105 | + | }); | |
| 86 | 106 | }); | |
| 87 | 107 | return button; | |
| 88 | 108 | } | |
| ⋯ | |||
| 251 | 271 | var status = kindStatus(kind, runner); | |
| 252 | 272 | if (busy.pressed(key, status)) busy.start(button); | |
| 253 | 273 | button.addEventListener("click", function () { | |
| 254 | − | busy.run(button, key, status, true, function () { | |
| 255 | − | return invoke("runner_control", { action: on ? "stop" : "start", capability: kind.id }); | |
| 256 | − | }, fail); | |
| 274 | + | busy.run( | |
| 275 | + | button, | |
| 276 | + | key, | |
| 277 | + | status, | |
| 278 | + | true, | |
| 279 | + | function () { | |
| 280 | + | return invoke("runner_control", { action: on ? "stop" : "start", capability: kind.id }); | |
| 281 | + | }, | |
| 282 | + | fail, | |
| 283 | + | ); | |
| 257 | 284 | }); | |
| 258 | 285 | return button; | |
| 259 | 286 | } | |
| ⋯ | |||
| 417 | 444 | var button = byId(id); | |
| 418 | 445 | button.addEventListener("click", function () { | |
| 419 | 446 | var status = current && current.runnerView ? runnerStatus(current.runnerView) : ""; | |
| 420 | − | busy.run(button, key, status, waits, function () { | |
| 421 | − | return invoke("runner_control", { action: typeof action === "function" ? action() : action }); | |
| 422 | − | }, fail); | |
| 447 | + | busy.run( | |
| 448 | + | button, | |
| 449 | + | key, | |
| 450 | + | status, | |
| 451 | + | waits, | |
| 452 | + | function () { | |
| 453 | + | return invoke("runner_control", { action: typeof action === "function" ? action() : action }); | |
| 454 | + | }, | |
| 455 | + | fail, | |
| 456 | + | ); | |
| 423 | 457 | }); | |
| 424 | 458 | } | |
| 425 | 459 | control("runner-view", "view", "view_runners", false); | |
| ⋯ | |||
| 434 | 468 | byId("engine-dot").className = "dot " + runner.chip.tone; | |
| 435 | 469 | var label = byId("engine-label"); | |
| 436 | 470 | if (label.textContent !== runner.chip.label) label.textContent = runner.chip.label; | |
| 437 | − | var about = [runner.diagnosis.title, runner.version ? "g1t-runner " + runner.version : null, runner.workspace ? "for " + runner.workspace : null].filter(Boolean); | |
| 471 | + | var about = [runner.diagnosis.title, runner.version ? "g1t-runner " + runner.version : null, runner.workspace ? "for " + runner.workspace : null].filter( | |
| 472 | + | Boolean, | |
| 473 | + | ); | |
| 438 | 474 | byId("engine-sub").textContent = about.join(" · "); | |
| 439 | 475 | var toggle = byId("engine-toggle"); | |
| 440 | 476 | var on = runner.enabled && !runner.paused; | |
| ⋯ | |||
| 444 | 480 | toggle.dataset.action = on ? "stop" : "start"; | |
| 445 | 481 | } | |
| 446 | 482 | ||
| 447 | − | control("engine-toggle", "engine", function () { | |
| 448 | − | return byId("engine-toggle").dataset.action; | |
| 449 | − | }, true); | |
| 483 | + | control( | |
| 484 | + | "engine-toggle", | |
| 485 | + | "engine", | |
| 486 | + | function () { | |
| 487 | + | return byId("engine-toggle").dataset.action; | |
| 488 | + | }, | |
| 489 | + | true, | |
| 490 | + | ); | |
| 450 | 491 | ||
| 451 | 492 | // Every setting, as the app has it now (the settings window changes the | |
| 452 | 493 | // rest), with the runner's own as they are on the page. | |
| 453 | − | var KEPT = ["startHidden", "closeToTray", "notifications", "flash", "badge", "systemTitleBar", "autoUpdate", "zoom", "developerTools", "runner", "runnerBackend", "runnerWorkspace", "runnerCapabilities"]; | |
| 494 | + | var KEPT = [ | |
| 495 | + | "startHidden", | |
| 496 | + | "closeToTray", | |
| 497 | + | "notifications", | |
| 498 | + | "flash", | |
| 499 | + | "badge", | |
| 500 | + | "systemTitleBar", | |
| 501 | + | "autoUpdate", | |
| 502 | + | "zoom", | |
| 503 | + | "developerTools", | |
| 504 | + | "runner", | |
| 505 | + | "runnerBackend", | |
| 506 | + | "runnerWorkspace", | |
| 507 | + | "runnerCapabilities", | |
| 508 | + | ]; | |
| 454 | 509 | function save() { | |
| 455 | 510 | invoke("get_settings") | |
| 456 | 511 | .then(function (fresh) { | |
A large diff (1,202 lines) is not shown until you ask for it.
| 5 | 5 | change is kept as soon as it is made; there is nothing to save. | |
| 6 | 6 | --> | |
| 7 | 7 | <html lang="en"> | |
| 8 | − | <head> | |
| 9 | − | <meta charset="utf-8" /> | |
| 10 | − | <meta name="viewport" content="width=device-width, initial-scale=1" /> | |
| 11 | − | <meta name="color-scheme" content="dark" /> | |
| 12 | − | <title>g1t settings</title> | |
| 13 | − | <link rel="stylesheet" href="settings.css" /> | |
| 14 | − | </head> | |
| 15 | − | <body> | |
| 16 | − | <!-- Its title bar, when g1t draws its own (src/frame.rs): drag it to move the window. --> | |
| 17 | − | <header class="titlebar" id="titlebar" hidden> | |
| 18 | − | <span>Settings</span> | |
| 19 | − | <button type="button" id="close-window" class="caption" aria-label="Close" title="Close" tabindex="-1"> | |
| 20 | − | <svg viewBox="0 0 16 16" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" aria-hidden="true"> | |
| 21 | − | <line x1="4" y1="4" x2="12" y2="12" /> | |
| 22 | − | <line x1="12" y1="4" x2="4" y2="12" /> | |
| 23 | − | </svg> | |
| 24 | − | </button> | |
| 25 | − | </header> | |
| 26 | − | <div class="page"> | |
| 27 | − | <main> | |
| 28 | − | <h1>Settings</h1> | |
| 29 | − | <p class="muted lede">For the desktop app on this computer. Your account's settings, notifications included, are on g1t itself.</p> | |
| 8 | + | <head> | |
| 9 | + | <meta charset="utf-8" /> | |
| 10 | + | <meta name="viewport" content="width=device-width, initial-scale=1" /> | |
| 11 | + | <meta name="color-scheme" content="dark" /> | |
| 12 | + | <title>g1t settings</title> | |
| 13 | + | <link rel="stylesheet" href="settings.css" /> | |
| 14 | + | </head> | |
| 15 | + | <body> | |
| 16 | + | <!-- Its title bar, when g1t draws its own (src/frame.rs): drag it to move the window. --> | |
| 17 | + | <header class="titlebar" id="titlebar" hidden> | |
| 18 | + | <span>Settings</span> | |
| 19 | + | <button type="button" id="close-window" class="caption" aria-label="Close" title="Close" tabindex="-1"> | |
| 20 | + | <svg viewBox="0 0 16 16" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" aria-hidden="true"> | |
| 21 | + | <line x1="4" y1="4" x2="12" y2="12" /> | |
| 22 | + | <line x1="12" y1="4" x2="4" y2="12" /> | |
| 23 | + | </svg> | |
| 24 | + | </button> | |
| 25 | + | </header> | |
| 26 | + | <div class="page"> | |
| 27 | + | <main> | |
| 28 | + | <h1>Settings</h1> | |
| 29 | + | <p class="muted lede">For the desktop app on this computer. Your account's settings, notifications included, are on g1t itself.</p> | |
| 30 | 30 | ||
| 31 | − | <section aria-labelledby="general-heading"> | |
| 32 | − | <h2 id="general-heading">Starting and closing</h2> | |
| 33 | − | <label class="setting"> | |
| 34 | − | <span><strong>Open g1t when you sign in</strong><span class="muted" id="open-at-login-note">g1t starts with your computer.</span></span> | |
| 35 | − | <input type="checkbox" role="switch" id="openAtLogin" /> | |
| 36 | − | </label> | |
| 37 | − | <label class="setting"> | |
| 38 | − | <span><strong>Start in the tray</strong><span class="muted" id="start-hidden-note">Opened at sign-in, g1t waits in the tray without opening its window.</span></span> | |
| 39 | − | <input type="checkbox" role="switch" id="startHidden" /> | |
| 40 | − | </label> | |
| 41 | − | <label class="setting"> | |
| 42 | − | <span><strong>Keep g1t running when the window closes</strong><span class="muted">It stays in the tray for notifications. Turned off, closing the window quits.</span></span> | |
| 43 | − | <input type="checkbox" role="switch" id="closeToTray" /> | |
| 44 | − | </label> | |
| 45 | − | </section> | |
| 31 | + | <section aria-labelledby="general-heading"> | |
| 32 | + | <h2 id="general-heading">Starting and closing</h2> | |
| 33 | + | <label class="setting"> | |
| 34 | + | <span><strong>Open g1t when you sign in</strong><span class="muted" id="open-at-login-note">g1t starts with your computer.</span></span> | |
| 35 | + | <input type="checkbox" role="switch" id="openAtLogin" /> | |
| 36 | + | </label> | |
| 37 | + | <label class="setting"> | |
| 38 | + | <span | |
| 39 | + | ><strong>Start in the tray</strong | |
| 40 | + | ><span class="muted" id="start-hidden-note">Opened at sign-in, g1t waits in the tray without opening its window.</span></span | |
| 41 | + | > | |
| 42 | + | <input type="checkbox" role="switch" id="startHidden" /> | |
| 43 | + | </label> | |
| 44 | + | <label class="setting"> | |
| 45 | + | <span | |
| 46 | + | ><strong>Keep g1t running when the window closes</strong | |
| 47 | + | ><span class="muted">It stays in the tray for notifications. Turned off, closing the window quits.</span></span | |
| 48 | + | > | |
| 49 | + | <input type="checkbox" role="switch" id="closeToTray" /> | |
| 50 | + | </label> | |
| 51 | + | </section> | |
| 46 | 52 | ||
| 47 | − | <section aria-labelledby="runner-heading" id="runner-section"> | |
| 48 | − | <h2 id="runner-heading">Runner</h2> | |
| 49 | − | <!-- What it is doing, in a line; the Runner window has the rest (runner.html). --> | |
| 50 | − | <div class="setting"> | |
| 51 | − | <span | |
| 52 | − | ><strong class="runner-line"><span class="dot" id="runner-dot" aria-hidden="true"></span><span id="runner-title" role="status" aria-live="polite">Runner</span></strong | |
| 53 | − | ><span class="muted" id="runner-summary">Your workspace's <code>runs-on: self-hosted</code> jobs, on this computer while g1t is open.</span></span | |
| 54 | − | > | |
| 55 | − | <span class="buttons"><button type="button" id="open-runner">Open runner</button></span> | |
| 56 | − | </div> | |
| 57 | − | </section> | |
| 53 | + | <section aria-labelledby="runner-heading" id="runner-section"> | |
| 54 | + | <h2 id="runner-heading">Runner</h2> | |
| 55 | + | <!-- What it is doing, in a line; the Runner window has the rest (runner.html). --> | |
| 56 | + | <div class="setting"> | |
| 57 | + | <span | |
| 58 | + | ><strong class="runner-line" | |
| 59 | + | ><span class="dot" id="runner-dot" aria-hidden="true"></span><span id="runner-title" role="status" aria-live="polite">Runner</span></strong | |
| 60 | + | ><span class="muted" id="runner-summary">Your workspace's <code>runs-on: self-hosted</code> jobs, on this computer while g1t is open.</span></span | |
| 61 | + | > | |
| 62 | + | <span class="buttons"><button type="button" id="open-runner">Open runner</button></span> | |
| 63 | + | </div> | |
| 64 | + | </section> | |
| 58 | 65 | ||
| 59 | − | <section aria-labelledby="notifications-heading"> | |
| 60 | − | <h2 id="notifications-heading">Notifications</h2> | |
| 61 | − | <label class="setting"> | |
| 62 | − | <span><strong>Show notifications</strong><span class="muted">From your system, for what needs you while g1t is behind another window. Which things notify you is set on g1t.</span></span> | |
| 63 | − | <input type="checkbox" role="switch" id="notifications" /> | |
| 64 | − | </label> | |
| 65 | − | <label class="setting"> | |
| 66 | − | <span><strong id="flash-label">Flash the taskbar icon</strong><span class="muted">When a notification arrives and the window is not in front.</span></span> | |
| 67 | − | <input type="checkbox" role="switch" id="flash" /> | |
| 68 | − | </label> | |
| 69 | − | <label class="setting"> | |
| 70 | − | <span><strong>Show a badge on the icon</strong><span class="muted">How many things are waiting for you.</span></span> | |
| 71 | − | <input type="checkbox" role="switch" id="badge" /> | |
| 72 | − | </label> | |
| 73 | − | </section> | |
| 66 | + | <section aria-labelledby="notifications-heading"> | |
| 67 | + | <h2 id="notifications-heading">Notifications</h2> | |
| 68 | + | <label class="setting"> | |
| 69 | + | <span | |
| 70 | + | ><strong>Show notifications</strong | |
| 71 | + | ><span class="muted">From your system, for what needs you while g1t is behind another window. Which things notify you is set on g1t.</span></span | |
| 72 | + | > | |
| 73 | + | <input type="checkbox" role="switch" id="notifications" /> | |
| 74 | + | </label> | |
| 75 | + | <label class="setting"> | |
| 76 | + | <span | |
| 77 | + | ><strong id="flash-label">Flash the taskbar icon</strong | |
| 78 | + | ><span class="muted">When a notification arrives and the window is not in front.</span></span | |
| 79 | + | > | |
| 80 | + | <input type="checkbox" role="switch" id="flash" /> | |
| 81 | + | </label> | |
| 82 | + | <label class="setting"> | |
| 83 | + | <span><strong>Show a badge on the icon</strong><span class="muted">How many things are waiting for you.</span></span> | |
| 84 | + | <input type="checkbox" role="switch" id="badge" /> | |
| 85 | + | </label> | |
| 86 | + | </section> | |
| 74 | 87 | ||
| 75 | − | <section aria-labelledby="window-heading"> | |
| 76 | − | <h2 id="window-heading">Window</h2> | |
| 77 | − | <label class="setting"> | |
| 78 | − | <span | |
| 79 | − | ><strong>Use the system's title bar</strong | |
| 80 | − | ><span class="muted" id="system-title-bar-note">In place of g1t's own, with the menu bar under it.</span></span | |
| 81 | − | > | |
| 82 | − | <input type="checkbox" role="switch" id="systemTitleBar" /> | |
| 83 | − | </label> | |
| 84 | − | <div class="setting" id="restart-row" hidden> | |
| 85 | − | <span><strong>Restart to change the title bar</strong><span class="muted">g1t opens again where you were.</span></span> | |
| 86 | − | <button type="button" id="restart-app" class="primary">Restart now</button> | |
| 87 | − | </div> | |
| 88 | − | <label class="setting"> | |
| 89 | − | <span><strong>Zoom</strong><span class="muted" id="zoom-note">The View menu changes it too.</span></span> | |
| 90 | − | <select id="zoom"> | |
| 91 | − | <option value="0.67">67%</option> | |
| 92 | − | <option value="0.75">75%</option> | |
| 93 | − | <option value="0.8">80%</option> | |
| 94 | − | <option value="0.9">90%</option> | |
| 95 | − | <option value="1">100%</option> | |
| 96 | − | <option value="1.1">110%</option> | |
| 97 | − | <option value="1.25">125%</option> | |
| 98 | − | <option value="1.5">150%</option> | |
| 99 | − | <option value="1.75">175%</option> | |
| 100 | − | <option value="2">200%</option> | |
| 101 | − | </select> | |
| 102 | − | </label> | |
| 103 | − | </section> | |
| 88 | + | <section aria-labelledby="window-heading"> | |
| 89 | + | <h2 id="window-heading">Window</h2> | |
| 90 | + | <label class="setting"> | |
| 91 | + | <span | |
| 92 | + | ><strong>Use the system's title bar</strong | |
| 93 | + | ><span class="muted" id="system-title-bar-note">In place of g1t's own, with the menu bar under it.</span></span | |
| 94 | + | > | |
| 95 | + | <input type="checkbox" role="switch" id="systemTitleBar" /> | |
| 96 | + | </label> | |
| 97 | + | <div class="setting" id="restart-row" hidden> | |
| 98 | + | <span><strong>Restart to change the title bar</strong><span class="muted">g1t opens again where you were.</span></span> | |
| 99 | + | <button type="button" id="restart-app" class="primary">Restart now</button> | |
| 100 | + | </div> | |
| 101 | + | <label class="setting"> | |
| 102 | + | <span><strong>Zoom</strong><span class="muted" id="zoom-note">The View menu changes it too.</span></span> | |
| 103 | + | <select id="zoom"> | |
| 104 | + | <option value="0.67">67%</option> | |
| 105 | + | <option value="0.75">75%</option> | |
| 106 | + | <option value="0.8">80%</option> | |
| 107 | + | <option value="0.9">90%</option> | |
| 108 | + | <option value="1">100%</option> | |
| 109 | + | <option value="1.1">110%</option> | |
| 110 | + | <option value="1.25">125%</option> | |
| 111 | + | <option value="1.5">150%</option> | |
| 112 | + | <option value="1.75">175%</option> | |
| 113 | + | <option value="2">200%</option> | |
| 114 | + | </select> | |
| 115 | + | </label> | |
| 116 | + | </section> | |
| 104 | 117 | ||
| 105 | − | <section aria-labelledby="updates-heading"> | |
| 106 | − | <h2 id="updates-heading">Updates</h2> | |
| 107 | − | <label class="setting"> | |
| 108 | − | <span><strong>Download updates by themselves</strong><span class="muted">Each one installs when you restart or quit g1t, never in the middle of something.</span></span> | |
| 109 | − | <input type="checkbox" role="switch" id="autoUpdate" /> | |
| 110 | − | </label> | |
| 111 | − | <div class="setting" id="updates-row"> | |
| 112 | − | <span><strong id="version">g1t</strong><span class="muted" id="update-status" aria-live="polite"> </span></span> | |
| 113 | − | <span class="buttons"> | |
| 114 | − | <button type="button" id="restart" class="primary" hidden>Restart now</button> | |
| 115 | − | <button type="button" id="check">Check for updates</button> | |
| 116 | − | </span> | |
| 117 | − | </div> | |
| 118 | − | </section> | |
| 118 | + | <section aria-labelledby="updates-heading"> | |
| 119 | + | <h2 id="updates-heading">Updates</h2> | |
| 120 | + | <label class="setting"> | |
| 121 | + | <span | |
| 122 | + | ><strong>Download updates by themselves</strong | |
| 123 | + | ><span class="muted">Each one installs when you restart or quit g1t, never in the middle of something.</span></span | |
| 124 | + | > | |
| 125 | + | <input type="checkbox" role="switch" id="autoUpdate" /> | |
| 126 | + | </label> | |
| 127 | + | <div class="setting" id="updates-row"> | |
| 128 | + | <span><strong id="version">g1t</strong><span class="muted" id="update-status" aria-live="polite"> </span></span> | |
| 129 | + | <span class="buttons"> | |
| 130 | + | <button type="button" id="restart" class="primary" hidden>Restart now</button> | |
| 131 | + | <button type="button" id="check">Check for updates</button> | |
| 132 | + | </span> | |
| 133 | + | </div> | |
| 134 | + | </section> | |
| 119 | 135 | ||
| 120 | − | <section aria-labelledby="server-heading"> | |
| 121 | − | <h2 id="server-heading">Server</h2> | |
| 122 | − | <div class="setting"> | |
| 123 | − | <span><strong id="server">g1t.sh</strong><span class="muted">The g1t this app opens. Change it if you run g1t yourself.</span></span> | |
| 124 | − | <button type="button" id="change-server">Change…</button> | |
| 125 | − | </div> | |
| 126 | − | </section> | |
| 136 | + | <section aria-labelledby="server-heading"> | |
| 137 | + | <h2 id="server-heading">Server</h2> | |
| 138 | + | <div class="setting"> | |
| 139 | + | <span><strong id="server">g1t.sh</strong><span class="muted">The g1t this app opens. Change it if you run g1t yourself.</span></span> | |
| 140 | + | <button type="button" id="change-server">Change…</button> | |
| 141 | + | </div> | |
| 142 | + | </section> | |
| 127 | 143 | ||
| 128 | − | <p class="error" id="error" role="alert" hidden></p> | |
| 129 | − | <p class="muted small foot"><a href="https://docs.g1t.sh/guides/desktop/">About the desktop app</a></p> | |
| 130 | − | </main> | |
| 131 | − | </div> | |
| 132 | − | <script src="busy.js"></script> | |
| 133 | − | <script src="settings.js"></script> | |
| 134 | − | </body> | |
| 144 | + | <p class="error" id="error" role="alert" hidden></p> | |
| 145 | + | <p class="muted small foot"><a href="https://docs.g1t.sh/guides/desktop/">About the desktop app</a></p> | |
| 146 | + | </main> | |
| 147 | + | </div> | |
| 148 | + | <script src="busy.js"></script> | |
| 149 | + | <script src="settings.js"></script> | |
| 150 | + | </body> | |
| 135 | 151 | </html> |
| 37 | 37 | ||
| 38 | 38 | // What changes between Windows, macOS and Linux. | |
| 39 | 39 | function platform(name) { | |
| 40 | − | byId("flash-label").textContent = | |
| 41 | − | name === "macos" ? "Bounce the dock icon" : name === "windows" ? "Flash the taskbar icon" : "Ask for attention"; | |
| 40 | + | byId("flash-label").textContent = name === "macos" ? "Bounce the dock icon" : name === "windows" ? "Flash the taskbar icon" : "Ask for attention"; | |
| 42 | 41 | // macOS keeps its menu bar at the top of the screen, whichever title bar the window has. | |
| 43 | 42 | if (name === "macos") byId("system-title-bar-note").textContent = "In place of g1t's own, which sits under the window's buttons."; | |
| 44 | 43 | if (name === "macos") byId("zoom-note").textContent = "The View menu changes it too: ⌘+, ⌘− and ⌘0."; | |
| ⋯ | |||
| 88 | 87 | return settings; | |
| 89 | 88 | } | |
| 90 | 89 | ||
| 91 | − | ||
| 92 | 90 | function save() { | |
| 93 | 91 | invoke("get_settings") | |
| 94 | 92 | .then(function (fresh) { | |
| ⋯ | |||
| 101 | 99 | } | |
| 102 | 100 | ||
| 103 | 101 | byId("open-runner").addEventListener("click", function () { | |
| 104 | − | window.g1tBusy.run(byId("open-runner"), "open-runner", "", false, function () { | |
| 105 | − | return invoke("runner_control", { action: "open_runner" }); | |
| 106 | − | }, fail); | |
| 102 | + | window.g1tBusy.run( | |
| 103 | + | byId("open-runner"), | |
| 104 | + | "open-runner", | |
| 105 | + | "", | |
| 106 | + | false, | |
| 107 | + | function () { | |
| 108 | + | return invoke("runner_control", { action: "open_runner" }); | |
| 109 | + | }, | |
| 110 | + | fail, | |
| 111 | + | ); | |
| 107 | 112 | }); | |
| 108 | 113 | ||
| 109 | 114 | SWITCHES.forEach(function (key) { | |
| ⋯ | |||
| 157 | 162 | }) | |
| 158 | 163 | .catch(function (error) { | |
| 159 | 164 | var text = typeof error === "string" ? error : ""; | |
| 160 | − | status.textContent = /sending request|connect|dns|timed out/i.test(text) || !text | |
| 161 | − | ? "Could not reach g1t.sh to check. Check your connection and try again." | |
| 162 | − | : "Could not check: " + text; | |
| 165 | + | status.textContent = | |
| 166 | + | /sending request|connect|dns|timed out/i.test(text) || !text | |
| 167 | + | ? "Could not reach g1t.sh to check. Check your connection and try again." | |
| 168 | + | : "Could not check: " + text; | |
| 163 | 169 | }) | |
| 164 | 170 | .then(function () { | |
| 165 | 171 | checking = false; | |
| ⋯ | |||
| 204 | 210 | }); | |
| 205 | 211 | ||
| 206 | 212 | byId("change-server").addEventListener("click", function () { | |
| 207 | − | window.g1tBusy.run(byId("change-server"), "change-server", "", false, function () { | |
| 208 | − | return invoke("change_server"); | |
| 209 | − | }, fail); | |
| 213 | + | window.g1tBusy.run( | |
| 214 | + | byId("change-server"), | |
| 215 | + | "change-server", | |
| 216 | + | "", | |
| 217 | + | false, | |
| 218 | + | function () { | |
| 219 | + | return invoke("change_server"); | |
| 220 | + | }, | |
| 221 | + | fail, | |
| 222 | + | ); | |
| 210 | 223 | }); | |
| 211 | 224 | ||
| 212 | 225 | // Links out, in the system's browser (src/bridge.js does the same on the site). | |
| 1 | 1 | /* The title bar, in the colours of the page under it (titlebar.js sets | |
| 2 | 2 | them): g1t's rail on g1t's pages, light or dark. 36px tall. */ | |
| 3 | 3 | :root { | |
| 4 | − | --bg: #050507; | |
| 5 | − | --fg: #ededef; | |
| 6 | − | --muted: #a0a0a8; | |
| 7 | − | --accent: #b6a8ff; | |
| 8 | − | --hover: rgba(237, 237, 239, 0.1); | |
| 9 | − | --pill: rgba(237, 237, 239, 0.09); | |
| 10 | − | --pill-hover: rgba(237, 237, 239, 0.14); | |
| 11 | − | --pill-edge: rgba(237, 237, 239, 0.08); | |
| 4 | + | --bg: #050507; | |
| 5 | + | --fg: #ededef; | |
| 6 | + | --muted: #a0a0a8; | |
| 7 | + | --accent: #b6a8ff; | |
| 8 | + | --hover: rgba(237, 237, 239, 0.1); | |
| 9 | + | --pill: rgba(237, 237, 239, 0.09); | |
| 10 | + | --pill-hover: rgba(237, 237, 239, 0.14); | |
| 11 | + | --pill-edge: rgba(237, 237, 239, 0.08); | |
| 12 | 12 | } | |
| 13 | 13 | * { | |
| 14 | − | box-sizing: border-box; | |
| 14 | + | box-sizing: border-box; | |
| 15 | 15 | } | |
| 16 | 16 | html, | |
| 17 | 17 | body { | |
| 18 | − | height: 100%; | |
| 19 | − | margin: 0; | |
| 20 | − | overflow: hidden; | |
| 21 | − | background: var(--bg); | |
| 18 | + | height: 100%; | |
| 19 | + | margin: 0; | |
| 20 | + | overflow: hidden; | |
| 21 | + | background: var(--bg); | |
| 22 | 22 | } | |
| 23 | 23 | .bar { | |
| 24 | − | height: 100%; | |
| 25 | − | display: flex; | |
| 26 | − | align-items: center; | |
| 27 | − | gap: 2px; | |
| 28 | − | padding-left: 6px; | |
| 29 | − | color: var(--muted); | |
| 30 | − | font: 500 12px/1 system-ui, "Segoe UI", -apple-system, Roboto, sans-serif; | |
| 31 | − | user-select: none; | |
| 32 | − | -webkit-user-select: none; | |
| 33 | − | cursor: default; | |
| 24 | + | height: 100%; | |
| 25 | + | display: flex; | |
| 26 | + | align-items: center; | |
| 27 | + | gap: 2px; | |
| 28 | + | padding-left: 6px; | |
| 29 | + | color: var(--muted); | |
| 30 | + | font: | |
| 31 | + | 500 12px/1 system-ui, | |
| 32 | + | "Segoe UI", | |
| 33 | + | -apple-system, | |
| 34 | + | Roboto, | |
| 35 | + | sans-serif; | |
| 36 | + | user-select: none; | |
| 37 | + | -webkit-user-select: none; | |
| 38 | + | cursor: default; | |
| 34 | 39 | } | |
| 35 | 40 | .mac .bar { | |
| 36 | − | padding-left: 78px; | |
| 41 | + | padding-left: 78px; | |
| 37 | 42 | } | |
| 38 | 43 | .side { | |
| 39 | − | display: flex; | |
| 40 | − | align-items: center; | |
| 41 | − | gap: 2px; | |
| 42 | − | flex: 1 1 0; | |
| 43 | − | /* Never narrower than its buttons: the search shrinks instead. */ | |
| 44 | − | min-width: min-content; | |
| 44 | + | display: flex; | |
| 45 | + | align-items: center; | |
| 46 | + | gap: 2px; | |
| 47 | + | flex: 1 1 0; | |
| 48 | + | /* Never narrower than its buttons: the search shrinks instead. */ | |
| 49 | + | min-width: min-content; | |
| 45 | 50 | } | |
| 46 | 51 | .end { | |
| 47 | − | justify-content: flex-end; | |
| 52 | + | justify-content: flex-end; | |
| 48 | 53 | } | |
| 49 | 54 | .middle { | |
| 50 | − | flex: 0 1 560px; | |
| 51 | − | min-width: 0; | |
| 52 | − | display: flex; | |
| 53 | − | justify-content: center; | |
| 55 | + | flex: 0 1 560px; | |
| 56 | + | min-width: 0; | |
| 57 | + | display: flex; | |
| 58 | + | justify-content: center; | |
| 54 | 59 | } | |
| 55 | 60 | button { | |
| 56 | − | all: unset; | |
| 57 | − | box-sizing: border-box; | |
| 58 | − | display: inline-flex; | |
| 59 | − | align-items: center; | |
| 60 | − | justify-content: center; | |
| 61 | − | color: inherit; | |
| 61 | + | all: unset; | |
| 62 | + | box-sizing: border-box; | |
| 63 | + | display: inline-flex; | |
| 64 | + | align-items: center; | |
| 65 | + | justify-content: center; | |
| 66 | + | color: inherit; | |
| 62 | 67 | } | |
| 63 | 68 | .icon { | |
| 64 | − | width: 28px; | |
| 65 | − | height: 26px; | |
| 66 | − | border-radius: 6px; | |
| 69 | + | width: 28px; | |
| 70 | + | height: 26px; | |
| 71 | + | border-radius: 6px; | |
| 67 | 72 | } | |
| 68 | 73 | .icon:hover { | |
| 69 | − | background: var(--hover); | |
| 70 | − | color: var(--fg); | |
| 74 | + | background: var(--hover); | |
| 75 | + | color: var(--fg); | |
| 71 | 76 | } | |
| 72 | 77 | .icon:disabled { | |
| 73 | − | opacity: 0.35; | |
| 74 | − | background: none; | |
| 75 | − | color: inherit; | |
| 78 | + | opacity: 0.35; | |
| 79 | + | background: none; | |
| 80 | + | color: inherit; | |
| 76 | 81 | } | |
| 77 | 82 | .search { | |
| 78 | − | width: 100%; | |
| 79 | − | height: 24px; | |
| 80 | − | gap: 8px; | |
| 81 | − | padding: 0 10px; | |
| 82 | − | justify-content: flex-start; | |
| 83 | − | border-radius: 6px; | |
| 84 | − | background: var(--pill); | |
| 85 | − | box-shadow: inset 0 0 0 1px var(--pill-edge); | |
| 83 | + | width: 100%; | |
| 84 | + | height: 24px; | |
| 85 | + | gap: 8px; | |
| 86 | + | padding: 0 10px; | |
| 87 | + | justify-content: flex-start; | |
| 88 | + | border-radius: 6px; | |
| 89 | + | background: var(--pill); | |
| 90 | + | box-shadow: inset 0 0 0 1px var(--pill-edge); | |
| 86 | 91 | } | |
| 87 | 92 | .search:hover { | |
| 88 | − | background: var(--pill-hover); | |
| 89 | − | color: var(--fg); | |
| 93 | + | background: var(--pill-hover); | |
| 94 | + | color: var(--fg); | |
| 90 | 95 | } | |
| 91 | 96 | .search span, | |
| 92 | 97 | .title { | |
| 93 | − | overflow: hidden; | |
| 94 | − | text-overflow: ellipsis; | |
| 95 | − | white-space: nowrap; | |
| 98 | + | overflow: hidden; | |
| 99 | + | text-overflow: ellipsis; | |
| 100 | + | white-space: nowrap; | |
| 96 | 101 | } | |
| 97 | 102 | .title { | |
| 98 | − | padding: 0 8px; | |
| 103 | + | padding: 0 8px; | |
| 99 | 104 | } | |
| 100 | 105 | .caption { | |
| 101 | − | width: 46px; | |
| 102 | − | height: 36px; | |
| 106 | + | width: 46px; | |
| 107 | + | height: 36px; | |
| 103 | 108 | } | |
| 104 | 109 | .caption:hover { | |
| 105 | − | background: var(--hover); | |
| 106 | − | color: var(--fg); | |
| 110 | + | background: var(--hover); | |
| 111 | + | color: var(--fg); | |
| 107 | 112 | } | |
| 108 | 113 | .caption.close:hover { | |
| 109 | − | background: #c42b1c; | |
| 110 | − | color: #fff; | |
| 114 | + | background: #c42b1c; | |
| 115 | + | color: #fff; | |
| 111 | 116 | } | |
| 112 | 117 | button:focus-visible { | |
| 113 | − | outline: 2px solid var(--accent); | |
| 114 | − | outline-offset: -2px; | |
| 118 | + | outline: 2px solid var(--accent); | |
| 119 | + | outline-offset: -2px; | |
| 115 | 120 | } | |
| 116 | 121 | /* The runner: a dot in its tone, right beside the settings, the size of | |
| 117 | 122 | an icon button. A wide window has room for what it is doing too. Its | |
| 118 | 123 | menu hangs under it, drawn by the page below (the site). */ | |
| 119 | 124 | .chip { | |
| 120 | − | gap: 7px; | |
| 121 | − | min-width: 28px; | |
| 122 | − | height: 26px; | |
| 123 | − | padding: 0 10px; | |
| 124 | − | border-radius: 6px; | |
| 125 | − | white-space: nowrap; | |
| 125 | + | gap: 7px; | |
| 126 | + | min-width: 28px; | |
| 127 | + | height: 26px; | |
| 128 | + | padding: 0 10px; | |
| 129 | + | border-radius: 6px; | |
| 130 | + | white-space: nowrap; | |
| 126 | 131 | } | |
| 127 | 132 | .chip[hidden] { | |
| 128 | − | display: none; | |
| 133 | + | display: none; | |
| 129 | 134 | } | |
| 130 | 135 | .chip:hover, | |
| 131 | 136 | .chip[aria-expanded="true"] { | |
| 132 | − | background: var(--hover); | |
| 133 | − | color: var(--fg); | |
| 137 | + | background: var(--hover); | |
| 138 | + | color: var(--fg); | |
| 134 | 139 | } | |
| 135 | 140 | .chip-dot { | |
| 136 | − | width: 8px; | |
| 137 | − | height: 8px; | |
| 138 | − | flex: none; | |
| 139 | − | border-radius: 50%; | |
| 140 | − | background: var(--muted); | |
| 141 | + | width: 8px; | |
| 142 | + | height: 8px; | |
| 143 | + | flex: none; | |
| 144 | + | border-radius: 50%; | |
| 145 | + | background: var(--muted); | |
| 141 | 146 | } | |
| 142 | 147 | .chip[data-tone="ok"] .chip-dot { | |
| 143 | − | background: #4ade80; | |
| 148 | + | background: #4ade80; | |
| 144 | 149 | } | |
| 145 | 150 | .chip[data-tone="working"] .chip-dot { | |
| 146 | − | background: #60a5fa; | |
| 147 | − | animation: breathe 1.6s ease-in-out infinite; | |
| 151 | + | background: #60a5fa; | |
| 152 | + | animation: breathe 1.6s ease-in-out infinite; | |
| 148 | 153 | } | |
| 149 | 154 | .chip[data-tone="warning"] .chip-dot { | |
| 150 | − | background: #fbbf24; | |
| 155 | + | background: #fbbf24; | |
| 151 | 156 | } | |
| 152 | 157 | .chip[data-tone="problem"] .chip-dot { | |
| 153 | − | background: #f87171; | |
| 158 | + | background: #f87171; | |
| 154 | 159 | } | |
| 155 | 160 | .chip[data-tone="off"] .chip-dot { | |
| 156 | − | background: var(--muted); | |
| 157 | − | opacity: 0.6; | |
| 161 | + | background: var(--muted); | |
| 162 | + | opacity: 0.6; | |
| 158 | 163 | } | |
| 159 | 164 | @keyframes breathe { | |
| 160 | − | 50% { | |
| 161 | − | opacity: 0.35; | |
| 162 | − | } | |
| 165 | + | 50% { | |
| 166 | + | opacity: 0.35; | |
| 167 | + | } | |
| 163 | 168 | } | |
| 164 | 169 | @media (prefers-reduced-motion: reduce) { | |
| 165 | − | .chip[data-tone="working"] .chip-dot { | |
| 166 | − | animation: none; | |
| 167 | − | } | |
| 170 | + | .chip[data-tone="working"] .chip-dot { | |
| 171 | + | animation: none; | |
| 172 | + | } | |
| 168 | 173 | } | |
| 169 | 174 | /* The dot alone, until the window is wide enough that the words fit | |
| 170 | 175 | beside it without crowding the search. */ | |
| 171 | 176 | .chip-text { | |
| 172 | − | display: none; | |
| 177 | + | display: none; | |
| 173 | 178 | } | |
| 174 | 179 | @media (min-width: 1360px) { | |
| 175 | − | .chip-text { | |
| 176 | − | display: inline; | |
| 177 | − | } | |
| 180 | + | .chip-text { | |
| 181 | + | display: inline; | |
| 182 | + | } | |
| 178 | 183 | } |
| 6 | 6 | its buttons act on the window and on that page through the app. | |
| 7 | 7 | --> | |
| 8 | 8 | <html lang="en"> | |
| 9 | − | <head> | |
| 10 | − | <meta charset="utf-8" /> | |
| 11 | − | <meta name="viewport" content="width=device-width, initial-scale=1" /> | |
| 12 | − | <title>g1t</title> | |
| 13 | − | <link rel="stylesheet" href="titlebar.css" /> | |
| 14 | − | </head> | |
| 15 | − | <body> | |
| 16 | − | <div class="bar" id="bar" role="toolbar" aria-label="Window"> | |
| 17 | − | <div class="side" id="left"></div> | |
| 18 | − | <div class="middle" id="middle"></div> | |
| 19 | − | <div class="side end" id="right"></div> | |
| 20 | − | </div> | |
| 21 | − | <script src="titlebar.js"></script> | |
| 22 | − | </body> | |
| 9 | + | <head> | |
| 10 | + | <meta charset="utf-8" /> | |
| 11 | + | <meta name="viewport" content="width=device-width, initial-scale=1" /> | |
| 12 | + | <title>g1t</title> | |
| 13 | + | <link rel="stylesheet" href="titlebar.css" /> | |
| 14 | + | </head> | |
| 15 | + | <body> | |
| 16 | + | <div class="bar" id="bar" role="toolbar" aria-label="Window"> | |
| 17 | + | <div class="side" id="left"></div> | |
| 18 | + | <div class="middle" id="middle"></div> | |
| 19 | + | <div class="side end" id="right"></div> | |
| 20 | + | </div> | |
| 21 | + | <script src="titlebar.js"></script> | |
| 22 | + | </body> | |
| 23 | 23 | </html> |
| 36 | 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 | 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 | 38 | search: svg('<circle cx="7" cy="7" r="4"/><line x1="10" y1="10" x2="13" y2="13"/>'), | |
| 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)"/>'), | |
| 39 | + | settings: svg( | |
| 40 | + | '<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)"/>', | |
| 41 | + | ), | |
| 40 | 42 | minimize: svg('<line x1="3.5" y1="8" x2="12.5" y2="8"/>'), | |
| 41 | 43 | maximize: svg('<rect x="3.5" y="3.5" width="9" height="9" rx="1"/>'), | |
| 42 | 44 | 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"/>'), | |
| ⋯ | |||
| 217 | 219 | }) | |
| 218 | 220 | .catch(function () {}); | |
| 219 | 221 | } | |
| 220 | − | invoke("runner_status").then(function (view) { | |
| 221 | − | drawChip(view && view.chip); | |
| 222 | − | }, function () {}); | |
| 222 | + | invoke("runner_status").then( | |
| 223 | + | function (view) { | |
| 224 | + | drawChip(view && view.chip); | |
| 225 | + | }, | |
| 226 | + | function () {}, | |
| 227 | + | ); | |
| 223 | 228 | })(); | |
| 1 | 1 | { | |
| 2 | − | "$schema": "https://schema.tauri.app/config/2", | |
| 3 | − | "productName": "g1t", | |
| 4 | − | "identifier": "sh.g1t.desktop", | |
| 5 | − | "build": { | |
| 6 | − | "frontendDist": "../launcher" | |
| 7 | − | }, | |
| 8 | − | "app": { | |
| 9 | − | "withGlobalTauri": true, | |
| 10 | − | "windows": [], | |
| 11 | − | "security": { | |
| 12 | − | "csp": "default-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:" | |
| 13 | − | } | |
| 14 | − | }, | |
| 15 | − | "bundle": { | |
| 16 | − | "active": true, | |
| 17 | − | "targets": "all", | |
| 18 | − | "createUpdaterArtifacts": true, | |
| 19 | − | "icon": [ | |
| 20 | − | "icons/32x32.png", | |
| 21 | − | "icons/128x128.png", | |
| 22 | − | "icons/128x128@2x.png", | |
| 23 | − | "icons/icon.icns", | |
| 24 | − | "icons/icon.ico" | |
| 25 | − | ], | |
| 26 | − | "category": "DeveloperTool", | |
| 27 | − | "shortDescription": "g1t on your desktop", | |
| 28 | − | "longDescription": "g1t in a window of its own: chat, artifacts and code, with notifications from your system, a badge on the icon, g1t:// links and updates that install themselves.", | |
| 29 | − | "publisher": "Flagon, Inc.", | |
| 30 | − | "copyright": "Flagon, Inc.", | |
| 31 | − | "homepage": "https://g1t.sh", | |
| 32 | − | "windows": { | |
| 33 | − | "webviewInstallMode": { "type": "downloadBootstrapper" }, | |
| 34 | − | "nsis": { | |
| 35 | − | "installMode": "currentUser", | |
| 36 | − | "installerHooks": "./windows/hooks.nsh", | |
| 37 | − | "languages": ["English"] | |
| 38 | − | } | |
| 39 | − | }, | |
| 40 | − | "macOS": { | |
| 41 | − | "minimumSystemVersion": "11.0" | |
| 42 | − | } | |
| 43 | − | }, | |
| 44 | − | "plugins": { | |
| 45 | − | "updater": { | |
| 46 | − | "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDdDMEU2MjkxRkU5N0RBRUMKUldUczJwZitrV0lPZkZVckJFeXdhMUMyN2s3a2VoZ2VYRkZESFBhQkY5UnBuS3RhbkNIbEU3bVMK", | |
| 47 | − | "endpoints": ["https://g1t.sh/downloads/desktop/latest.json"], | |
| 48 | − | "windows": { "installMode": "passive" } | |
| 49 | − | }, | |
| 50 | − | "deep-link": { | |
| 51 | − | "desktop": { "schemes": ["g1t"] } | |
| 52 | − | } | |
| 53 | − | } | |
| 2 | + | "$schema": "https://schema.tauri.app/config/2", | |
| 3 | + | "productName": "g1t", | |
| 4 | + | "identifier": "sh.g1t.desktop", | |
| 5 | + | "build": { | |
| 6 | + | "frontendDist": "../launcher" | |
| 7 | + | }, | |
| 8 | + | "app": { | |
| 9 | + | "withGlobalTauri": true, | |
| 10 | + | "windows": [], | |
| 11 | + | "security": { | |
| 12 | + | "csp": "default-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:" | |
| 13 | + | } | |
| 14 | + | }, | |
| 15 | + | "bundle": { | |
| 16 | + | "active": true, | |
| 17 | + | "targets": "all", | |
| 18 | + | "createUpdaterArtifacts": true, | |
| 19 | + | "icon": ["icons/32x32.png", "icons/128x128.png", "icons/128x128@2x.png", "icons/icon.icns", "icons/icon.ico"], | |
| 20 | + | "category": "DeveloperTool", | |
| 21 | + | "shortDescription": "g1t on your desktop", | |
| 22 | + | "longDescription": "g1t in a window of its own: chat, artifacts and code, with notifications from your system, a badge on the icon, g1t:// links and updates that install themselves.", | |
| 23 | + | "publisher": "Flagon, Inc.", | |
| 24 | + | "copyright": "Flagon, Inc.", | |
| 25 | + | "homepage": "https://g1t.sh", | |
| 26 | + | "windows": { | |
| 27 | + | "webviewInstallMode": { "type": "downloadBootstrapper" }, | |
| 28 | + | "nsis": { | |
| 29 | + | "installMode": "currentUser", | |
| 30 | + | "installerHooks": "./windows/hooks.nsh", | |
| 31 | + | "languages": ["English"] | |
| 32 | + | } | |
| 33 | + | }, | |
| 34 | + | "macOS": { | |
| 35 | + | "minimumSystemVersion": "11.0" | |
| 36 | + | } | |
| 37 | + | }, | |
| 38 | + | "plugins": { | |
| 39 | + | "updater": { | |
| 40 | + | "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDdDMEU2MjkxRkU5N0RBRUMKUldUczJwZitrV0lPZkZVckJFeXdhMUMyN2s3a2VoZ2VYRkZESFBhQkY5UnBuS3RhbkNIbEU3bVMK", | |
| 41 | + | "endpoints": ["https://g1t.sh/downloads/desktop/latest.json"], | |
| 42 | + | "windows": { "installMode": "passive" } | |
| 43 | + | }, | |
| 44 | + | "deep-link": { | |
| 45 | + | "desktop": { "schemes": ["g1t"] } | |
| 46 | + | } | |
| 47 | + | } | |
| 54 | 48 | } |
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
A large diff (1,640 lines) is not shown until you ask for it.
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
Loading the diff…
More files changed than one page lists: these are the first 300.
Comments
Sign in to comment.