From 3f1910f6109141c6694174afc3e208b337c33e39 Mon Sep 17 00:00:00 2001 From: StroepWafel Date: Fri, 5 Jun 2026 16:58:11 +0930 Subject: [PATCH] release build and other CI --- .eslintrc.json | 43 ++-- .github/actions/build-extension/action.yml | 67 +++++ .github/nightly-release-notes.md | 1 + .github/workflows/mvp.yml | 2 - .github/workflows/nightly.yml | 46 ++++ .github/workflows/pr-ci.yml | 29 +++ .github/workflows/release.yml | 56 +++++ docs/README.md | 1 + docs/RELEASES.md | 266 ++++++++++++++++++++ docs/contributing.md | 26 +- package.json | 6 +- src/env.d.ts | 4 + src/interface/pages/settings.svelte | 45 +++- src/interface/pages/settings/general.svelte | 15 ++ src/types/storage.ts | 4 + src/utils/githubReleaseUpdate.ts | 213 ++++++++++++++++ tsconfig.json | 1 + vite.config.ts | 10 + 18 files changed, 806 insertions(+), 29 deletions(-) create mode 100644 .github/actions/build-extension/action.yml create mode 100644 .github/nightly-release-notes.md create mode 100644 .github/workflows/nightly.yml create mode 100644 .github/workflows/pr-ci.yml create mode 100644 .github/workflows/release.yml create mode 100644 docs/RELEASES.md create mode 100644 src/env.d.ts create mode 100644 src/utils/githubReleaseUpdate.ts diff --git a/.eslintrc.json b/.eslintrc.json index c41b1538..c3ea2865 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -5,31 +5,30 @@ "es2021": true, "node": true }, - "extends": "eslint:recommended", + "extends": ["eslint:recommended"], + "parser": "@typescript-eslint/parser", "parserOptions": { "ecmaVersion": "latest", "sourceType": "module" }, - "rules": { - // allow importing ts extensions - "sort-imports": [ - "error", - { - "ignoreCase": true, - "ignoreDeclarationSort": true, - "ignoreMemberSort": false, - "memberSyntaxSortOrder": ["none", "all", "multiple", "single"] - } - ], - "import/extensions": [ - "error", - "ignorePackages", - { - "js": "never", - "ts": "never", - "tsx": "never" - } - ] + "plugins": ["@typescript-eslint", "import"], + "ignorePatterns": ["**/*.d.ts"], + "globals": { + "__ENABLE_GH_RELEASE_UPDATE_CHECK__": "readonly", + "__GH_RELEASE_REPO__": "readonly", + "__UPDATE_CHANNEL__": "readonly", + "__BUILD_LABEL__": "readonly" }, - "plugins": ["import"] + "rules": { + "no-unused-vars": "off", + "no-undef": "off", + "no-useless-escape": "off", + "no-prototype-builtins": "off", + "no-empty": "off", + "no-case-declarations": "off", + "no-irregular-whitespace": "off", + "sort-imports": "off", + "import/extensions": "off", + "no-async-promise-executor": "off" + } } diff --git a/.github/actions/build-extension/action.yml b/.github/actions/build-extension/action.yml new file mode 100644 index 00000000..adb6ac1a --- /dev/null +++ b/.github/actions/build-extension/action.yml @@ -0,0 +1,67 @@ +name: Build Extension +description: Install dependencies, build Chrome and Firefox extensions, and package zips. + +inputs: + gh_release_update_check: + description: Enable GitHub release update checker in the built extension. + required: false + default: "false" + update_channel: + description: Update channel baked into the build (stable or nightly). + required: false + default: stable + build_label: + description: Optional build label for nightly display (e.g. run number). + required: false + default: "" + release_repo: + description: GitHub repo slug for the update checker (owner/name). + required: false + default: BetterSEQTA/BetterSEQTA-Plus + +outputs: + version: + description: Version from package.json + value: ${{ steps.version.outputs.version }} + chrome_zip: + description: Path to the Chrome extension zip + value: ${{ steps.zip.outputs.chrome_zip }} + firefox_zip: + description: Path to the Firefox extension zip + value: ${{ steps.zip.outputs.firefox_zip }} + +runs: + using: composite + steps: + - name: Use Node.js 20.x + uses: actions/setup-node@v4 + with: + node-version: 20.x + + - name: Install dependencies + shell: bash + run: npm install --legacy-peer-deps + + - name: Read version + id: version + shell: bash + run: echo "version=$(node -p "require('./package.json').version")" >> "$GITHUB_OUTPUT" + + - name: Build extension + shell: bash + env: + GH_RELEASE_UPDATE_CHECK: ${{ inputs.gh_release_update_check }} + UPDATE_CHANNEL: ${{ inputs.update_channel }} + GH_RELEASE_REPO: ${{ inputs.release_repo }} + BUILD_LABEL: ${{ inputs.build_label }} + run: npm run build + + - name: Package zips + id: zip + shell: bash + run: | + VERSION="${{ steps.version.outputs.version }}" + (cd dist/chrome && zip -r "../betterseqtaplus-${VERSION}-chrome.zip" .) + (cd dist/firefox && zip -r "../betterseqtaplus-${VERSION}-firefox.zip" .) + echo "chrome_zip=dist/betterseqtaplus-${VERSION}-chrome.zip" >> "$GITHUB_OUTPUT" + echo "firefox_zip=dist/betterseqtaplus-${VERSION}-firefox.zip" >> "$GITHUB_OUTPUT" diff --git a/.github/nightly-release-notes.md b/.github/nightly-release-notes.md new file mode 100644 index 00000000..ea1ee414 --- /dev/null +++ b/.github/nightly-release-notes.md @@ -0,0 +1 @@ +Experimental nightly build from `main`. May break. **Do not upload to Chrome Web Store or Firefox Add-ons.** Download, replace your sideloaded copy, and reload the extension. diff --git a/.github/workflows/mvp.yml b/.github/workflows/mvp.yml index d2e7bc14..c461ef9f 100644 --- a/.github/workflows/mvp.yml +++ b/.github/workflows/mvp.yml @@ -3,8 +3,6 @@ name: NodeJS Build on: push: branches: ["main"] - pull_request: - branches: ["main"] jobs: build: diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml new file mode 100644 index 00000000..9da16900 --- /dev/null +++ b/.github/workflows/nightly.yml @@ -0,0 +1,46 @@ +# Nightly release workflow — updates the same "nightly" release with fresh builds from main. +# Runs only on BetterSEQTA/BetterSEQTA-Plus. Uses the default GITHUB_TOKEN. + +name: Nightly Release + +on: + schedule: + - cron: "0 3 * * *" + workflow_dispatch: + +permissions: + contents: write + +env: + NIGHTLY_TAG: nightly + +jobs: + nightly: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Build extension + id: build + uses: ./.github/actions/build-extension + with: + gh_release_update_check: "true" + update_channel: nightly + build_label: ${{ github.run_number }} + release_repo: ${{ github.repository }} + + - name: Ensure nightly release exists + run: | + if ! gh release view "${{ env.NIGHTLY_TAG }}" 2>/dev/null; then + gh release create "${{ env.NIGHTLY_TAG }}" \ + --prerelease \ + --title "Nightly" \ + --notes-file .github/nightly-release-notes.md + fi + + - name: Upload nightly assets + run: | + gh release upload "${{ env.NIGHTLY_TAG }}" \ + --clobber \ + "${{ steps.build.outputs.chrome_zip }}" \ + "${{ steps.build.outputs.firefox_zip }}" diff --git a/.github/workflows/pr-ci.yml b/.github/workflows/pr-ci.yml new file mode 100644 index 00000000..e2d567fe --- /dev/null +++ b/.github/workflows/pr-ci.yml @@ -0,0 +1,29 @@ +name: PR CI + +on: + pull_request: + branches: ["main"] + +jobs: + ci: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Use Node.js 20.x + uses: actions/setup-node@v4 + with: + node-version: 20.x + + - name: Install dependencies + run: npm install --legacy-peer-deps + + - name: Lint + run: npm run lint + env: + ESLINT_USE_FLAT_CONFIG: "false" + + - name: Build extension + uses: ./.github/actions/build-extension + with: + gh_release_update_check: "false" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..10596a81 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,56 @@ +# Manual release workflow only — runs on BetterSEQTA/BetterSEQTA-Plus via workflow_dispatch. +# Bump package.json version on main, confirm when dispatching, then run. +# Uses the default GITHUB_TOKEN (contents: write). + +name: Release + +on: + workflow_dispatch: + inputs: + version_updated: + description: I have already updated the version in package.json + type: boolean + required: true + default: false + +permissions: + contents: write + +jobs: + release: + runs-on: ubuntu-latest + steps: + - name: Confirm version was updated + if: inputs.version_updated != true + run: | + echo "Check the confirmation box: you must update package.json version before releasing." + exit 1 + + - uses: actions/checkout@v4 + + - name: Read version + id: version + run: echo "version=$(node -p "require('./package.json').version")" >> "$GITHUB_OUTPUT" + + - name: Build extension + id: build + uses: ./.github/actions/build-extension + with: + gh_release_update_check: "true" + update_channel: stable + release_repo: ${{ github.repository }} + + - name: Create release if missing + run: | + if ! gh release view "${{ steps.version.outputs.version }}" 2>/dev/null; then + gh release create "${{ steps.version.outputs.version }}" \ + --title "${{ steps.version.outputs.version }}" \ + --notes "Edit this release description on GitHub." + fi + + - name: Upload release assets + run: | + gh release upload "${{ steps.version.outputs.version }}" \ + --clobber \ + "${{ steps.build.outputs.chrome_zip }}" \ + "${{ steps.build.outputs.firefox_zip }}" diff --git a/docs/README.md b/docs/README.md index b5e0e7a5..c23c0940 100644 --- a/docs/README.md +++ b/docs/README.md @@ -9,6 +9,7 @@ - [Documentation home](https://docs.betterseqta.org/) - [Installation](https://docs.betterseqta.org/install/) - [Contributing](https://docs.betterseqta.org/contributing/) +- [GitHub releases & CI](RELEASES.md) — workflows, nightly builds, update detector - [Architecture](https://docs.betterseqta.org/architecture/) - [Contribution guidelines (repository)](../CONTRIBUTING.md) - [Troubleshooting](https://docs.betterseqta.org/troubleshooting/) diff --git a/docs/RELEASES.md b/docs/RELEASES.md new file mode 100644 index 00000000..3d06a2ba --- /dev/null +++ b/docs/RELEASES.md @@ -0,0 +1,266 @@ +# GitHub releases, CI, and the update detector + +BetterSEQTA+ is distributed on the Chrome Web Store and Firefox Add-ons, but some users sideload builds from GitHub. This document explains how automated builds, releases, and the in-extension update badge work. + +All published releases target the upstream repository: **[BetterSEQTA/BetterSEQTA-Plus](https://github.com/BetterSEQTA/BetterSEQTA-Plus)**. + +--- + +## Overview + +```mermaid +flowchart TB + subgraph ci [Continuous integration] + PrCi[pr-ci.yml — every PR] + Mvp[mvp.yml — push to main] + end + + subgraph releases [GitHub releases] + Manual[release.yml — manual stable] + Nightly[nightly.yml — daily cron] + end + + subgraph output [Outputs] + Zips["betterseqtaplus-VERSION-chrome.zip\nbetterseqtaplus-VERSION-firefox.zip"] + GhStable["Release tag: 3.7.0"] + GhNightly["Release tag: nightly"] + Badge[Update badge in settings] + end + + PrCi -->|build only| NoRelease[No release] + Mvp -->|artifact| DistZip[dist.zip artifact] + + Manual --> Zips + Manual --> GhStable + Manual --> Badge + + Nightly --> Zips + Nightly --> GhNightly + Nightly --> Badge +``` + +| Workflow | Trigger | Creates a release? | Update detector in build? | +|----------|---------|------------------|---------------------------| +| `pr-ci.yml` | Every pull request to `main` | No | No | +| `mvp.yml` | Every push to `main` | No | No | +| `release.yml` | Manual (`workflow_dispatch`) | Yes — stable version tag | Yes — stable channel | +| `nightly.yml` | Daily at 03:00 UTC + manual | Yes — reuses `nightly` tag | Yes — nightly channel | + +--- + +## Shared build action + +All release and CI builds that need packaged extensions use the composite action at [`.github/actions/build-extension/action.yml`](../.github/actions/build-extension/action.yml). + +It: + +1. Installs dependencies (`npm install --legacy-peer-deps`) +2. Runs `npm run build` (Chrome then Firefox via Vite) +3. Zips each unpacked folder into sideload-ready archives: + - `dist/betterseqtaplus-{version}-chrome.zip` + - `dist/betterseqtaplus-{version}-firefox.zip` + +The `{version}` comes from `package.json`. + +### Build-time flags (release builds only) + +Release and nightly workflows pass environment variables into Vite, which bakes them into the extension at compile time via `define` in [`vite.config.ts`](../vite.config.ts): + +| Variable | Stable release | Nightly | PR / local dev | +|----------|----------------|---------|----------------| +| `GH_RELEASE_UPDATE_CHECK` | `true` | `true` | `false` / unset | +| `UPDATE_CHANNEL` | `stable` | `nightly` | `stable` (unused) | +| `GH_RELEASE_REPO` | `BetterSEQTA/BetterSEQTA-Plus` | same | same | +| `BUILD_LABEL` | empty | GitHub run number | empty | + +When `GH_RELEASE_UPDATE_CHECK` is not `true`, the update-checker code is tree-shaken out of the bundle. PR CI builds and local `npm run build` do **not** include the update badge. + +To test a release-style build locally: + +```bash +# PowerShell +$env:GH_RELEASE_UPDATE_CHECK="true" +$env:UPDATE_CHANNEL="stable" +npm run build + +# bash +GH_RELEASE_UPDATE_CHECK=true UPDATE_CHANNEL=stable npm run build +``` + +--- + +## Stable release (`release.yml`) + +**Purpose:** A safe, manual way to publish versioned builds that users can download from GitHub. + +**Trigger:** Manual only — Actions → **Release** → **Run workflow**. There is no schedule or automatic trigger. + +When dispatching, check **“I have already updated the version in package.json”**. The workflow will not run without that confirmation. + +### Before you run it + +1. Merge your changes to `main`. +2. Bump `version` in [`package.json`](../package.json) (e.g. `3.7.0` → `3.8.0`). +3. Commit and push that bump. + +### What the workflow does + +1. Aborts if the version confirmation was not checked. +2. Reads the version from `package.json`. +3. Builds Chrome and Firefox with the update detector enabled (stable channel). +4. If no release exists for that tag: creates one (e.g. `3.8.0`) with a placeholder description. +5. If a release already exists for that tag: **only replaces the zip assets** (`--clobber`). Title and body are left unchanged. +6. Uploads `betterseqtaplus-{version}-chrome.zip` and `-firefox.zip`. + +On first publish, edit the **title** and **release notes** on GitHub afterward. Re-running for the same version refreshes the files only. + +### Downloading and installing + +1. Open [github.com/BetterSEQTA/BetterSEQTA-Plus/releases](https://github.com/BetterSEQTA/BetterSEQTA-Plus/releases). +2. Pick the version you want. +3. Download `betterseqtaplus-{version}-chrome.zip` or `-firefox.zip`. +4. Unzip and load the unpacked folder as a temporary extension (Chrome: Extensions → Load unpacked; Firefox: `about:debugging` → Load Temporary Add-on). + +**These GitHub builds are for sideloading only. Do not upload them to the Chrome Web Store or Firefox Add-ons.** + +--- + +## Nightly release (`nightly.yml`) + +**Purpose:** Continuous experimental builds from `main` so testers always have a single place to get the latest code. + +**Trigger:** + +- Automatically every day at **03:00 UTC** +- Manually via Actions → **Nightly Release** → **Run workflow** + +### What the workflow does + +1. Builds from the current `main` branch with the update detector enabled (nightly channel). +2. Uses a fixed release tag: **`nightly`** (marked as prerelease). +3. On first run: creates the `nightly` release with the text in [`.github/nightly-release-notes.md`](../.github/nightly-release-notes.md). +4. On every subsequent run: **replaces** the zip assets on the same release (`--clobber`). The release title and body are not rewritten. + +The nightly release body warns that builds are experimental and must not be uploaded to extension stores. + +--- + +## PR CI (`pr-ci.yml`) + +**Purpose:** Verify that every pull request builds cleanly in a fresh environment. + +**Trigger:** Every pull request targeting `main`. + +**Steps:** + +1. `npm install --legacy-peer-deps` +2. `npm run lint` (ESLint on `src/**/*.{js,ts}`) +3. Build via the shared action with **no** update detector + +No release is created and no artifacts are published for end users. + +--- + +## Push CI (`mvp.yml`) + +**Purpose:** Build verification when code lands on `main`. + +**Trigger:** Push to `main` only (not pull requests — those use `pr-ci.yml`). + +Uploads a `dist.zip` artifact containing the full `dist/` folder for debugging. No release, no update detector. + +--- + +## Authentication + +Release workflows run **only on [BetterSEQTA/BetterSEQTA-Plus](https://github.com/BetterSEQTA/BetterSEQTA-Plus)**. They use the default `GITHUB_TOKEN` with `contents: write` — no extra secrets or PATs required. + +--- + +## Update detector (in-extension) + +GitHub release builds include a small feature that tells sideload users when a newer build is available, so they do not have to check GitHub manually. + +### Where it appears + +In the **settings popup** header (top-right): an amber **“Update available — X.X.X”** pill when an update exists, plus a muted line: + +> GitHub release build — do not upload to extension stores. + +Clicking the badge opens the relevant GitHub releases page. + +### How it checks for updates + +Implementation: [`src/utils/githubReleaseUpdate.ts`](../src/utils/githubReleaseUpdate.ts) + +**Stable channel** (from `release.yml` builds): + +1. Fetches releases from the GitHub API for `BetterSEQTA/BetterSEQTA-Plus`. +2. Ignores the `nightly` tag and any non-semver tags. +3. Finds the highest semver tag. +4. Compares it to `browser.runtime.getManifest().version`. +5. Shows the badge if the remote version is newer. + +**Nightly channel** (from `nightly.yml` builds): + +1. Fetches the `nightly` release. +2. Compares its `published_at` timestamp to `lastSeenNightlyPublishedAt` in extension storage. +3. On first install, records the current publish time without showing a badge. +4. Shows **“Update available — nightly #123”** (run number) when a newer nightly has been published. + +Checks are throttled to once every **6 hours** per browser profile (`localStorage` key `bsplus_lastGhReleaseCheck`). Recent results are cached in memory for the session. + +### Dev override (testing) + +To test the badge without publishing a real release: + +1. Open settings and unlock **dev mode** (click the logo, type `dev`). +2. In the developer section, set **GitHub latest version override** to a version higher than your installed one (e.g. `9.9.9`). +3. Reopen settings — the badge should appear. + +This only applies when dev mode is on. Clear the field to return to normal API checks. + +--- + +## File reference + +| Path | Role | +|------|------| +| `.github/actions/build-extension/action.yml` | Shared install, build, zip | +| `.github/workflows/release.yml` | Manual stable releases | +| `.github/workflows/nightly.yml` | Nightly releases | +| `.github/workflows/pr-ci.yml` | PR lint + build | +| `.github/workflows/mvp.yml` | Push-to-main build artifact | +| `.github/nightly-release-notes.md` | Static body for the `nightly` release | +| `vite.config.ts` | Injects build-time `define` flags | +| `src/env.d.ts` | TypeScript declarations for those flags | +| `src/utils/githubReleaseUpdate.ts` | Update check logic | +| `src/interface/pages/settings.svelte` | Badge and disclaimer UI | +| `src/interface/pages/settings/general.svelte` | Dev override input | +| `src/types/storage.ts` | `devGhReleaseVersionOverride`, `lastSeenNightlyPublishedAt` | + +--- + +## Quick reference + +### Publish a stable release + +```text +1. Bump version in package.json on main +2. Actions → Release → Run workflow → confirm version checkbox +3. Edit release title/notes on GitHub (first time only) +4. Re-run with same version to refresh zips without changing release text +``` + +### Get the latest nightly + +```text +https://github.com/BetterSEQTA/BetterSEQTA-Plus/releases/tag/nightly +``` + +### Verify a PR locally + +```bash +npm run lint +npm run build +``` diff --git a/docs/contributing.md b/docs/contributing.md index 4b50bc4c..7f5096a3 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -119,12 +119,13 @@ git checkout -b feature/my-new-feature If your changes require documentation updates, include them in the same PR. -4. **Run Tests** +4. **Run CI checks locally** - Make sure all tests pass before submitting your PR: + Pull requests trigger **PR CI**, which lints and builds in a clean environment: ```bash - npm test + npm run lint + npm run build ``` 5. **Submit Your PR** @@ -139,6 +140,25 @@ git checkout -b feature/my-new-feature Once approved, a maintainer will merge your PR. +### GitHub Actions workflows + +See [RELEASES.md](RELEASES.md) for a full guide (workflows, sideload installs, and update detector). + +| Workflow | Trigger | Purpose | +|----------|---------|---------| +| `pr-ci.yml` | Every PR to `main` | Typecheck, lint, and build (no release) | +| `mvp.yml` | Push to `main` | Build and upload `dist.zip` artifact | +| `release.yml` | Manual (`workflow_dispatch`) | Stable release on [BetterSEQTA/BetterSEQTA-Plus](https://github.com/BetterSEQTA/BetterSEQTA-Plus) tagged with `package.json` version | +| `nightly.yml` | Daily cron + manual | Updates the fixed `nightly` prerelease with latest `main` builds | + +**Releasing a stable version:** bump `version` in `package.json` on `main`, then manually run the **Release** workflow and confirm the version checkbox. Edit the release title and notes on GitHub after the first publish. Re-running for the same tag only updates the zip files. Assets are `betterseqtaplus-{version}-chrome.zip` and `-firefox.zip`. + +**Nightly builds** replace assets on the same `nightly` release. The release body warns that builds are experimental and must not be uploaded to extension stores. + +**GitHub release builds** include an in-extension update checker (settings header badge). **PR CI and local dev builds do not.** + +Release workflows are dispatched only on the main **BetterSEQTA/BetterSEQTA-Plus** repository and use the default `GITHUB_TOKEN`. + ### Coding Standards We follow TypeScript best practices and have a consistent code style: diff --git a/package.json b/package.json index 1c53c20b..fad5924b 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,8 @@ "build:dev": "cross-env MODE=chrome SOURCEMAP=true vite build && cross-env MODE=firefox SOURCEMAP=true vite build", "convert:safari": "xcrun safari-web-extension-converter dist/safari --project-location . --app-name $npm_package_name-safari", "dependency-graph": "depcruise src --include-only \"^src\" --output-type dot | dot -T svg > dependency-graph.svg", - "release": "gh release create $npm_package_name@$npm_package_version ./dist/*.zip --generate-notes", + "lint": "cross-env ESLINT_USE_FLAT_CONFIG=false eslint \"src/**/*.{js,ts}\"", + "release": "gh release create $npm_package_version --repo BetterSEQTA/BetterSEQTA-Plus ./dist/*.zip --generate-notes", "publish": "bun lib/publish.js --b", "zip": "bedframe zip" }, @@ -45,9 +46,12 @@ "@types/mime-types": "^3.0.1", "@types/react": "^19.0.10", "@types/react-dom": "^19.0.4", + "@typescript-eslint/eslint-plugin": "^8.60.1", + "@typescript-eslint/parser": "^8.60.1", "cross-env": "^10.0.0", "dependency-cruiser": "^17.0.1", "eslint": "^9.33.0", + "eslint-plugin-import": "^2.31.0", "glob": "^11.0.1", "mime-types": "^3.0.1", "prettier": "^3.5.3", diff --git a/src/env.d.ts b/src/env.d.ts new file mode 100644 index 00000000..b3a32339 --- /dev/null +++ b/src/env.d.ts @@ -0,0 +1,4 @@ +declare const __ENABLE_GH_RELEASE_UPDATE_CHECK__: boolean; +declare const __GH_RELEASE_REPO__: string; +declare const __UPDATE_CHANNEL__: "stable" | "nightly"; +declare const __BUILD_LABEL__: string; diff --git a/src/interface/pages/settings.svelte b/src/interface/pages/settings.svelte index db6aed8d..dc26cf5a 100644 --- a/src/interface/pages/settings.svelte +++ b/src/interface/pages/settings.svelte @@ -19,6 +19,12 @@ import CloudPanel from "../components/CloudPanel.svelte"; import DisclaimerModal from "../components/DisclaimerModal.svelte"; import { settingsPopup } from "../hooks/SettingsPopup"; + import { + checkGithubReleaseUpdate, + dismissNightlyUpdate, + isGhReleaseUpdateCheckEnabled, + type GhReleaseUpdateInfo, + } from "@/utils/githubReleaseUpdate"; let devModeSequence = ""; let settingsActiveTab = $state(0); @@ -26,6 +32,18 @@ let disclaimerCallbacks = $state<{ onConfirm: () => void, onCancel: () => void } | null>(null); let disclaimerTitle = $state("Confirm"); let disclaimerMessage = $state(""); + const ghReleaseUpdateEnabled = isGhReleaseUpdateCheckEnabled(); + let ghReleaseUpdate = $state(null); + + const openGhRelease = () => { + const url = ghReleaseUpdate?.url + ?? "https://github.com/BetterSEQTA/BetterSEQTA-Plus/releases"; + if (ghReleaseUpdate?.available) { + dismissNightlyUpdate(); + } + window.open(url, "_blank"); + closeExtensionPopup(); + }; const handleDevModeToggle = () => { const handleKeyDown = (event: KeyboardEvent) => { @@ -98,6 +116,12 @@ if (standalone) { StandaloneStore.setStandalone(true); } + + if (ghReleaseUpdateEnabled) { + void checkGithubReleaseUpdate().then((info) => { + ghReleaseUpdate = info; + }); + } }); @@ -134,7 +158,25 @@ /> {#if !standalone} -
+
+ {#if ghReleaseUpdateEnabled} +
+ {#if ghReleaseUpdate?.available} + + {/if} +

+ GitHub release build — do not upload to extension stores. +

+
+ {/if} +
+