提交
This commit is contained in:
283
TUIKit/TUICallKit/TUICallKit-Swift/View/Root/GroupCallView.swift
Normal file
283
TUIKit/TUICallKit/TUICallKit-Swift/View/Root/GroupCallView.swift
Normal file
@@ -0,0 +1,283 @@
|
||||
//
|
||||
// GroupCallView.swift
|
||||
// TUICallKit
|
||||
//
|
||||
// Created by vincepzhang on 2023/1/6.
|
||||
//
|
||||
|
||||
class GroupCallView: UIView {
|
||||
|
||||
let selfCallStatusObserver = Observer()
|
||||
let mediaTypeObserver = Observer()
|
||||
private var isViewReady: Bool = false
|
||||
|
||||
let backgroundView = {
|
||||
return GroupBackgroundView(frame: CGRect.zero)
|
||||
}()
|
||||
|
||||
let maskedView = {
|
||||
let maskedView = UIView(frame: CGRect.zero)
|
||||
maskedView.backgroundColor = UIColor.t_colorWithHexString(color: "#22262E", alpha: 0.85)
|
||||
return maskedView
|
||||
}()
|
||||
|
||||
let layoutView = {
|
||||
return GroupCallVideoLayout(frame: CGRect.zero)
|
||||
}()
|
||||
|
||||
let floatingWindowBtn = {
|
||||
return FloatingWindowButton(frame: CGRect.zero)
|
||||
}()
|
||||
|
||||
let inviteUserButton = {
|
||||
return InviteUserButton(frame: CGRect.zero)
|
||||
}()
|
||||
|
||||
let inviterUserInfoView = {
|
||||
return GroupCallerUserInfoView(frame: CGRect.zero)
|
||||
}()
|
||||
|
||||
lazy var inviteeAvatarListView = {
|
||||
return InviteeAvatarListView(frame: CGRect.zero)
|
||||
}()
|
||||
|
||||
let waitingHintView = {
|
||||
return CallWaitingHintView(frame: CGRect.zero)
|
||||
}()
|
||||
|
||||
let functionView = {
|
||||
let height = groupFunctionViewHeight + 30.scaleWidth()
|
||||
return GroupCallerAndCalleeAcceptedView(frame: CGRect(x: 0, y: Screen_Height - height, width: Screen_Width, height: height))
|
||||
}()
|
||||
|
||||
let inviteeWaitFunctionView = {
|
||||
return AudioAndVideoCalleeWaitingView(frame: CGRect.zero)
|
||||
}()
|
||||
|
||||
let timerView: TimerView = {
|
||||
return TimerView(frame: CGRect.zero)
|
||||
}()
|
||||
|
||||
let callStatusTipLabel: UILabel = {
|
||||
let tipLabel = UILabel()
|
||||
tipLabel.font = UIFont.systemFont(ofSize: 15.0)
|
||||
tipLabel.textColor = UIColor.t_colorWithHexString(color: "#FFFFFF")
|
||||
tipLabel.textAlignment = .center
|
||||
tipLabel.text = TUICallKitLocalize(key: "TUICallKit.Group.waitAccept") ?? ""
|
||||
return tipLabel
|
||||
}()
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
self.frame = CGRect(x: 0, y: 0, width: Screen_Width, height: Screen_Height)
|
||||
backgroundColor = UIColor.t_colorWithHexString(color: "#303132")
|
||||
functionView.delegate = self
|
||||
createGroupCallView()
|
||||
registerObserveState()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
deinit {
|
||||
TUICallState.instance.selfUser.value.callStatus.removeObserver(selfCallStatusObserver)
|
||||
TUICallState.instance.mediaType.removeObserver(mediaTypeObserver)
|
||||
|
||||
for view in subviews {
|
||||
view.removeFromSuperview()
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: UI Specification Processing
|
||||
override func didMoveToWindow() {
|
||||
super.didMoveToWindow()
|
||||
if isViewReady { return }
|
||||
constructViewHierarchy()
|
||||
activateConstraints()
|
||||
isViewReady = true
|
||||
}
|
||||
|
||||
func constructViewHierarchy() {
|
||||
addSubview(backgroundView)
|
||||
addSubview(maskedView)
|
||||
addSubview(layoutView)
|
||||
addSubview(floatingWindowBtn)
|
||||
addSubview(inviteUserButton)
|
||||
addSubview(inviterUserInfoView)
|
||||
addSubview(waitingHintView)
|
||||
addSubview(functionView)
|
||||
addSubview(inviteeWaitFunctionView)
|
||||
addSubview(timerView)
|
||||
addSubview(callStatusTipLabel)
|
||||
}
|
||||
|
||||
func activateConstraints() {
|
||||
backgroundView.snp.makeConstraints { make in
|
||||
make.edges.equalTo(self)
|
||||
}
|
||||
maskedView.snp.makeConstraints { make in
|
||||
make.edges.equalTo(self)
|
||||
}
|
||||
layoutView.snp.makeConstraints { make in
|
||||
make.top.equalToSuperview().offset(StatusBar_Height + 48)
|
||||
make.centerX.equalTo(self)
|
||||
make.width.equalTo(Screen_Width)
|
||||
make.bottom.equalTo(functionView.snp.top)
|
||||
}
|
||||
floatingWindowBtn.snp.makeConstraints { make in
|
||||
make.top.equalToSuperview().offset(StatusBar_Height + 12.scaleHeight())
|
||||
make.leading.equalToSuperview().offset(12.scaleWidth())
|
||||
make.size.equalTo(kFloatWindowButtonSize)
|
||||
}
|
||||
inviteUserButton.snp.makeConstraints { make in
|
||||
make.size.equalTo(kInviteUserButtonSize)
|
||||
make.top.equalToSuperview().offset(StatusBar_Height + 12.scaleHeight())
|
||||
make.trailing.equalTo(snp.trailing).offset(-12.scaleWidth())
|
||||
}
|
||||
inviterUserInfoView.snp.makeConstraints { make in
|
||||
make.top.equalTo(self).offset(StatusBar_Height + 150.scaleHeight())
|
||||
make.leading.equalTo(self).offset(20)
|
||||
make.trailing.equalTo(self).offset(-20)
|
||||
make.height.equalTo(100.scaleWidth() + 30.scaleHeight() + 50)
|
||||
}
|
||||
inviteeWaitFunctionView.snp.makeConstraints({ make in
|
||||
make.centerX.equalTo(self)
|
||||
make.bottom.equalTo(self.snp.bottom).offset(-Bottom_SafeHeight - 40.scaleHeight())
|
||||
make.height.equalTo(60.scaleWidth() + 5.scaleHeight() + 20)
|
||||
make.width.equalTo(self.snp.width)
|
||||
})
|
||||
timerView.snp.makeConstraints { make in
|
||||
make.centerX.equalTo(self)
|
||||
make.centerY.equalTo(floatingWindowBtn)
|
||||
make.width.equalTo(200)
|
||||
make.height.equalTo(30)
|
||||
}
|
||||
callStatusTipLabel.snp.makeConstraints { make in
|
||||
make.edges.equalTo(timerView)
|
||||
}
|
||||
waitingHintView.snp.makeConstraints { make in
|
||||
make.centerX.equalTo(self)
|
||||
make.height.equalTo(20)
|
||||
make.width.equalTo(self)
|
||||
make.bottom.equalTo(self.timerView.snp.top)
|
||||
}
|
||||
}
|
||||
|
||||
func addInviteeAvatarListView() {
|
||||
maskedView.addSubview(inviteeAvatarListView)
|
||||
inviteeAvatarListView.snp.makeConstraints { make in
|
||||
make.centerX.equalTo(maskedView)
|
||||
make.width.equalTo(maskedView)
|
||||
make.height.equalTo(60 + 5.scaleWidth())
|
||||
make.top.equalTo(maskedView).offset(Screen_Height * 3 / 5)
|
||||
}
|
||||
}
|
||||
|
||||
func removeInviteeAvatarListView() {
|
||||
inviteeAvatarListView.removeFromSuperview()
|
||||
}
|
||||
|
||||
// MARK: View Create & Manage
|
||||
func createGroupCallView() {
|
||||
handleFloatingWindowBtn()
|
||||
|
||||
if TUICallState.instance.selfUser.value.callStatus.value == .waiting {
|
||||
if TUICallState.instance.selfUser.value.callRole.value == .call {
|
||||
createCallWaitingView()
|
||||
} else if TUICallState.instance.selfUser.value.callRole.value == .called {
|
||||
createCalledWaitingView()
|
||||
}
|
||||
} else if TUICallState.instance.selfUser.value.callStatus.value == .accept {
|
||||
createCallingView()
|
||||
}
|
||||
}
|
||||
|
||||
func handleFloatingWindowBtn() {
|
||||
if TUICallState.instance.enableFloatWindow {
|
||||
floatingWindowBtn.isHidden = false
|
||||
} else {
|
||||
floatingWindowBtn.isHidden = true
|
||||
}
|
||||
}
|
||||
|
||||
func createCallWaitingView() {
|
||||
hiddenChangeSubview()
|
||||
layoutView.isHidden = false
|
||||
inviteUserButton.isHidden = false
|
||||
functionView.isHidden = false
|
||||
callStatusTipLabel.isHidden = false
|
||||
waitingHintView.isHidden = TUICallState.instance.selfUser.value.callRole.value == .call ? true : false
|
||||
}
|
||||
|
||||
func createCalledWaitingView() {
|
||||
hiddenChangeSubview()
|
||||
inviterUserInfoView.isHidden = false
|
||||
inviteeWaitFunctionView.isHidden = false
|
||||
addInviteeAvatarListView()
|
||||
}
|
||||
|
||||
func createCallingView() {
|
||||
removeInviteeAvatarListView()
|
||||
hiddenChangeSubview()
|
||||
layoutView.isHidden = false
|
||||
inviteUserButton.isHidden = false
|
||||
functionView.isHidden = false
|
||||
timerView.isHidden = false
|
||||
}
|
||||
|
||||
func hiddenChangeSubview() {
|
||||
layoutView.isHidden = true
|
||||
inviteUserButton.isHidden = true
|
||||
inviterUserInfoView.isHidden = true
|
||||
functionView.isHidden = true
|
||||
inviteeWaitFunctionView.isHidden = true
|
||||
timerView.isHidden = true
|
||||
callStatusTipLabel.isHidden = true
|
||||
waitingHintView.isHidden = true
|
||||
}
|
||||
|
||||
// MARK: Register TUICallState Observer && Update UI
|
||||
func registerObserveState() {
|
||||
callStatusChanged()
|
||||
mediaTypeChanged()
|
||||
}
|
||||
|
||||
func callStatusChanged() {
|
||||
TUICallState.instance.selfUser.value.callStatus.addObserver(selfCallStatusObserver, closure: { [weak self] newValue, _ in
|
||||
guard let self = self else { return }
|
||||
self.createGroupCallView()
|
||||
})
|
||||
}
|
||||
|
||||
func mediaTypeChanged() {
|
||||
TUICallState.instance.mediaType.addObserver(mediaTypeObserver) { [weak self] newValue, _ in
|
||||
guard let self = self else { return }
|
||||
self.createGroupCallView()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension GroupCallView: GroupCallerAndCalleeAcceptedViewDelegate {
|
||||
|
||||
func showAnimation() {
|
||||
UIView.animate(withDuration: groupFunctionAnimationDuration) {
|
||||
self.functionView.frame = CGRect(x: 0,
|
||||
y: Screen_Height - groupSmallFunctionViewHeight,
|
||||
width: Screen_Width,
|
||||
height: groupSmallFunctionViewHeight)
|
||||
}
|
||||
}
|
||||
|
||||
func restoreExpansion() {
|
||||
UIView.animate(withDuration: groupFunctionAnimationDuration) {
|
||||
self.functionView.frame = CGRect(x: 0, y: Screen_Height - groupFunctionViewHeight, width: Screen_Width, height: groupFunctionViewHeight)
|
||||
}
|
||||
}
|
||||
|
||||
func handleTransform(animationScale: CGFloat) {
|
||||
let height = groupFunctionViewHeight - (groupFunctionViewHeight - groupSmallFunctionViewHeight) * animationScale
|
||||
self.functionView.frame = CGRect(x: 0, y: Screen_Height - height, width: Screen_Width, height: height)
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user