Proje: Okul B2B App · Hub: Okul B2B App — Decisions

OTA Update Ekranı — Min Gösterim + Fade-in

Karar

useForceUpdate hook’u update indirme aşamasında UpdateLoadingScreen’i gösterir. Ekran en az 2500ms görünür kalır, sonra Updates.reloadAsync() tetiklenir. Mount’ta Animated.View opacity 0→1 fade-in ile native splash’tan yumuşak geçiş.

Gerekçe

Önceki durum (silent update):

  • shouldShowUpdateScreen hep false dönüyordu
  • Update arka planda indiriliyor, kullanıcı hiçbir şey görmüyor
  • İndirme bitince reloadAsync() anında tetikleniyor → kullanıcı için “ne oldu?” anı

Sorun:

  • Hızlı indirmelerde (100-200ms) kullanıcı yalnızca flicker görür, reload’un neden olduğunu anlamaz
  • İndirme başarısız olursa kullanıcı bilgilendirilmez (error state sessiz tutuluyordu)

Çözüm:

  • Update mevcut ise UpdateLoadingScreen göster (isUpdateAvailable || isDownloading true)
  • Kontrol fazı (isChecking) sessiz kalır — kullanıcı “güncelleme yok”u görmez
  • Min 2500ms gösterim: screenStartTimeRef ile geçen süre ölçülür, reloadAsync öncesi yeterli süre bekletilir
  • Fade-in: Animated.Value(0).start({toValue: 1, duration: 350, Easing.out(quad)}) native driver

Neden 2500ms

Çok kısa olursa (< 1s) flash hissi kalmaya devam eder. Çok uzun olursa (> 3s) hızlı indirmelerde kullanıcı bekletilmiş hisseder. 2.5s sweet spot — kullanıcı mesajı (“Güncelleme indiriliyor”) okur, progress bar’ı görür, bilinçli geçiş yaşar.

Flash Önleme Akışı

Native splash (#ffffff)
  ↓ (JS mount)
MainApp
  ↓ (isUpdateAvailable=true)
UpdateLoadingScreen (fade-in, #ffffff)
  ↓ (download + min 2500ms)
Updates.reloadAsync()
  ↓ (native restart)
Native splash (#ffffff)
  ↓ (yeni bundle)
LoadingScreen / Main App

Tüm geçişlerde arka plan beyaz — renk flash’ı yok. UpdateLoadingScreen.tsx’in backgroundColor’u APP_COLORS.BACKGROUND_WHITE ile native splash config’inde (app.config.ts’teki expo-splash-screen plugin) tanımlı #ffffff ile eşleşir.

Alternatifler (Reddedildi)

AlternatifNeden Reddedildi
Silent update (önceki hali)Flash + kullanıcı farkındasızlığı
Update screen’i isChecking’de de gösterKontrol fazı genelde <500ms, ekran yanıp söner
LottieSpinner yerine custom progressMevcut LottieSpinner tutarlı, marka ile uyumlu
Progress bar yerine yalnız spinnerProgress bar “indirme ilerliyor” sinyali verir

Dosyalar

  • hooks/useForceUpdate.tsisUpdateAvailable state, MIN_UPDATE_SCREEN_MS = 2500, screenStartTimeRef
  • components/UpdateLoadingScreen.tsxAnimated.View fade-in + progress bar
  • app/_layout.tsxshouldShowUpdateScreen wire-up + downloadProgress prop