From 33f6837147cfd9dff8790c61e1ec1f5ae69e8417 Mon Sep 17 00:00:00 2001 From: geekgeekrun Date: Sat, 26 Apr 2025 14:40:55 +0800 Subject: [PATCH] add check update logic --- .github/workflows/release-ui.yml | 1 + packages/ui/src/common/types/update.ts | 7 ++ packages/ui/src/main/features/updater.ts | 103 ++++++++++++++++++ .../main/flow/OPEN_SETTING_WINDOW/index.ts | 3 + 4 files changed, 114 insertions(+) create mode 100644 packages/ui/src/common/types/update.ts create mode 100644 packages/ui/src/main/features/updater.ts diff --git a/.github/workflows/release-ui.yml b/.github/workflows/release-ui.yml index dafbecd..424236d 100644 --- a/.github/workflows/release-ui.yml +++ b/.github/workflows/release-ui.yml @@ -152,6 +152,7 @@ jobs: - name: Create release uses: ncipollo/release-action@v1 with: + prerelease: true allowUpdates: true artifacts: geekgeekrun-ui@${{ github.sha }}/* tag: ${{ github.ref }} diff --git a/packages/ui/src/common/types/update.ts b/packages/ui/src/common/types/update.ts new file mode 100644 index 0000000..67ff361 --- /dev/null +++ b/packages/ui/src/common/types/update.ts @@ -0,0 +1,7 @@ +export interface NewReleaseInfo { + releaseVersion: string + releasePageUrl: string + assetUrl: string + assetName: string + releaseNote: string +} diff --git a/packages/ui/src/main/features/updater.ts b/packages/ui/src/main/features/updater.ts new file mode 100644 index 0000000..c527309 --- /dev/null +++ b/packages/ui/src/main/features/updater.ts @@ -0,0 +1,103 @@ +import semver from 'semver' +import packageJson from '../../../package.json' +import os from 'node:os' +import gtag from '../utils/gtag' +import { NewReleaseInfo } from '../../common/types/update' + +export const currentOsPlatform = os.platform() +const RELEASE_LIST_URL = `https://api.github.com/repos/geekgeekrun/geekgeekrun/releases` + +export interface GitHubReleaseItem { + tag_name: string + prerelease: boolean + draft: boolean + html_url: string + body: string + assets: Array<{ + browser_download_url: string + name: string + }> +} + +// find by arch, appendix +function findTargetAsset( + assets: GitHubReleaseItem['assets'] +): null | GitHubReleaseItem['assets'][number] { + let assetsFilteredByPlatform: GitHubReleaseItem['assets'] = [] + switch (os.platform()) { + case 'win32': { + assetsFilteredByPlatform = assets.filter((it) => it.name.endsWith('.exe')) + break + } + case 'darwin': { + assetsFilteredByPlatform = assets.filter((it) => it.name.endsWith('.dmg')) + break + } + case 'linux': { + assetsFilteredByPlatform = assets.filter((it) => it.name.endsWith('.deb')) + break + } + } + if (!assetsFilteredByPlatform?.length) { + return null + } + if (assetsFilteredByPlatform.length === 1) { + return assetsFilteredByPlatform[0] + } + let targetAsset + if (os.platform() === 'darwin') { + targetAsset = assetsFilteredByPlatform.find((it) => it.name.includes(`_${os.arch()}`)) + } + return targetAsset +} + +export const checkUpdateForUi = async (): Promise => { + let releaseList: GitHubReleaseItem[] = [] + try { + const headers = new Headers() + headers.append('Accept', 'application/vnd.github+json') + headers.append('X-GitHub-Api-Version', '2022-11-28') + await fetch(RELEASE_LIST_URL, { + method: 'GET', + headers: headers, + redirect: 'follow' + }) + .then((res) => res.json()) + .then((res) => { + if (Array.isArray(res)) { + releaseList = res + } else { + throw res + } + }) + } catch (err) { + gtag('check_update_error', { err: JSON.stringify(err) }) + console.log(err) + } + console.log(releaseList) + const availableRelease = releaseList.find((it) => !it.draft && !it.prerelease) + if (!availableRelease) { + return null + } + const availableReleaseVersion = availableRelease.tag_name.replace(/^(ui-v)/, '') + if (!semver.gt(availableReleaseVersion, packageJson.version)) { + return null + } + const { assets } = availableRelease + const targetAsset = findTargetAsset(assets ?? []) + if (targetAsset) { + gtag('update_found', { + currentVersion: packageJson.version, + newVersion: availableReleaseVersion + }) + console.log(targetAsset) + return { + releaseVersion: availableReleaseVersion, + releasePageUrl: availableRelease.html_url, + assetUrl: targetAsset.browser_download_url, + assetName: targetAsset.name, + releaseNote: availableRelease.body + } + } + return null +} diff --git a/packages/ui/src/main/flow/OPEN_SETTING_WINDOW/index.ts b/packages/ui/src/main/flow/OPEN_SETTING_WINDOW/index.ts index 8d2409c..bdd9941 100644 --- a/packages/ui/src/main/flow/OPEN_SETTING_WINDOW/index.ts +++ b/packages/ui/src/main/flow/OPEN_SETTING_WINDOW/index.ts @@ -5,6 +5,7 @@ import './app-menu' import initIpc from './ipc' import gtag from '../../utils/gtag' import initPublicIpc from '../../utils/initPublicIpc' +import { checkUpdateForUi } from '../../features/updater' export function openSettingWindow() { // TODO: singleton lock; how can we check if there is another process should run as singleton with arguments? if (!app.requestSingleInstanceLock()) { @@ -65,4 +66,6 @@ export function openSettingWindow() { globalShortcut.unregister('Command+Option+Shift+/') }) }) + + checkUpdateForUi() }