import Constants from 'expo-constants'; import * as Updates from 'expo-updates'; /** * Aktualna wersja appki, używana do display'u (BugReportFAB, Update dialog) * i porównań z `/version` z serwera. * * Źródła w kolejności preferencji: * 1. `Constants.expoConfig?.version`, działa gdy OTA manifest ma `extra.expoClient` * (publish_update.py embeduje tam app.json). W release APK przed pierwszym OTA * bierze się to z app.json bundled w build. * 2. Hardcoded fallback, chroni przed OTA-z-pustego-extra (bug 2026-05-12, gdzie * stara wersja publish_update.py wysyłała `extra: {}` → expoConfig=null po * reload-zie → version='0.0.0' → fałszywy "Update available" dialog). * * **Bump przy każdym APK release** żeby APK fallback pasował do realnej wersji. * OTA-only releases (silent JS update) NIE bumpują tego, wtedy version w app.json * też nie idzie do góry, więc consistency jest zachowana. */ export const APP_VERSION: string = (Constants.expoConfig?.version as string | undefined) || '0.4.0'; /** * Runtime zapisany w APK (`EXPO_RUNTIME_VERSION` w AndroidManifest). JEDYNY numer, po * którym aplikacja pozna, jaką paczkę natywną ma naprawdę zainstalowaną. * * Po co osobno, skoro jest `APP_VERSION`: ta bierze się z `app.json`, a `app.json` * przyjeżdża do aplikacji RAZEM Z PACZKĄ OTA. Po podbiciu wersji na 0.3.0 i wysłaniu tej * paczki na stary kanał każdy użytkownik APK 0.2.2 zaczął raportować 0.3.0 i sam siebie * uznał za aktualnego: nie dostał ani monitu o nowym APK, ani wpisu w changelogu, który * właśnie do niego był kierowany. Runtime siedzi w natywnym manifeście i OTA go nie rusza. */ export const NATIVE_RUNTIME: string | null = (() => { try { return Updates.runtimeVersion ?? null; } catch { return null; } })(); /** „0.3.0" → [0,3,0]. Człony nieliczbowe (np. „0.3.0-rc1") lecą na 0. */ function versionParts(v: string): number[] { return String(v || '').split('.').map((x) => parseInt(x, 10) || 0); } /** * Czy `candidate` jest NOWSZA niż `current`. * * Po co, skoro wcześniej wystarczyło `!==`: serwer trzyma numer najnowszego APK na * sztywno, a przy wydaniu 0.3.0 nie został podbity od razu. Porównanie „różne" kazało * wtedy KAŻDEMU użytkownikowi 0.3.0 zainstalować 0.2.2, czyli cofnąć się o wersję. * Złapane na emulatorze przed publikacją. */ export function isNewerVersion(candidate: string, current: string): boolean { const a = versionParts(candidate); const b = versionParts(current); for (let i = 0; i < Math.max(a.length, b.length); i++) { const d = (a[i] ?? 0) - (b[i] ?? 0); if (d !== 0) return d > 0; } return false; }