Application mobile : vérification automatique de mise à jour #66
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Contexte
Sur l'application mobile, détecter automatiquement qu'une nouvelle version
est disponible et le signaler à l'utilisateur.
Contrainte de départ à ne pas manquer : l'app n'est distribuée nulle
part sur le Play Store (hors scope explicite de #64/#65 — juste un APK
téléchargeable) — l'API "In-App Updates" de Google Play n'a donc aucune
prise ici, elle ne fonctionne que pour une app installée depuis le Play
Store. Ce ticket construit un mécanisme maison, pas une intégration de
cette API.
Conception — la source de vérité pour "quelle est la dernière version"
Réutilise directement l'infrastructure déjà posée par
#64/#65,
zéro nouveau endpoint backend : l'API Releases de Forgejo est déjà publique
et non authentifiée pour ce dépôt (déjà utilisée pour vérifier le statut
de CI sans jeton, voir
local-verification-while-ci-disabled) :Comparer
tag_nameà la version installée(
@capacitor/app'sApp.getInfo()→{ version, build }— nouvelledépendance, plugin officiel Capacitor, pas encore présent) ; si plus
récent, proposer le téléchargement vers l'URL stable déjà définie par #65
(
.../releases/latest/download/batchcooking.apk).Dépendance trouvée —
versionName/versionCodene sont jamais mis à jourVérifié dans
apps/web/android/app/build.gradle(lignes 10-11) :versionCode 1/versionName "1.0", toujours la valeur générée par défautpar
npx cap add android(#63) — rien ne les fait jamais évoluer. Sanscorrectif, la comparaison de version n'aurait aucun sens (toujours "1.0",
quelle que soit la version réellement installée). Cette itération de
versionName/versionCodedoit se faire au moment du build de release(même job que #65 construit déjà) :
versionName= le tag débarrassé de sonpréfixe
v(v1.4.2→1.4.2),versionCode= un entier qui augmentestrictement à chaque release (Android refuse une "mise à jour" avec un
versionCodeinférieur ou égal à l'existant) — proposé :majeur×10000 + mineur×100 + correctif(tient tant que mineur/correctifrestent sous 100, élargir le multiplicateur sinon). Ajouté au périmètre de
la tâche déjà déposée pour release.yml plutôt qu'une tâche de plus.
Conception — mécanisme de vérification côté app
Capacitor.isNativePlatform()) — même garde que leTokenStorede #39 ; sur le web, l'app se met à jour simplement enrechargeant la page servie par le serveur, aucune notion de "version
installée" n'existe.
plan (
@capacitor/app's événementappStateChange), avec un throttle(dernier check horodaté dans
@capacitor/preferences, pas plus d'une foistoutes les quelques heures) pour ne pas solliciter l'API Forgejo à chaque
passage au premier plan.
ThemeContext's propre fetch de préférences ("failure swallowedsilently"), une vérification de version n'est jamais bloquante.
Dialogmodal pour ça), avec un bouton "Mettre à jour" qui ouvre l'URL de
téléchargement dans le navigateur système (laisser Android gérer le
téléchargement + l'invite d'installation ensuite — pas de téléchargement/
installation in-app via
PackageInstaller, qui demanderait la permissionREQUEST_INSTALL_PACKAGESet beaucoup plus de code natif pour un gaind'expérience marginal).
proposée (
@capacitor/preferences) ; la bannière ne se réaffiche que siune version encore plus récente que celle déjà rejetée sort — pas à
chaque redémarrage tant que rien n'a changé.
Fichiers à toucher
apps/web/package.json— ajoute@capacitor/app.apps/web/src/features/app-update/(nouveau) —useAppUpdateCheck(hook),UpdateBanner.tsx+ scss, appelés depuisAppLayout.tsx(même positionque les autres providers/effets globaux de l'espace connecté).
apps/web/src/locales/fr/translation.json— namespaceappUpdate.*.release.yml/le workflow réutilisable de buildAPK — étendue pour injecter
versionName/versionCodeavant./gradlew assembleRelease.Tests
Capacitor.isNativePlatform(), toujours faux dans un navigateur de test)— un test unitaire (Vitest/pure function, si l'outillage existe, sinon un
test Mocha du côté partagé) sur la seule logique pure testable sans
Capacitor : la comparaison de versions et la logique "ne pas re-harceler".
Hors scope
PackageInstaller— cf. le choixci-dessus, ouverture externe suffit pour cette itération.
règles Apple totalement différentes (pas de sideload équivalent).
🤖 Filed by Claude Code