Skip to content

Commit

Permalink
Release/3.14 (#82) (#83)
Browse files Browse the repository at this point in the history
KitchenSink example
  • Loading branch information
urmitchauhan authored Nov 13, 2024
1 parent 6e77128 commit 3f5fd33
Show file tree
Hide file tree
Showing 11 changed files with 143 additions and 27 deletions.
8 changes: 4 additions & 4 deletions KitchenSink.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1834,7 +1834,7 @@
CODE_SIGN_ENTITLEMENTS = KitchenSink/KitchenSink.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 3130;
CURRENT_PROJECT_VERSION = 3140;
DEVELOPMENT_TEAM = 9X38D433RE;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
Expand All @@ -1857,7 +1857,7 @@
"@executable_path/Frameworks",
executable_path/Frameworks,
);
MARKETING_VERSION = 3.13;
MARKETING_VERSION = 3.14;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.webex.sdk.KitchenSinkv3.0;
Expand Down Expand Up @@ -1894,7 +1894,7 @@
CODE_SIGN_ENTITLEMENTS = KitchenSink/KitchenSink.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 3130;
CURRENT_PROJECT_VERSION = 3140;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = 9X38D433RE;
ENABLE_BITCODE = NO;
Expand All @@ -1913,7 +1913,7 @@
"@executable_path/Frameworks",
executable_path/Frameworks,
);
MARKETING_VERSION = 3.13;
MARKETING_VERSION = 3.14;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.webex.sdk.KitchenSinkv3.0;
PRODUCT_NAME = "$(TARGET_NAME)";
Expand Down
4 changes: 4 additions & 0 deletions KitchenSink/Controllers/LoginViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,10 @@ class LoginViewController: UIViewController {
self?.loginButton.isEnabled = true
print("Login failed!")
UserDefaults.standard.removeObject(forKey: Constants.emailKey)

let alert = UIAlertController(title: "Error", message: result.rawValue, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self?.present(alert, animated: true, completion: nil)
return
}
UserDefaults.standard.setValue(Constants.loginTypeValue.email.rawValue, forKey: Constants.loginTypeKey)
Expand Down
24 changes: 23 additions & 1 deletion KitchenSink/NewUI/ViewModels/CallViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ class CallViewModel: ObservableObject
@Published var showDTMFControl = false
@Published var placeholderText1 = ""
@Published var placeholderText2 = ""
@Published var speechEnhancement = false
let renderModes: [Call.VideoRenderMode] = [.fit, .cropFill, .stretchFill]
let flashModes: [Call.FlashMode] = [.on, .off, .auto]
let torchModes: [Call.TorchMode] = [.on, .off, .auto]
Expand Down Expand Up @@ -835,6 +836,7 @@ class CallViewModel: ObservableObject
self?.canControlWXA = call.canControlWXA
self?.isClosedCaptionAllowed = call.isClosedCaptionAllowed
self?.isClosedCaptionEnabled = call.isClosedCaptionEnabled
self?.speechEnhancement = call.isSpeechEnhancementEnabled
}
self.updateNameLabels(connected: call.isConnected)
}
Expand Down Expand Up @@ -888,7 +890,27 @@ class CallViewModel: ObservableObject
self?.currentCall?.receivingScreenShare = isOn
}
}


// Handles Speech Enhancement for the call.
func handleSpeechEnhancement(isOn: Bool) {
if isOn == self.speechEnhancement {
return
}
self.currentCall?.enableSpeechEnhancement(shouldEnable: isOn, completionHandler: { result in
switch result
{
case .success():
DispatchQueue.main.async { [weak self] in
self?.speechEnhancement.toggle()
}
case .failure(let err):
DispatchQueue.main.async { [weak self] in
self?.showError("Speech Enhancement Error ", err.localizedDescription)
}
}
})
}

