@@ -62,7 +62,13 @@ open class CallMultiViewController: UIViewController {
6262 }
6363
6464 public private( set) var role : CallRole = . caller
65-
65+
66+ // 本地摄像头预览视图(未接听状态下使用)
67+ public var localPreviewView : PixelBufferRenderView ?
68+
69+ // 跟踪摄像头状态
70+ public var isCameraPreviewEnabled : Bool = false
71+
6672 @objc public init ( role: CallRole ) {
6773 self . role = role
6874 super. init ( nibName: nil , bundle: nil )
@@ -88,7 +94,8 @@ open class CallMultiViewController: UIViewController {
8894 } else {
8995 self . bottomView. isCallConnected = false
9096 }
91- self . bottomView. updateButtonSelectedStatus ( selectedIndex: 3 )
97+ // 初始化时不触发回调,只更新按钮状态
98+ self . bottomView. updateButtonSelectedStatus ( selectedIndex: 3 , triggerCallback: false )
9299 self . callView. isHidden = !state
93100 // Do any additional setup after loading the view.
94101 self . setupNavigationState ( )
@@ -99,7 +106,6 @@ open class CallMultiViewController: UIViewController {
99106 self . bottomView. didTapButton = { [ weak self] in
100107 self ? . bottomClick ( type: $0)
101108 }
102- CallKitManager . shared. enableLocalVideo ( false )
103109 }
104110
105111 func updateNavigationBar( ) {
@@ -122,6 +128,11 @@ open class CallMultiViewController: UIViewController {
122128
123129 func updateBottomState( ) {
124130 if self . connected {
131+ // 连接成功后移除预览视图
132+ self . removeLocalPreview ( )
133+ self . isCameraPreviewEnabled = false
134+
135+ // 原有逻辑
125136 self . callView. isHidden = !self . connected
126137 self . bottomView. animateToExpandedState ( )
127138 self . bottomView. isCallConnected = true
@@ -168,7 +179,6 @@ open class CallMultiViewController: UIViewController {
168179 }
169180
170181 @objc open func bottomClick( type: CallButtonType ) {
171-
172182 switch type {
173183 case . mic_on:
174184 guard let currentUserId = ChatClient . shared ( ) . currentUsername, let item = CallKitManager . shared. itemsCache [ currentUserId] , let canvas = CallKitManager . shared. canvasCache [ currentUserId] else {
@@ -189,22 +199,39 @@ open class CallMultiViewController: UIViewController {
189199 case . flip_back: CallKitManager . shared. switchCamera ( )
190200 case . flip_front: CallKitManager . shared. switchCamera ( )
191201 case . camera_on:
192- guard let currentUserId = ChatClient . shared ( ) . currentUsername, let item = CallKitManager . shared. itemsCache [ currentUserId] , let canvas = CallKitManager . shared. canvasCache [ currentUserId] else {
193- consoleLogInfo ( " CallMultiViewController: Current user not found in items cache. " , type: . error)
194- return
202+ if !self . connected {
203+ // 未连接状态:显示全屏预览
204+ self . setupLocalPreview ( )
205+ CallKitManager . shared. setupLocalVideo ( )
206+ CallKitManager . shared. enableLocalVideo ( true )
207+ self . isCameraPreviewEnabled = true
208+ } else {
209+ // 已连接状态:正常处理(保持现有逻辑)
210+ guard let currentUserId = ChatClient . shared ( ) . currentUsername, let item = CallKitManager . shared. itemsCache [ currentUserId] , let canvas = CallKitManager . shared. canvasCache [ currentUserId] else {
211+ consoleLogInfo ( " CallMultiViewController: Current user not found in items cache. " , type: . error)
212+ return
213+ }
214+ CallKitManager . shared. setupLocalVideo ( )
215+ CallKitManager . shared. enableLocalVideo ( true )
216+ item. videoMuted = false
217+ canvas. updateItem ( item)
195218 }
196- CallKitManager . shared. setupLocalVideo ( )
197- CallKitManager . shared. enableLocalVideo ( true )
198- item. videoMuted = false
199- canvas. updateItem ( item)
200219 case . camera_off:
201- guard let currentUserId = ChatClient . shared ( ) . currentUsername, let item = CallKitManager . shared. itemsCache [ currentUserId] , let canvas = CallKitManager . shared. canvasCache [ currentUserId] else {
202- consoleLogInfo ( " CallMultiViewController: Current user not found in items cache. " , type: . error)
203- return
220+ if !self . connected {
221+ // 未连接状态:移除预览
222+ self . removeLocalPreview ( )
223+ CallKitManager . shared. enableLocalVideo ( false )
224+ self . isCameraPreviewEnabled = false
225+ } else {
226+ // 已连接状态:正常处理(保持现有逻辑)
227+ guard let currentUserId = ChatClient . shared ( ) . currentUsername, let item = CallKitManager . shared. itemsCache [ currentUserId] , let canvas = CallKitManager . shared. canvasCache [ currentUserId] else {
228+ consoleLogInfo ( " CallMultiViewController: Current user not found in items cache. " , type: . error)
229+ return
230+ }
231+ CallKitManager . shared. enableLocalVideo ( false )
232+ item. videoMuted = true
233+ canvas. updateItem ( item)
204234 }
205- CallKitManager . shared. enableLocalVideo ( false )
206- item. videoMuted = true
207- canvas. updateItem ( item)
208235 case . speaker_on:
209236 CallKitManager . shared. turnSpeakerOn ( on: true )
210237 case . speaker_off:
@@ -214,6 +241,13 @@ open class CallMultiViewController: UIViewController {
214241 self . dismiss ( animated: true , completion: nil )
215242 CallKitManager . shared. hangup ( )
216243 case . accept:
244+ // 保存摄像头开启状态(在移除预览前检查)
245+ let wasCameraOn = self . isCameraPreviewEnabled
246+
247+ // 接受通话前先移除预览视图
248+ self . removeLocalPreview ( )
249+ self . isCameraPreviewEnabled = false
250+
217251 if let call = CallKitManager . shared. callInfo {
218252 GlobalTimerManager . shared. registerListener ( self , timerIdentify: " call- \( call. channelName) -answering-timer " )
219253 GlobalTimerManager . shared. registerListener ( CallKitManager . shared, timerIdentify: " call- \( call. channelName) -answering-timer " )
@@ -228,6 +262,32 @@ open class CallMultiViewController: UIViewController {
228262 CallKitManager . shared. accept ( )
229263 }
230264 self . callView. isHidden = false
265+
266+ // 如果接听前摄像头是开启的,需要同步状态到 MultiPersonCallView
267+ if wasCameraOn {
268+ consoleLogInfo ( " CallMultiViewController: Camera was on before accept, restoring state... " , type: . debug)
269+
270+ // accept() 方法会调用 enableLocalVideo(false),需要立即覆盖
271+ CallKitManager . shared. setupLocalVideo ( )
272+ CallKitManager . shared. enableLocalVideo ( true )
273+
274+ // 延迟更新,确保 canvas 已创建并同步状态
275+ DispatchQueue . main. asyncAfter ( deadline: . now( ) + 0.5 ) { [ weak self] in
276+ guard let self = self else { return }
277+ if let currentUserId = ChatClient . shared ( ) . currentUsername {
278+ if let item = CallKitManager . shared. itemsCache [ currentUserId] ,
279+ let canvas = CallKitManager . shared. canvasCache [ currentUserId] {
280+ item. videoMuted = false
281+ canvas. updateItem ( item)
282+ // 触发 MultiPersonCallView 更新
283+ self . callView. updateWithItems ( )
284+ consoleLogInfo ( " CallMultiViewController: Camera state synced - userId= \( currentUserId) , videoMuted=false " , type: . debug)
285+ } else {
286+ consoleLogInfo ( " CallMultiViewController: Failed to sync camera state - item or canvas not found for userId= \( currentUserId) " , type: . error)
287+ }
288+ }
289+ }
290+ }
231291 case . end:
232292 if let call = CallKitManager . shared. callInfo {
233293 GlobalTimerManager . shared. removeListener ( self , timerIdentify: " call- \( call. channelName) -answering-timer " )
@@ -272,6 +332,9 @@ open class CallMultiViewController: UIViewController {
272332 }
273333
274334 open override func dismiss( animated flag: Bool , completion: ( ( ) -> Void ) ? = nil ) {
335+ // 页面关闭时清理预览
336+ self . removeLocalPreview ( )
337+ self . isCameraPreviewEnabled = false
275338 super. dismiss ( animated: flag, completion: completion)
276339 }
277340
@@ -353,6 +416,28 @@ open class CallMultiViewController: UIViewController {
353416 }
354417 }
355418 }
419+
420+ // 设置本地摄像头预览(全屏)
421+ private func setupLocalPreview( ) {
422+ guard localPreviewView == nil else { return }
423+
424+ let previewView = PixelBufferRenderView ( frame: self . view. bounds)
425+ previewView. backgroundColor = . clear
426+ previewView. userId = ChatClient . shared ( ) . currentUsername ?? " "
427+ previewView. dragEnable = false
428+ previewView. tag = 9999 // 特殊标记
429+
430+ // 插入到背景和 navigationBar 之间
431+ self . view. insertSubview ( previewView, aboveSubview: self . background)
432+
433+ self . localPreviewView = previewView
434+ }
435+
436+ // 移除本地摄像头预览
437+ private func removeLocalPreview( ) {
438+ localPreviewView? . removeFromSuperview ( )
439+ localPreviewView = nil
440+ }
356441}
357442
358443extension CallMultiViewController : TimerServiceListener {
0 commit comments