meteo-exam/web/src/update.ts

79 lines
2.3 KiB
TypeScript
Raw Normal View History

import { Capacitor } from '@capacitor/core'
import { getBaseUrl } from './config'
export interface UpdateInfo {
version: string
apkUrl: string | null
apkSize: number | null
notes: string | null
}
/** Compare deux versions sémantiques. Renvoie 1 si a > b, -1 si a < b, 0 si égales. */
function compareVersions(a: string, b: string): number {
const pa = a.split('.').map(Number)
const pb = b.split('.').map(Number)
for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
const na = pa[i] ?? 0
const nb = pb[i] ?? 0
if (na > nb) return 1
if (na < nb) return -1
}
return 0
}
/**
* Vérifie si une mise à jour est disponible sur le serveur.
* Ne retourne que sur Android natif (Capacitor) : la PWA iOS se met à jour
* en rechargeant simplement la page.
*/
export async function checkForUpdate(): Promise<UpdateInfo | null> {
if (!Capacitor.isNativePlatform() || Capacitor.getPlatform() !== 'android') {
return null
}
const localVersion = __APP_VERSION__
try {
const response = await fetch(`${getBaseUrl()}/api/version`, {
headers: { Accept: 'application/json' },
})
if (!response.ok) return null
const remote = (await response.json()) as UpdateInfo
// Le serveur est plus vieux ou à jour : rien à faire.
if (compareVersions(remote.version, localVersion) <= 0) return null
// L'utilisateur a déjà ignoré cette version-là.
const dismissed = localStorage.getItem('meteo-exam.dismissed-update')
if (dismissed === remote.version) return null
return remote
} catch {
// Serveur injoignable : on ne bloque pas le démarrage de l'app.
return null
}
}
export const currentAppVersion = (): string => __APP_VERSION__
export function dismissUpdate(version: string): void {
localStorage.setItem('meteo-exam.dismissed-update', version)
}
/**
* Déclenche le téléchargement de l'APK. Sur Android, le WebView enregistre
* le fichier et l'utilisateur ouvre la notification pour installer.
*/
export function downloadApk(apkUrl: string): void {
const url = apkUrl.startsWith('http') ? apkUrl : `${getBaseUrl()}${apkUrl}`
const anchor = document.createElement('a')
anchor.href = url
anchor.download = 'meteo-exam.apk'
anchor.rel = 'noopener'
anchor.style.display = 'none'
document.body.append(anchor)
anchor.click()
anchor.remove()
}