Skip to content

Commit 644dd02

Browse files
committed
fix UI
1 parent 6dc92aa commit 644dd02

File tree

11 files changed

+136
-58
lines changed

11 files changed

+136
-58
lines changed

Sources/EaseCallUIKit/Classes/CoreService/Implements/CallKitManager+RTC.swift

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -638,24 +638,16 @@ extension CallKitManager: AgoraRtcEngineDelegate {
638638
}
639639

640640
public func rtcEngine(_ engine: AgoraRtcEngineKit, reportAudioVolumeIndicationOfSpeakers speakers: [AgoraRtcAudioVolumeInfo], totalVolume: Int) {//On audio volume indication change of speakers
641-
if let call = self.callInfo {
642-
if call.type == .groupCall {// Only handle audio volume indication in multi call
643-
var speakerInfos = [UInt:UInt]()
644-
for speaker in speakers {
645-
speakerInfos[speaker.uid] = speaker.volume
646-
}
647-
let uids = speakers.map { NSNumber(value: $0.uid) }
648-
ChatClient.shared().getUserId(byRTCUIds: uids) { [weak self] relations, error in
649-
guard let `self` = self else { return }
650-
if error == nil {
651-
let relationships = relations ?? [:]
652-
for ship in relationships {
653-
if let streamView = self.canvasCache[ship.value],streamView.item.uid == UInt32(truncating: ship.key) {
654-
streamView.updateAudioVolume(speakerInfos[UInt(streamView.item.uid)] ?? 0)
641+
DispatchQueue.main.async {
642+
if let call = self.callInfo {
643+
if call.type == .groupCall {// Only handle audio volume indication in multi call
644+
for speaker in speakers {
645+
if let item = self.itemsCache.values.first(where: { $0.uid == speaker.uid }) {
646+
let streamView = self.canvasCache[item.userId]
647+
if item.uid == speaker.uid {
648+
streamView?.updateAudioVolume(speaker.volume)
655649
}
656650
}
657-
} else {
658-
consoleLogInfo("Failed to get userId by RTC UIDs: \(error?.errorDescription ?? "Unknown error")", type: .error)
659651
}
660652
}
661653
}

Sources/EaseCallUIKit/Classes/CoreService/Implements/CallKitManager.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ public let CallKitVersion = "1.0.0"
166166
}
167167
self.engine?.enableAudio()
168168
self.engine?.enable(inEarMonitoring: true)
169-
self.engine?.enableAudioVolumeIndication(618, smooth: 10, reportVad: true)
169+
self.engine?.enableAudioVolumeIndication(618, smooth: 5, reportVad: true)
170170
self.engine?.setDefaultAudioRouteToSpeakerphone(true)
171171
self.engine?.setVideoFrameDelegate(self)
172172
return nil
653 Bytes
Loading
952 Bytes
Loading

Sources/EaseCallUIKit/Classes/UI/Cells/GroupParticipantsCell.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,11 @@ import UIKit
4848
self.nickName.text = nickName
4949
self.nickName.font = UIFont.callTheme.labelLarge
5050
self.avatar.image(with: profile.avatarURL, placeHolder: CallAppearance.avatarPlaceHolder)
51-
self.checkbox.image = UIImage(named: profile.selected ? "select":"unselect", in: .callBundle, compatibleWith: nil)
51+
if let user = CallKitManager.shared.itemsCache[profile.id] {
52+
self.checkbox.image = UIImage(named: "already_seleted", in: .callBundle, compatibleWith: nil)
53+
} else {
54+
self.checkbox.image = UIImage(named: profile.selected ? "select":"unselect", in: .callBundle, compatibleWith: nil)
55+
}
5256
self.separatorLine.backgroundColor = Theme.style == .dark ? UIColor.callTheme.neutralColor2:UIColor.callTheme.neutralColor9
5357
}
5458

Sources/EaseCallUIKit/Classes/UI/Controllers/Call1v1VideoViewController.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,7 @@ extension Call1v1VideoViewController: AVPictureInPictureControllerDelegate {
674674
UIApplication.shared.call.keyWindow?.rootViewController?.present(existingVC, animated: true) {
675675
// 将floatView恢复到existingVC
676676
existingVC.ensureFloatViewVisible()
677+
existingVC.floatViewClicked(dragView: existingVC.floatView)
677678
completionHandler(true)
678679
}
679680
} else {
@@ -683,6 +684,7 @@ extension Call1v1VideoViewController: AVPictureInPictureControllerDelegate {
683684
UIApplication.shared.call.keyWindow?.rootViewController?.present(self, animated: true) {
684685
// 恢复floatView
685686
self.ensureFloatViewVisible()
687+
self.floatViewClicked(dragView: self.floatView)
686688
completionHandler(true)
687689
}
688690
}

Sources/EaseCallUIKit/Classes/UI/Controllers/MultiCallParticipantsController.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,6 @@ import UIKit
162162
}))
163163
}
164164
self.participants.removeAll { $0.id == ChatClient.shared().currentUsername ?? "" }
165-
self.participants.removeAll { self.excludeUsers.contains($0.id) }
166165
DispatchQueue.main.async {
167166
self.participantsList.reloadData()
168167
}
@@ -202,6 +201,9 @@ extension MultiCallParticipantsController: UITableViewDelegate,UITableViewDataSo
202201

203202
@objc open func didSelectRowAt(indexPath: IndexPath) {
204203
if let profile = self.participants[safely: indexPath.row] {
204+
if let user = CallKitManager.shared.itemsCache[profile.id] {
205+
return
206+
}
205207
profile.selected = !profile.selected
206208
self.participantsList.reloadData()
207209
}

Sources/EaseCallUIKit/Classes/UI/Views/Call1v1BottomView.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,7 @@ public class Call1v1BottomView: UIView {
371371
// MARK: - Actions
372372
private func handleButtonTap(_ sender: CallButtonView) {
373373
// Haptic feedback
374-
UIImpactFeedbackGenerator.impactOccurred(style: .light)
374+
UIImpactFeedbackGenerator.impactOccurred(style: .medium)
375375
print("tag: \(sender.buttonTag)")
376376

377377
guard let data = sender.data, let buttonType = self.getActionType(for: data, button: sender) else { return }

Sources/EaseCallUIKit/Classes/UI/Views/CallStreamView.swift

Lines changed: 71 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public class CallStreamView: UIImageView {
2121
private let loadingView = UIImageView().contentMode(.scaleAspectFit)
2222
public let userInfoView = UserInfoView()
2323

24-
var displayMode: UserInfoDisplayMode = .all {
24+
var displayMode: UserInfoDisplayMode = .nameOnly {
2525
didSet {
2626
userInfoView.displayMode = displayMode
2727
if self.item.isExpanded {
@@ -215,7 +215,26 @@ public class CallStreamView: UIImageView {
215215
}
216216

217217
func updateAudioVolume(_ volume: UInt) {
218-
self.userInfoView.isSpeaking = volume > 10 // Adjust threshold as needed
218+
if self.item.waiting {
219+
return
220+
}
221+
// 设置说话状态
222+
self.userInfoView.isSpeaking = volume > 0
223+
224+
// 根据音量动态调整显示模式
225+
if volume > 0 && !self.item.audioMuted {
226+
// 有音量且未静音时,显示音频图标
227+
if self.userInfoView.displayMode == .nameOnly {
228+
self.userInfoView.displayMode = .all
229+
}
230+
} else if volume == 0 && !self.item.audioMuted {
231+
// 无音量且未静音时,隐藏音频图标(仅显示昵称)
232+
if self.userInfoView.displayMode == .all {
233+
self.userInfoView.displayMode = .nameOnly
234+
}
235+
}
236+
237+
// 清理覆盖视图
219238
coverView.isHidden = true
220239
coverView.removeFromSuperview()
221240
}
@@ -289,6 +308,15 @@ public class CallStreamItem: NSObject {
289308
}
290309

291310
}
311+
// MARK: - User Info Component
312+
// MARK: - Display Mode
313+
public enum UserInfoDisplayMode {
314+
case all // 显示昵称和按钮
315+
case nameOnly // 只显示昵称
316+
case buttonsOnly // 只显示按钮
317+
case hidden // 完全隐藏
318+
}
319+
292320
// MARK: - User Info Component
293321
public class UserInfoView: UIView {
294322

@@ -300,7 +328,7 @@ public class UserInfoView: UIView {
300328
private var containerTrailingConstraint: NSLayoutConstraint?
301329
private var nicknameLabelWidthConstraint: NSLayoutConstraint?
302330

303-
var displayMode: UserInfoDisplayMode = .all {
331+
var displayMode: UserInfoDisplayMode = .nameOnly {
304332
didSet {
305333
updateDisplayMode()
306334
}
@@ -318,13 +346,35 @@ public class UserInfoView: UIView {
318346
}
319347
}
320348

321-
var isSpeaking: Bool = false {
349+
@MainActor var isSpeaking: Bool = false {
322350
didSet {
323-
if isSpeaking,!isAudioMuted {
351+
if isSpeaking && !isAudioMuted {
352+
// 正在说话且未静音时显示说话图标
324353
audioButton.setImage(UIImage(named: "speaking", in: .callBundle, with: nil), for: .normal)
354+
audioButton.isHidden = false
355+
356+
// 动态更新约束以显示音频按钮
357+
containerStackView.spacing = 6
358+
setNeedsUpdateConstraints()
359+
360+
} else if !isSpeaking && !isAudioMuted {
361+
// 不说话且未静音时清空图标
362+
audioButton.setImage(nil, for: .normal)
363+
audioButton.isHidden = true
364+
365+
// 动态更新约束以隐藏音频按钮
366+
containerStackView.spacing = 0
367+
setNeedsUpdateConstraints()
368+
325369
} else {
370+
// 静音状态保持原有逻辑
326371
updateAudioButton()
327372
}
373+
374+
// 触发布局更新
375+
invalidateIntrinsicContentSize()
376+
setNeedsLayout()
377+
layoutIfNeeded()
328378
}
329379
}
330380

@@ -405,7 +455,7 @@ public class UserInfoView: UIView {
405455
if isAudioMuted {
406456
audioButton.setImage(UIImage(systemName: "mic.slash.fill"), for: .normal)
407457
} else {
408-
audioButton.setImage(UIImage(systemName: "mic.fill"), for: .normal)
458+
audioButton.setImage(nil, for: .normal)
409459
}
410460
}
411461

@@ -421,6 +471,16 @@ public class UserInfoView: UIView {
421471
containerStackView.spacing = 6
422472
nicknameLabelWidthConstraint?.constant = 80
423473

474+
case .nameOnly:
475+
// 只显示昵称,隐藏音频按钮
476+
nicknameLabel.isHidden = false
477+
audioButton.isHidden = true
478+
self.isHidden = false
479+
480+
// 移除间距,因为没有按钮
481+
containerStackView.spacing = 0
482+
nicknameLabelWidthConstraint?.constant = 80
483+
424484
case .buttonsOnly:
425485
// 只显示按钮
426486
nicknameLabel.isHidden = true
@@ -438,7 +498,6 @@ public class UserInfoView: UIView {
438498
// 触发布局更新
439499
setNeedsLayout()
440500
layoutIfNeeded()
441-
442501
}
443502

444503
// 重写 intrinsicContentSize 以支持自动布局
@@ -460,13 +519,6 @@ public class UserInfoView: UIView {
460519
}
461520
}
462521

463-
// MARK: - Display Mode
464-
public enum UserInfoDisplayMode {
465-
case all // 显示昵称和按钮
466-
case buttonsOnly // 只显示按钮
467-
case hidden // 完全隐藏
468-
}
469-
470522
// MARK: - 便利方法
471523
extension UserInfoView {
472524

@@ -485,6 +537,11 @@ extension UserInfoView {
485537
let nicknameWidth = min(nicknameLabel.intrinsicContentSize.width, 80)
486538
return 6 + nicknameWidth + 6 + 16 + 6 // padding + nickname + spacing + button + padding
487539

540+
case .nameOnly:
541+
// 只有昵称,没有音频按钮
542+
let nicknameWidth = min(nicknameLabel.intrinsicContentSize.width, 80)
543+
return 6 + nicknameWidth + 6 // padding + nickname + padding
544+
488545
case .buttonsOnly:
489546
return 6 + 16 + 6 // padding + button + padding
490547

@@ -505,21 +562,3 @@ extension UserInfoView {
505562
})
506563
}
507564
}
508-
509-
// MARK: - 调试辅助
510-
#if DEBUG
511-
extension UserInfoView {
512-
513-
/// 添加边框以便调试
514-
public func enableDebugMode() {
515-
layer.borderWidth = 1
516-
layer.borderColor = UIColor.red.cgColor
517-
518-
nicknameLabel.layer.borderWidth = 0.5
519-
nicknameLabel.layer.borderColor = UIColor.green.cgColor
520-
521-
audioButton.layer.borderWidth = 0.5
522-
audioButton.layer.borderColor = UIColor.blue.cgColor
523-
}
524-
}
525-
#endif

Sources/EaseCallUIKit/Classes/UI/Views/MultiCallBottomView.swift

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,24 +35,42 @@ public class MultiCallBottomView: UIView {
3535

3636
public var didTapButton: ((CallButtonType) -> Void)?
3737
public var animationToExpand: (() -> Void)?
38+
3839
// 添加属性来控制按钮的启用状态
3940
public var isCallConnected: Bool = false {
4041
didSet {
4142
updateButtonsInteractionState()
4243
}
4344
}
4445

46+
// 添加属性来跟踪摄像头状态
47+
private var isCameraOn: Bool = true {
48+
didSet {
49+
updateFlipButtonState()
50+
}
51+
}
52+
4553
// 添加需要在通话接通后才能使用的按钮索引
4654
private let requiresConnectionButtonIndexes = [3] // Camera 按钮
4755

56+
// 更新Flip按钮状态(基于Camera状态)
57+
private func updateFlipButtonState() {
58+
guard buttonViews.count > 0 else { return }
59+
let flipButton = buttonViews[0] // Flip按钮是第一个
60+
// flipButton.isUserInteractionEnabled = isCameraOn
61+
flipButton.alpha = isCameraOn ? 1.0 : 0.5
62+
}
63+
4864
// 更新按钮交互状态
4965
private func updateButtonsInteractionState() {
5066
for (index, buttonView) in buttonViews.enumerated() {
5167
if requiresConnectionButtonIndexes.contains(index) {
52-
buttonView.isUserInteractionEnabled = isCallConnected
68+
// buttonView.isUserInteractionEnabled = isCallConnected
5369
buttonView.alpha = isCallConnected ? 1.0 : 0.5 // 视觉提示
5470
}
5571
}
72+
// 同时更新Flip按钮状态
73+
updateFlipButtonState()
5674
}
5775

5876
override init(frame: CGRect) {
@@ -129,17 +147,29 @@ public class MultiCallBottomView: UIView {
129147
buttonView.didTap = { [weak self] button in
130148
guard let self = self else { return }
131149

150+
// 检查Flip按钮是否因Camera关闭而不可用
151+
if button.tag == 0 && !self.isCameraOn {
152+
self.shakeButton(button)
153+
return
154+
}
155+
132156
// 检查按钮是否需要通话接通
133157
if self.requiresConnectionButtonIndexes.contains(button.tag) && !self.isCallConnected {
134158
// 提供视觉反馈但不执行操作
135159
self.shakeButton(button)
136160
return
137161
}
138162

139-
UIImpactFeedbackGenerator.impactOccurred(style: .light)
163+
UIImpactFeedbackGenerator.impactOccurred(style: .medium)
140164
if let buttonData = button.data {
141165
buttonData.isSelected.toggle()
142166
buttonView.configure(data: buttonData)
167+
168+
// 如果是Camera按钮,更新摄像头状态
169+
if button.tag == 3 {
170+
self.isCameraOn = !buttonData.isSelected // isSelected为true表示camera_off状态
171+
}
172+
143173
if let buttonType = self.getActionType(for: buttonData, button: button) {
144174
self.didTapButton?(buttonType)
145175
}
@@ -149,10 +179,14 @@ public class MultiCallBottomView: UIView {
149179
addSubview(buttonView)
150180
buttonViews.append(buttonView)
151181
}
182+
183+
// 初始化Flip按钮状态
184+
updateFlipButtonState()
152185
}
153186

154187
// 添加摇晃动画提示按钮不可用
155188
private func shakeButton(_ button: UIView) {
189+
UIImpactFeedbackGenerator.impactOccurred(style: .medium)
156190
let animation = CAKeyframeAnimation(keyPath: "transform.translation.x")
157191
animation.timingFunction = CAMediaTimingFunction(name: .linear)
158192
animation.duration = 0.4
@@ -376,11 +410,16 @@ public class MultiCallBottomView: UIView {
376410
if let data = buttonView.data {
377411
data.isSelected.toggle()
378412
buttonView.configure(data: data)
413+
414+
// 如果是Camera按钮,更新摄像头状态
415+
if selectedIndex == 3 {
416+
isCameraOn = !data.isSelected
417+
}
418+
379419
// 执行对应的操作
380420
if let actionType = getActionType(for: data, button: buttonView) {
381421
didTapButton?(actionType)
382422
}
383423
}
384-
385424
}
386425
}

0 commit comments

Comments
 (0)