Commit b82c2bf5 authored by Kateryna Kostiuk's avatar Kateryna Kostiuk Committed by Andreas Traczyk

call: refine call options

This patch adds the next changes:
- refactor call screen UI
- introduce audio service
- add switch speakerphone
- add headset support

Change-Id: Ie17df97eb64b6d0f6912451e69d67ce8647b4c38
parent e455c9bf
...@@ -114,6 +114,9 @@ ...@@ -114,6 +114,9 @@
0E49097A1FEAC9E1005CAA50 /* CallViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E4909791FEAC9E1005CAA50 /* CallViewController.swift */; }; 0E49097A1FEAC9E1005CAA50 /* CallViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E4909791FEAC9E1005CAA50 /* CallViewController.swift */; };
0E49097C1FEACA4B005CAA50 /* CallViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E49097B1FEACA4B005CAA50 /* CallViewModel.swift */; }; 0E49097C1FEACA4B005CAA50 /* CallViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E49097B1FEACA4B005CAA50 /* CallViewModel.swift */; };
0E6949791FA7E71C0029B60A /* BaseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E6949781FA7E71C0029B60A /* BaseViewController.swift */; }; 0E6949791FA7E71C0029B60A /* BaseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E6949781FA7E71C0029B60A /* BaseViewController.swift */; };
0E7CF4DB20164B6700CD967D /* ButtonsContainerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E7CF4DA20164B6700CD967D /* ButtonsContainerView.swift */; };
0E7CF4DD20165BFB00CD967D /* ButtonsContainerViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E7CF4DC20165BFB00CD967D /* ButtonsContainerViewModel.swift */; };
0E7CF4DF2017918300CD967D /* ButtonsContainerView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0E7CF4DE2017918300CD967D /* ButtonsContainerView.xib */; };
0E983E6E1FC77C3E0082103E /* ConversationModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E983E6D1FC77C3E0082103E /* ConversationModel.swift */; }; 0E983E6E1FC77C3E0082103E /* ConversationModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E983E6D1FC77C3E0082103E /* ConversationModel.swift */; };
0E9D84491FA7DA6A00C561EB /* ChatTabBarItemViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E9D84481FA7DA6A00C561EB /* ChatTabBarItemViewModel.swift */; }; 0E9D84491FA7DA6A00C561EB /* ChatTabBarItemViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E9D84481FA7DA6A00C561EB /* ChatTabBarItemViewModel.swift */; };
0E9D844B1FA7DBAA00C561EB /* ContactRequestTabBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E9D844A1FA7DBAA00C561EB /* ContactRequestTabBarItem.swift */; }; 0E9D844B1FA7DBAA00C561EB /* ContactRequestTabBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E9D844A1FA7DBAA00C561EB /* ContactRequestTabBarItem.swift */; };
...@@ -241,6 +244,8 @@ ...@@ -241,6 +244,8 @@
62AA15BF1FFC36840064A063 /* VideoAdapter.mm in Sources */ = {isa = PBXBuildFile; fileRef = 62AA15BE1FFC36840064A063 /* VideoAdapter.mm */; }; 62AA15BF1FFC36840064A063 /* VideoAdapter.mm in Sources */ = {isa = PBXBuildFile; fileRef = 62AA15BE1FFC36840064A063 /* VideoAdapter.mm */; };
62AA15C31FFC39C80064A063 /* VideoAdapterDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62AA15C21FFC39C80064A063 /* VideoAdapterDelegate.swift */; }; 62AA15C31FFC39C80064A063 /* VideoAdapterDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62AA15C21FFC39C80064A063 /* VideoAdapterDelegate.swift */; };
62AA15CA1FFD3D7E0064A063 /* VideoService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62AA15C91FFD3D7E0064A063 /* VideoService.swift */; }; 62AA15CA1FFD3D7E0064A063 /* VideoService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62AA15C91FFD3D7E0064A063 /* VideoService.swift */; };
62AF685E201A61FF003AA9E8 /* AudioService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62AF685D201A61FF003AA9E8 /* AudioService.swift */; };
62AF6862201A66CF003AA9E8 /* AudioAdapter.mm in Sources */ = {isa = PBXBuildFile; fileRef = 62AF6861201A66CF003AA9E8 /* AudioAdapter.mm */; };
62DFAB2C1F9FF030002D6F9C /* Reachability.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 62DFAB2B1F9FF030002D6F9C /* Reachability.framework */; }; 62DFAB2C1F9FF030002D6F9C /* Reachability.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 62DFAB2B1F9FF030002D6F9C /* Reachability.framework */; };
62DFAB2E1F9FF0D0002D6F9C /* NetworkService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62DFAB2D1F9FF0D0002D6F9C /* NetworkService.swift */; }; 62DFAB2E1F9FF0D0002D6F9C /* NetworkService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62DFAB2D1F9FF0D0002D6F9C /* NetworkService.swift */; };
62E55B6D1F758E6F00D3FEF4 /* String+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62E55B6C1F758E6F00D3FEF4 /* String+Helpers.swift */; }; 62E55B6D1F758E6F00D3FEF4 /* String+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62E55B6C1F758E6F00D3FEF4 /* String+Helpers.swift */; };
...@@ -375,6 +380,9 @@ ...@@ -375,6 +380,9 @@
0E4909791FEAC9E1005CAA50 /* CallViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallViewController.swift; sourceTree = "<group>"; }; 0E4909791FEAC9E1005CAA50 /* CallViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallViewController.swift; sourceTree = "<group>"; };
0E49097B1FEACA4B005CAA50 /* CallViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallViewModel.swift; sourceTree = "<group>"; }; 0E49097B1FEACA4B005CAA50 /* CallViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallViewModel.swift; sourceTree = "<group>"; };
0E6949781FA7E71C0029B60A /* BaseViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseViewController.swift; sourceTree = "<group>"; }; 0E6949781FA7E71C0029B60A /* BaseViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseViewController.swift; sourceTree = "<group>"; };
0E7CF4DA20164B6700CD967D /* ButtonsContainerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonsContainerView.swift; sourceTree = "<group>"; };
0E7CF4DC20165BFB00CD967D /* ButtonsContainerViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonsContainerViewModel.swift; sourceTree = "<group>"; };
0E7CF4DE2017918300CD967D /* ButtonsContainerView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ButtonsContainerView.xib; sourceTree = "<group>"; };
0E983E6D1FC77C3E0082103E /* ConversationModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationModel.swift; sourceTree = "<group>"; }; 0E983E6D1FC77C3E0082103E /* ConversationModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationModel.swift; sourceTree = "<group>"; };
0E9D84481FA7DA6A00C561EB /* ChatTabBarItemViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatTabBarItemViewModel.swift; sourceTree = "<group>"; }; 0E9D84481FA7DA6A00C561EB /* ChatTabBarItemViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatTabBarItemViewModel.swift; sourceTree = "<group>"; };
0E9D844A1FA7DBAA00C561EB /* ContactRequestTabBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactRequestTabBarItem.swift; sourceTree = "<group>"; }; 0E9D844A1FA7DBAA00C561EB /* ContactRequestTabBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactRequestTabBarItem.swift; sourceTree = "<group>"; };
...@@ -561,6 +569,9 @@ ...@@ -561,6 +569,9 @@
62AD0C281FE03FF600BEA1F6 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = "<group>"; }; 62AD0C281FE03FF600BEA1F6 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = "<group>"; };
62AD0C2A1FE054DD00BEA1F6 /* zh-Hans-CN */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans-CN"; path = "zh-Hans-CN.lproj/Localizable.strings"; sourceTree = "<group>"; }; 62AD0C2A1FE054DD00BEA1F6 /* zh-Hans-CN */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans-CN"; path = "zh-Hans-CN.lproj/Localizable.strings"; sourceTree = "<group>"; };
62AD0C2B1FE0557D00BEA1F6 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = "<group>"; }; 62AD0C2B1FE0557D00BEA1F6 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = "<group>"; };
62AF685D201A61FF003AA9E8 /* AudioService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioService.swift; sourceTree = "<group>"; };
62AF6861201A66CF003AA9E8 /* AudioAdapter.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = AudioAdapter.mm; sourceTree = "<group>"; };
62AF6863201A66F0003AA9E8 /* AudioAdapter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AudioAdapter.h; sourceTree = "<group>"; };
62DFAB2B1F9FF030002D6F9C /* Reachability.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Reachability.framework; path = Carthage/Build/iOS/Reachability.framework; sourceTree = "<group>"; }; 62DFAB2B1F9FF030002D6F9C /* Reachability.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Reachability.framework; path = Carthage/Build/iOS/Reachability.framework; sourceTree = "<group>"; };
62DFAB2D1F9FF0D0002D6F9C /* NetworkService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkService.swift; sourceTree = "<group>"; }; 62DFAB2D1F9FF0D0002D6F9C /* NetworkService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkService.swift; sourceTree = "<group>"; };
62E55B6C1F758E6F00D3FEF4 /* String+Helpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+Helpers.swift"; sourceTree = "<group>"; }; 62E55B6C1F758E6F00D3FEF4 /* String+Helpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+Helpers.swift"; sourceTree = "<group>"; };
...@@ -730,6 +741,7 @@ ...@@ -730,6 +741,7 @@
0E49096D1FEAC0DE005CAA50 /* CallsService.swift */, 0E49096D1FEAC0DE005CAA50 /* CallsService.swift */,
62AA15C21FFC39C80064A063 /* VideoAdapterDelegate.swift */, 62AA15C21FFC39C80064A063 /* VideoAdapterDelegate.swift */,
62AA15C91FFD3D7E0064A063 /* VideoService.swift */, 62AA15C91FFD3D7E0064A063 /* VideoService.swift */,
62AF685D201A61FF003AA9E8 /* AudioService.swift */,
); );
path = Services; path = Services;
sourceTree = "<group>"; sourceTree = "<group>";
...@@ -767,6 +779,8 @@ ...@@ -767,6 +779,8 @@
0E4909691FEAB156005CAA50 /* CallsAdapter.mm */, 0E4909691FEAB156005CAA50 /* CallsAdapter.mm */,
62AA15BD1FFC366D0064A063 /* VideoAdapter.h */, 62AA15BD1FFC366D0064A063 /* VideoAdapter.h */,
62AA15BE1FFC36840064A063 /* VideoAdapter.mm */, 62AA15BE1FFC36840064A063 /* VideoAdapter.mm */,
62AF6861201A66CF003AA9E8 /* AudioAdapter.mm */,
62AF6863201A66F0003AA9E8 /* AudioAdapter.h */,
); );
path = Bridging; path = Bridging;
sourceTree = "<group>"; sourceTree = "<group>";
...@@ -967,6 +981,9 @@ ...@@ -967,6 +981,9 @@
0E4909741FEAC943005CAA50 /* CallViewController.storyboard */, 0E4909741FEAC943005CAA50 /* CallViewController.storyboard */,
0E4909791FEAC9E1005CAA50 /* CallViewController.swift */, 0E4909791FEAC9E1005CAA50 /* CallViewController.swift */,
0E49097B1FEACA4B005CAA50 /* CallViewModel.swift */, 0E49097B1FEACA4B005CAA50 /* CallViewModel.swift */,
0E7CF4DA20164B6700CD967D /* ButtonsContainerView.swift */,
0E7CF4DC20165BFB00CD967D /* ButtonsContainerViewModel.swift */,
0E7CF4DE2017918300CD967D /* ButtonsContainerView.xib */,
); );
path = Calls; path = Calls;
sourceTree = "<group>"; sourceTree = "<group>";
...@@ -1504,6 +1521,7 @@ ...@@ -1504,6 +1521,7 @@
1A5DC03E1F35678D0075E8EF /* ContactRequestsViewController.storyboard in Resources */, 1A5DC03E1F35678D0075E8EF /* ContactRequestsViewController.storyboard in Resources */,
0EB1A5CF1F8EBE03009923E2 /* DeviceCell.xib in Resources */, 0EB1A5CF1F8EBE03009923E2 /* DeviceCell.xib in Resources */,
1A2D18B31F2915C500B2C785 /* ConversationViewController.storyboard in Resources */, 1A2D18B31F2915C500B2C785 /* ConversationViewController.storyboard in Resources */,
0E7CF4DF2017918300CD967D /* ButtonsContainerView.xib in Resources */,
1A2D18A01F27A6D600B2C785 /* LinkDeviceViewController.storyboard in Resources */, 1A2D18A01F27A6D600B2C785 /* LinkDeviceViewController.storyboard in Resources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
...@@ -1638,6 +1656,7 @@ ...@@ -1638,6 +1656,7 @@
56BBC99F1ED714CB00CDAF8B /* MessagesAdapter.mm in Sources */, 56BBC99F1ED714CB00CDAF8B /* MessagesAdapter.mm in Sources */,
0E49096A1FEAB156005CAA50 /* CallsAdapter.mm in Sources */, 0E49096A1FEAB156005CAA50 /* CallsAdapter.mm in Sources */,
1A2D18A61F27F7A400B2C785 /* UIViewController+Rx.swift in Sources */, 1A2D18A61F27F7A400B2C785 /* UIViewController+Rx.swift in Sources */,
0E7CF4DB20164B6700CD967D /* ButtonsContainerView.swift in Sources */,
0E49097A1FEAC9E1005CAA50 /* CallViewController.swift in Sources */, 0E49097A1FEAC9E1005CAA50 /* CallViewController.swift in Sources */,
1A5DC0241F3564360075E8EF /* ContactRequestModel.swift in Sources */, 1A5DC0241F3564360075E8EF /* ContactRequestModel.swift in Sources */,
0E4909701FEAC1C6005CAA50 /* CallModel.swift in Sources */, 0E4909701FEAC1C6005CAA50 /* CallModel.swift in Sources */,
...@@ -1674,6 +1693,7 @@ ...@@ -1674,6 +1693,7 @@
1A2D189A1F2642C000B2C785 /* NotificationCenter+Ring.swift in Sources */, 1A2D189A1F2642C000B2C785 /* NotificationCenter+Ring.swift in Sources */,
1A2D18FC1F292DAD00B2C785 /* ConversationCell.swift in Sources */, 1A2D18FC1F292DAD00B2C785 /* ConversationCell.swift in Sources */,
0E48F9D31FDF150700D6CC08 /* ContactRequestManager.swift in Sources */, 0E48F9D31FDF150700D6CC08 /* ContactRequestManager.swift in Sources */,
0E7CF4DD20165BFB00CD967D /* ButtonsContainerViewModel.swift in Sources */,
1A5DC0371F35675E0075E8EF /* ContactRequestCell.swift in Sources */, 1A5DC0371F35675E0075E8EF /* ContactRequestCell.swift in Sources */,
1A20417C1F1E56FF00C08435 /* WelcomeViewModel.swift in Sources */, 1A20417C1F1E56FF00C08435 /* WelcomeViewModel.swift in Sources */,
1A5DC03D1F35678D0075E8EF /* ContactRequestItem.swift in Sources */, 1A5DC03D1F35678D0075E8EF /* ContactRequestItem.swift in Sources */,
...@@ -1682,6 +1702,7 @@ ...@@ -1682,6 +1702,7 @@
1A0C4EE31F1D673600550433 /* InjectionBag.swift in Sources */, 1A0C4EE31F1D673600550433 /* InjectionBag.swift in Sources */,
564C44641E943E1E000F92B1 /* NameRegistrationAdapterDelegate.swift in Sources */, 564C44641E943E1E000F92B1 /* NameRegistrationAdapterDelegate.swift in Sources */,
1A2D18AA1F29131900B2C785 /* ConversationsCoordinator.swift in Sources */, 1A2D18AA1F29131900B2C785 /* ConversationsCoordinator.swift in Sources */,
62AF685E201A61FF003AA9E8 /* AudioService.swift in Sources */,
043999F71D1C2D9D00E99CD9 /* AppDelegate.swift in Sources */, 043999F71D1C2D9D00E99CD9 /* AppDelegate.swift in Sources */,
1A2041861F1EA19600C08435 /* CreateAccountViewController.swift in Sources */, 1A2041861F1EA19600C08435 /* CreateAccountViewController.swift in Sources */,
0EDCC8601F98150500B121D7 /* UIView+Rx.swift in Sources */, 0EDCC8601F98150500B121D7 /* UIView+Rx.swift in Sources */,
...@@ -1711,6 +1732,7 @@ ...@@ -1711,6 +1732,7 @@
0273C3081E0C68BF00CF00BA /* DesignableButton.swift in Sources */, 0273C3081E0C68BF00CF00BA /* DesignableButton.swift in Sources */,
1A5DC0321F3566140075E8EF /* ConversationSection.swift in Sources */, 1A5DC0321F3566140075E8EF /* ConversationSection.swift in Sources */,
1A2D18C41F29180700B2C785 /* ConfigKeyModel.swift in Sources */, 1A2D18C41F29180700B2C785 /* ConfigKeyModel.swift in Sources */,
62AF6862201A66CF003AA9E8 /* AudioAdapter.mm in Sources */,
1A20417A1F1E547F00C08435 /* Stateable.swift in Sources */, 1A20417A1F1E547F00C08435 /* Stateable.swift in Sources */,
1A2D18F51F292D7200B2C785 /* MessageCellReceived.swift in Sources */, 1A2D18F51F292D7200B2C785 /* MessageCellReceived.swift in Sources */,
56BBC9BC1ED7161200CDAF8B /* Date+Helpers.swift in Sources */, 56BBC9BC1ED7161200CDAF8B /* Date+Helpers.swift in Sources */,
......
...@@ -38,6 +38,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { ...@@ -38,6 +38,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
private let presenceService = PresenceService(withPresenceAdapter: PresenceAdapter()) private let presenceService = PresenceService(withPresenceAdapter: PresenceAdapter())
private let callService = CallsService(withCallsAdapter: CallsAdapter()) private let callService = CallsService(withCallsAdapter: CallsAdapter())
private let videoService = VideoService(withVideoAdapter: VideoAdapter()) private let videoService = VideoService(withVideoAdapter: VideoAdapter())
private let audioService = AudioService(withAudioAdapter: AudioAdapter())
private let networkService = NetworkService() private let networkService = NetworkService()
private var conversationManager: ConversationsManager? private var conversationManager: ConversationsManager?
private var contactRequestManager: ContactRequestManager? private var contactRequestManager: ContactRequestManager?
...@@ -51,7 +52,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate { ...@@ -51,7 +52,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
withPresenceService: self.presenceService, withPresenceService: self.presenceService,
withNetworkService: self.networkService, withNetworkService: self.networkService,
withCallService: self.callService, withCallService: self.callService,
withVideoService: self.videoService) withVideoService: self.videoService,
withAudioService: self.audioService)
}() }()
private lazy var appCoordinator: AppCoordinator = { private lazy var appCoordinator: AppCoordinator = {
return AppCoordinator(with: self.injectionBag) return AppCoordinator(with: self.injectionBag)
...@@ -86,6 +88,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate { ...@@ -86,6 +88,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
// start monitoring for network changes // start monitoring for network changes
self.networkService.monitorNetworkType() self.networkService.monitorNetworkType()
// set device to headset if present
self.audioService.overrideAudioRoute(.override)
// themetize the app // themetize the app
Chameleon.setGlobalThemeUsingPrimaryColor(UIColor.ringMain, withSecondaryColor: UIColor.ringSecondary, andContentStyle: .light) Chameleon.setGlobalThemeUsingPrimaryColor(UIColor.ringMain, withSecondaryColor: UIColor.ringSecondary, andContentStyle: .light)
Chameleon.setRingThemeUsingPrimaryColor(UIColor.ringMain, withSecondaryColor: UIColor.ringSecondary, andContentStyle: .light) Chameleon.setRingThemeUsingPrimaryColor(UIColor.ringMain, withSecondaryColor: UIColor.ringSecondary, andContentStyle: .light)
......
/*
* Copyright (C) 2018 Savoir-faire Linux Inc.
*
* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
*
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#import <Foundation/Foundation.h>
@interface AudioAdapter : NSObject
- (void)setAudioOutputDevice:(NSInteger)index;
- (void)setAudioInputDevice:(NSInteger)index;
- (void)setAudioRingtoneDevice:(NSInteger)index;
@end
/*
* Copyright (C) 2018 Savoir-faire Linux Inc.
*
* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
*
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#import "AudioAdapter.h"
#import "dring/configurationmanager_interface.h"
@implementation AudioAdapter
- (void)setAudioOutputDevice:(NSInteger)index {
DRing::setAudioOutputDevice((int32_t)index);
}
- (void)setAudioInputDevice:(NSInteger)index {
DRing::setAudioInputDevice((int32_t)index);
}
- (void)setAudioRingtoneDevice:(NSInteger)index {
DRing::setAudioRingtoneDevice((int32_t)index);
}
@end
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
- (BOOL)holdCallWithId:(NSString*)callId; - (BOOL)holdCallWithId:(NSString*)callId;
- (BOOL)unholdCallWithId:(NSString*)callId; - (BOOL)unholdCallWithId:(NSString*)callId;
- (NSString*)placeCallWithAccountId:(NSString*)accountId toRingId:(NSString*)ringId; - (NSString*)placeCallWithAccountId:(NSString*)accountId toRingId:(NSString*)ringId details:(NSDictionary*)details;
- (NSDictionary<NSString*,NSString*>*)callDetailsWithCallId:(NSString*)callId; - (NSDictionary<NSString*,NSString*>*)callDetailsWithCallId:(NSString*)callId;
- (NSArray<NSString*>*)calls; - (NSArray<NSString*>*)calls;
- (void) sendTextMessageWithCallID:(NSString*)callId message:(NSDictionary*)message accountId:(NSString*)accountId sMixed:(bool)isMixed; - (void) sendTextMessageWithCallID:(NSString*)callId message:(NSDictionary*)message accountId:(NSString*)accountId sMixed:(bool)isMixed;
......
...@@ -155,8 +155,9 @@ static id <CallsAdapterDelegate> _delegate; ...@@ -155,8 +155,9 @@ static id <CallsAdapterDelegate> _delegate;
return unhold(std::string([callId UTF8String])); return unhold(std::string([callId UTF8String]));
} }
- (NSString*)placeCallWithAccountId:(NSString*)accountId toRingId:(NSString*)ringId { - (NSString*)placeCallWithAccountId:(NSString*)accountId toRingId:(NSString*)ringId details:(NSDictionary*)details {
std::string callId = placeCall(std::string([accountId UTF8String]), std::string([ringId UTF8String])); std::string callId;
callId = placeCall(std::string([accountId UTF8String]), std::string([ringId UTF8String]), [Utils dictionnaryToMap:details]);
return [NSString stringWithUTF8String:callId.c_str()]; return [NSString stringWithUTF8String:callId.c_str()];
} }
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#import "ContactsAdapter.h" #import "ContactsAdapter.h"
#import "PresenceAdapter.h" #import "PresenceAdapter.h"
#import "VideoAdapter.h" #import "VideoAdapter.h"
#import "AudioAdapter.h"
#import <CommonCrypto/CommonCrypto.h> #import <CommonCrypto/CommonCrypto.h>
#import <Contacts/Contacts.h> #import <Contacts/Contacts.h>
#import "CallsAdapter.h" #import "CallsAdapter.h"
/*
* Copyright (C) 2017 Savoir-faire Linux Inc.
*
* Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com>
*
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
import UIKit
import Reusable
import RxSwift
class ButtonsContainerView: UIView, NibLoadable {
@IBOutlet var containerView: UIView!
@IBOutlet weak var container: UIView!
@IBOutlet weak var muteAudioButton: UIButton!
@IBOutlet weak var muteVideoButton: UIButton!
@IBOutlet weak var pauseCallButton: UIButton!
@IBOutlet weak var switchCameraButton: UIButton!
@IBOutlet weak var switchSpeakerButton: UIButton!
@IBOutlet weak var cancelButton: UIButton!
@IBOutlet weak var containerHeightConstraint: NSLayoutConstraint!
@IBOutlet weak var bottomSpaceConstraint: NSLayoutConstraint!
let disposeBag = DisposeBag()
var viewModel: ButtonsContainerViewModel? {
didSet {
self.viewModel?.observableCallOptions
.subscribe(onNext: { (callOptions) in
switch callOptions {
case .none:
self.withoutOptions()
case .optionsWithoutSpeakerphone:
self.optionsWithoutSpeaker()
case .optionsWithSpeakerphone:
self.optionsWithSpeaker()
}
}).disposed(by: self.disposeBag)
}
}
override init(frame: CGRect) {
super.init(frame: frame)
self.commonInit()
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
self.commonInit()
}
override open func didMoveToWindow() {
super.didMoveToWindow()
self.cancelButton.backgroundColor = UIColor.red
if #available(iOS 11.0, *) {
guard let window = self.window else {
return
}
self.container.bottomAnchor.constraint(equalTo: window.bottomAnchor).isActive = true
}
}
func commonInit() {
Bundle.main.loadNibNamed("ButtonsContainerView", owner: self, options: nil)
addSubview(containerView)
containerView.frame = self.bounds
}
func withoutOptions() {
containerHeightConstraint.priority = UILayoutPriority(rawValue: 250.00)
bottomSpaceConstraint.priority = UILayoutPriority(rawValue: 999.00)
self.container.backgroundColor = UIColor.clear
muteAudioButton.isHidden = true
muteVideoButton.isHidden = true
pauseCallButton.isHidden = true
switchCameraButton.isHidden = true
switchSpeakerButton.isHidden = true
cancelButton.isHidden = false
}
func optionsWithSpeaker() {
containerHeightConstraint.priority = UILayoutPriority(rawValue: 999.00)
bottomSpaceConstraint.priority = UILayoutPriority(rawValue: 250.00)
self.container.backgroundColor = UIColor.black.withAlphaComponent(0.3)
muteAudioButton.isHidden = false
muteVideoButton.isHidden = false
pauseCallButton.isHidden = false
switchCameraButton.isHidden = false
switchSpeakerButton.isHidden = false
switchSpeakerButton.alpha = 1.00
switchSpeakerButton.isEnabled = true
cancelButton.isHidden = false
}
func optionsWithoutSpeaker() {
containerHeightConstraint.priority = UILayoutPriority(rawValue: 250.00)
bottomSpaceConstraint.priority = UILayoutPriority(rawValue: 999.00)
self.container.backgroundColor = UIColor.black.withAlphaComponent(0.3)
muteAudioButton.isHidden = false
muteVideoButton.isHidden = false
pauseCallButton.isHidden = false
switchCameraButton.isHidden = false
switchSpeakerButton.isHidden = false
switchSpeakerButton.alpha = 0.00
switchSpeakerButton.isEnabled = false
cancelButton.isHidden = false
}
}
This diff is collapsed.
/*
* Copyright (C) 2017 Savoir-faire Linux Inc.
*
* Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com>
*
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
import RxSwift
enum CallOptions {
case none
case optionsWithoutSpeakerphone
case optionsWithSpeakerphone
}
class ButtonsContainerViewModel {
let callService: CallsService
let callID: String
let disposeBag = DisposeBag()
let avalaibleCallOptions = BehaviorSubject<CallOptions>(value: .none)
lazy var observableCallOptions: Observable<CallOptions> = {
return self.avalaibleCallOptions.asObservable()
}()
init(with callService: CallsService, callID: String) {
self.callService = callService
self.callID = callID
checkCallOptions()
}
private func checkCallOptions() {
let callIsActive: Observable<Bool> = {
self.callService.currentCall.filter({ call in
return call.state == .current && call.callId == self.callID
}).map({_ in
return true
})
}()
callIsActive.subscribe(onNext: { active in
if !active {
return
}
if UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiom.pad {
self.avalaibleCallOptions.onNext(.optionsWithoutSpeakerphone)
return
}
self.connectToSpeaker()
}).disposed(by: self.disposeBag)
}
private func connectToSpeaker() {
let speakerIsAvailable: Observable<Bool> = {
//TODO map to service
return Observable.just(true)
}()
speakerIsAvailable.subscribe(onNext: { available in
if available {
self.avalaibleCallOptions.onNext(.optionsWithSpeakerphone)
return
}
self.avalaibleCallOptions.onNext(.optionsWithoutSpeakerphone)
}).disposed(by: self.disposeBag)
}
}
This diff is collapsed.
...@@ -36,9 +36,14 @@ class CallViewModel: Stateable, ViewModel { ...@@ -36,9 +36,14 @@ class CallViewModel: Stateable, ViewModel {
fileprivate let contactsService: ContactsService fileprivate let contactsService: ContactsService
fileprivate let accountService: AccountsService fileprivate let accountService: AccountsService
fileprivate let videoService: VideoService fileprivate let videoService: VideoService
fileprivate let audioService: AudioService
private let disposeBag = DisposeBag() private let disposeBag = DisposeBag()
fileprivate let log = SwiftyBeaver.self fileprivate let log = SwiftyBeaver.self
var isHeadsetConnected = false
var isAudioOnly = false
var call: CallModel? { var call: CallModel? {
didSet { didSet {
guard let call = self.call else { guard let call = self.call else {
...@@ -67,6 +72,9 @@ class CallViewModel: Stateable, ViewModel { ...@@ -67,6 +72,9 @@ class CallViewModel: Stateable, ViewModel {
.disposed(by: self.disposeBag) .disposed(by: self.disposeBag)
}) })
.disposed(by: disposeBag) .disposed(by: disposeBag)
isHeadsetConnected = self.audioService.isHeadsetConnected.value
isAudioOnly = call.isAudioOnly
} }
} }
...@@ -141,18 +149,21 @@ class CallViewModel: Stateable, ViewModel { ...@@ -141,18 +149,21 @@ class CallViewModel: Stateable, ViewModel {
}) })
}() }()
lazy var showCallOptions: Observable<Bool> = { lazy var showCallOptions: Observable<Bool> = {
return Observable.combineLatest(self.callIsActive, return Observable.combineLatest(self.screenTapped.asObservable(), callPaused) { (tapped, paused) in
self.screenTapped.asObservable()) {(active, tapped) -> Bool in if self.isAudioOnly {
return active && tapped return false
}
if tapped && !paused {
return true
}
return false
} }
}() }()
lazy var callIsActive: Observable<Bool> = { lazy var showCancelOption: Observable<Bool> = {
self.callService.currentCall.filter({ call in return self.callService.currentCall.map({ call in
return call.state == .current && call.callId == self.call?.callId return call.state == .connecting || call.state == .ringing
}).map({_ in
return true
}) })
}() }()
...@@ -162,8 +173,9 @@ class CallViewModel: Stateable, ViewModel { ...@@ -162,8 +173,9 @@ class CallViewModel: Stateable, ViewModel {
let onImage = UIImage(asset: Asset.videoRunning) let onImage = UIImage(asset: Asset.videoRunning)
let offImage = UIImage(asset: Asset.videoMuted) let offImage = UIImage(asset: Asset.videoMuted)
return self.videoMuted.map({ muted in return self.videoMuted.map({ [unowned self] muted in
if muted { let audioOnly = self.call?.isAudioOnly ?? false
if audioOnly || muted {
return offImage return offImage
} }
return onImage return onImage
...@@ -191,6 +203,28 @@ class CallViewModel: Stateable, ViewModel { ...@@ -191,6 +203,28 @@ class CallViewModel: Stateable, ViewModel {
}) })
}() }()
lazy var speakerButtonState: Observable<UIImage?> = {
let offImage = UIImage(asset: Asset.disableSpeakerphone)
let onImage = UIImage(asset: Asset.enableSpeakerphone)
return self.isOutputToSpeaker
.map({ speaker in
if speaker {
return onImage
}
return offImage
})
}()
lazy var isOutputToSpeaker: Observable<Bool> = {
return self.audioService.isOutputToSpeaker.asObservable()
}()
lazy var speakerSwitchable: Observable<Bool> = {
return self.audioService.isHeadsetConnected.asObservable()
.map { value in return !value }
}()
lazy var audioMuted: Observable<Bool> = { lazy var audioMuted: Observable<Bool> = {
return self.callService.currentCall.filter({ call in return self.callService.currentCall.filter({ call in
call.callId == self.call?.callId && call.callId == self.call?.callId &&
...@@ -200,7 +234,7 @@ class CallViewModel: Stateable, ViewModel { ...@@ -200,7 +234,7 @@ class CallViewModel: Stateable, ViewModel {
}) })
}() }()
lazy var callButtonState: Observable<UIImage?> = { lazy var pauseCallButtonState: Observable<UIImage?> = {
let unpauseCall = UIImage(asset: Asset.unpauseCall) let unpauseCall = UIImage(asset: Asset.unpauseCall)
let pauseCall = UIImage(asset: Asset.pauseCall) let pauseCall = UIImage(asset: Asset.pauseCall)
...@@ -227,12 +261,18 @@ class CallViewModel: Stateable, ViewModel { ...@@ -227,12 +261,18 @@ class CallViewModel: Stateable, ViewModel {
}) })
}() }()
lazy var containerViewModel: ButtonsContainerViewModel = {
return ButtonsContainerViewModel(with: self.callService, callID: (self.call?.callId)!)
}()
required init(with injectionBag: InjectionBag) { required init(with injectionBag: InjectionBag) {
self.callService = injectionBag.callService self.callService = injectionBag.callService
self.contactsService = injectionBag.contactsService self.contactsService = injectionBag.contactsService
self.accountService = injectionBag.accountService self.accountService = injectionBag.accountService