@@ -26,7 +26,8 @@ import { gunzip } from 'node:zlib'
2626import { promisify } from 'node:util'
2727import { mkdir , rename , rm , writeFile , chmod } from 'node:fs/promises'
2828import { app } from 'electron'
29- import type { EngineDownloadProgress , EngineErrorCode , EngineRelease , EngineStatus } from '../shared/types'
29+ import type { EngineDownloadProgress , EngineErrorCode , EngineRelease , EngineStatus , EngineUpdateCheck } from '../shared/types'
30+ import { compareSemver } from '../shared/semver'
3031import { parseSha256Sum , parseVersion } from '../shared/ipatool/parse'
3132import { findTarFile , parseTar } from '../shared/tar'
3233import {
@@ -287,6 +288,37 @@ export class EngineManager extends EventEmitter {
287288 }
288289 }
289290
291+ /**
292+ * Compares the installed ipatool with the newest published release.
293+ *
294+ * `checkAppUpdate` is about *this* GUI; engine updates are separate and only
295+ * look at majd/ipatool tags. Prereleases never count as "newer".
296+ */
297+ async checkUpdate ( ) : Promise < EngineUpdateCheck > {
298+ const current = ( this . current . version ?? '' ) . replace ( / ^ v / , '' )
299+ try {
300+ const list = await this . releases ( 15 )
301+ const stable = list
302+ . filter ( ( r ) => ! r . prerelease && r . hasAssetForThisPlatform )
303+ . map ( ( r ) => r . version . replace ( / ^ v / , '' ) )
304+ const latest = stable . length > 0 ? ( stable [ 0 ] ?? '' ) : ''
305+ // releases() is newest-first; pick the max in case GitHub order shifts.
306+ let newest = latest
307+ for ( const v of stable ) {
308+ if ( compareSemver ( v , newest ) > 0 ) newest = v
309+ }
310+ const hasUpdate = current !== '' && newest !== '' && compareSemver ( newest , current ) > 0
311+ return { current, latest : newest === '' ? null : newest , hasUpdate, error : null }
312+ } catch ( error ) {
313+ return {
314+ current,
315+ latest : null ,
316+ hasUpdate : false ,
317+ error : error instanceof Error ? error . message : String ( error )
318+ }
319+ }
320+ }
321+
290322 /**
291323 * Downloads, verifies and installs ipatool. Emits progress through the
292324 * `status` event so the UI can show a real percentage.
0 commit comments