Audio/video call statistics
|
|
@ -95,6 +95,7 @@
|
|||
D78290BB2ADD40B2004AA85C /* ContactViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D78290BA2ADD40B2004AA85C /* ContactViewModel.swift */; };
|
||||
D783C77C2B1089B200622CC2 /* assistant_linphone_default_values in Resources */ = {isa = PBXBuildFile; fileRef = D783C77A2B1089B200622CC2 /* assistant_linphone_default_values */; };
|
||||
D783C77D2B1089B200622CC2 /* assistant_third_party_default_values in Resources */ = {isa = PBXBuildFile; fileRef = D783C77B2B1089B200622CC2 /* assistant_third_party_default_values */; };
|
||||
D78E06282BE3811D00CE3783 /* CallStatsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D78E06272BE3811D00CE3783 /* CallStatsModel.swift */; };
|
||||
D79622342B1DFE600037EACD /* DialerBottomSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = D79622332B1DFE600037EACD /* DialerBottomSheet.swift */; };
|
||||
D796F2002B0BB61A0041115F /* ToastViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D796F1FF2B0BB61A0041115F /* ToastViewModel.swift */; };
|
||||
D7A03FBD2ACC2DB60081A588 /* ContactsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7A03FBC2ACC2DB60081A588 /* ContactsView.swift */; };
|
||||
|
|
@ -248,6 +249,7 @@
|
|||
D78290BA2ADD40B2004AA85C /* ContactViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactViewModel.swift; sourceTree = "<group>"; };
|
||||
D783C77A2B1089B200622CC2 /* assistant_linphone_default_values */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = assistant_linphone_default_values; sourceTree = "<group>"; };
|
||||
D783C77B2B1089B200622CC2 /* assistant_third_party_default_values */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = assistant_third_party_default_values; sourceTree = "<group>"; };
|
||||
D78E06272BE3811D00CE3783 /* CallStatsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallStatsModel.swift; sourceTree = "<group>"; };
|
||||
D79622332B1DFE600037EACD /* DialerBottomSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DialerBottomSheet.swift; sourceTree = "<group>"; };
|
||||
D796F1FF2B0BB61A0041115F /* ToastViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToastViewModel.swift; sourceTree = "<group>"; };
|
||||
D7A03FBC2ACC2DB60081A588 /* ContactsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactsView.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -526,6 +528,7 @@
|
|||
children = (
|
||||
D720E6AC2BAD822000DDFD87 /* ParticipantModel.swift */,
|
||||
D714035A2BE11E00004BD8CA /* CallMediaEncryptionModel.swift */,
|
||||
D78E06272BE3811D00CE3783 /* CallStatsModel.swift */,
|
||||
);
|
||||
path = Model;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -993,6 +996,7 @@
|
|||
D726E4392B16440C0083C415 /* ContactAvatarModel.swift in Sources */,
|
||||
6613A0B02BAEB7F4008923A4 /* MeetingsListFragment.swift in Sources */,
|
||||
D76005F62B0798B00054B79A /* IntExtension.swift in Sources */,
|
||||
D78E06282BE3811D00CE3783 /* CallStatsModel.swift in Sources */,
|
||||
D7E6D0512AEBDBD500A57AAF /* ContactsListBottomSheet.swift in Sources */,
|
||||
D75759322B56D40900E7AC10 /* ZRTPPopup.swift in Sources */,
|
||||
D7A2EDD62AC18115005D90FC /* SharedMainViewModel.swift in Sources */,
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="#4e6074" viewBox="0 0 256 256"><path d="M168,72V200a8,8,0,0,1-16,0V72a8,8,0,0,1,16,0Zm32-48a8,8,0,0,0-8,8V200a8,8,0,0,0,16,0V32A8,8,0,0,0,200,24Zm-80,80a8,8,0,0,0-8,8v88a8,8,0,0,0,16,0V112A8,8,0,0,0,120,104ZM80,144a8,8,0,0,0-8,8v48a8,8,0,0,0,16,0V152A8,8,0,0,0,80,144ZM40,184a8,8,0,0,0-8,8v8a8,8,0,0,0,16,0v-8A8,8,0,0,0,40,184Z"></path></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M168,72V200a8,8,0,0,1-16,0V72a8,8,0,0,1,16,0Zm32-48a8,8,0,0,0-8,8V200a8,8,0,0,0,16,0V32A8,8,0,0,0,200,24Zm-80,80a8,8,0,0,0-8,8v88a8,8,0,0,0,16,0V112A8,8,0,0,0,120,104ZM80,144a8,8,0,0,0-8,8v48a8,8,0,0,0,16,0V152A8,8,0,0,0,80,144ZM40,184a8,8,0,0,0-8,8v8a8,8,0,0,0,16,0v-8A8,8,0,0,0,40,184Z"></path></svg>
|
||||
|
Before Width: | Height: | Size: 411 B After Width: | Height: | Size: 411 B |
21
Linphone/Assets.xcassets/cell-signal-high.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "cell-signal-high.svg",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
1
Linphone/Assets.xcassets/cell-signal-high.imageset/cell-signal-high.svg
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M168,72V200a8,8,0,0,1-16,0V72a8,8,0,0,1,16,0Zm-48,32a8,8,0,0,0-8,8v88a8,8,0,0,0,16,0V112A8,8,0,0,0,120,104ZM80,144a8,8,0,0,0-8,8v48a8,8,0,0,0,16,0V152A8,8,0,0,0,80,144ZM40,184a8,8,0,0,0-8,8v8a8,8,0,0,0,16,0v-8A8,8,0,0,0,40,184Z"></path></svg>
|
||||
|
After Width: | Height: | Size: 351 B |
|
|
@ -1 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="#4e6074" viewBox="0 0 256 256"><path d="M88,152v48a8,8,0,0,1-16,0V152a8,8,0,0,1,16,0ZM40,184a8,8,0,0,0-8,8v8a8,8,0,0,0,16,0v-8A8,8,0,0,0,40,184Z"></path></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M88,152v48a8,8,0,0,1-16,0V152a8,8,0,0,1,16,0ZM40,184a8,8,0,0,0-8,8v8a8,8,0,0,0,16,0v-8A8,8,0,0,0,40,184Z"></path></svg>
|
||||
|
Before Width: | Height: | Size: 228 B After Width: | Height: | Size: 228 B |
21
Linphone/Assets.xcassets/cell-signal-medium.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "cell-signal-medium.svg",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
1
Linphone/Assets.xcassets/cell-signal-medium.imageset/cell-signal-medium.svg
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M128,112v88a8,8,0,0,1-16,0V112a8,8,0,0,1,16,0ZM80,144a8,8,0,0,0-8,8v48a8,8,0,0,0,16,0V152A8,8,0,0,0,80,144ZM40,184a8,8,0,0,0-8,8v8a8,8,0,0,0,16,0v-8A8,8,0,0,0,40,184Z"></path></svg>
|
||||
|
After Width: | Height: | Size: 290 B |
21
Linphone/Assets.xcassets/cell-signal-none.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "cell-signal-none.svg",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
1
Linphone/Assets.xcassets/cell-signal-none.imageset/cell-signal-none.svg
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M48,192v8a8,8,0,0,1-16,0v-8a8,8,0,0,1,16,0Z"></path></svg>
|
||||
|
After Width: | Height: | Size: 167 B |
|
|
@ -221,6 +221,9 @@
|
|||
},
|
||||
"Attended transfer" : {
|
||||
|
||||
},
|
||||
"Audio" : {
|
||||
|
||||
},
|
||||
"Audio seulement" : {
|
||||
|
||||
|
|
@ -806,6 +809,9 @@
|
|||
},
|
||||
"Validate the device" : {
|
||||
|
||||
},
|
||||
"Vidéo" : {
|
||||
|
||||
},
|
||||
"Video Call" : {
|
||||
|
||||
|
|
|
|||
|
|
@ -398,7 +398,6 @@ class TelecomManager: ObservableObject {
|
|||
} else {
|
||||
self.remoteConfVideo = false
|
||||
}
|
||||
|
||||
} else {
|
||||
self.remoteConfVideo = false
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ struct CallView: View {
|
|||
@State var audioRouteSheet: Bool = false
|
||||
@State var changeLayoutSheet: Bool = false
|
||||
@State var mediaEncryptedSheet: Bool = false
|
||||
@State var callStatisticsSheet: Bool = false
|
||||
@State var optionsAudioRoute: Int = 1
|
||||
@State var optionsChangeLayout: Int = 2
|
||||
@State var imageAudioRoute: String = ""
|
||||
|
|
@ -71,6 +72,12 @@ struct CallView: View {
|
|||
mediaEncryptedSheetBottomSheet()
|
||||
.presentationDetents([.medium])
|
||||
}
|
||||
.sheet(isPresented: $callStatisticsSheet, onDismiss: {
|
||||
callStatisticsSheet = false
|
||||
}) {
|
||||
callStatisticsSheetBottomSheet()
|
||||
.presentationDetents(!callViewModel.callStatsModel.isVideoEnabled ? [.fraction(0.3)] : [.medium])
|
||||
}
|
||||
.sheet(isPresented: $audioRouteSheet, onDismiss: {
|
||||
audioRouteSheet = false
|
||||
}) {
|
||||
|
|
@ -100,6 +107,12 @@ struct CallView: View {
|
|||
mediaEncryptedSheetBottomSheet()
|
||||
.presentationDetents([.medium])
|
||||
}
|
||||
.sheet(isPresented: $callStatisticsSheet, onDismiss: {
|
||||
callStatisticsSheet = false
|
||||
}) {
|
||||
callStatisticsSheetBottomSheet()
|
||||
.presentationDetents(!callViewModel.callStatsModel.isVideoEnabled ? [.fraction(0.3)] : [.medium])
|
||||
}
|
||||
.sheet(isPresented: $audioRouteSheet, onDismiss: {
|
||||
audioRouteSheet = false
|
||||
}) {
|
||||
|
|
@ -127,6 +140,11 @@ struct CallView: View {
|
|||
} onDismiss: {
|
||||
mediaEncryptedSheet = false
|
||||
}
|
||||
.halfSheet(showSheet: $callStatisticsSheet) {
|
||||
callStatisticsSheetBottomSheet()
|
||||
} onDismiss: {
|
||||
callStatisticsSheet = false
|
||||
}
|
||||
.halfSheet(showSheet: $audioRouteSheet) {
|
||||
audioRouteBottomSheet()
|
||||
} onDismiss: {
|
||||
|
|
@ -263,6 +281,74 @@ struct CallView: View {
|
|||
.background(Color.gray600)
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
func callStatisticsSheetBottomSheet() -> some View {
|
||||
VStack {
|
||||
if idiom != .pad && (orientation == .landscapeLeft
|
||||
|| orientation == .landscapeRight
|
||||
|| UIScreen.main.bounds.size.width > UIScreen.main.bounds.size.height) {
|
||||
Spacer()
|
||||
HStack {
|
||||
Spacer()
|
||||
Button("Close") {
|
||||
mediaEncryptedSheet = false
|
||||
}
|
||||
}
|
||||
.padding(.trailing)
|
||||
} else {
|
||||
Capsule()
|
||||
.fill(Color.grayMain2c300)
|
||||
.frame(width: 75, height: 5)
|
||||
.padding(15)
|
||||
}
|
||||
|
||||
Text("Audio")
|
||||
.default_text_style_white_600(styleSize: 15)
|
||||
.padding(.top, 10)
|
||||
|
||||
Spacer()
|
||||
|
||||
Text(callViewModel.callStatsModel.audioCodec)
|
||||
.default_text_style_white(styleSize: 15)
|
||||
|
||||
Spacer()
|
||||
|
||||
Text(callViewModel.callStatsModel.audioBandwidth)
|
||||
.default_text_style_white(styleSize: 15)
|
||||
|
||||
Spacer()
|
||||
|
||||
if callViewModel.callStatsModel.isVideoEnabled {
|
||||
Text("Vidéo")
|
||||
.default_text_style_white_600(styleSize: 15)
|
||||
.padding(.top, 10)
|
||||
|
||||
Spacer()
|
||||
|
||||
Text(callViewModel.callStatsModel.videoCodec)
|
||||
.default_text_style_white(styleSize: 15)
|
||||
|
||||
Spacer()
|
||||
|
||||
Text(callViewModel.callStatsModel.videoBandwidth)
|
||||
.default_text_style_white(styleSize: 15)
|
||||
|
||||
Spacer()
|
||||
|
||||
Text(callViewModel.callStatsModel.videoResolution)
|
||||
.default_text_style_white(styleSize: 15)
|
||||
|
||||
Spacer()
|
||||
|
||||
Text(callViewModel.callStatsModel.videoFps)
|
||||
.default_text_style_white(styleSize: 15)
|
||||
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
.frame(maxWidth: .infinity)
|
||||
.background(Color.gray600)
|
||||
}
|
||||
@ViewBuilder
|
||||
func audioRouteBottomSheet() -> some View {
|
||||
VStack(spacing: 0) {
|
||||
|
|
@ -533,8 +619,9 @@ struct CallView: View {
|
|||
Spacer()
|
||||
|
||||
Button {
|
||||
callStatisticsSheet = true
|
||||
} label: {
|
||||
Image("cell-signal-full")
|
||||
Image(callViewModel.qualityIcon)
|
||||
.renderingMode(.template)
|
||||
.resizable()
|
||||
.foregroundStyle(.white)
|
||||
|
|
|
|||
|
|
@ -53,8 +53,6 @@ class CallMediaEncryptionModel: ObservableObject {
|
|||
mediaEncryptionTmp = "Media encryption: " + "ZRTP"
|
||||
case .DTLS:
|
||||
mediaEncryptionTmp = "Media encryption: " + "DTLS"
|
||||
default:
|
||||
mediaEncryptionTmp = "Media encryption: " + "None"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
85
Linphone/UI/Call/Model/CallStatsModel.swift
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2020 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-iphone
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
import linphonesw
|
||||
|
||||
class CallStatsModel: ObservableObject {
|
||||
var coreContext = CoreContext.shared
|
||||
|
||||
@Published var audioCodec = ""
|
||||
@Published var audioBandwidth = ""
|
||||
|
||||
@Published var isVideoEnabled = false
|
||||
@Published var videoCodec = ""
|
||||
@Published var videoBandwidth = ""
|
||||
@Published var videoResolution = ""
|
||||
@Published var videoFps = ""
|
||||
|
||||
func update(call: Call, stats: CallStats) {
|
||||
coreContext.doOnCoreQueue { core in
|
||||
if call.params != nil {
|
||||
self.isVideoEnabled = call.params!.videoEnabled && call.currentParams!.videoDirection != .Inactive
|
||||
switch stats.type {
|
||||
case .Audio:
|
||||
if call.currentParams != nil {
|
||||
let payloadType = call.currentParams!.usedAudioPayloadType
|
||||
let clockRate = (payloadType?.clockRate != nil ? payloadType!.clockRate : 0) / 1000
|
||||
let codecLabel = "Codec: " + "\(payloadType != nil ? payloadType!.mimeType : "")/\(clockRate) kHz"
|
||||
|
||||
let uploadBandwidth = Int(stats.uploadBandwidth.rounded())
|
||||
let downloadBandwidth = Int(stats.downloadBandwidth.rounded())
|
||||
let bandwidthLabel = "Bandwidth: " + "↑ \(uploadBandwidth) kbits/s ↓ \(downloadBandwidth) kbits/s"
|
||||
|
||||
DispatchQueue.main.async {
|
||||
self.audioCodec = codecLabel
|
||||
self.audioBandwidth = bandwidthLabel
|
||||
}
|
||||
}
|
||||
case .Video:
|
||||
if call.currentParams != nil {
|
||||
let payloadType = call.currentParams!.usedVideoPayloadType
|
||||
let clockRate = (payloadType?.clockRate != nil ? payloadType!.clockRate : 0) / 1000
|
||||
let codecLabel = "Codec: " + "\(payloadType!.mimeType)/\(clockRate) kHz"
|
||||
|
||||
let uploadBandwidth = Int(stats.uploadBandwidth.rounded())
|
||||
let downloadBandwidth = Int(stats.downloadBandwidth.rounded())
|
||||
let bandwidthLabel = "Bandwidth: " + "↑ \(uploadBandwidth) kbits/s ↓ \(downloadBandwidth) kbits/s"
|
||||
|
||||
let sentResolution = call.currentParams!.sentVideoDefinition!.name
|
||||
let receivedResolution = call.currentParams!.receivedVideoDefinition!.name
|
||||
let resolutionLabel = "Resolution: " + "↑ \(sentResolution!) ↓ \(receivedResolution!)"
|
||||
|
||||
let sentFps = Int(call.currentParams!.sentFramerate.rounded())
|
||||
let receivedFps = Int(call.currentParams!.receivedFramerate.rounded())
|
||||
let fpsLabel = "FPS: " + "↑ \(sentFps) ↓ \(receivedFps)"
|
||||
|
||||
DispatchQueue.main.async {
|
||||
self.videoCodec = codecLabel
|
||||
self.videoBandwidth = bandwidthLabel
|
||||
self.videoResolution = resolutionLabel
|
||||
self.videoFps = fpsLabel
|
||||
}
|
||||
}
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -54,6 +54,10 @@ class CallViewModel: ObservableObject {
|
|||
@Published var activeSpeakerName: String = ""
|
||||
@Published var myParticipantModel: ParticipantModel?
|
||||
@Published var callMediaEncryptionModel = CallMediaEncryptionModel()
|
||||
@Published var callStatsModel = CallStatsModel()
|
||||
|
||||
@Published var qualityValue: Float = 0.0
|
||||
@Published var qualityIcon = "cell-signal-full"
|
||||
|
||||
private var mConferenceSuscriptions = Set<AnyCancellable?>()
|
||||
|
||||
|
|
@ -153,6 +157,9 @@ class CallViewModel: ObservableObject {
|
|||
|
||||
if self.currentCall != nil {
|
||||
self.callMediaEncryptionModel.update(call: self.currentCall!)
|
||||
if self.currentCall!.audioStats != nil {
|
||||
self.callStatsModel.update(call: self.currentCall!, stats: self.currentCall!.audioStats!)
|
||||
}
|
||||
}
|
||||
|
||||
DispatchQueue.main.async {
|
||||
|
|
@ -201,6 +208,14 @@ class CallViewModel: ObservableObject {
|
|||
self.callMediaEncryptionModel.update(call: self.currentCall!)
|
||||
}
|
||||
})
|
||||
|
||||
self.callSuscriptions.insert(self.currentCall!.publisher?.onStatsUpdated?.postOnMainQueue {(cbVal: (call: Call, stats: CallStats)) in
|
||||
if self.currentCall != nil {
|
||||
self.callStatsModel.update(call: self.currentCall!, stats: cbVal.stats)
|
||||
}
|
||||
})
|
||||
|
||||
self.updateCallQualityIcon()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -575,6 +590,7 @@ class CallViewModel: ObservableObject {
|
|||
if core.callsNb == 0 {
|
||||
DispatchQueue.main.async {
|
||||
self.timer.upstream.connect().cancel()
|
||||
self.currentCall = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -966,5 +982,32 @@ class CallViewModel: ObservableObject {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func updateCallQualityIcon() {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
|
||||
self.coreContext.doOnCoreQueue { core in
|
||||
if self.currentCall != nil {
|
||||
let quality = self.currentCall!.currentQuality
|
||||
let icon = switch floor(quality) {
|
||||
case 4, 5: "cell-signal-full"
|
||||
case 3: "cell-signal-high"
|
||||
case 2: "cell-signal-medium"
|
||||
case 1: "cell-signal-low"
|
||||
default: "cell-signal-none"
|
||||
}
|
||||
|
||||
print("iconiconicon \(icon) \(self.currentCall!.currentQuality)")
|
||||
DispatchQueue.main.async {
|
||||
self.qualityValue = quality
|
||||
self.qualityIcon = icon
|
||||
}
|
||||
|
||||
if core.callsNb > 0 {
|
||||
self.updateCallQualityIcon()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// swiftlint:enable type_body_length
|
||||
|
|
|
|||