expo-realtime-ivs-broadcast 0.2.1 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,7 +8,8 @@ This module provides React Native components and a comprehensive API to integrat
8
8
 
9
9
  | Library Version | Expo SDK | React Native | React | Notes |
10
10
  |-----------------|----------|--------------|---------|-------|
11
- | 0.2.0 | 54 | 0.81.x | 19.1.x | **Added Picture-in-Picture support** |
11
+ | 0.2.1 | 54 | 0.81.x | 19.1.x | **Fixed iOS PiP pre-warming reliability** |
12
+ | 0.2.0 | 54 | 0.81.x | 19.1.x | Added Picture-in-Picture support |
12
13
  | 0.1.7 | 54 | 0.81.x | 19.1.x | |
13
14
  | 0.1.4 | 53 | 0.79.x | 19.0.x | |
14
15
 
@@ -103,9 +103,17 @@ class ExpoIVSRemoteStreamView: ExpoView {
103
103
  print("✅ [REMOTE VIEW] Manager commanded me to render URN: \(deviceUrn)")
104
104
 
105
105
  // Notify the stage manager that a stream started rendering (for PiP)
106
- // Use a small delay to ensure the view is fully set up
107
- DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [weak self] in
108
- self?.stageManager?.notifyRemoteStreamRendered()
106
+ // Use a longer delay to ensure the view hierarchy is fully set up
107
+ DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { [weak self] in
108
+ guard let self = self else { return }
109
+ print("✅ [REMOTE VIEW] Notifying PiP system - view in window: \(self.window != nil), isRenderingVideo: \(self.isRenderingVideo)")
110
+ self.stageManager?.notifyRemoteStreamRendered()
111
+ }
112
+
113
+ // Also notify immediately for faster setup if view is already ready
114
+ if self.window != nil {
115
+ print("✅ [REMOTE VIEW] View already in window, notifying PiP immediately")
116
+ self.stageManager?.notifyRemoteStreamRendered()
109
117
  }
110
118
  } catch {
111
119
  print("❌ [REMOTE VIEW] Failed to create preview for URN \(deviceUrn): \(error)")
@@ -1057,13 +1057,27 @@ class IVSStageManager: NSObject, IVSStageStreamDelegate, IVSStageStrategy, IVSSt
1057
1057
  let previewView = try device.previewView()
1058
1058
  pipController.setupWithSourceView(previewView)
1059
1059
  pipTargetView = previewView
1060
+ print("🖼️ [PiP] Set up with device preview view")
1060
1061
  } catch {
1061
1062
  print("🖼️ [PiP] Warning: Could not get preview view from device: \(error)")
1062
1063
  // Try to find a remote view that's rendering this device
1063
- if let remoteView = remoteViews.compactMap({ $0.value }).first(where: { $0.currentRenderedDeviceUrn == device.descriptor().urn }),
1064
- let previewViewForPiP = remoteView.previewViewForPiP {
1064
+ if let remoteView = remoteViews.compactMap({ $0.value }).first(where: { $0.currentRenderedDeviceUrn == device.descriptor().urn }) {
1065
+ // Always set up with the remote view container - it's the visible video view
1065
1066
  pipController.setupWithSourceView(remoteView as UIView)
1066
- pipTargetView = previewViewForPiP
1067
+ pipTargetView = remoteView.previewViewForPiP ?? remoteView
1068
+ print("🖼️ [PiP] Set up with matching remote view container")
1069
+ } else if let anyRenderingView = remoteViews.compactMap({ $0.value }).first(where: { $0.isRenderingVideo }) {
1070
+ // Fallback: use any view that's rendering
1071
+ pipController.setupWithSourceView(anyRenderingView as UIView)
1072
+ pipTargetView = anyRenderingView.previewViewForPiP ?? anyRenderingView
1073
+ print("🖼️ [PiP] Set up with fallback rendering view")
1074
+ } else if let anyView = remoteViews.compactMap({ $0.value }).first {
1075
+ // Last resort: use any registered view
1076
+ pipController.setupWithSourceView(anyView as UIView)
1077
+ pipTargetView = anyView
1078
+ print("🖼️ [PiP] Set up with any available view (last resort)")
1079
+ } else {
1080
+ print("🖼️ [PiP] ERROR: No source view found for PiP - controller will NOT be initialized!")
1067
1081
  }
1068
1082
  }
1069
1083
  }
@@ -1111,20 +1125,43 @@ class IVSStageManager: NSObject, IVSStageStreamDelegate, IVSStageStrategy, IVSSt
1111
1125
  if currentPiPSourceDeviceUrn != imageDevice.descriptor().urn {
1112
1126
  print("🖼️ [PiP] Found new remote video stream: \(imageDevice.descriptor().urn)")
1113
1127
 
1128
+ // Debug: Log all registered remote views and their URNs
1129
+ print("🖼️ [PiP] Registered remote views: \(remoteViews.count)")
1130
+ for (index, viewWrapper) in remoteViews.enumerated() {
1131
+ if let view = viewWrapper.value {
1132
+ print("🖼️ [PiP] View \(index): URN=\(view.currentRenderedDeviceUrn ?? "nil"), isRendering=\(view.isRenderingVideo)")
1133
+ }
1134
+ }
1135
+
1114
1136
  // Try to find the remote view that's rendering this stream
1115
1137
  if let remoteView = remoteViews.compactMap({ $0.value }).first(where: { $0.currentRenderedDeviceUrn == imageDevice.descriptor().urn }) {
1116
- // Use the remote view (container) as the source view for Video Call API
1117
- // Cast to UIView explicitly since ExpoIVSRemoteStreamView extends ExpoView -> UIView
1118
1138
  candidateSourceView = remoteView as UIView
1119
1139
  print("🖼️ [PiP] Found matching remote view for source")
1140
+ } else {
1141
+ // Fallback: Use ANY remote view that's rendering video
1142
+ if let anyRenderingView = remoteViews.compactMap({ $0.value }).first(where: { $0.isRenderingVideo }) {
1143
+ candidateSourceView = anyRenderingView as UIView
1144
+ print("🖼️ [PiP] Using fallback remote view (URN didn't match but view is rendering)")
1145
+ } else if let anyView = remoteViews.compactMap({ $0.value }).first {
1146
+ // Last resort: use any registered view
1147
+ candidateSourceView = anyView as UIView
1148
+ print("🖼️ [PiP] Using any available remote view as last resort")
1149
+ }
1120
1150
  }
1121
1151
 
1122
1152
  attachToDevice(imageDevice, sourceView: candidateSourceView)
1123
1153
  }
1124
1154
  } else {
1125
- // No candidate stream found
1155
+ // No candidate stream found - log why
1126
1156
  if currentPiPDevice == nil {
1127
1157
  print("🖼️ [PiP] No active remote video stream found yet")
1158
+ print("🖼️ [PiP] Total participants: \(participants.count)")
1159
+ for p in participants {
1160
+ print("🖼️ [PiP] Participant \(p.info.participantId ?? "nil"): \(p.streams.count) streams")
1161
+ for s in p.streams {
1162
+ print("🖼️ [PiP] Stream type: \(s.device.descriptor().type.rawValue), URN: \(s.device.descriptor().urn)")
1163
+ }
1164
+ }
1128
1165
  }
1129
1166
  }
1130
1167
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-realtime-ivs-broadcast",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "description": "An Expo module for real-time broadcasting using Amazon IVS.",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",