-
Notifications
You must be signed in to change notification settings - Fork 12
/
VTUXConferenceController.swift
164 lines (139 loc) · 6.43 KB
/
VTUXConferenceController.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
//
// VTUXConferenceController.swift
// VoxeetUXKit
//
// Created by Corentin Larroque on 05/08/2019.
// Copyright © 2019 Voxeet. All rights reserved.
//
import VoxeetSDK
@objc public class VTUXConferenceController: NSObject {
private var viewController: ConferenceViewController?
private var currentStatus: VTConferenceStatus?
private var previousStatus: VTConferenceStatus?
/// Conference configuration.
@objc public var configuration = VTUXConferenceControllerConfiguration()
/// Conference appear animation default starts maximized. If false, the conference will appear minimized.
@objc public var appearMaximized = true
/// If true, the conference will behave like a cellular call. if a participant hangs up or declines a call, the caller will be disconnected.
@objc public var telecom = false {
didSet {
if telecom {
NotificationCenter.default.addObserver(self, selector: #selector(participantUpdated), name: .VTParticipantUpdated, object: nil)
} else {
NotificationCenter.default.removeObserver(self, name: .VTParticipantUpdated, object: nil)
}
}
}
/// Enable or disable the mirror effect for all `VTVideoView`s. Setting the value to `nil` enables an automatic mirror effect.
public var isVideoViewMirrorEffect: Bool? = nil {
didSet {
let isMirrorEffect = isVideoViewMirrorEffect
DispatchQueue.main.async { [weak self] in
self?.viewController?.ownVideoRenderer.isMirrorEffect = isMirrorEffect
self?.viewController?.speakerVideoVC.videoRenderer.isMirrorEffect = isMirrorEffect
self?.viewController?.participantsVC.reload()
}
}
}
public override init() {
super.init()
// Voxeet's socket notifications.
NotificationCenter.default.addObserver(self, selector: #selector(ownParticipantSwitched), name: .VTOwnParticipantSwitched, object: nil)
// Conference status notifications.
NotificationCenter.default.addObserver(self, selector: #selector(conferenceStatusUpdated), name: .VTConferenceStatusUpdated, object: nil)
}
@objc public func maximize() {
viewController?.maximize()
}
@objc public func minimize() {
viewController?.minimize()
}
}
/*
* MARK: - Notifications: Voxeet
*/
extension VTUXConferenceController {
@objc private func participantUpdated(notification: NSNotification) {
// Get participant.
guard let participant = notification.userInfo?["participant"] as? VTParticipant else {
return
}
// Debug.
print("[VoxeetUXKit] \(String(describing: VoxeetUXKit.self)).\(#function).\(#line)")
// Stop conference if a participant declines or leaves it.
if participant.status == .decline || participant.status == .left {
// Update conference state label.
if participant.status == .decline {
self.viewController?.conferenceStateLabel.text = VTUXLocalized.string("VTUX_CONFERENCE_STATE_DECLINED")
}
// Leave current conference.
VoxeetSDK.shared.conference.leave()
}
}
@objc private func ownParticipantSwitched(notification: NSNotification) {
// Debug.
print("[VoxeetUXKit] \(String(describing: VoxeetUXKit.self)).\(#function).\(#line)")
// Stop the current conference.
VoxeetSDK.shared.conference.leave()
}
}
/*
* MARK: - Notifications: conference status
*/
extension VTUXConferenceController {
@objc private func conferenceStatusUpdated(notification: NSNotification) {
guard let rawStatus = notification.userInfo?["status"] as? Int,
let status = VTConferenceStatus(rawValue: rawStatus) else {
return
}
// Save current conference status.
currentStatus = status
switch status {
case .creating, .joining:
// Properly remove the viewController from superview when joining
// if the previous conference status wasn't one of the expected (`created`, `joined`).
if status == .joining, ![VTConferenceStatus.created, .joined].contains(previousStatus) {
// Remove conference view from superview.
self.viewController?.view.removeFromSuperview()
self.viewController = nil
}
// Create and show conference view.
if viewController == nil {
// Create conference UI and adds it to the window.
let storyboard = UIStoryboard(name: "VoxeetUXKit", bundle: .module)
viewController = storyboard.instantiateInitialViewController() as? ConferenceViewController
if let vc = viewController {
vc.view.accessibilityIdentifier = "ConferenceView"
vc.view.translatesAutoresizingMaskIntoConstraints = false
guard let window = UIApplication.keyWindow else { return }
window.addSubview(vc.view)
}
// Show conference.
if appearMaximized {
viewController?.show()
} else {
viewController?.view.alpha = 0
viewController?.minimize(animated: false)
UIView.animate(withDuration: 0.25) {
self.viewController?.view.alpha = 1
}
}
}
case .left, .destroyed, .error:
// Hide conference.
viewController?.hide {
// Only remove the viewController from superview if the initial operation was intended for (during the hidding animation, another conference could be joined and we shouldn't call the code below in that case).
if self.currentStatus == .left || self.currentStatus == .destroyed || self.currentStatus == .error {
// Remove conference view from superview.
self.viewController?.view.removeFromSuperview()
self.viewController = nil
}
}
default: break
}
// Update conference UI.
viewController?.updateConferenceStatus(status)
// Save previous conference status.
previousStatus = status
}
}