Adapt to latest sdk change related to conference + implemented joining spinner + refactored conference miniatures update

This commit is contained in:
Christophe Deschamps 2022-07-11 20:51:51 +02:00
parent 5040e6dae9
commit ec70c161f3
5 changed files with 188 additions and 112 deletions

View file

@ -26,11 +26,14 @@ class ConferenceParticipantDeviceData {
let isMe:Bool
let videoEnabled = MutableLiveData<Bool>()
let activeSpeaker = MutableLiveData<Bool>()
let isSpeaking = MutableLiveData<Bool>()
let micMuted = MutableLiveData<Bool>()
let isInConference = MutableLiveData<Bool>()
let isJoining = MutableLiveData<Bool>()
var core : Core { get { Core.get() } }
private var participantDeviceDelegate : ParticipantDeviceDelegate?
@ -41,19 +44,22 @@ class ConferenceParticipantDeviceData {
participantDeviceDelegate = ParticipantDeviceDelegateStub(
onIsSpeakingChanged: { (participantDevice, isSpeaking) in
Log.i("[Conference Participant Device] Participant \(participantDevice.address?.asStringUriOnly()) isspeaking = \(isSpeaking)")
self.activeSpeaker.value = isSpeaking
self.isSpeaking.value = isSpeaking
},
onIsMuted: { (participantDevice, isMuted) in
Log.i("[Conference Participant Device] Participant \(participantDevice.address?.asStringUriOnly()) muted = \(isMuted)")
self.micMuted.value = isMuted
},
onConferenceJoined: { (participantDevice) in
Log.i("[Conference Participant Device] Participant \(participantDevice.address?.asStringUriOnly()) has joined the conference")
self.isInConference.value = true
},
onConferenceLeft: { (participantDevice) in
Log.i("[Conference Participant Device] Participant \(participantDevice.address?.asStringUriOnly()) has left the conference")
self.isInConference.value = false
onStateChanged: { (participantDevice, state) in
Log.i("[Conference Participant Device] Participant \(participantDevice.address?.asStringUriOnly()) state has changed: \(state)")
if ([.Joining,.Alerting].contains(state)) {
self.isJoining.value = true
} else if (state == .OnHold) {
self.isInConference.value = false
} else if (state == .Present) {
self.isJoining.value = false
self.isInConference.value = true
}
},
onStreamCapabilityChanged: { (participantDevice, direction, streamType) in
Log.i("[Conference Participant Device] Participant \(participantDevice.address?.asStringUriOnly()) video stream direction changed: \(direction)")
@ -72,7 +78,7 @@ class ConferenceParticipantDeviceData {
)
participantDevice.addDelegate(delegate: participantDeviceDelegate!)
activeSpeaker.value = false
isSpeaking.value = false
micMuted.value = participantDevice.isMuted
videoEnabled.value = participantDevice.getStreamAvailability(streamType: .Video)
@ -90,7 +96,7 @@ class ConferenceParticipantDeviceData {
func clearObservers() {
isInConference.clearObservers()
videoEnabled.clearObservers()
activeSpeaker.clearObservers()
isSpeaking.clearObservers()
}
func switchCamera() {

View file

@ -97,16 +97,16 @@ class ConferenceViewModel {
Log.w("[Conference] Failed to find participant [\(participant.address!.asStringUriOnly())] in conferenceParticipants list")
}
},
onParticipantDeviceLeft: { (conference: Conference, device: ParticipantDevice) in
onParticipantDeviceStateChanged: { (conference: Conference, device: ParticipantDevice, state: ParticipantDeviceState) in
if (conference.isMe(uri: device.address!)) {
Log.i("[Conference] Left conference")
self.isConferenceLocallyPaused.value = true
}
},
onParticipantDeviceJoined: { (conference: Conference, device: ParticipantDevice) in
if (conference.isMe(uri: device.address!)) {
Log.i("[Conference] Joined conference")
self.isConferenceLocallyPaused.value = false
if (state == .Present) {
Log.i("[Conference] Entered conference")
self.isConferenceLocallyPaused.value = false
}
if (state == .OnHold) {
Log.i("[Conference] Left conference")
self.isConferenceLocallyPaused.value = true
}
}
},
onStateChanged: { (conference: Conference, state: Conference.State) in

View file

@ -32,39 +32,31 @@ class VoipActiveSpeakerParticipantCell: UICollectionViewCell {
let switch_camera_button_size = 30
static let mute_size = 25
let mute_margin = 5
let videoView = UIView()
let avatar = Avatar(diameter:VoipActiveSpeakerParticipantCell.avatar_size,color:VoipTheme.voipBackgroundColor, textStyle: VoipTheme.call_generated_avatar_medium)
let pause = UIImageView(image: UIImage(named: "voip_pause")?.tinted(with: .white))
let switchCamera = UIImageView(image: UIImage(named:"voip_change_camera")?.tinted(with:.white))
let displayName = StyledLabel(VoipTheme.conference_participant_name_font_as)
let pauseLabel = StyledLabel(VoipTheme.conference_participant_name_font_as,VoipTexts.conference_participant_paused)
let muted = MicMuted(VoipActiveSpeakerParticipantCell.mute_size)
let joining = RotatingSpinner()
var participantData: ConferenceParticipantDeviceData? = nil {
didSet {
if let data = participantData {
self.updateElements()
data.isJoining.clearObservers()
data.isJoining.observe { _ in
self.updateElements()
}
data.isInConference.clearObservers()
data.isInConference.readCurrentAndObserve { (isIn) in
self.updateBackground()
self.pause.isHidden = isIn == true
self.pauseLabel.isHidden = self.pause.isHidden
self.videoView.isHidden = data.videoEnabled.value != true
self.switchCamera.isHidden = data.videoEnabled.value != true || !data.isSwitchCameraAvailable()
data.isInConference.observe { _ in
self.updateElements()
}
data.videoEnabled.clearObservers()
data.videoEnabled.readCurrentAndObserve { (videoEnabled) in
self.updateBackground()
if (videoEnabled == true) {
self.videoView.isHidden = false
data.setVideoView(view: self.videoView)
self.avatar.isHidden = true
} else {
self.videoView.isHidden = true
self.avatar.isHidden = false
}
self.switchCamera.isHidden = videoEnabled != true || !data.isSwitchCameraAvailable()
data.videoEnabled.observe { _ in
self.updateElements()
}
data.participantDevice.address.map {
avatar.fillFromAddress(address: $0)
@ -72,32 +64,60 @@ class VoipActiveSpeakerParticipantCell: UICollectionViewCell {
self.displayName.text = displayName
}
}
data.activeSpeaker.clearObservers()
data.activeSpeaker.readCurrentAndObserve { (active) in
if (active == true) {
self.layer.borderWidth = 2
} else {
self.layer.borderWidth = 0
}
data.isSpeaking.clearObservers()
data.isSpeaking.observe { _ in
self.updateElements(skipVideo: true)
}
data.micMuted.clearObservers()
data.micMuted.readCurrentAndObserve { (muted) in
self.muted.isHidden = muted != true
data.micMuted.observe { _ in
self.updateElements(skipVideo: true)
}
}
}
}
func updateBackground() {
func updateElements(skipVideo:Bool = false) {
if let data = participantData {
if (data.isInConference.value != true) {
// Background
if (data.isInConference.value != true && data.isJoining.value != true) {
self.contentView.backgroundColor = VoipTheme.voip_conference_participant_paused_background
} else if (data.videoEnabled.value == true) {
self.contentView.backgroundColor = .black
} else {
self.contentView.backgroundColor = VoipTheme.voipParticipantBackgroundColor.get()
}
// Avatar
self.avatar.isHidden = (data.isInConference.value != true && data.isJoining.value != true) || data.videoEnabled.value == true
// Video
if (!skipVideo) {
self.videoView.isHidden = data.isInConference.value != true || data.videoEnabled.value != true
if (!self.videoView.isHidden) {
data.setVideoView(view: self.videoView)
}
self.switchCamera.isHidden = self.videoView.isHidden || !data.isSwitchCameraAvailable()
}
// Pause
self.pause.isHidden = data.isInConference.value == true || data.isJoining.value == true
// Border for active speaker
self.layer.borderWidth = data.isSpeaking.value == true ? 2 : 0
// Joining indicator
if (data.isJoining.value == true) {
self.joining.isHidden = false
self.joining.startRotation()
} else {
self.joining.isHidden = true
self.joining.stopRotation()
}
// Muted
self.muted.isHidden = data.micMuted.value != true
}
}
@ -130,14 +150,13 @@ class VoipActiveSpeakerParticipantCell: UICollectionViewCell {
contentView.addSubview(displayName)
displayName.matchParentSideBorders(insetedByDx:ActiveCallView.bottom_displayname_margin_left).alignParentBottom(withMargin:ActiveCallView.bottom_displayname_margin_bottom).done()
// Paused label commented out as in Android 10.06.2022
// contentView.addSubview(pauseLabel)
//pauseLabel.toRightOf(displayName).alignParentBottom(withMargin:ActiveCallView.bottom_displayname_margin_bottom).done()
contentView.addSubview(muted)
muted.alignParentLeft(withMargin: mute_margin).alignParentTop(withMargin:mute_margin).done()
contentView.addSubview(joining)
joining.square(VoipActiveSpeakerParticipantCell.mute_size).alignParentTop(withMargin: mute_margin).alignParentLeft(withMargin: mute_margin).done()
contentView.matchParentDimmensions().done()
makeHeightMatchWidth().done()

View file

@ -36,43 +36,68 @@ class VoipAudioOnlyParticipantCell: UICollectionViewCell {
let avatar = Avatar(diameter:VoipCallCell.avatar_size,color:VoipTheme.voipBackgroundColor, textStyle: VoipTheme.call_generated_avatar_small)
let paused = UIImageView(image: UIImage(named: "voip_pause")?.tinted(with: .white))
let muted = MicMuted(VoipAudioOnlyParticipantCell.mute_size)
let joining = RotatingSpinner()
let displayName = StyledLabel(VoipTheme.conference_participant_name_font_as)
var participantData: ConferenceParticipantDeviceData? = nil {
didSet {
if let data = participantData {
self.displayName.text = ""
self.updateElements()
data.isJoining.clearObservers()
data.isJoining.observe { _ in
self.updateElements()
}
data.isInConference.clearObservers()
data.isInConference.readCurrentAndObserve { (isIn) in
self.avatar.isHidden = isIn != true
self.paused.isHidden = isIn == true
data.participantDevice.address.map {
self.avatar.fillFromAddress(address: $0)
if let displayName = $0.addressBookEnhancedDisplayName() {
self.displayName.text = displayName + (isIn == true ? "" : " \(VoipTexts.conference_participant_paused)")
}
data.isInConference.observe { _ in
self.updateElements()
}
data.participantDevice.address.map {
avatar.fillFromAddress(address: $0)
if let displayName = $0.addressBookEnhancedDisplayName() {
self.displayName.text = displayName
}
}
if (data.participantDevice.address == nil) {
avatar.isHidden = true
}
data.activeSpeaker.clearObservers()
data.activeSpeaker.readCurrentAndObserve { (active) in
if (active == true) {
self.layer.borderWidth = 2
} else {
self.layer.borderWidth = 0
}
data.isSpeaking.clearObservers()
data.isSpeaking.observe { _ in
self.updateElements(skipVideo: true)
}
data.micMuted.clearObservers()
data.micMuted.readCurrentAndObserve { (muted) in
self.muted.isHidden = muted != true
data.micMuted.observe { _ in
self.updateElements(skipVideo: true)
}
}
}
}
func updateElements(skipVideo:Bool = false) {
if let data = participantData {
// Avatar
self.avatar.isHidden = data.isInConference.value != true && data.isJoining.value != true
// Pause
self.paused.isHidden = data.isInConference.value == true || data.isJoining.value == true
// Border for active speaker
self.layer.borderWidth = data.isSpeaking.value == true ? 2 : 0
// Joining indicator
if (data.isJoining.value == true) {
self.joining.isHidden = false
self.joining.startRotation()
} else {
self.joining.isHidden = true
self.joining.stopRotation()
}
// Muted
self.muted.isHidden = data.micMuted.value != true
}
}
override init(frame:CGRect) {
super.init(frame:.zero)
@ -98,6 +123,10 @@ class VoipAudioOnlyParticipantCell: UICollectionViewCell {
contentView.addSubview(muted)
muted.alignParentRight(withMargin: common_margin).toRightOf(displayName,withLeftMargin: common_margin).centerY().done()
contentView.addSubview(joining)
joining.alignParentRight(withMargin: common_margin).toRightOf(displayName,withLeftMargin: common_margin).centerY().done()
}
required init?(coder: NSCoder) {

View file

@ -42,67 +42,85 @@ class VoipGridParticipantCell: UICollectionViewCell {
let displayName = StyledLabel(VoipTheme.conference_participant_name_font_grid)
let pauseLabel = StyledLabel(VoipTheme.conference_participant_name_font_grid,VoipTexts.conference_participant_paused)
let muted = MicMuted(VoipActiveSpeakerParticipantCell.mute_size)
let joining = RotatingSpinner()
var participantData: ConferenceParticipantDeviceData? = nil {
didSet {
if let data = participantData {
self.updateElements()
data.isJoining.clearObservers()
data.isJoining.observe { _ in
self.updateElements()
}
data.isInConference.clearObservers()
data.isInConference.readCurrentAndObserve { (isIn) in
self.updateBackground()
self.pause.isHidden = isIn == true
self.pauseLabel.isHidden = self.pause.isHidden
self.videoView.isHidden = data.videoEnabled.value != true
self.switchCamera.isHidden = data.videoEnabled.value != true || !data.isSwitchCameraAvailable()
data.isInConference.observe { _ in
self.updateElements()
}
data.videoEnabled.clearObservers()
data.videoEnabled.readCurrentAndObserve { (videoEnabled) in
self.updateBackground()
if (videoEnabled == true) {
self.videoView.isHidden = false
data.setVideoView(view: self.videoView)
self.avatar.isHidden = true
} else {
self.videoView.isHidden = true
self.avatar.isHidden = false
}
self.switchCamera.isHidden = videoEnabled != true || !data.isSwitchCameraAvailable()
data.videoEnabled.observe { _ in
self.updateElements()
}
if (data.participantDevice.address == nil) {
avatar.isHidden = true
}
self.displayName.text = ""
data.participantDevice.address.map {
avatar.fillFromAddress(address: $0)
if let displayName = $0.addressBookEnhancedDisplayName() {
self.displayName.text = displayName
}
}
data.activeSpeaker.clearObservers()
data.activeSpeaker.readCurrentAndObserve { (active) in
if (active == true) {
self.layer.borderWidth = 2
} else {
self.layer.borderWidth = 0
}
data.isSpeaking.clearObservers()
data.isSpeaking.observe { _ in
self.updateElements(skipVideo: true)
}
data.micMuted.clearObservers()
data.micMuted.readCurrentAndObserve { (muted) in
self.muted.isHidden = muted != true
data.micMuted.observe { _ in
self.updateElements(skipVideo: true)
}
}
}
}
func updateBackground() {
func updateElements(skipVideo:Bool = false) {
if let data = participantData {
if (data.isInConference.value != true) {
// Background
if (data.isInConference.value != true && data.isJoining.value != true) {
self.contentView.backgroundColor = VoipTheme.voip_conference_participant_paused_background
} else if (data.videoEnabled.value == true) {
self.contentView.backgroundColor = .black
} else {
self.contentView.backgroundColor = VoipTheme.voipParticipantBackgroundColor.get()
}
// Avatar
self.avatar.isHidden = (data.isInConference.value != true && data.isJoining.value != true) || data.videoEnabled.value == true
// Video
if (!skipVideo) {
self.videoView.isHidden = data.isInConference.value != true || data.videoEnabled.value != true
if (!self.videoView.isHidden) {
data.setVideoView(view: self.videoView)
}
self.switchCamera.isHidden = self.videoView.isHidden || !data.isSwitchCameraAvailable()
}
// Pause
self.pause.isHidden = data.isInConference.value == true || data.isJoining.value == true
self.pauseLabel.isHidden = self.pause.isHidden
// Border for active speaker
self.layer.borderWidth = data.isSpeaking.value == true ? 2 : 0
// Joining indicator
if (data.isJoining.value == true) {
self.joining.isHidden = false
self.joining.startRotation()
} else {
self.joining.isHidden = true
self.joining.stopRotation()
}
// Muted
self.muted.isHidden = data.micMuted.value != true
}
}
@ -142,6 +160,10 @@ class VoipGridParticipantCell: UICollectionViewCell {
contentView.addSubview(muted)
muted.alignParentLeft(withMargin: mute_margin).alignParentTop(withMargin:mute_margin).done()
contentView.addSubview(joining)
joining.square(VoipActiveSpeakerParticipantCell.mute_size).alignParentTop(withMargin: mute_margin).alignParentLeft(withMargin: mute_margin).done()
contentView.matchParentDimmensions().done()
}