# Gestion d'erreurs — iMedia TV+ ## Architecture ```mermaid flowchart TB API[Serveur Xtream] -->|Timeout / 4xx / 5xx| Interceptor[OkHttp ErrorInterceptor] Interceptor -->|Exception typée| Repository Repository -->|Result / UiState.Error| ViewModel ViewModel -->|Message localisé| UI[Écran Compose] UI -->|Snackbar / Toast / Overlay| User[Utilisateur] ``` ## Hiérarchie d'erreurs ```kotlin /** * Toutes les erreurs Xtream sont des sealed classes * pour un `when` exhaustif dans l'UI. */ sealed class XtreamException(message: String, cause: Throwable? = null) : Exception(message, cause) { class NetworkException(message: String) : XtreamException(message) class TimeoutException(message: String) : XtreamException(message) class AuthException(message: String) : XtreamException(message) class ServerException(val code: Int, message: String) : XtreamException(message) class ParseException(message: String, cause: Throwable) : XtreamException(message, cause) class StreamUnavailableException(message: String) : XtreamException(message) } ``` ## Table des erreurs | N° | Condition | Exception | Code UI | Message FR | Message EN | |----|-----------|-----------|---------|------------|------------| | 1 | Serveur injoignable | `NetworkException` | Erreur réseau | "Impossible de se connecter au serveur. Vérifiez votre réseau." | "Cannot reach server. Check your network." | | 2 | Timeout dépassé (15s) | `TimeoutException` | Erreur réseau | "Le serveur ne répond pas. Réessayez plus tard." | "Server is not responding. Try again later." | | 3 | Auth invalide | `AuthException` | Login bloqué | "Identifiants incorrects ou serveur invalide." | "Invalid credentials or server." | | 4 | Flux vidéo cassé | `StreamUnavailableException` | Overlay erreur | "Flux indisponible pour cette chaîne." | "Stream unavailable for this channel." | | 5 | HTTP 4xx | `ServerException` | Toast | "Erreur serveur (code X). Contactez votre fournisseur." | "Server error (code X). Contact your provider." | | 6 | HTTP 5xx | `ServerException` | Toast | "Le serveur Xtream rencontre un problème." | "Xtream server is having issues." | | 7 | JSON mal formé | `ParseException` | Fallback silencieux | "Données reçues incorrectes." | "Received data is malformed." | | 8 | EPG vide | N/A (pas une erreur) | Texte vide | "Aucun programme trouvé pour cette chaîne." | "No program found for this channel." | | 9 | Cache corrompu | N/A | Suppression + reload | "Mise à jour des données..." | "Updating data..." | ## État loading global ```kotlin /** * État unique pour TOUS les écrans. * Permet un traitement uniforme dans les composants UI. */ sealed interface UiState { data object Idle : UiState data object Loading : UiState data class Success(val data: T) : UiState data class Error( val message: String, // Message affiché à l'utilisateur val retry: Boolean = true, // Afficher un bouton "Réessayer" ? val exception: XtreamException? = null // Pour logging uniquement ) : UiState } ``` ## Intercepteur OkHttp ```kotlin class XtreamErrorInterceptor : Interceptor { override fun intercept(chain: Interceptor.Chain): Response { val request = chain.request() return try { val response = chain.proceed(request) if (!response.isSuccessful) { when (response.code) { 401, 403 -> throw XtreamException.AuthException( "Authentication failed" ) in 400..499 -> throw XtreamException.ServerException( response.code, "Client error" ) in 500..599 -> throw XtreamException.ServerException( response.code, "Server error" ) } } response } catch (e: SocketTimeoutException) { throw XtreamException.TimeoutException("Connection timed out") } catch (e: ConnectException) { throw XtreamException.NetworkException("Cannot connect") } catch (e: UnknownHostException) { throw XtreamException.NetworkException("DNS resolution failed") } } } ``` ## Comportement UI par erreur ### Écran de connexion ``` [Champs vides] ❌ Bouton Connexion désactivé [Erreur réseau] ✅ Bouton actif, message rouge sous le formulaire ✅ Champs conservés (pas de reset) [Auth refusée] ✅ Message : "Identifiants incorrects" ✅ Focus revient sur le champ mot de passe ``` ### Écran Live TV ``` [Erreur chargement chaînes] ✅ Toast 3s : "Impossible de charger les chaînes" ✅ Cache affiché si disponible [Chaîne sans flux] ✅ Overlay : "Flux indisponible" + bouton "Chaîne suivante" ``` ### Lecteur vidéo ``` [Flux mort pendant lecture] ✅ Remplacer par écran noir + message ✅ Bouton "Chaîne suivante" visible ✅ Retour possible vers le menu ``` ## Règles de logging | Niveau | Usage | Exemple | |--------|-------|---------| | `Timber.d` | Debug uniquement (pas en prod) | "Loading 42 live channels" | | `Timber.i` | Événements importants | "User logged in: user123" | | `Timber.w` | Anomalies non bloquantes | "EPG cache expired for stream 99" | | `Timber.e` | Erreurs utilisateur | "Stream unavailable for stream 42" | **❌ Interdit** : `Log.d("PASSWORD", password)` ou tout log contenant des credentials. ## Annexes ### Codes Xtream que l'on peut rencontrer | Code | Signification | Action | |------|--------------|--------| | `auth = "0"` | Compte invalide | Message login | | `status = "Expired"` | Abonnement expiré | Message distinct | | `status = "Disabled"` | Compte désactivé | Message distinct | | `tv_archive = 0` | Pas d'archive | Cacher bouton Replay | | `has_archive = false` | Pas d'archive | Cacher bouton Replay | | Réponse vide | Serveur HS ou mauvaise URL | Erreur réseau générique |