From eb9a8b55928e8b3fec74f3b4179802e91e8b7364 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 13 Jun 2026 11:16:14 +0000 Subject: [PATCH] =?UTF-8?q?iOS=20Cast=20:=20d=C3=A9marrer=20la=20d=C3=A9co?= =?UTF-8?q?uverte=20pour=20d=C3=A9clencher=20la=20permission=20R=C3=A9seau?= =?UTF-8?q?=20local?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Symptôme : le picker Cast s'ouvre et « cherche » mais ne trouve aucun Chromecast, et l'app n'apparaît même pas dans Réglages → Réseau local (la popup de permission iOS ne s'affiche jamais). Cause : le SDK Google Cast ne lance la découverte réseau automatiquement QUE lorsqu'un GCKUICastButton est affiché pour la première fois. Movix ouvre le picker programmatiquement (presentCastDialog) sans jamais instancier de cast button → la découverte ne démarre jamais → aucun scan Bonjour → iOS ne déclenche jamais la popup « Réseau local » → aucun appareil trouvé. Les clés Info.plist (NSLocalNetworkUsageDescription, NSBonjourServices) sont nécessaires mais ne suffisent pas : il faut réellement tenter un accès réseau local pour que la popup apparaisse. Correctif : startDiscoveryIfNeeded() lance explicitement discoveryManager.startDiscovery() (passiveScan = false, idempotent), appelé depuis isSupported() (au chargement de la page en mode Chromecast), showPicker() et loadMedia(). Le scan Bonjour fait alors apparaître la popup de permission et pré-remplit la liste d'appareils. https://claude.ai/code/session_01X52sah6aUu3ou26uJWHgzr --- app/ios/Movix/Cast/CastModule.swift | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/app/ios/Movix/Cast/CastModule.swift b/app/ios/Movix/Cast/CastModule.swift index 2f8d32a..5508744 100644 --- a/app/ios/Movix/Cast/CastModule.swift +++ b/app/ios/Movix/Cast/CastModule.swift @@ -72,6 +72,11 @@ class CastModule: RCTEventEmitter { // Cast est disponible dès que le SDK est lié (le picker affichera // « aucun appareil » s'il n'y a pas de Chromecast à proximité). Identique // au comportement Android qui renvoie true si Play Services est présent. + // isSupported() est appelé par le shim au chargement de la page (mode + // Chromecast uniquement) : c'est le bon moment pour lancer le scan réseau, + // ce qui déclenche la popup iOS « Réseau local » et pré-remplit la liste + // d'appareils avant même que l'utilisateur n'ouvre le picker. + DispatchQueue.main.async { self.startDiscoveryIfNeeded() } resolve(true) #else resolve(false) @@ -85,6 +90,7 @@ class CastModule: RCTEventEmitter { ) { #if canImport(GoogleCast) DispatchQueue.main.async { + self.startDiscoveryIfNeeded() GCKCastContext.sharedInstance().presentCastDialog() resolve(true) } @@ -109,6 +115,7 @@ class CastModule: RCTEventEmitter { return } DispatchQueue.main.async { + self.startDiscoveryIfNeeded() let manager = GCKCastContext.sharedInstance().sessionManager if let session = manager.currentCastSession, session.connectionState == .connected { self.playMedia(on: session, url: url, title: title, poster: poster, position: currentTimeSec) @@ -191,6 +198,26 @@ class CastModule: RCTEventEmitter { } #if canImport(GoogleCast) + /// Démarre le scan réseau Bonjour si nécessaire. + /// + /// Le SDK Google Cast ne lance la découverte automatiquement que lorsqu'un + /// `GCKUICastButton` est affiché pour la première fois. Or Movix présente le + /// picker programmatiquement (`presentCastDialog`) sans jamais instancier de + /// cast button : la découverte ne démarrait donc JAMAIS, aucun scan réseau + /// n'avait lieu, et iOS n'affichait jamais la popup « Réseau local » (l'app + /// n'apparaissait même pas dans Réglages → Réseau local). + /// + /// Démarrer la découverte manuellement déclenche le scan Bonjour, ce qui fait + /// apparaître la popup de permission iOS et permet de trouver les Chromecast. + /// Idempotent : ne relance pas si déjà en cours. + private func startDiscoveryIfNeeded() { + let dm = GCKCastContext.sharedInstance().discoveryManager + dm.passiveScan = false + if dm.discoveryState != .running { + dm.startDiscovery() + } + } + private func playMedia( on session: GCKCastSession, url: String,