From 18c4b46d6356a9448b6fc6434000542e5c747197 Mon Sep 17 00:00:00 2001 From: Benoit Martins Date: Tue, 7 May 2024 16:17:19 +0200 Subject: [PATCH] Dismiss bottom sheet in call view --- Linphone.xcodeproj/project.pbxproj | 108 +++++ Linphone/UI/Call/CallView.swift | 376 +----------------- .../Fragments/AudioRouteBottomSheet.swift | 141 +++++++ .../CallStatisticsSheetBottomSheet.swift | 100 +++++ .../Fragments/ChangeLayoutBottomSheet.swift | 131 ++++++ .../MediaEncryptedSheetBottomSheet.swift | 109 +++++ Linphone/UI/Call/Model/CallStatsModel.swift | 6 +- 7 files changed, 605 insertions(+), 366 deletions(-) create mode 100644 Linphone/UI/Call/Fragments/AudioRouteBottomSheet.swift create mode 100644 Linphone/UI/Call/Fragments/CallStatisticsSheetBottomSheet.swift create mode 100644 Linphone/UI/Call/Fragments/ChangeLayoutBottomSheet.swift create mode 100644 Linphone/UI/Call/Fragments/MediaEncryptedSheetBottomSheet.swift diff --git a/Linphone.xcodeproj/project.pbxproj b/Linphone.xcodeproj/project.pbxproj index 2dae51c9e..4f16d3ea5 100644 --- a/Linphone.xcodeproj/project.pbxproj +++ b/Linphone.xcodeproj/project.pbxproj @@ -35,6 +35,7 @@ 66FBFC492B83BD2400BC6AB1 /* ConfigExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66C491F82B24D25A00CEA16D /* ConfigExtension.swift */; }; 66FBFC4A2B83BD3300BC6AB1 /* FileUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66C491FE2B24D4AC00CEA16D /* FileUtils.swift */; }; 66FBFC4B2B83BD7B00BC6AB1 /* CoreExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66C491FA2B24D32600CEA16D /* CoreExtension.swift */; }; + B7B8D61A96BD84CFE971D91A /* Pods_Linphone.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 58C93C0613C0C9EE9F683101 /* Pods_Linphone.framework */; }; D706BA822ADD72D100278F45 /* DeviceRotationViewModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = D706BA812ADD72D100278F45 /* DeviceRotationViewModifier.swift */; }; D70959F12B8DF3EC0014AC0B /* ConversationModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D70959F02B8DF3EC0014AC0B /* ConversationModel.swift */; }; D70A26EE2B7CF60B006CC8FC /* ConversationsListBottomSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = D70A26ED2B7CF60B006CC8FC /* ConversationsListBottomSheet.swift */; }; @@ -96,6 +97,10 @@ 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 */; }; + D78E062A2BEA698E00CE3783 /* MediaEncryptedSheetBottomSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = D78E06292BEA698E00CE3783 /* MediaEncryptedSheetBottomSheet.swift */; }; + D78E062C2BEA69BC00CE3783 /* CallStatisticsSheetBottomSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = D78E062B2BEA69BC00CE3783 /* CallStatisticsSheetBottomSheet.swift */; }; + D78E062E2BEA69F400CE3783 /* AudioRouteBottomSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = D78E062D2BEA69F400CE3783 /* AudioRouteBottomSheet.swift */; }; + D78E06302BEA6A4A00CE3783 /* ChangeLayoutBottomSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = D78E062F2BEA6A4A00CE3783 /* ChangeLayoutBottomSheet.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 */; }; @@ -136,6 +141,7 @@ D7EAACCF2AD6ED8000AA6A8A /* PermissionsFragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7EAACCE2AD6ED8000AA6A8A /* PermissionsFragment.swift */; }; D7F4D9CB2B5FD27200CDCD76 /* CallsListFragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7F4D9CA2B5FD27200CDCD76 /* CallsListFragment.swift */; }; D7FB55112AD447FD00A5AB15 /* RegisterFragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7FB55102AD447FD00A5AB15 /* RegisterFragment.swift */; }; + F9B4F742AD49194891FD3229 /* Pods_msgNotificationService.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F354247FC9212E91C1A125F /* Pods_msgNotificationService.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -163,6 +169,9 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 4354755A6D707621E1E163BA /* Pods-msgNotificationService.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-msgNotificationService.debug.xcconfig"; path = "Target Support Files/Pods-msgNotificationService/Pods-msgNotificationService.debug.xcconfig"; sourceTree = ""; }; + 4A44483E8A6A48F06F982C27 /* Pods-Linphone.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Linphone.release.xcconfig"; path = "Target Support Files/Pods-Linphone/Pods-Linphone.release.xcconfig"; sourceTree = ""; }; + 58C93C0613C0C9EE9F683101 /* Pods_Linphone.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Linphone.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 660AAF7B2B839271004C0FA6 /* msgNotificationService.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = msgNotificationService.appex; sourceTree = BUILT_PRODUCTS_DIR; }; 660AAF842B8392E0004C0FA6 /* msgNotificationService.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = msgNotificationService.entitlements; sourceTree = ""; }; 660D8A702B517D260092694D /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; @@ -187,6 +196,9 @@ 66E56BCB2BA9A1E0006CE56F /* MeetingsListItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeetingsListItemModel.swift; sourceTree = ""; }; 66E56BCD2BA9A1F8006CE56F /* MeetingModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeetingModel.swift; sourceTree = ""; }; 66F626B12BCEBB86003E2DEC /* AddParticipantsFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddParticipantsFragment.swift; sourceTree = ""; }; + 7B05388834A68F3139984AF9 /* Pods-Linphone.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Linphone.debug.xcconfig"; path = "Target Support Files/Pods-Linphone/Pods-Linphone.debug.xcconfig"; sourceTree = ""; }; + 7F354247FC9212E91C1A125F /* Pods_msgNotificationService.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_msgNotificationService.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 8ED7664E120A7A0B96AF2301 /* Pods-msgNotificationService.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-msgNotificationService.release.xcconfig"; path = "Target Support Files/Pods-msgNotificationService/Pods-msgNotificationService.release.xcconfig"; sourceTree = ""; }; D706BA812ADD72D100278F45 /* DeviceRotationViewModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceRotationViewModifier.swift; sourceTree = ""; }; D70959F02B8DF3EC0014AC0B /* ConversationModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationModel.swift; sourceTree = ""; }; D70A26ED2B7CF60B006CC8FC /* ConversationsListBottomSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationsListBottomSheet.swift; sourceTree = ""; }; @@ -250,6 +262,10 @@ D783C77A2B1089B200622CC2 /* assistant_linphone_default_values */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = assistant_linphone_default_values; sourceTree = ""; }; D783C77B2B1089B200622CC2 /* assistant_third_party_default_values */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = assistant_third_party_default_values; sourceTree = ""; }; D78E06272BE3811D00CE3783 /* CallStatsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallStatsModel.swift; sourceTree = ""; }; + D78E06292BEA698E00CE3783 /* MediaEncryptedSheetBottomSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaEncryptedSheetBottomSheet.swift; sourceTree = ""; }; + D78E062B2BEA69BC00CE3783 /* CallStatisticsSheetBottomSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallStatisticsSheetBottomSheet.swift; sourceTree = ""; }; + D78E062D2BEA69F400CE3783 /* AudioRouteBottomSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioRouteBottomSheet.swift; sourceTree = ""; }; + D78E062F2BEA6A4A00CE3783 /* ChangeLayoutBottomSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChangeLayoutBottomSheet.swift; sourceTree = ""; }; D79622332B1DFE600037EACD /* DialerBottomSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DialerBottomSheet.swift; sourceTree = ""; }; D796F1FF2B0BB61A0041115F /* ToastViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToastViewModel.swift; sourceTree = ""; }; D7A03FBC2ACC2DB60081A588 /* ContactsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactsView.swift; sourceTree = ""; }; @@ -298,6 +314,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + F9B4F742AD49194891FD3229 /* Pods_msgNotificationService.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -305,12 +322,22 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + B7B8D61A96BD84CFE971D91A /* Pods_Linphone.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 09575EFA659D4B5A36D3567A /* Frameworks */ = { + isa = PBXGroup; + children = ( + 58C93C0613C0C9EE9F683101 /* Pods_Linphone.framework */, + 7F354247FC9212E91C1A125F /* Pods_msgNotificationService.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; 660AAF7C2B839272004C0FA6 /* msgNotificationService */ = { isa = PBXGroup; children = ( @@ -387,6 +414,10 @@ A31AF2AB8C6A3D7B7EA3B424 /* Pods */ = { isa = PBXGroup; children = ( + 7B05388834A68F3139984AF9 /* Pods-Linphone.debug.xcconfig */, + 4A44483E8A6A48F06F982C27 /* Pods-Linphone.release.xcconfig */, + 4354755A6D707621E1E163BA /* Pods-msgNotificationService.debug.xcconfig */, + 8ED7664E120A7A0B96AF2301 /* Pods-msgNotificationService.release.xcconfig */, ); path = Pods; sourceTree = ""; @@ -428,6 +459,7 @@ 660AAF7C2B839272004C0FA6 /* msgNotificationService */, D719ABB42ABC67BF00B41C10 /* Products */, A31AF2AB8C6A3D7B7EA3B424 /* Pods */, + 09575EFA659D4B5A36D3567A /* Frameworks */, ); sourceTree = ""; }; @@ -593,6 +625,10 @@ D75759312B56D40900E7AC10 /* ZRTPPopup.swift */, D7F4D9CA2B5FD27200CDCD76 /* CallsListFragment.swift */, D717630C2BD7BD0E00464097 /* ParticipantsListFragment.swift */, + D78E06292BEA698E00CE3783 /* MediaEncryptedSheetBottomSheet.swift */, + D78E062B2BEA69BC00CE3783 /* CallStatisticsSheetBottomSheet.swift */, + D78E062D2BEA69F400CE3783 /* AudioRouteBottomSheet.swift */, + D78E062F2BEA6A4A00CE3783 /* ChangeLayoutBottomSheet.swift */, ); path = Fragments; sourceTree = ""; @@ -772,6 +808,7 @@ isa = PBXNativeTarget; buildConfigurationList = 660AAF832B839272004C0FA6 /* Build configuration list for PBXNativeTarget "msgNotificationService" */; buildPhases = ( + 24598C3B27268E421F6C44CE /* [CP] Check Pods Manifest.lock */, 660AAF772B839271004C0FA6 /* Sources */, 660AAF782B839271004C0FA6 /* Frameworks */, 660AAF792B839271004C0FA6 /* Resources */, @@ -789,12 +826,14 @@ isa = PBXNativeTarget; buildConfigurationList = D719ABC22ABC67BF00B41C10 /* Build configuration list for PBXNativeTarget "Linphone" */; buildPhases = ( + 4CE154B79984202D6309AD08 /* [CP] Check Pods Manifest.lock */, D719ABAF2ABC67BF00B41C10 /* Sources */, D719ABB02ABC67BF00B41C10 /* Frameworks */, 660AAF802B839272004C0FA6 /* Embed Foundation Extensions */, D719ABB12ABC67BF00B41C10 /* Resources */, D7FB55122AD53FE200A5AB15 /* Run Script */, 66BF2D4B2B558A3100A5F2E3 /* Crashlytics */, + F29799A2294ED13B2953DBDE /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -878,6 +917,50 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ + 24598C3B27268E421F6C44CE /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-msgNotificationService-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 4CE154B79984202D6309AD08 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Linphone-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; 66BF2D4B2B558A3100A5F2E3 /* Crashlytics */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -920,6 +1003,23 @@ shellPath = /bin/sh; shellScript = "if [[ \"$(uname -m)\" == arm64 ]]; then\n export PATH=\"/opt/homebrew/bin:$PATH\"\nfi\n\nif which swiftlint > /dev/null; then\n swiftlint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n"; }; + F29799A2294ED13B2953DBDE /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Linphone/Pods-Linphone-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Linphone/Pods-Linphone-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Linphone/Pods-Linphone-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -947,6 +1047,7 @@ D719ABB92ABC67BF00B41C10 /* ContentView.swift in Sources */, D71FCA832AE14D6E00D2E43E /* ContactFragment.swift in Sources */, D7C3650C2AF0084000FE6142 /* EditContactViewModel.swift in Sources */, + D78E062A2BEA698E00CE3783 /* MediaEncryptedSheetBottomSheet.swift in Sources */, D7B5678E2B28888F00DE63EB /* CallView.swift in Sources */, D71A0E192B485ADF0002C6CD /* ViewExtension.swift in Sources */, D750D3392AD3E6EE00EC99C5 /* PopupLoadingView.swift in Sources */, @@ -992,6 +1093,7 @@ 66162A202BDFC2F900DCE913 /* AddParticipantsViewModel.swift in Sources */, D732A91B2B061BD900DB42BA /* HistoryListBottomSheet.swift in Sources */, D72250632ADE9615008FB426 /* HistoryViewModel.swift in Sources */, + D78E06302BEA6A4A00CE3783 /* ChangeLayoutBottomSheet.swift in Sources */, 66E56BC92BA4A6D7006CE56F /* MeetingsListViewModel.swift in Sources */, D726E4392B16440C0083C415 /* ContactAvatarModel.swift in Sources */, 6613A0B02BAEB7F4008923A4 /* MeetingsListFragment.swift in Sources */, @@ -999,6 +1101,7 @@ D78E06282BE3811D00CE3783 /* CallStatsModel.swift in Sources */, D7E6D0512AEBDBD500A57AAF /* ContactsListBottomSheet.swift in Sources */, D75759322B56D40900E7AC10 /* ZRTPPopup.swift in Sources */, + D78E062E2BEA69F400CE3783 /* AudioRouteBottomSheet.swift in Sources */, D7A2EDD62AC18115005D90FC /* SharedMainViewModel.swift in Sources */, D7A03FC62ACC458A0081A588 /* SplashScreen.swift in Sources */, D7E6ADF52B9876ED0009A2BC /* Attachment.swift in Sources */, @@ -1041,6 +1144,7 @@ D7CEE03D2B7A23B200FD79B7 /* ConversationsListFragment.swift in Sources */, D74C9CFC2ACACF370021626A /* WelcomePage3Fragment.swift in Sources */, D719ABCC2ABC769C00B41C10 /* AssistantView.swift in Sources */, + D78E062C2BEA69BC00CE3783 /* CallStatisticsSheetBottomSheet.swift in Sources */, D7C365082AEFAB7F00FE6142 /* ContactListBottomSheet.swift in Sources */, D7E6D04B2AE9347D00A57AAF /* FavoriteContactsListViewModel.swift in Sources */, D74C9CFA2ACACF2D0021626A /* WelcomePage2Fragment.swift in Sources */, @@ -1062,6 +1166,7 @@ /* Begin XCBuildConfiguration section */ 660AAF812B839272004C0FA6 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 4354755A6D707621E1E163BA /* Pods-msgNotificationService.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ENABLE_MODULES = YES; @@ -1104,6 +1209,7 @@ }; 660AAF822B839272004C0FA6 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 8ED7664E120A7A0B96AF2301 /* Pods-msgNotificationService.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ENABLE_MODULES = YES; @@ -1257,6 +1363,7 @@ }; D719ABC32ABC67BF00B41C10 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 7B05388834A68F3139984AF9 /* Pods-Linphone.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; @@ -1313,6 +1420,7 @@ }; D719ABC42ABC67BF00B41C10 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 4A44483E8A6A48F06F982C27 /* Pods-Linphone.release.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; diff --git a/Linphone/UI/Call/CallView.swift b/Linphone/UI/Call/CallView.swift index cac96dcae..47614097b 100644 --- a/Linphone/UI/Call/CallView.swift +++ b/Linphone/UI/Call/CallView.swift @@ -69,25 +69,25 @@ struct CallView: View { .sheet(isPresented: $mediaEncryptedSheet, onDismiss: { mediaEncryptedSheet = false }) { - mediaEncryptedSheetBottomSheet() + MediaEncryptedSheetBottomSheet(callViewModel: callViewModel, mediaEncryptedSheet: $mediaEncryptedSheet) .presentationDetents([.medium]) } .sheet(isPresented: $callStatisticsSheet, onDismiss: { callStatisticsSheet = false }) { - callStatisticsSheetBottomSheet() + CallStatisticsSheetBottomSheet(callViewModel: callViewModel, callStatisticsSheet: $callStatisticsSheet) .presentationDetents(!callViewModel.callStatsModel.isVideoEnabled ? [.fraction(0.3)] : [.medium]) } .sheet(isPresented: $audioRouteSheet, onDismiss: { audioRouteSheet = false }) { - audioRouteBottomSheet() + AudioRouteBottomSheet(callViewModel: callViewModel, optionsAudioRoute: $optionsAudioRoute) .presentationDetents([.fraction(0.3)]) } .sheet(isPresented: $changeLayoutSheet, onDismiss: { changeLayoutSheet = false }) { - changeLayoutBottomSheet() + ChangeLayoutBottomSheet(callViewModel: callViewModel, changeLayoutSheet: $changeLayoutSheet, optionsChangeLayout: $optionsChangeLayout) .presentationDetents([.fraction(0.3)]) } .sheet(isPresented: $showingDialer) { @@ -104,25 +104,25 @@ struct CallView: View { .sheet(isPresented: $mediaEncryptedSheet, onDismiss: { mediaEncryptedSheet = false }) { - mediaEncryptedSheetBottomSheet() + MediaEncryptedSheetBottomSheet(callViewModel: callViewModel, mediaEncryptedSheet: $mediaEncryptedSheet) .presentationDetents([.medium]) } .sheet(isPresented: $callStatisticsSheet, onDismiss: { callStatisticsSheet = false }) { - callStatisticsSheetBottomSheet() + CallStatisticsSheetBottomSheet(callViewModel: callViewModel, callStatisticsSheet: $callStatisticsSheet) .presentationDetents(!callViewModel.callStatsModel.isVideoEnabled ? [.fraction(0.3)] : [.medium]) } .sheet(isPresented: $audioRouteSheet, onDismiss: { audioRouteSheet = false }) { - audioRouteBottomSheet() + AudioRouteBottomSheet(callViewModel: callViewModel, optionsAudioRoute: $optionsAudioRoute) .presentationDetents([.fraction(0.3)]) } .sheet(isPresented: $changeLayoutSheet, onDismiss: { changeLayoutSheet = false }) { - changeLayoutBottomSheet() + ChangeLayoutBottomSheet(callViewModel: callViewModel, changeLayoutSheet: $changeLayoutSheet, optionsChangeLayout: $optionsChangeLayout) .presentationDetents([.fraction(0.3)]) } .sheet(isPresented: $showingDialer) { @@ -136,22 +136,22 @@ struct CallView: View { } else { innerView(geometry: geo) .halfSheet(showSheet: $mediaEncryptedSheet) { - mediaEncryptedSheetBottomSheet() + MediaEncryptedSheetBottomSheet(callViewModel: callViewModel, mediaEncryptedSheet: $mediaEncryptedSheet) } onDismiss: { mediaEncryptedSheet = false } .halfSheet(showSheet: $callStatisticsSheet) { - callStatisticsSheetBottomSheet() + CallStatisticsSheetBottomSheet(callViewModel: callViewModel, callStatisticsSheet: $callStatisticsSheet) } onDismiss: { callStatisticsSheet = false } .halfSheet(showSheet: $audioRouteSheet) { - audioRouteBottomSheet() + AudioRouteBottomSheet(callViewModel: callViewModel, optionsAudioRoute: $optionsAudioRoute) } onDismiss: { audioRouteSheet = false } .halfSheet(showSheet: $changeLayoutSheet) { - changeLayoutBottomSheet() + ChangeLayoutBottomSheet(callViewModel: callViewModel, changeLayoutSheet: $changeLayoutSheet, optionsChangeLayout: $optionsChangeLayout) } onDismiss: { changeLayoutSheet = false } @@ -204,358 +204,6 @@ struct CallView: View { } } - @ViewBuilder - func mediaEncryptedSheetBottomSheet() -> 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("Chiffrement du média") - .default_text_style_white_600(styleSize: 15) - .padding(.top, 10) - - Spacer() - - Text(callViewModel.callMediaEncryptionModel.mediaEncryption) - .default_text_style_white(styleSize: 15) - - Spacer() - - Text(callViewModel.callMediaEncryptionModel.zrtpCipher) - .default_text_style_white(styleSize: 15) - - Spacer() - - Text(callViewModel.callMediaEncryptionModel.zrtpKeyAgreement) - .default_text_style_white(styleSize: 15) - - Spacer() - - Text(callViewModel.callMediaEncryptionModel.zrtpHash) - .default_text_style_white(styleSize: 15) - - Spacer() - - Text(callViewModel.callMediaEncryptionModel.zrtpAuthTag) - .default_text_style_white(styleSize: 15) - - Spacer() - - Text(callViewModel.callMediaEncryptionModel.zrtpAuthSas) - .default_text_style_white(styleSize: 15) - .padding(.bottom, 10) - - Spacer() - - Button(action: { - callViewModel.showZrtpSasDialogIfPossible() - mediaEncryptedSheet = false - }, label: { - Text("Faire la validation à nouveau") - .default_text_style_white_600(styleSize: 20) - .frame(height: 35) - .frame(maxWidth: .infinity) - }) - .padding(.horizontal, 20) - .padding(.vertical, 10) - .background(Color.orangeMain500) - .cornerRadius(60) - .padding(.bottom) - .padding(.horizontal, 10) - } - .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) { - Button(action: { - optionsAudioRoute = 1 - - do { - try AVAudioSession.sharedInstance().overrideOutputAudioPort(.none) - if callViewModel.isHeadPhoneAvailable() { - try AVAudioSession.sharedInstance().setPreferredInput(AVAudioSession.sharedInstance().availableInputs?.filter({ $0.portType.rawValue.contains("Receiver") }).first) - } else { - try AVAudioSession.sharedInstance().setPreferredInput(AVAudioSession.sharedInstance().availableInputs?.first) - } - } catch _ { - - } - }, label: { - HStack { - Image(optionsAudioRoute == 1 ? "radio-button-fill" : "radio-button") - .renderingMode(.template) - .resizable() - .foregroundStyle(.white) - .frame(width: 25, height: 25, alignment: .leading) - .padding(.all, 10) - - Text(!callViewModel.isHeadPhoneAvailable() ? "Earpiece" : "Headphones") - .default_text_style_white(styleSize: 15) - - Spacer() - - Image(!callViewModel.isHeadPhoneAvailable() ? "ear" : "headset") - .renderingMode(.template) - .resizable() - .foregroundStyle(.white) - .frame(width: 25, height: 25, alignment: .leading) - .padding(.all, 10) - } - }) - .frame(maxHeight: .infinity) - - Button(action: { - optionsAudioRoute = 2 - - do { - try AVAudioSession.sharedInstance().overrideOutputAudioPort(.speaker) - } catch _ { - - } - }, label: { - HStack { - Image(optionsAudioRoute == 2 ? "radio-button-fill" : "radio-button") - .renderingMode(.template) - .resizable() - .foregroundStyle(.white) - .frame(width: 25, height: 25, alignment: .leading) - .padding(.all, 10) - - Text("Speaker") - .default_text_style_white(styleSize: 15) - - Spacer() - - Image("speaker-high") - .renderingMode(.template) - .resizable() - .foregroundStyle(.white) - .frame(width: 25, height: 25, alignment: .leading) - .padding(.all, 10) - } - }) - .frame(maxHeight: .infinity) - - Button(action: { - optionsAudioRoute = 3 - - do { - try AVAudioSession.sharedInstance().overrideOutputAudioPort(.none) - try AVAudioSession.sharedInstance().setPreferredInput(AVAudioSession.sharedInstance().availableInputs?.filter({ $0.portType.rawValue.contains("Bluetooth") }).first) - } catch _ { - - } - }, label: { - HStack { - Image(optionsAudioRoute == 3 ? "radio-button-fill" : "radio-button") - .renderingMode(.template) - .resizable() - .foregroundStyle(.white) - .frame(width: 25, height: 25, alignment: .leading) - .padding(.all, 10) - - Text("Bluetooth") - .default_text_style_white(styleSize: 15) - - Spacer() - - Image("bluetooth") - .renderingMode(.template) - .resizable() - .foregroundStyle(.white) - .frame(width: 25, height: 25, alignment: .leading) - .padding(.all, 10) - } - }) - .frame(maxHeight: .infinity) - } - .padding(.horizontal, 20) - .background(Color.gray600) - .frame(maxHeight: .infinity) - } - - @ViewBuilder - func changeLayoutBottomSheet() -> some View { - VStack(spacing: 0) { - Button(action: { - optionsChangeLayout = 1 - callViewModel.toggleVideoMode(isAudioOnlyMode: false) - changeLayoutSheet = false - }, label: { - HStack { - Image(optionsChangeLayout == 1 ? "radio-button-fill" : "radio-button") - .renderingMode(.template) - .resizable() - .foregroundStyle(callViewModel.participantList.count > 5 ? Color.gray500 : .white) - .frame(width: 25, height: 25, alignment: .leading) - .padding(.all, 10) - - Text("Mosaïque") - .foregroundStyle(callViewModel.participantList.count > 5 ? Color.gray500 : .white) - .default_text_style_white(styleSize: 15) - - Spacer() - - Image("squares-four") - .renderingMode(.template) - .resizable() - .foregroundStyle(callViewModel.participantList.count > 5 ? Color.gray500 : .white) - .frame(width: 25, height: 25, alignment: .leading) - .padding(.all, 10) - } - }) - .disabled(callViewModel.participantList.count > 5) - .frame(maxHeight: .infinity) - - Button(action: { - optionsChangeLayout = 2 - callViewModel.toggleVideoMode(isAudioOnlyMode: false) - changeLayoutSheet = false - }, label: { - HStack { - Image(optionsChangeLayout == 2 ? "radio-button-fill" : "radio-button") - .renderingMode(.template) - .resizable() - .foregroundStyle(.white) - .frame(width: 25, height: 25, alignment: .leading) - .padding(.all, 10) - - Text("Participant actif") - .default_text_style_white(styleSize: 15) - - Spacer() - - Image("picture-in-picture") - .renderingMode(.template) - .resizable() - .foregroundStyle(.white) - .frame(width: 25, height: 25, alignment: .leading) - .padding(.all, 10) - } - }) - .frame(maxHeight: .infinity) - - Button(action: { - optionsChangeLayout = 3 - if callViewModel.videoDisplayed { - callViewModel.displayMyVideo() - } - callViewModel.toggleVideoMode(isAudioOnlyMode: true) - changeLayoutSheet = false - }, label: { - HStack { - Image(optionsChangeLayout == 3 ? "radio-button-fill" : "radio-button") - .renderingMode(.template) - .resizable() - .foregroundStyle(.white) - .frame(width: 25, height: 25, alignment: .leading) - .padding(.all, 10) - - Text("Audio seulement") - .default_text_style_white(styleSize: 15) - - Spacer() - - Image("waveform") - .renderingMode(.template) - .resizable() - .foregroundStyle(.white) - .frame(width: 25, height: 25, alignment: .leading) - .padding(.all, 10) - } - }) - .frame(maxHeight: .infinity) - } - .padding(.horizontal, 20) - .background(Color.gray600) - .frame(maxHeight: .infinity) - } - @ViewBuilder // swiftlint:disable:next cyclomatic_complexity func innerView(geometry: GeometryProxy) -> some View { diff --git a/Linphone/UI/Call/Fragments/AudioRouteBottomSheet.swift b/Linphone/UI/Call/Fragments/AudioRouteBottomSheet.swift new file mode 100644 index 000000000..4b85ee333 --- /dev/null +++ b/Linphone/UI/Call/Fragments/AudioRouteBottomSheet.swift @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2010-2023 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 . + */ + +import SwiftUI +import AVFAudio + +struct AudioRouteBottomSheet: View { + @Environment(\.dismiss) private var dismiss + + @ObservedObject var callViewModel: CallViewModel + + private var idiom: UIUserInterfaceIdiom { UIDevice.current.userInterfaceIdiom } + @State private var orientation = UIDevice.current.orientation + + @Binding var optionsAudioRoute: Int + + var body: some View { + VStack(spacing: 0) { + Button(action: { + optionsAudioRoute = 1 + + do { + try AVAudioSession.sharedInstance().overrideOutputAudioPort(.none) + if callViewModel.isHeadPhoneAvailable() { + try AVAudioSession.sharedInstance().setPreferredInput(AVAudioSession.sharedInstance().availableInputs?.filter({ $0.portType.rawValue.contains("Receiver") }).first) + } else { + try AVAudioSession.sharedInstance().setPreferredInput(AVAudioSession.sharedInstance().availableInputs?.first) + } + } catch _ { + + } + }, label: { + HStack { + Image(optionsAudioRoute == 1 ? "radio-button-fill" : "radio-button") + .renderingMode(.template) + .resizable() + .foregroundStyle(.white) + .frame(width: 25, height: 25, alignment: .leading) + .padding(.all, 10) + + Text(!callViewModel.isHeadPhoneAvailable() ? "Earpiece" : "Headphones") + .default_text_style_white(styleSize: 15) + + Spacer() + + Image(!callViewModel.isHeadPhoneAvailable() ? "ear" : "headset") + .renderingMode(.template) + .resizable() + .foregroundStyle(.white) + .frame(width: 25, height: 25, alignment: .leading) + .padding(.all, 10) + } + }) + .frame(maxHeight: .infinity) + + Button(action: { + optionsAudioRoute = 2 + + do { + try AVAudioSession.sharedInstance().overrideOutputAudioPort(.speaker) + } catch _ { + + } + }, label: { + HStack { + Image(optionsAudioRoute == 2 ? "radio-button-fill" : "radio-button") + .renderingMode(.template) + .resizable() + .foregroundStyle(.white) + .frame(width: 25, height: 25, alignment: .leading) + .padding(.all, 10) + + Text("Speaker") + .default_text_style_white(styleSize: 15) + + Spacer() + + Image("speaker-high") + .renderingMode(.template) + .resizable() + .foregroundStyle(.white) + .frame(width: 25, height: 25, alignment: .leading) + .padding(.all, 10) + } + }) + .frame(maxHeight: .infinity) + + Button(action: { + optionsAudioRoute = 3 + + do { + try AVAudioSession.sharedInstance().overrideOutputAudioPort(.none) + try AVAudioSession.sharedInstance().setPreferredInput(AVAudioSession.sharedInstance().availableInputs?.filter({ $0.portType.rawValue.contains("Bluetooth") }).first) + } catch _ { + + } + }, label: { + HStack { + Image(optionsAudioRoute == 3 ? "radio-button-fill" : "radio-button") + .renderingMode(.template) + .resizable() + .foregroundStyle(.white) + .frame(width: 25, height: 25, alignment: .leading) + .padding(.all, 10) + + Text("Bluetooth") + .default_text_style_white(styleSize: 15) + + Spacer() + + Image("bluetooth") + .renderingMode(.template) + .resizable() + .foregroundStyle(.white) + .frame(width: 25, height: 25, alignment: .leading) + .padding(.all, 10) + } + }) + .frame(maxHeight: .infinity) + } + .padding(.horizontal, 20) + .background(Color.gray600) + .frame(maxHeight: .infinity) + } +} diff --git a/Linphone/UI/Call/Fragments/CallStatisticsSheetBottomSheet.swift b/Linphone/UI/Call/Fragments/CallStatisticsSheetBottomSheet.swift new file mode 100644 index 000000000..3b94f53b5 --- /dev/null +++ b/Linphone/UI/Call/Fragments/CallStatisticsSheetBottomSheet.swift @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2010-2023 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 . + */ + +import SwiftUI + +struct CallStatisticsSheetBottomSheet: View { + @Environment(\.dismiss) private var dismiss + + @ObservedObject var callViewModel: CallViewModel + + private var idiom: UIUserInterfaceIdiom { UIDevice.current.userInterfaceIdiom } + @State private var orientation = UIDevice.current.orientation + + @Binding var callStatisticsSheet: Bool + + var body: 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") { + callStatisticsSheet = false + dismiss() + } + } + .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) + } +} diff --git a/Linphone/UI/Call/Fragments/ChangeLayoutBottomSheet.swift b/Linphone/UI/Call/Fragments/ChangeLayoutBottomSheet.swift new file mode 100644 index 000000000..7a7bbc7d6 --- /dev/null +++ b/Linphone/UI/Call/Fragments/ChangeLayoutBottomSheet.swift @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2010-2023 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 . + */ + +import SwiftUI + +struct ChangeLayoutBottomSheet: View { + @Environment(\.dismiss) private var dismiss + + @ObservedObject var callViewModel: CallViewModel + + private var idiom: UIUserInterfaceIdiom { UIDevice.current.userInterfaceIdiom } + @State private var orientation = UIDevice.current.orientation + + @Binding var changeLayoutSheet: Bool + @Binding var optionsChangeLayout: Int + + var body: some View { + VStack(spacing: 0) { + Button(action: { + optionsChangeLayout = 1 + callViewModel.toggleVideoMode(isAudioOnlyMode: false) + changeLayoutSheet = false + dismiss() + }, label: { + HStack { + Image(optionsChangeLayout == 1 ? "radio-button-fill" : "radio-button") + .renderingMode(.template) + .resizable() + .foregroundStyle(callViewModel.participantList.count > 5 ? Color.gray500 : .white) + .frame(width: 25, height: 25, alignment: .leading) + .padding(.all, 10) + + Text("Mosaïque") + .foregroundStyle(callViewModel.participantList.count > 5 ? Color.gray500 : .white) + .default_text_style_white(styleSize: 15) + + Spacer() + + Image("squares-four") + .renderingMode(.template) + .resizable() + .foregroundStyle(callViewModel.participantList.count > 5 ? Color.gray500 : .white) + .frame(width: 25, height: 25, alignment: .leading) + .padding(.all, 10) + } + }) + .disabled(callViewModel.participantList.count > 5) + .frame(maxHeight: .infinity) + + Button(action: { + optionsChangeLayout = 2 + callViewModel.toggleVideoMode(isAudioOnlyMode: false) + changeLayoutSheet = false + dismiss() + }, label: { + HStack { + Image(optionsChangeLayout == 2 ? "radio-button-fill" : "radio-button") + .renderingMode(.template) + .resizable() + .foregroundStyle(.white) + .frame(width: 25, height: 25, alignment: .leading) + .padding(.all, 10) + + Text("Participant actif") + .default_text_style_white(styleSize: 15) + + Spacer() + + Image("picture-in-picture") + .renderingMode(.template) + .resizable() + .foregroundStyle(.white) + .frame(width: 25, height: 25, alignment: .leading) + .padding(.all, 10) + } + }) + .frame(maxHeight: .infinity) + + Button(action: { + optionsChangeLayout = 3 + if callViewModel.videoDisplayed { + callViewModel.displayMyVideo() + } + callViewModel.toggleVideoMode(isAudioOnlyMode: true) + changeLayoutSheet = false + dismiss() + }, label: { + HStack { + Image(optionsChangeLayout == 3 ? "radio-button-fill" : "radio-button") + .renderingMode(.template) + .resizable() + .foregroundStyle(.white) + .frame(width: 25, height: 25, alignment: .leading) + .padding(.all, 10) + + Text("Audio seulement") + .default_text_style_white(styleSize: 15) + + Spacer() + + Image("waveform") + .renderingMode(.template) + .resizable() + .foregroundStyle(.white) + .frame(width: 25, height: 25, alignment: .leading) + .padding(.all, 10) + } + }) + .frame(maxHeight: .infinity) + } + .padding(.horizontal, 20) + .background(Color.gray600) + .frame(maxHeight: .infinity) + } +} diff --git a/Linphone/UI/Call/Fragments/MediaEncryptedSheetBottomSheet.swift b/Linphone/UI/Call/Fragments/MediaEncryptedSheetBottomSheet.swift new file mode 100644 index 000000000..cbf9832e4 --- /dev/null +++ b/Linphone/UI/Call/Fragments/MediaEncryptedSheetBottomSheet.swift @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2010-2023 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 . + */ + +import SwiftUI + +struct MediaEncryptedSheetBottomSheet: View { + @Environment(\.dismiss) private var dismiss + + @ObservedObject var callViewModel: CallViewModel + + private var idiom: UIUserInterfaceIdiom { UIDevice.current.userInterfaceIdiom } + @State private var orientation = UIDevice.current.orientation + + @Binding var mediaEncryptedSheet: Bool + + var body: 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 + dismiss() + } + } + .padding(.trailing) + } else { + Capsule() + .fill(Color.grayMain2c300) + .frame(width: 75, height: 5) + .padding(15) + } + + Text("Chiffrement du média") + .default_text_style_white_600(styleSize: 15) + .padding(.top, 10) + + Spacer() + + Text(callViewModel.callMediaEncryptionModel.mediaEncryption) + .default_text_style_white(styleSize: 15) + + Spacer() + + Text(callViewModel.callMediaEncryptionModel.zrtpCipher) + .default_text_style_white(styleSize: 15) + + Spacer() + + Text(callViewModel.callMediaEncryptionModel.zrtpKeyAgreement) + .default_text_style_white(styleSize: 15) + + Spacer() + + Text(callViewModel.callMediaEncryptionModel.zrtpHash) + .default_text_style_white(styleSize: 15) + + Spacer() + + Text(callViewModel.callMediaEncryptionModel.zrtpAuthTag) + .default_text_style_white(styleSize: 15) + + Spacer() + + Text(callViewModel.callMediaEncryptionModel.zrtpAuthSas) + .default_text_style_white(styleSize: 15) + .padding(.bottom, 10) + + Spacer() + + Button(action: { + callViewModel.showZrtpSasDialogIfPossible() + mediaEncryptedSheet = false + dismiss() + }, label: { + Text("Faire la validation à nouveau") + .default_text_style_white_600(styleSize: 20) + .frame(height: 35) + .frame(maxWidth: .infinity) + }) + .padding(.horizontal, 20) + .padding(.vertical, 10) + .background(Color.orangeMain500) + .cornerRadius(60) + .padding(.bottom) + .padding(.horizontal, 10) + } + .background(Color.gray600) + } +} diff --git a/Linphone/UI/Call/Model/CallStatsModel.swift b/Linphone/UI/Call/Model/CallStatsModel.swift index d48e09f96..32b8b36e8 100644 --- a/Linphone/UI/Call/Model/CallStatsModel.swift +++ b/Linphone/UI/Call/Model/CallStatsModel.swift @@ -43,9 +43,10 @@ class CallStatsModel: ObservableObject { let clockRate = (payloadType?.clockRate != nil ? payloadType!.clockRate : 0) / 1000 let codecLabel = "Codec: " + "\(payloadType != nil ? payloadType!.mimeType : "")/\(clockRate) kHz" - guard !(stats.uploadBandwidth.rounded().isNaN || stats.uploadBandwidth.rounded().isInfinite || stats.downloadBandwidth.rounded().isNaN || stats.downloadBandwidth.rounded().isInfinite) else { + if !(stats.uploadBandwidth.rounded().isNaN || stats.uploadBandwidth.rounded().isInfinite || stats.downloadBandwidth.rounded().isNaN || stats.downloadBandwidth.rounded().isInfinite) { return } + let uploadBandwidth = Int(stats.uploadBandwidth.rounded()) let downloadBandwidth = Int(stats.downloadBandwidth.rounded()) let bandwidthLabel = "Bandwidth: " + "↑ \(uploadBandwidth) kbits/s ↓ \(downloadBandwidth) kbits/s" @@ -61,9 +62,10 @@ class CallStatsModel: ObservableObject { let clockRate = (payloadType?.clockRate != nil ? payloadType!.clockRate : 0) / 1000 let codecLabel = "Codec: " + "\(payloadType != nil ? payloadType!.mimeType : "null")/\(clockRate) kHz" - guard !(stats.uploadBandwidth.rounded().isNaN || stats.uploadBandwidth.rounded().isInfinite || stats.downloadBandwidth.rounded().isNaN || stats.downloadBandwidth.rounded().isInfinite) else { + if !(stats.uploadBandwidth.rounded().isNaN || stats.uploadBandwidth.rounded().isInfinite || stats.downloadBandwidth.rounded().isNaN || stats.downloadBandwidth.rounded().isInfinite) { return } + let uploadBandwidth = Int(stats.uploadBandwidth.rounded()) let downloadBandwidth = Int(stats.downloadBandwidth.rounded()) let bandwidthLabel = "Bandwidth: " + "↑ \(uploadBandwidth) kbits/s ↓ \(downloadBandwidth) kbits/s"