// Handles EndCall Action.
func handleEndCall()
{
Expand Down
14 changes: 9 additions & 5 deletions KitchenSink/NewUI/ViewModels/LoginViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -70,17 +70,21 @@ class LoginViewModel: ObservableObject {
webex = Webex(authenticator: authenticator)
loadingIndicator(show: true)
guard let redirectUri = self.getRedirectUri() else { return }
self.webexAuthenticator.getAuthorizationUrl(authenticator: authenticator, completion: { url in
guard let url = url else {
self.webexAuthenticator.getAuthorizationUrl(authenticator: authenticator) { result, url in
if result == .success, let url = url {
self.link = url
self.redirectUri = redirectUri
self.showWebView = true
}
else {
self.showErrorAlert = true
self.alertErrorMessage = "Invalid email"
self.alertErrorMessage = result.rawValue
self.loadingIndicator(show: false)
return
}
self.link = url
self.redirectUri = redirectUri
self.showWebView = true
})
}
}

/// Logs in using the authentication code.
Expand Down
35 changes: 34 additions & 1 deletion KitchenSink/NewUI/ViewModels/SettingsViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ class SettingsViewModel: ObservableObject {
@Published var enableBackgroundConnection = false
@Published var isAuxiliaryMode = false
@Published var enable1080pVideo = false
@Published var useLegacyNoiseRemoval = false
@Published var enableSpeechEnhancement = false
@Published var showError: Bool = false
@Published var error: String = ""
@Published var videoStreamModeLabel = ""

var webexAuthenticator = WebexAuthenticator()
Expand All @@ -31,6 +35,14 @@ class SettingsViewModel: ObservableObject {
self.mailVM = mailVM
}

/// Asynchronously displays an error message on the main queue.
func showError(error: Error) {
DispatchQueue.main.async {
self.showError = true
self.error = error.localizedDescription
}
}

/// Fetches and updates the version of the Webex SDK and the build version of the application.
func updateVersion() {
let bundleVersion = Bundle.main.infoDictionary!["CFBundleVersion"] as! String
Expand Down Expand Up @@ -78,8 +90,9 @@ class SettingsViewModel: ObservableObject {
isStartCallWithVideoOn = UserDefaults.standard.bool(forKey: "hasVideo")
isAuxiliaryMode = UserDefaults.standard.bool(forKey: "compositeMode")
enable1080pVideo = UserDefaults.standard.bool(forKey: "VideoRes1080p")
enable1080pVideo = UserDefaults.standard.bool(forKey: "VideoRes1080p")
enableBackgroundConnection = UserDefaults.standard.bool(forKey: "backgroundConnection")
useLegacyNoiseRemoval = UserDefaults.standard.bool(forKey: "legacyNoiseRemoval")
enableSpeechEnhancement = webexPhone.isSpeechEnhancementEnabled
}

func updateStartCallWithVideoOn() {
Expand Down Expand Up @@ -116,4 +129,24 @@ class SettingsViewModel: ObservableObject {
webexPhone.enableBackgroundConnection = false
}
}

func updateUseLegacyNoiseRemoval() {
useLegacyNoiseRemoval.toggle()
webexPhone.useLegacyReceiverNoiseRemoval(useLegacy: useLegacyNoiseRemoval)
UserDefaults.standard.setValue(useLegacyNoiseRemoval, forKey: "legacyNoiseRemoval")
}

func updateSpeechEnhancementEnabled() {
enableSpeechEnhancement.toggle()
webexPhone.enableSpeechEnhancement(shouldEnable: enableSpeechEnhancement, completionHandler: { result in
switch result {
case .success():
self.enableSpeechEnhancement.toggle()
case .failure(let err):
DispatchQueue.main.async {
self.showError(error: err)
}
}
})
}
}
12 changes: 12 additions & 0 deletions KitchenSink/NewUI/Views/MoreOptionsCallView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ struct MoreOptionsCallView: View {
@State private var receivingVideo = false
@State private var receivingAudio = false
@State private var receivingScreenShare = false
@State private var speechEnhancement = false
//@State private var isVirtualBGListPresent = false
@State private var externalCamera = false
var isVirtualBGListPresent: Bool {
Expand Down Expand Up @@ -69,6 +70,17 @@ struct MoreOptionsCallView: View {
}
}
.accessibilityIdentifier("receivingScreenShareToggle")

Toggle("Speech Enhancement ", isOn: $speechEnhancement)
.onChange(of: speechEnhancement) { newValue in
callingVM.handleSpeechEnhancement(isOn: newValue)
}
.onReceive(callingVM.$speechEnhancement) { newValue in
if newValue != speechEnhancement {
speechEnhancement = newValue
}
}
.accessibilityIdentifier("speechEnhancementToggle")
}

if callingVM.isCUCMOrWxcCall {
Expand Down
23 changes: 22 additions & 1 deletion KitchenSink/NewUI/Views/SettingsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ struct SettingsView: View {
@State private var alertTitle = ""
@State private var isPhoneServicesOn = false
@State private var showSetupView = false
@State private var isSpeechEnhancementEnabled: Bool = true

@Environment(\.dismiss) var dismiss

Expand Down Expand Up @@ -72,7 +73,21 @@ struct SettingsView: View {
}.onTapGesture {
model.updateStartCallWithVideoOn()
}


HStack {
Toggle("Use Legacy Noise Removal", isOn: $model.useLegacyNoiseRemoval)
.accessibilityIdentifier("isSpeechEnhancementEnabled")
}.onTapGesture {
model.updateUseLegacyNoiseRemoval()
}

HStack {
Toggle("Enable Speech Enhancement", isOn: $model.enableSpeechEnhancement)
.accessibilityIdentifier("isSpeechEnhancementEnabled")
}.onTapGesture {
model.updateSpeechEnhancementEnabled()
}

HStack {
Toggle("Auxiliary Mode", isOn: $model.isAuxiliaryMode)
.accessibilityIdentifier("auxiliaryMode")
Expand Down Expand Up @@ -156,6 +171,12 @@ struct SettingsView: View {
.foregroundColor(.secondary)
}
}// nav
.alert("Error", isPresented: $model.showError) {
Button("Ok") { }
.accessibilityIdentifier("errorOkButton")
} message: {
Text(model.error)
}
.alert("Could Not Send Email", isPresented: $mailSentFailAlert) {
Button("Ok") {}
} message: {
Expand Down
12 changes: 3 additions & 9 deletions KitchenSink/NewUI/Webex/WebexAuthenticator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import WebexSDK

protocol OAuthAuthenticationProtocol: AnyObject {
func getOAuthAuthenticator(email: String, isFedRAMP: Bool) -> OAuthAuthenticator?
func getAuthorizationUrl(authenticator: OAuthAuthenticator, completion: @escaping ((URL?) -> Void))
func getAuthorizationUrl(authenticator: OAuthAuthenticator, completion: @escaping ((OAuthResult, URL?) -> Void))
func loginWithAuthCode(code: String, completion: @escaping (Bool) -> Void)
}

Expand Down Expand Up @@ -65,14 +65,8 @@ extension WebexAuthenticator : OAuthAuthenticationProtocol {
}

/// Retrieves the authorization URL.
func getAuthorizationUrl(authenticator: OAuthAuthenticator, completion: @escaping ((URL?) -> Void)) {
authenticator.getAuthorizationUrl(completionHandler: { result, url in
if result == .success {
completion(url)
} else {
completion(nil)
}
})
func getAuthorizationUrl(authenticator: OAuthAuthenticator, completion: @escaping ((OAuthResult, URL?) -> Void)) {
authenticator.getAuthorizationUrl(completionHandler: completion)
}

/// Login the user using an authorization code.
Expand Down
14 changes: 13 additions & 1 deletion KitchenSink/NewUI/Webex/WebexCall.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public protocol CallProtocol: AnyObject {
var isWXAEnabled: Bool {get set}
var isClosedCaptionEnabled: Bool {get}
var isClosedCaptionAllowed: Bool {get}
var isSpeechEnhancementEnabled: Bool {get}
var videoRenderViews: (local: MediaRenderView?, remote: MediaRenderView?) {get set}
var screenShareView: MediaRenderView? {get set}
var mediaStream: MediaStream? {get set}
Expand Down Expand Up @@ -119,6 +120,7 @@ public protocol CallProtocol: AnyObject {
func getClosedCaptions() -> [CaptionItem]
func enableWXA(isEnabled: Bool, callback:@escaping ((Bool)->Void)) -> Void
func send(dtmfCode: String, completionHandler: ((Error?) -> Void)?)
func enableSpeechEnhancement(shouldEnable: Bool, completionHandler: @escaping (Result<Void>) -> Void)
}

@available(iOS 16.0, *)
Expand Down Expand Up @@ -272,7 +274,13 @@ class CallKS: CallProtocol
var cameraDuration: WebexSDK.Call.CameraExposureDuration? {
return call?.exposureDuration
}


var isSpeechEnhancementEnabled: Bool {
get {
return call?.isReceiverSpeechEnhancementEnabled ?? false
}
}

private var call: Call?

init(call: WebexSDK.Call) {
Expand Down Expand Up @@ -678,6 +686,10 @@ class CallKS: CallProtocol
public func send(dtmfCode: String, completionHandler: ((Error?) -> Void)?) {
call?.send(dtmf: dtmfCode, completionHandler: completionHandler)
}

public func enableSpeechEnhancement(shouldEnable: Bool, completionHandler: @escaping (Result<Void>) -> Void) {
call?.enableReceiverSpeechEnhancement(shouldEnable: shouldEnable, completionHandler: completionHandler)
}
}

extension Call.BreakoutSession: Hashable {
Expand Down
16 changes: 15 additions & 1 deletion KitchenSink/NewUI/Webex/WebexPhone.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ protocol PhoneProtocol: AnyObject
var videoMaxRxBandwidth: UInt32 { get set }
var videoMaxTxBandwidth: UInt32 { get set }
var defaultFacingMode: FacingModeKS { get set }

var isSpeechEnhancementEnabled: Bool {get}

func setPushTokens(bundleId: String, deviceId: String, deviceToken: String, voipToken: String, appId: String?)
func dial(joinAddress: String, isPhoneNumber: Bool, isMoveMeeting: Bool, isModerator: Bool, pin: String?, captchaId: String, captchaVerifyCode: String, selfVideoView: MediaRenderViewKS, remoteVideoViewRepresentable: RemoteVideoViewRepresentable, screenShareView: MediaRenderViewKS, completionHandler: @escaping (Swift.Result<CallProtocol, Error>) -> Void)

Expand All @@ -25,6 +26,8 @@ protocol PhoneProtocol: AnyObject
func refreshMeetingCaptcha(completionHandler: @escaping (Result<Phone.Captcha>) -> Void)
func updateSystemPreferredCamera(camera: Camera, completionHandler: @escaping (Result<Void>) -> Void)
func getListOfCameras() -> [Camera]
func useLegacyReceiverNoiseRemoval(useLegacy: Bool)
func enableSpeechEnhancement(shouldEnable: Bool, completionHandler: @escaping (Result<Void>) -> Void)
}

@available(iOS 16.0, *)
Expand Down Expand Up @@ -117,6 +120,10 @@ class WebexPhone: PhoneProtocol {
}
}

var isSpeechEnhancementEnabled: Bool {
return webex.phone.isReceiverSpeechEnhancementEnabled
}

// Sets the push tokens for WxC calling push notifications
func setPushTokens(bundleId: String, deviceId: String, deviceToken: String, voipToken: String, appId: String? = nil) {
webex.phone.setPushTokens(bundleId: bundleId, deviceId: deviceId, deviceToken: deviceToken, voipToken: voipToken, appId: nil)
Expand Down Expand Up @@ -215,6 +222,13 @@ class WebexPhone: PhoneProtocol {
return webex.phone.getListOfCameras()
}

func useLegacyReceiverNoiseRemoval(useLegacy: Bool) {
webex.phone.useLegacyReceiverNoiseRemoval(useLegacy: useLegacy)
}

func enableSpeechEnhancement(shouldEnable: Bool, completionHandler: @escaping (Result<Void>) -> Void) {
webex.phone.enableReceiverSpeechEnhancement(shouldEnable: shouldEnable, completionHandler: completionHandler)
}
}


Expand Down
8 changes: 4 additions & 4 deletions Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ target 'KitchenSink' do
use_frameworks!

# Pods for KitchenSink
pod 'WebexSDK','~> 3.13.0'
# pod 'WebexSDK/Meeting','~> 3.13.0' # Uncomment this line and comment the above line for Meeting-only SDK
# pod 'WebexSDK/Wxc','~> 3.13.0' # Uncomment this line and comment the above line for Calling-only SDK
pod 'WebexSDK','~> 3.14.0'
# pod 'WebexSDK/Meeting','~> 3.14.0' # Uncomment this line and comment the above line for Meeting-only SDK
# pod 'WebexSDK/Wxc','~> 3.14.0' # Uncomment this line and comment the above line for Calling-only SDK


target 'KitchenSinkUITests' do
Expand All @@ -23,7 +23,7 @@ target 'KitchenSinkBroadcastExtension' do
use_frameworks!

# Pods for KitchenSinkBroadcastExtension
pod 'WebexBroadcastExtensionKit','~> 3.13.0'
pod 'WebexBroadcastExtensionKit','~> 3.14.0'

end

0 comments on commit 3f5fd33

Please sign in to comment.