From 29b34f2cb977c029e7e30c0ddc8add7eb31a2864 Mon Sep 17 00:00:00 2001 From: Rasmus Tauts Date: Tue, 26 Sep 2023 15:32:35 +0300 Subject: [PATCH] Convert ScreenSharingView to SwiftUI This PR converts ScreenSharingView to SwiftUI MOB-2720 --- GliaWidgets.xcodeproj/project.pbxproj | 62 ++++--- GliaWidgets/Public/Glia/Glia.swift | 3 +- ...SecureConversations.ConfirmationView.swift | 8 +- ...ersations.ConfirmationViewController.swift | 9 +- .../CallVisualizer+Environment.swift | 1 + .../CallVisualizer/CallVisualizer.swift | 3 +- ...llVisualizer.Coordinator.Environment.swift | 1 + .../CallVisualizer.Coordinator.swift | 3 +- .../CallVisualizer.Environment.Mock.swift | 3 +- .../Mock/ScreenSharingViewModel.mock.swift | 19 ++ ...ScreenSharingCoordinator+Environment.swift | 1 + .../ScreenSharingCoordinator.swift | 35 ++-- .../Model/ScreenSharingViewModel.swift | 110 ++++++++++++ ...ScreenSharingViewStyle.Accessibility.swift | 0 .../{ => Style}/ScreenSharingViewStyle.swift | 0 .../View/ScreenSharingView.swift | 166 ++++++------------ .../ScreenSharingViewController+Props.swift | 7 - .../ScreenSharingViewController.swift | 40 +++-- .../ScreenSharingViewModel+Environment.swift | 7 - .../ScreenSharingViewModel+Output.swift | 7 - .../ViewModel/ScreenSharingViewModel.swift | 66 ------- .../Components/BackgroundSwiftUI.swift | 24 +++ .../Buttons/ActionButtonSwiftUI.swift | 8 +- .../Buttons/HeaderButtonSwiftUI.swift | 8 +- .../Components/Header/HeaderSwiftUI.swift | 6 +- .../Extensions/View+Accessibility.swift | 92 +++++++++- .../Mocks/ScreenSharingView.Mock.swift | 15 -- .../ScreenSharingViewController.Mock.swift | 13 -- .../Mocks/ScreenSharingViewStyle+Mock.swift | 2 +- .../ScreenSharingViewModelTests.swift | 29 +-- .../VideoCall/Mocks/HeaderStyle.Mock.swift | 2 +- ...reViewControllerDynamicTypeFontTests.swift | 22 +-- ...ScreenShareViewControllerLayoutTests.swift | 22 +-- ...eenShareViewControllerVoiceOverTests.swift | 20 +-- .../SwiftPackageManager/spm-project.yml | 2 +- 35 files changed, 409 insertions(+), 407 deletions(-) create mode 100644 GliaWidgets/Sources/CallVisualizer/Mock/ScreenSharingViewModel.mock.swift create mode 100644 GliaWidgets/Sources/CallVisualizer/ScreenSharing/Model/ScreenSharingViewModel.swift rename GliaWidgets/Sources/CallVisualizer/ScreenSharing/{ => Style}/ScreenSharingViewStyle.Accessibility.swift (100%) rename GliaWidgets/Sources/CallVisualizer/ScreenSharing/{ => Style}/ScreenSharingViewStyle.swift (100%) delete mode 100644 GliaWidgets/Sources/CallVisualizer/ScreenSharing/ViewController/ScreenSharingViewController+Props.swift delete mode 100644 GliaWidgets/Sources/CallVisualizer/ScreenSharing/ViewModel/ScreenSharingViewModel+Environment.swift delete mode 100644 GliaWidgets/Sources/CallVisualizer/ScreenSharing/ViewModel/ScreenSharingViewModel+Output.swift delete mode 100644 GliaWidgets/Sources/CallVisualizer/ScreenSharing/ViewModel/ScreenSharingViewModel.swift create mode 100644 GliaWidgets/SwiftUI/Components/BackgroundSwiftUI.swift delete mode 100644 GliaWidgetsTests/CallVisualizer/ScreenSharing/Mocks/ScreenSharingView.Mock.swift delete mode 100644 GliaWidgetsTests/CallVisualizer/ScreenSharing/Mocks/ScreenSharingViewController.Mock.swift diff --git a/GliaWidgets.xcodeproj/project.pbxproj b/GliaWidgets.xcodeproj/project.pbxproj index eaa6de030..5b67da6b2 100644 --- a/GliaWidgets.xcodeproj/project.pbxproj +++ b/GliaWidgets.xcodeproj/project.pbxproj @@ -311,16 +311,12 @@ 84265E07298AE96B00D65842 /* ScreenSharingViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84265E06298AE96B00D65842 /* ScreenSharingViewModelTests.swift */; }; 84265E4B298D7B1900D65842 /* CallVisualizer.Coordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84265E49298D7B1900D65842 /* CallVisualizer.Coordinator.swift */; }; 84265E4C298D7B1900D65842 /* CallVisualizer.Coordinator.Environment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84265E4A298D7B1900D65842 /* CallVisualizer.Coordinator.Environment.swift */; }; - 84265E5D298D7B2900D65842 /* ScreenSharingViewModel+Environment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84265E4F298D7B2900D65842 /* ScreenSharingViewModel+Environment.swift */; }; - 84265E5E298D7B2900D65842 /* ScreenSharingViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84265E50298D7B2900D65842 /* ScreenSharingViewModel.swift */; }; - 84265E5F298D7B2900D65842 /* ScreenSharingViewModel+Output.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84265E51298D7B2900D65842 /* ScreenSharingViewModel+Output.swift */; }; 84265E60298D7B2900D65842 /* ScreenSharingCoordinator+Environment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84265E53298D7B2900D65842 /* ScreenSharingCoordinator+Environment.swift */; }; 84265E61298D7B2900D65842 /* ScreenSharingCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84265E54298D7B2900D65842 /* ScreenSharingCoordinator.swift */; }; 84265E62298D7B2900D65842 /* ScreenSharingCoordinator+DelegateEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84265E55298D7B2900D65842 /* ScreenSharingCoordinator+DelegateEvent.swift */; }; 84265E63298D7B2900D65842 /* ScreenSharingViewStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84265E56298D7B2900D65842 /* ScreenSharingViewStyle.swift */; }; 84265E64298D7B2900D65842 /* ScreenSharingViewStyle.Accessibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84265E57298D7B2900D65842 /* ScreenSharingViewStyle.Accessibility.swift */; }; 84265E65298D7B2900D65842 /* ScreenSharingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84265E59298D7B2900D65842 /* ScreenSharingView.swift */; }; - 84265E66298D7B2900D65842 /* ScreenSharingViewController+Props.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84265E5B298D7B2900D65842 /* ScreenSharingViewController+Props.swift */; }; 84265E67298D7B2900D65842 /* ScreenSharingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84265E5C298D7B2900D65842 /* ScreenSharingViewController.swift */; }; 84265E6B29912E2100D65842 /* RemoteConfiguration+CallVisualizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84265E6A29912E2100D65842 /* RemoteConfiguration+CallVisualizer.swift */; }; 84265E6E29914DDA00D65842 /* ViewController+CallVisualizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84265E6D29914DDA00D65842 /* ViewController+CallVisualizer.swift */; }; @@ -603,11 +599,12 @@ C06A7586296ECC57006B69A2 /* VisitorCodeStyle.Accessibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = C06A7585296ECC57006B69A2 /* VisitorCodeStyle.Accessibility.swift */; }; C06A7588296ECD75006B69A2 /* Theme+VisitorCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = C06A7587296ECD75006B69A2 /* Theme+VisitorCode.swift */; }; C07F62462ABC322B003EFC97 /* OrientationManager.Mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = C07F62452ABC322B003EFC97 /* OrientationManager.Mock.swift */; }; + C07F62792AC2D2E8003EFC97 /* BackgroundSwiftUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = C07F62782AC2D2E8003EFC97 /* BackgroundSwiftUI.swift */; }; + C07F627D2AC2F31F003EFC97 /* ScreenSharingViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C07F627C2AC2F31F003EFC97 /* ScreenSharingViewModel.swift */; }; + C07F62812AC3057C003EFC97 /* ScreenSharingViewModel.mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = C07F62802AC3057C003EFC97 /* ScreenSharingViewModel.mock.swift */; }; C07F62772AC1BA2B003EFC97 /* UIViewController+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C07F62762AC1BA2B003EFC97 /* UIViewController+Extensions.swift */; }; C07F62832AC33BB9003EFC97 /* UIView+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C07F62822AC33BB9003EFC97 /* UIView+Extensions.swift */; }; C07FA04029AF542A00E9FB7F /* ScreenSharingViewStyle+Mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84265E0B298AECBA00D65842 /* ScreenSharingViewStyle+Mock.swift */; }; - C07FA04329AF551D00E9FB7F /* ScreenSharingView.Mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = C07FA04129AF550500E9FB7F /* ScreenSharingView.Mock.swift */; }; - C07FA04629AF560A00E9FB7F /* ScreenSharingViewController.Mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = C07FA04429AF55F600E9FB7F /* ScreenSharingViewController.Mock.swift */; }; C07FA04B29AF83B900E9FB7F /* ActionButton.Mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = C07FA04929AF83A400E9FB7F /* ActionButton.Mock.swift */; }; C07FA04F29B0E41A00E9FB7F /* ScreenShareViewControllerVoiceOverTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C07FA04C29B0E41A00E9FB7F /* ScreenShareViewControllerVoiceOverTests.swift */; }; C07FA05029B0E41A00E9FB7F /* VideoCallViewControllerVoiceOverTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C07FA04D29B0E41A00E9FB7F /* VideoCallViewControllerVoiceOverTests.swift */; }; @@ -1051,16 +1048,12 @@ 84265E0B298AECBA00D65842 /* ScreenSharingViewStyle+Mock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ScreenSharingViewStyle+Mock.swift"; sourceTree = ""; }; 84265E49298D7B1900D65842 /* CallVisualizer.Coordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallVisualizer.Coordinator.swift; sourceTree = ""; }; 84265E4A298D7B1900D65842 /* CallVisualizer.Coordinator.Environment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallVisualizer.Coordinator.Environment.swift; sourceTree = ""; }; - 84265E4F298D7B2900D65842 /* ScreenSharingViewModel+Environment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ScreenSharingViewModel+Environment.swift"; sourceTree = ""; }; - 84265E50298D7B2900D65842 /* ScreenSharingViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScreenSharingViewModel.swift; sourceTree = ""; }; - 84265E51298D7B2900D65842 /* ScreenSharingViewModel+Output.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ScreenSharingViewModel+Output.swift"; sourceTree = ""; }; 84265E53298D7B2900D65842 /* ScreenSharingCoordinator+Environment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ScreenSharingCoordinator+Environment.swift"; sourceTree = ""; }; 84265E54298D7B2900D65842 /* ScreenSharingCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScreenSharingCoordinator.swift; sourceTree = ""; }; 84265E55298D7B2900D65842 /* ScreenSharingCoordinator+DelegateEvent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ScreenSharingCoordinator+DelegateEvent.swift"; sourceTree = ""; }; 84265E56298D7B2900D65842 /* ScreenSharingViewStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScreenSharingViewStyle.swift; sourceTree = ""; }; 84265E57298D7B2900D65842 /* ScreenSharingViewStyle.Accessibility.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScreenSharingViewStyle.Accessibility.swift; sourceTree = ""; }; 84265E59298D7B2900D65842 /* ScreenSharingView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScreenSharingView.swift; sourceTree = ""; }; - 84265E5B298D7B2900D65842 /* ScreenSharingViewController+Props.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ScreenSharingViewController+Props.swift"; sourceTree = ""; }; 84265E5C298D7B2900D65842 /* ScreenSharingViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScreenSharingViewController.swift; sourceTree = ""; }; 84265E6A29912E2100D65842 /* RemoteConfiguration+CallVisualizer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "RemoteConfiguration+CallVisualizer.swift"; sourceTree = ""; }; 84265E6D29914DDA00D65842 /* ViewController+CallVisualizer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ViewController+CallVisualizer.swift"; sourceTree = ""; }; @@ -1348,6 +1341,9 @@ C06A7585296ECC57006B69A2 /* VisitorCodeStyle.Accessibility.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VisitorCodeStyle.Accessibility.swift; sourceTree = ""; }; C06A7587296ECD75006B69A2 /* Theme+VisitorCode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Theme+VisitorCode.swift"; sourceTree = ""; }; C07F62452ABC322B003EFC97 /* OrientationManager.Mock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrientationManager.Mock.swift; sourceTree = ""; }; + C07F62782AC2D2E8003EFC97 /* BackgroundSwiftUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundSwiftUI.swift; sourceTree = ""; }; + C07F627C2AC2F31F003EFC97 /* ScreenSharingViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenSharingViewModel.swift; sourceTree = ""; }; + C07F62802AC3057C003EFC97 /* ScreenSharingViewModel.mock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenSharingViewModel.mock.swift; sourceTree = ""; }; C07F62762AC1BA2B003EFC97 /* UIViewController+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+Extensions.swift"; sourceTree = ""; }; C07F62822AC33BB9003EFC97 /* UIView+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Extensions.swift"; sourceTree = ""; }; C07FA04129AF550500E9FB7F /* ScreenSharingView.Mock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenSharingView.Mock.swift; sourceTree = ""; }; @@ -2919,6 +2915,7 @@ children = ( 75940978298D38C2008B173A /* CallVisualizer.Environment.Mock.swift */, 75940979298D38C2008B173A /* CallVisualizer.VisitorCodeViewModel.Mock.swift */, + C07F62802AC3057C003EFC97 /* ScreenSharingViewModel.mock.swift */, ); path = Mock; sourceTree = ""; @@ -2988,8 +2985,6 @@ children = ( 84265E0B298AECBA00D65842 /* ScreenSharingViewStyle+Mock.swift */, C07FA04929AF83A400E9FB7F /* ActionButton.Mock.swift */, - C07FA04129AF550500E9FB7F /* ScreenSharingView.Mock.swift */, - C07FA04429AF55F600E9FB7F /* ScreenSharingViewController.Mock.swift */, ); path = Mocks; sourceTree = ""; @@ -3007,26 +3002,15 @@ 84265E4D298D7B2900D65842 /* ScreenSharing */ = { isa = PBXGroup; children = ( - 84265E4E298D7B2900D65842 /* ViewModel */, 84265E52298D7B2900D65842 /* Coordinator */, - 84265E56298D7B2900D65842 /* ScreenSharingViewStyle.swift */, - 84265E57298D7B2900D65842 /* ScreenSharingViewStyle.Accessibility.swift */, + C07F627A2AC2F2F4003EFC97 /* Model */, + C07F627B2AC2F301003EFC97 /* Style */, 84265E58298D7B2900D65842 /* View */, 84265E5A298D7B2900D65842 /* ViewController */, ); path = ScreenSharing; sourceTree = ""; }; - 84265E4E298D7B2900D65842 /* ViewModel */ = { - isa = PBXGroup; - children = ( - 84265E4F298D7B2900D65842 /* ScreenSharingViewModel+Environment.swift */, - 84265E50298D7B2900D65842 /* ScreenSharingViewModel.swift */, - 84265E51298D7B2900D65842 /* ScreenSharingViewModel+Output.swift */, - ); - path = ViewModel; - sourceTree = ""; - }; 84265E52298D7B2900D65842 /* Coordinator */ = { isa = PBXGroup; children = ( @@ -3048,7 +3032,6 @@ 84265E5A298D7B2900D65842 /* ViewController */ = { isa = PBXGroup; children = ( - 84265E5B298D7B2900D65842 /* ScreenSharingViewController+Props.swift */, 84265E5C298D7B2900D65842 /* ScreenSharingViewController.swift */, ); path = ViewController; @@ -3598,6 +3581,23 @@ path = extensions; sourceTree = ""; }; + C07F627A2AC2F2F4003EFC97 /* Model */ = { + isa = PBXGroup; + children = ( + C07F627C2AC2F31F003EFC97 /* ScreenSharingViewModel.swift */, + ); + path = Model; + sourceTree = ""; + }; + C07F627B2AC2F301003EFC97 /* Style */ = { + isa = PBXGroup; + children = ( + 84265E56298D7B2900D65842 /* ScreenSharingViewStyle.swift */, + 84265E57298D7B2900D65842 /* ScreenSharingViewStyle.Accessibility.swift */, + ); + path = Style; + sourceTree = ""; + }; C096B408297EBCEB00F0C552 /* CallVisualizer */ = { isa = PBXGroup; children = ( @@ -3728,6 +3728,7 @@ children = ( C0E948072AB1D69C00890026 /* Header */, C0E948022AB1D5BC00890026 /* Buttons */, + C07F62782AC2D2E8003EFC97 /* BackgroundSwiftUI.swift */, ); path = Components; sourceTree = ""; @@ -4401,9 +4402,11 @@ 8491AF132A7ACC5400CC3E72 /* Theme.OperatorChatMessageStyle.swift in Sources */, 845E2F93283FB6D000C04D56 /* Theme.Survey.Accessibility.swift in Sources */, 75940959298D386F008B173A /* UIStackView.Extensions.swift in Sources */, + C07F627D2AC2F31F003EFC97 /* ScreenSharingViewModel.swift in Sources */, 1A0C9A9125C41AB900815406 /* CallButtonBar.swift in Sources */, C0D2F0302991229F00803B47 /* VideoCallCoordinator.Environment.swift in Sources */, 1AE15E3B257A5CC900A642C0 /* AlertConfiguration.swift in Sources */, + C07F62792AC2D2E8003EFC97 /* BackgroundSwiftUI.swift in Sources */, 75AF8D1027DFF4B3009EEE2C /* Survey.ValidationErrorView.swift in Sources */, 75940986298D38C2008B173A /* VisitorCodeView.swift in Sources */, 9A8130B927D757F900220BBD /* LocalFile.Mock.swift in Sources */, @@ -4477,19 +4480,17 @@ 1A0452F025DBE268000DA0C1 /* MessageButtonStyle.swift in Sources */, EB2CBB1227D89F7D004F178E /* OnHoldOverlayStyle.swift in Sources */, 75940983298D38C2008B173A /* VisitorCodeViewModel+Delegate.swift in Sources */, - 84265E66298D7B2900D65842 /* ScreenSharingViewController+Props.swift in Sources */, C07FA04B29AF83B900E9FB7F /* ActionButton.Mock.swift in Sources */, C0D2F08C29A4EBA900803B47 /* VIdeoCallView.Environment.Mock.swift in Sources */, 313EBD552943116E008E9597 /* SecureConversations.swift in Sources */, - C07FA04329AF551D00E9FB7F /* ScreenSharingView.Mock.swift in Sources */, 7529F2B627E1EB9A004D3581 /* Survey.ButtonView.swift in Sources */, + C07F62812AC3057C003EFC97 /* ScreenSharingViewModel.mock.swift in Sources */, C49A29E42614A29700819269 /* FilePreviewView.swift in Sources */, 1A5F815F258A43E600A605DA /* Section.swift in Sources */, 1A60AFBF2566834400E53F53 /* BaseViewController.swift in Sources */, 6E60DD5627146C9D001422EF /* AlertViewController+SingleAction.swift in Sources */, 845E2F70283CF94100C04D56 /* VisitorChatMessageStyle.Accessibility.swift in Sources */, 8491AF4E2A9CB3A400CC3E72 /* SecureConversations.TranscriptModel+GVA.swift in Sources */, - 84265E5F298D7B2900D65842 /* ScreenSharingViewModel+Output.swift in Sources */, 8491AF062A77F16D00CC3E72 /* GvaGalleryCardStyle.swift in Sources */, 1A60AFF12566A4B300E53F53 /* NavigationPresenter.swift in Sources */, 1AC7A74F2582571100567FF8 /* Interactor.swift in Sources */, @@ -4600,7 +4601,6 @@ 1AA738B925790DB400E1120F /* ActionButtonStyle.swift in Sources */, C06A7582296EC856006B69A2 /* NumberSlotStyle.swift in Sources */, 1A2DA71F25EF720400032611 /* FilePickerViewModel.swift in Sources */, - 84265E5D298D7B2900D65842 /* ScreenSharingViewModel+Environment.swift in Sources */, 750C0ADD2850D53F003E0415 /* Theme.Survey.ScaleQuestion.swift in Sources */, 9A1992E927D6BCD700161AAE /* FileDownload.Mock.swift in Sources */, AF3D520D2983B3DD00AD8E69 /* FileUploader.Environment.Interface.swift in Sources */, @@ -4711,7 +4711,6 @@ 3197F7B829F7C318008EE9F7 /* SecureConversations.CommonEngagementModel.swift in Sources */, 31DD41652A57105400F92612 /* SecureConversations.TranscriptModel.Environment.swift in Sources */, 1A277A1225FA604E009FE131 /* ChatFileContentView.swift in Sources */, - 84265E5E298D7B2900D65842 /* ScreenSharingViewModel.swift in Sources */, 75B7BD802A39D5A70060794D /* Layoutable.swift in Sources */, 845876AB282A959C007AC3DF /* SingleChoiceQuestionView.Props.Accessibility.swift in Sources */, 9AB3402327FC859E006E0FE2 /* CallButtonStyle.StateStyle.Accessibility.swift in Sources */, @@ -4799,7 +4798,6 @@ 846A5C3629CB3E270049B29F /* ScreenShareHandler.Mock.swift in Sources */, C0D2F03B299149D600803B47 /* VideoCallViewModel.swift in Sources */, C0D2F02E2991221900803B47 /* VideoCallCoordinator.DelegateEvent.swift in Sources */, - C07FA04629AF560A00E9FB7F /* ScreenSharingViewController.Mock.swift in Sources */, 1A2DA73125EFA77E00032611 /* FileUploader.swift in Sources */, 1A60B0272568070800E53F53 /* UIStackView+Extensions.swift in Sources */, 75940945298D378A008B173A /* CoreSDKClient.Mock.swift in Sources */, diff --git a/GliaWidgets/Public/Glia/Glia.swift b/GliaWidgets/Public/Glia/Glia.swift index 5fbf3c006..538370f33 100644 --- a/GliaWidgets/Public/Glia/Glia.swift +++ b/GliaWidgets/Public/Glia/Glia.swift @@ -83,7 +83,8 @@ public class Glia { uiConfig: { [weak self] in self?.uiConfig }, assetsBuilder: { [weak self] in self?.assetsBuilder ?? .standard }, getCurrentEngagement: environment.coreSdk.getCurrentEngagement, - eventHandler: onEvent + eventHandler: onEvent, + orientationManager: environment.orientationManager ) ) var rootCoordinator: EngagementCoordinator? diff --git a/GliaWidgets/SecureConversations/Confirmation/SecureConversations.ConfirmationView.swift b/GliaWidgets/SecureConversations/Confirmation/SecureConversations.ConfirmationView.swift index 08ce4c92d..d15265e26 100644 --- a/GliaWidgets/SecureConversations/Confirmation/SecureConversations.ConfirmationView.swift +++ b/GliaWidgets/SecureConversations/Confirmation/SecureConversations.ConfirmationView.swift @@ -40,7 +40,7 @@ private extension SecureConversations.ConfirmationViewSwiftUI { .frame(width: model.orientation.isPortrait ? 100.0 : 70.0) .foregroundColor(SwiftUI.Color(model.style.confirmationImageTint)) .padding(.bottom, model.orientation.isPortrait ? 32 : 8) - .accessibility(hidden: true) + .migrationAccessibilityHidden(true) } @ViewBuilder @@ -80,8 +80,8 @@ private extension SecureConversations.ConfirmationViewSwiftUI { .background(SwiftUI.Color(model.style.checkMessagesButtonStyle.backgroundColor)) .cornerRadius(4) } - .accessibility(identifier: "secureConversations_confirmationCheckMessages_button") - .accessibility(label: Text(model.style.checkMessagesButtonStyle.accessibility.label)) - .accessibility(hint: Text(model.style.checkMessagesButtonStyle.accessibility.hint)) + .migrationAccessibilityIdentifier("secureConversations_confirmationCheckMessages_button") + .migrationAccessibilityLabel(model.style.checkMessagesButtonStyle.accessibility.label) + .migrationAccessibilityHint(model.style.checkMessagesButtonStyle.accessibility.hint) } } diff --git a/GliaWidgets/SecureConversations/Confirmation/SecureConversations.ConfirmationViewController.swift b/GliaWidgets/SecureConversations/Confirmation/SecureConversations.ConfirmationViewController.swift index 053cf7374..c7f2a64ab 100644 --- a/GliaWidgets/SecureConversations/Confirmation/SecureConversations.ConfirmationViewController.swift +++ b/GliaWidgets/SecureConversations/Confirmation/SecureConversations.ConfirmationViewController.swift @@ -5,9 +5,7 @@ extension SecureConversations { final class ConfirmationViewController: UIViewController { private let model: ConfirmationViewSwiftUI.Model - init( - model: ConfirmationViewSwiftUI.Model - ) { + init(model: ConfirmationViewSwiftUI.Model) { self.model = model super.init(nibName: nil, bundle: nil) } @@ -20,11 +18,10 @@ extension SecureConversations { override func loadView() { super.loadView() let hostingController: UIHostingController - let confirmationView = ConfirmationViewSwiftUI( - model: model - ) + let confirmationView = ConfirmationViewSwiftUI(model: model) hostingController = UIHostingController(rootView: confirmationView) + hostingController.willMove(toParent: self) addChild(hostingController) view.addSubview(hostingController.view) hostingController.didMove(toParent: self) diff --git a/GliaWidgets/Sources/CallVisualizer/CallVisualizer+Environment.swift b/GliaWidgets/Sources/CallVisualizer/CallVisualizer+Environment.swift index 9c376668c..79f1ecdde 100644 --- a/GliaWidgets/Sources/CallVisualizer/CallVisualizer+Environment.swift +++ b/GliaWidgets/Sources/CallVisualizer/CallVisualizer+Environment.swift @@ -23,5 +23,6 @@ extension CallVisualizer { var assetsBuilder: () -> RemoteConfiguration.AssetsBuilder var getCurrentEngagement: CoreSdkClient.GetCurrentEngagement var eventHandler: ((GliaEvent) -> Void)? + var orientationManager: OrientationManager } } diff --git a/GliaWidgets/Sources/CallVisualizer/CallVisualizer.swift b/GliaWidgets/Sources/CallVisualizer/CallVisualizer.swift index 4684b8e3a..ad8760831 100644 --- a/GliaWidgets/Sources/CallVisualizer/CallVisualizer.swift +++ b/GliaWidgets/Sources/CallVisualizer/CallVisualizer.swift @@ -57,7 +57,8 @@ public final class CallVisualizer { case .maximized: self?.environment.eventHandler?(.maximized) } - } + }, + orientationManager: environment.orientationManager ) ) }() diff --git a/GliaWidgets/Sources/CallVisualizer/Coordinator/CallVisualizer.Coordinator.Environment.swift b/GliaWidgets/Sources/CallVisualizer/Coordinator/CallVisualizer.Coordinator.Environment.swift index 079ce7f0d..cfc07aa4c 100644 --- a/GliaWidgets/Sources/CallVisualizer/Coordinator/CallVisualizer.Coordinator.Environment.swift +++ b/GliaWidgets/Sources/CallVisualizer/Coordinator/CallVisualizer.Coordinator.Environment.swift @@ -20,5 +20,6 @@ extension CallVisualizer.Coordinator { var date: () -> Date var engagedOperator: () -> CoreSdkClient.Operator? var eventHandler: (DelegateEvent) -> Void + var orientationManager: OrientationManager } } diff --git a/GliaWidgets/Sources/CallVisualizer/Coordinator/CallVisualizer.Coordinator.swift b/GliaWidgets/Sources/CallVisualizer/Coordinator/CallVisualizer.Coordinator.swift index e9a4b6f65..302b708ae 100644 --- a/GliaWidgets/Sources/CallVisualizer/Coordinator/CallVisualizer.Coordinator.swift +++ b/GliaWidgets/Sources/CallVisualizer/Coordinator/CallVisualizer.Coordinator.swift @@ -182,7 +182,8 @@ extension CallVisualizer { let coordinator = ScreenSharingCoordinator( environment: .init( theme: environment.viewFactory.theme, - screenShareHandler: environment.screenShareHandler + screenShareHandler: environment.screenShareHandler, + orientationManager: environment.orientationManager ) ) diff --git a/GliaWidgets/Sources/CallVisualizer/Mock/CallVisualizer.Environment.Mock.swift b/GliaWidgets/Sources/CallVisualizer/Mock/CallVisualizer.Environment.Mock.swift index 34e3d57d0..be3732d4d 100644 --- a/GliaWidgets/Sources/CallVisualizer/Mock/CallVisualizer.Environment.Mock.swift +++ b/GliaWidgets/Sources/CallVisualizer/Mock/CallVisualizer.Environment.Mock.swift @@ -21,7 +21,8 @@ extension CallVisualizer.Environment { engagedOperator: { .mock() }, uiConfig: { nil }, assetsBuilder: { .standard }, - getCurrentEngagement: CoreSdkClient.mock.getCurrentEngagement + getCurrentEngagement: CoreSdkClient.mock.getCurrentEngagement, + orientationManager: .mock() ) } diff --git a/GliaWidgets/Sources/CallVisualizer/Mock/ScreenSharingViewModel.mock.swift b/GliaWidgets/Sources/CallVisualizer/Mock/ScreenSharingViewModel.mock.swift new file mode 100644 index 000000000..e2134370e --- /dev/null +++ b/GliaWidgets/Sources/CallVisualizer/Mock/ScreenSharingViewModel.mock.swift @@ -0,0 +1,19 @@ +#if DEBUG +import SwiftUI + +extension CallVisualizer.ScreenSharingView.Model { + static func mock( + style: ScreenSharingViewStyle = .mock(), + screenSharingHandler: ScreenShareHandler = .mock + ) -> CallVisualizer.ScreenSharingView.Model { + .init( + style: style, + environment: .init( + orientationManager: .mock(), + uiApplication: .mock, + screenShareHandler: screenSharingHandler + ) + ) + } +} +#endif diff --git a/GliaWidgets/Sources/CallVisualizer/ScreenSharing/Coordinator/ScreenSharingCoordinator+Environment.swift b/GliaWidgets/Sources/CallVisualizer/ScreenSharing/Coordinator/ScreenSharingCoordinator+Environment.swift index 07db8aa3c..ae170d9ac 100644 --- a/GliaWidgets/Sources/CallVisualizer/ScreenSharing/Coordinator/ScreenSharingCoordinator+Environment.swift +++ b/GliaWidgets/Sources/CallVisualizer/ScreenSharing/Coordinator/ScreenSharingCoordinator+Environment.swift @@ -4,5 +4,6 @@ extension CallVisualizer.ScreenSharingCoordinator { struct Environment { let theme: Theme let screenShareHandler: ScreenShareHandler + let orientationManager: OrientationManager } } diff --git a/GliaWidgets/Sources/CallVisualizer/ScreenSharing/Coordinator/ScreenSharingCoordinator.swift b/GliaWidgets/Sources/CallVisualizer/ScreenSharing/Coordinator/ScreenSharingCoordinator.swift index a86068077..75ab11f25 100644 --- a/GliaWidgets/Sources/CallVisualizer/ScreenSharing/Coordinator/ScreenSharingCoordinator.swift +++ b/GliaWidgets/Sources/CallVisualizer/ScreenSharing/Coordinator/ScreenSharingCoordinator.swift @@ -6,7 +6,7 @@ extension CallVisualizer { var delegate: ((DelegateEvent) -> Void)? private let environment: Environment - private var viewModel: ScreenSharingViewModel? + private var viewModel: ScreenSharingView.Model? var viewController: ScreenSharingViewController? // MARK: - Initialization @@ -24,20 +24,25 @@ extension CallVisualizer { // MARK: - Private private func showEndScreenSharingViewController() -> ViewController { - let viewModel = ScreenSharingViewModel( - style: environment.theme.screenSharing, - environment: .init(screenShareHandler: environment.screenShareHandler) + let environment: ScreenSharingView.Model.Environment = .init( + orientationManager: self.environment.orientationManager, + uiApplication: .live, + screenShareHandler: environment.screenShareHandler + ) + let model: ScreenSharingView.Model = .init( + style: self.environment.theme.screenSharing, + environment: environment ) - self.viewModel = viewModel + self.viewModel = model - let viewController = ScreenSharingViewController(props: viewModel.props()) + let viewController: ScreenSharingViewController = .init(model: model) viewController.modalPresentationStyle = .overFullScreen self.viewController = viewController - viewModel.delegate = .init { [weak self, weak viewController] event in + model.delegate = .init { [weak self, weak viewController] event in switch event { - case .close: + case .closeTapped: viewController?.dismiss(animated: true) self?.delegate?(.close) } @@ -45,19 +50,5 @@ extension CallVisualizer { return viewController } - - private static func createHeaderProps(with header: HeaderStyle) -> Header.Props { - let backButton = header.backButton.map { HeaderButton.Props(style: $0) } - - return .init( - title: "", - effect: .none, - endButton: .init(), - backButton: backButton, - closeButton: .init(style: header.closeButton), - endScreenshareButton: .init(style: header.endScreenShareButton), - style: header - ) - } } } diff --git a/GliaWidgets/Sources/CallVisualizer/ScreenSharing/Model/ScreenSharingViewModel.swift b/GliaWidgets/Sources/CallVisualizer/ScreenSharing/Model/ScreenSharingViewModel.swift new file mode 100644 index 000000000..1be19193a --- /dev/null +++ b/GliaWidgets/Sources/CallVisualizer/ScreenSharing/Model/ScreenSharingViewModel.swift @@ -0,0 +1,110 @@ +import SwiftUI +import Combine + +extension CallVisualizer.ScreenSharingView { + final class Model: ObservableObject { + @Published private(set) var orientation: UIInterfaceOrientation + let style: ScreenSharingViewStyle + let environment: Environment + let orientationManager: OrientationManager + var delegate: Command = .nop + var cancellables: Set = [] + + init(style: ScreenSharingViewStyle, environment: Environment) { + self.style = style + self.environment = environment + self.orientationManager = environment.orientationManager + self.orientation = orientationManager.orientation + + orientationManager.$orientation + .sink { [weak self] orientation in + self?.orientation = orientation + } + .store(in: &self.cancellables) + } + } +} + +extension CallVisualizer.ScreenSharingView.Model { + func event(_ event: Event) { + switch event { + case .closeTapped: + delegate(.closeTapped) + case .endScreenShareTapped: + endScreenSharing() + } + } + + func makeHeaderModel() -> HeaderSwiftUI.Model { + let endButtonProps: ActionButtonSwiftUI.Model = .init( + style: style.header.endButton, + accessibilityIdentifier: "header_end_button", + isEnabled: false, + isHidden: true + ) + + var backButton: HeaderButtonSwiftUI.Model? + if let endButtonStyle = style.header.backButton { + backButton = .init( + tap: Cmd { [weak self] in + self?.delegate(.closeTapped) + }, + style: endButtonStyle, + accessibilityIdentifier: "header_back_button", + size: .init(width: 20, height: 20), + isEnabled: true, + isHidden: false + ) + } + + let closeButtonProps: HeaderButtonSwiftUI.Model = .init( + style: style.header.closeButton, + accessibilityIdentifier: "header_close_button", + isEnabled: false, + isHidden: true + ) + + let endScreenShareButtonProps: HeaderButtonSwiftUI.Model = .init( + style: style.header.endScreenShareButton, + accessibilityIdentifier: "header_end_screen_sharing_button", + isEnabled: false, + isHidden: true + ) + + let environment: HeaderSwiftUI.Environment = .init(uiApplication: environment.uiApplication) + + return .init( + title: style.title, + effect: .none, + endButton: endButtonProps, + backButton: backButton, + closeButton: closeButtonProps, + endScreenshareButton: endScreenShareButtonProps, + style: style.header, + environment: environment + ) + } +} + +private extension CallVisualizer.ScreenSharingView.Model { + func endScreenSharing() { + environment.screenShareHandler.stop(nil) + } +} + +extension CallVisualizer.ScreenSharingView.Model { + struct Environment { + let orientationManager: OrientationManager + let uiApplication: UIKitBased.UIApplication + let screenShareHandler: ScreenShareHandler + } + + enum DelegateEvent { + case closeTapped + } + + enum Event { + case closeTapped + case endScreenShareTapped + } +} diff --git a/GliaWidgets/Sources/CallVisualizer/ScreenSharing/ScreenSharingViewStyle.Accessibility.swift b/GliaWidgets/Sources/CallVisualizer/ScreenSharing/Style/ScreenSharingViewStyle.Accessibility.swift similarity index 100% rename from GliaWidgets/Sources/CallVisualizer/ScreenSharing/ScreenSharingViewStyle.Accessibility.swift rename to GliaWidgets/Sources/CallVisualizer/ScreenSharing/Style/ScreenSharingViewStyle.Accessibility.swift diff --git a/GliaWidgets/Sources/CallVisualizer/ScreenSharing/ScreenSharingViewStyle.swift b/GliaWidgets/Sources/CallVisualizer/ScreenSharing/Style/ScreenSharingViewStyle.swift similarity index 100% rename from GliaWidgets/Sources/CallVisualizer/ScreenSharing/ScreenSharingViewStyle.swift rename to GliaWidgets/Sources/CallVisualizer/ScreenSharing/Style/ScreenSharingViewStyle.swift diff --git a/GliaWidgets/Sources/CallVisualizer/ScreenSharing/View/ScreenSharingView.swift b/GliaWidgets/Sources/CallVisualizer/ScreenSharing/View/ScreenSharingView.swift index 86fcc7a7d..033f18f7c 100644 --- a/GliaWidgets/Sources/CallVisualizer/ScreenSharing/View/ScreenSharingView.swift +++ b/GliaWidgets/Sources/CallVisualizer/ScreenSharing/View/ScreenSharingView.swift @@ -1,127 +1,59 @@ -import UIKit +import SwiftUI extension CallVisualizer { - final class ScreenSharingView: BaseView { - - // MARK: - Props - - struct Props: Equatable { - let style: ScreenSharingViewStyle - let header: Header.Props - let endScreenSharing: ActionButton.Props - - init( - style: ScreenSharingViewStyle, - header: Header.Props, - endScreenSharing: ActionButton.Props - ) { - self.style = style - self.header = header - self.endScreenSharing = endScreenSharing - } - } - - // MARK: - Properties - - private lazy var header = Header(props: props.header) - .make { header in - header.endScreenShareButton.isHidden = true - header.closeButton.isHidden = true - header.endButton.isHidden = true - } - private lazy var messageLabel = UILabel().make { - $0.font = props.style.messageTextFont - $0.textColor = props.style.messageTextColor - $0.text = props.style.messageText - $0.adjustsFontSizeToFitWidth = true - $0.numberOfLines = 2 - $0.textAlignment = .center - $0.accessibilityIdentifier = "end_screen_sharing_message" - $0.translatesAutoresizingMaskIntoConstraints = false - } - private lazy var endScreenSharingButton = ActionButton(props: props.endScreenSharing).make { - $0.setImage(props.style.buttonIcon, for: .normal) - $0.tintColor = props.style.buttonStyle.titleColor - $0.titleEdgeInsets = .init(top: 0, left: 8, bottom: 0, right: 0) - $0.titleLabel?.numberOfLines = 0 - $0.titleLabel?.translatesAutoresizingMaskIntoConstraints = false - $0.accessibilityIdentifier = "end_screen_sharing_button" - $0.accessibilityLabel = Localization.ScreenSharing.VisitorScreen.End.title - $0.accessibilityHint = Localization.ScreenSharing.VisitorScreen.End.Accessibility.hint - } - private lazy var contentStackView = UIStackView.make( - .vertical, - spacing: 16 - )( - messageLabel, - endScreenSharingButton - ) - - var props: Props { - didSet { - renderProps() - } - } - - // MARK: - Initialization - - init(props: Props) { - self.props = props - super.init() - } - - required init() { - fatalError("init() has not been implemented") - } - - // MARK: - Overrides - - override func setup() { - super.setup() - - addSubview(header) - header.translatesAutoresizingMaskIntoConstraints = false - var constraints = [NSLayoutConstraint](); defer { constraints.activate() } - constraints += header.layoutInSuperview(edges: .horizontal) - - addSubview(contentStackView) - contentStackView.translatesAutoresizingMaskIntoConstraints = false - constraints += contentStackView.centerXAnchor.constraint(equalTo: centerXAnchor) - constraints += contentStackView.centerYAnchor.constraint(equalTo: centerYAnchor) - constraints += contentStackView.layoutIn(layoutMarginsGuide, edges: .horizontal, insets: .init(top: 0, left: 42, bottom: 0, right: 42)) - - constraints += endScreenSharingButton.heightAnchor.constraint(greaterThanOrEqualToConstant: 40) - - if let imageView = endScreenSharingButton.imageView { - constraints += imageView.widthAnchor.constraint(equalToConstant: 24) - } - - setFontScalingEnabled( - props.style.accessibility.isFontScalingEnabled, - for: messageLabel - ) - setFontScalingEnabled( - props.style.buttonStyle.accessibility.isFontScalingEnabled, - for: endScreenSharingButton - ) - } - - override func layoutSubviews() { - switch props.style.backgroundColor { - case .fill(let color): - backgroundColor = color - case .gradient(let colors): - makeGradientBackground(colors: colors) + struct ScreenSharingView: View { + @ObservedObject var model: Model + + var body: some View { + ZStack { + Background(model.style.backgroundColor) + .edgesIgnoringSafeArea(.all) + VStack(spacing: 0) { + HeaderSwiftUI(model: model.makeHeaderModel()) + VStack(spacing: 16) { + mainLabel + endScreenShareButton + } + .frame(maxWidth: .infinity, maxHeight: .infinity) + }.edgesIgnoringSafeArea(.top) } } } } -// MARK: - Private +extension CallVisualizer.ScreenSharingView { + var mainLabel: some View { + Text(model.style.messageText) + .font(.convert(model.style.messageTextFont)) + .foregroundColor(SwiftUI.Color(model.style.messageTextColor)) + .lineLimit(2) + .multilineTextAlignment(.center) + .migrationAccessibilityIdentifier("end_screen_sharing_message") + } -private extension CallVisualizer.ScreenSharingView { - func renderProps() { - header.props = props.header - endScreenSharingButton.props = props.endScreenSharing + var endScreenShareButton: some View { + SwiftUI.Button(action: { + model.event(.endScreenShareTapped) + }, label: { + HStack(spacing: 8) { + SwiftUI.Image(uiImage: model.style.buttonIcon) + .resizable() + .aspectRatio(contentMode: .fit) + .frame(height: 24) + .foregroundColor(SwiftUI.Color(model.style.buttonStyle.titleColor)) + Text(model.style.buttonStyle.title) + .font(.convert(model.style.buttonStyle.titleFont)) + .foregroundColor(SwiftUI.Color(model.style.buttonStyle.titleColor)) + .lineLimit(nil) + } + .padding(.horizontal, 4) + .frame(maxWidth: .infinity, minHeight: 40, idealHeight: 40) + .background(Background(model.style.buttonStyle.backgroundColor)) + .cornerRadius(4) + .padding(.horizontal, 60) + }) + .migrationAccessibilityIdentifier("end_screen_sharing_button") + .migrationAccessibilityLabel(L10n.CallVisualizer.ScreenSharing.Accessibility.buttonLabel) + .migrationAccessibilityHint(L10n.CallVisualizer.ScreenSharing.Accessibility.buttonHint) } } diff --git a/GliaWidgets/Sources/CallVisualizer/ScreenSharing/ViewController/ScreenSharingViewController+Props.swift b/GliaWidgets/Sources/CallVisualizer/ScreenSharing/ViewController/ScreenSharingViewController+Props.swift deleted file mode 100644 index a6a8c2969..000000000 --- a/GliaWidgets/Sources/CallVisualizer/ScreenSharing/ViewController/ScreenSharingViewController+Props.swift +++ /dev/null @@ -1,7 +0,0 @@ -import Foundation - -extension CallVisualizer.ScreenSharingViewController { - struct Props: Equatable { - let screenSharingViewProps: CallVisualizer.ScreenSharingView.Props - } -} diff --git a/GliaWidgets/Sources/CallVisualizer/ScreenSharing/ViewController/ScreenSharingViewController.swift b/GliaWidgets/Sources/CallVisualizer/ScreenSharing/ViewController/ScreenSharingViewController.swift index 8d206c6c6..a2e726bff 100644 --- a/GliaWidgets/Sources/CallVisualizer/ScreenSharing/ViewController/ScreenSharingViewController.swift +++ b/GliaWidgets/Sources/CallVisualizer/ScreenSharing/ViewController/ScreenSharingViewController.swift @@ -1,38 +1,42 @@ import UIKit +import SwiftUI extension CallVisualizer { final class ScreenSharingViewController: UIViewController { - private lazy var screenSharingView = ScreenSharingView(props: props.screenSharingViewProps) - private var props: Props + let model: ScreenSharingView.Model // MARK: - Initialization - init(props: Props) { - self.props = props - super.init(nibName: "", bundle: nil) + init( + model: ScreenSharingView.Model + ) { + self.model = model + super.init(nibName: nil, bundle: nil) } + @available(*, unavailable) required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } // MARK: - View lifecycle - override func loadView() { - view = screenSharingView - } - override func viewDidLoad() { super.viewDidLoad() - renderProps() + let hostingController: UIHostingController + let screenSharingView = ScreenSharingView(model: model) + hostingController = UIHostingController(rootView: screenSharingView) + hostingController.willMove(toParent: self) + addChild(hostingController) + view.addSubview(hostingController.view) + hostingController.didMove(toParent: self) + hostingController.view.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + hostingController.view.topAnchor.constraint(equalTo: view.topAnchor), + hostingController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor), + hostingController.view.leadingAnchor.constraint(equalTo: view.leadingAnchor), + hostingController.view.trailingAnchor.constraint(equalTo: view.trailingAnchor) + ]) } } } - -// MARK: - Private - -private extension CallVisualizer.ScreenSharingViewController { - func renderProps() { - screenSharingView.props = props.screenSharingViewProps - } -} diff --git a/GliaWidgets/Sources/CallVisualizer/ScreenSharing/ViewModel/ScreenSharingViewModel+Environment.swift b/GliaWidgets/Sources/CallVisualizer/ScreenSharing/ViewModel/ScreenSharingViewModel+Environment.swift deleted file mode 100644 index 4229ab78a..000000000 --- a/GliaWidgets/Sources/CallVisualizer/ScreenSharing/ViewModel/ScreenSharingViewModel+Environment.swift +++ /dev/null @@ -1,7 +0,0 @@ -import Foundation - -extension CallVisualizer.ScreenSharingViewModel { - struct Environment { - let screenShareHandler: ScreenShareHandler - } -} diff --git a/GliaWidgets/Sources/CallVisualizer/ScreenSharing/ViewModel/ScreenSharingViewModel+Output.swift b/GliaWidgets/Sources/CallVisualizer/ScreenSharing/ViewModel/ScreenSharingViewModel+Output.swift deleted file mode 100644 index eb87e8234..000000000 --- a/GliaWidgets/Sources/CallVisualizer/ScreenSharing/ViewModel/ScreenSharingViewModel+Output.swift +++ /dev/null @@ -1,7 +0,0 @@ -import Foundation - -extension CallVisualizer.ScreenSharingViewModel { - enum DelegateEvent { - case close - } -} diff --git a/GliaWidgets/Sources/CallVisualizer/ScreenSharing/ViewModel/ScreenSharingViewModel.swift b/GliaWidgets/Sources/CallVisualizer/ScreenSharing/ViewModel/ScreenSharingViewModel.swift deleted file mode 100644 index 03288bc7f..000000000 --- a/GliaWidgets/Sources/CallVisualizer/ScreenSharing/ViewModel/ScreenSharingViewModel.swift +++ /dev/null @@ -1,66 +0,0 @@ -import Foundation - -extension CallVisualizer { - final class ScreenSharingViewModel { - typealias Props = CallVisualizer.ScreenSharingViewController.Props - - private let environment: Environment - private let style: ScreenSharingViewStyle - - var delegate: Command = .nop - - init( - style: ScreenSharingViewStyle, - environment: Environment - ) { - self.style = style - self.environment = environment - } - } -} - -// MARK: - Private - -extension CallVisualizer.ScreenSharingViewModel { - func props() -> Props { - let backButton = style.header.backButton.map { - HeaderButton.Props( - tap: Cmd { [weak self] in self?.delegate(.close) }, - style: $0 - ) - } - - let headerProps = Header.Props( - title: style.title, - effect: .none, - endButton: .init(style: style.header.endButton), - backButton: backButton, - closeButton: .init( - style: style.header.closeButton - ), - endScreenshareButton: .init( - tap: Cmd { [weak self] in self?.endScreenSharing() }, - style: style.header.endScreenShareButton - ), - style: style.header - ) - let endScreenSharingButtonProps = ActionButton.Props( - style: style.buttonStyle, - tap: Cmd { [weak self] in self?.endScreenSharing() } - ) - - let screenSharingViewProps = CallVisualizer.ScreenSharingView.Props( - style: style, - header: headerProps, - endScreenSharing: endScreenSharingButtonProps - ) - - return Props( - screenSharingViewProps: screenSharingViewProps - ) - } - - func endScreenSharing() { - environment.screenShareHandler.stop(nil) - } -} diff --git a/GliaWidgets/SwiftUI/Components/BackgroundSwiftUI.swift b/GliaWidgets/SwiftUI/Components/BackgroundSwiftUI.swift new file mode 100644 index 000000000..bbce1869d --- /dev/null +++ b/GliaWidgets/SwiftUI/Components/BackgroundSwiftUI.swift @@ -0,0 +1,24 @@ +import SwiftUI + +struct Background: View { + let colorType: ColorType + + init(_ colorType: ColorType) { + self.colorType = colorType + } + var body: some View { + switch colorType { + case .fill(let color): + SwiftUI.Color(color) + case .gradient(let colors): + let convertedColors = colors + .map { UIColor(cgColor: $0) } + .map { SwiftUI.Color($0) } + LinearGradient( + colors: convertedColors, + startPoint: .top, + endPoint: .bottom + ) + } + } +} diff --git a/GliaWidgets/SwiftUI/Components/Buttons/ActionButtonSwiftUI.swift b/GliaWidgets/SwiftUI/Components/Buttons/ActionButtonSwiftUI.swift index 77fe8c833..377436d00 100644 --- a/GliaWidgets/SwiftUI/Components/Buttons/ActionButtonSwiftUI.swift +++ b/GliaWidgets/SwiftUI/Components/Buttons/ActionButtonSwiftUI.swift @@ -25,10 +25,10 @@ struct ActionButtonSwiftUI: View { x: model.style.shadowOffset?.width ?? 0, y: model.style.shadowOffset?.height ?? 0 ) - .accessibility(identifier: model.accessibilityIdentifier) - .accessibility(addTraits: .isButton) - .accessibility(removeTraits: .isImage) - .onTapGesture(perform: model.tap.callAsFunction) + .migrationAccessibilityIdentifier(model.accessibilityIdentifier) + .migrationAccessibilityAddTrait(.isButton) + .migrationAccessibilityRemoveTrait(.isImage) + .onTapGesture(perform: model.tap.execute) } } diff --git a/GliaWidgets/SwiftUI/Components/Buttons/HeaderButtonSwiftUI.swift b/GliaWidgets/SwiftUI/Components/Buttons/HeaderButtonSwiftUI.swift index fd71f847b..e72df6cea 100644 --- a/GliaWidgets/SwiftUI/Components/Buttons/HeaderButtonSwiftUI.swift +++ b/GliaWidgets/SwiftUI/Components/Buttons/HeaderButtonSwiftUI.swift @@ -16,11 +16,11 @@ struct HeaderButtonSwiftUI: View { .contentShape(Rectangle()) .foregroundColor(SwiftUI.Color(model.style.color)) .opacity(model.isEnabled ? 1.0 : 0.6) - .accessibility(label: Text(model.style.accessibility.label)) - .accessibility(addTraits: .isButton) - .accessibility(removeTraits: .isImage) - .onTapGesture(perform: model.tap.execute) + .migrationAccessibilityLabel(model.style.accessibility.label) + .migrationAccessibilityAddTrait(.isButton) + .migrationAccessibilityRemoveTrait(.isImage) .migrationAccessibilityIdentifier(model.accessibilityIdentifier) + .onTapGesture(perform: model.tap.execute) } } diff --git a/GliaWidgets/SwiftUI/Components/Header/HeaderSwiftUI.swift b/GliaWidgets/SwiftUI/Components/Header/HeaderSwiftUI.swift index 1c64e7d3f..f0c436937 100644 --- a/GliaWidgets/SwiftUI/Components/Header/HeaderSwiftUI.swift +++ b/GliaWidgets/SwiftUI/Components/Header/HeaderSwiftUI.swift @@ -26,9 +26,9 @@ struct HeaderSwiftUI: View { Text(model.title) .font(.convert(model.style.titleFont)) .foregroundColor(SwiftUI.Color(model.style.titleColor)) - .accessibility(identifier: "header_view_title_label") - .accessibility(label: Text(model.title)) - .accessibility(addTraits: .isHeader) + .migrationAccessibilityIdentifier("header_view_title_label") + .migrationAccessibilityLabel(model.title) + .migrationAccessibilityAddTrait(.isHeader) } .padding(.horizontal, 16) .padding(.bottom, 12) diff --git a/GliaWidgets/SwiftUI/Extensions/View+Accessibility.swift b/GliaWidgets/SwiftUI/Extensions/View+Accessibility.swift index e50c5c34e..583181a50 100644 --- a/GliaWidgets/SwiftUI/Extensions/View+Accessibility.swift +++ b/GliaWidgets/SwiftUI/Extensions/View+Accessibility.swift @@ -14,9 +14,99 @@ struct MigrationAccessibilityIdentifierModifier: ViewModifier { } } -/// Modifier for specifying accessibility identifier for avoiding deprecation warning. +/// Accessibility label view modifier for resolving between +/// deprecated and new method to specify accessibility label. +struct MigrationAccessibilityLabelModifier: ViewModifier { + let label: String + + func body(content: Content) -> some View { + if #available(iOS 14, *) { + content.accessibilityLabel(label) + } else { + content.accessibility(label: .init(label)) + } + } +} + +/// Accessibility hint view modifier for resolving between +/// deprecated and new method to specify accessibility hint. +struct MigrationAccessibilityHintModifier: ViewModifier { + let hint: String + + func body(content: Content) -> some View { + if #available(iOS 14, *) { + content.accessibilityHint(hint) + } else { + content.accessibility(hint: .init(hint)) + } + } +} + +/// Accessibility addTraits view modifier for resolving between +/// deprecated and new method to add accessibility traits. +struct MigrationAccessibilityAddTraitModifier: ViewModifier { + let trait: AccessibilityTraits + + func body(content: Content) -> some View { + if #available(iOS 14, *) { + content.accessibilityAddTraits(trait) + } else { + content.accessibility(addTraits: trait) + } + } +} + +/// Accessibility removeTraits view modifier for resolving between +/// deprecated and new method to accessibility traits. +struct MigrationAccessibilityDropTraitModifier: ViewModifier { + let trait: AccessibilityTraits + + func body(content: Content) -> some View { + if #available(iOS 14, *) { + content.accessibilityRemoveTraits(trait) + } else { + content.accessibility(removeTraits: trait) + } + } +} + +/// Accessibility hidden view modifier for resolving between +/// deprecated and new method to hidden or show accessibility. +struct MigrationAccessibilityHiddenModifier: ViewModifier { + let isHidden: Bool + + func body(content: Content) -> some View { + if #available(iOS 14, *) { + content.accessibilityHidden(isHidden) + } else { + content.accessibility(hidden: isHidden) + } + } +} + +/// Modifiers for specifying accessibility for avoiding deprecation warning. extension View { func migrationAccessibilityIdentifier(_ identifier: String) -> some View { self.modifier(MigrationAccessibilityIdentifierModifier(identifier: identifier)) } + + func migrationAccessibilityLabel(_ label: String) -> some View { + self.modifier(MigrationAccessibilityLabelModifier(label: label)) + } + + func migrationAccessibilityHint(_ hint: String) -> some View { + self.modifier(MigrationAccessibilityHintModifier(hint: hint)) + } + + func migrationAccessibilityAddTrait(_ trait: AccessibilityTraits) -> some View { + self.modifier(MigrationAccessibilityAddTraitModifier(trait: trait)) + } + + func migrationAccessibilityRemoveTrait(_ trait: AccessibilityTraits) -> some View { + self.modifier(MigrationAccessibilityDropTraitModifier(trait: trait)) + } + + func migrationAccessibilityHidden(_ isHidden: Bool) -> some View { + self.modifier(MigrationAccessibilityHiddenModifier(isHidden: isHidden)) + } } diff --git a/GliaWidgetsTests/CallVisualizer/ScreenSharing/Mocks/ScreenSharingView.Mock.swift b/GliaWidgetsTests/CallVisualizer/ScreenSharing/Mocks/ScreenSharingView.Mock.swift deleted file mode 100644 index 37436e052..000000000 --- a/GliaWidgetsTests/CallVisualizer/ScreenSharing/Mocks/ScreenSharingView.Mock.swift +++ /dev/null @@ -1,15 +0,0 @@ -#if DEBUG - -import UIKit - -extension CallVisualizer.ScreenSharingView.Props { - static func mock( - style: ScreenSharingViewStyle = .mock(), - header: Header.Props = .mock(), - endScreenSharing: ActionButton.Props = .mock() - ) -> CallVisualizer.ScreenSharingView.Props { - return .init(style: style, header: header, endScreenSharing: endScreenSharing) - } -} - -#endif diff --git a/GliaWidgetsTests/CallVisualizer/ScreenSharing/Mocks/ScreenSharingViewController.Mock.swift b/GliaWidgetsTests/CallVisualizer/ScreenSharing/Mocks/ScreenSharingViewController.Mock.swift deleted file mode 100644 index e9c084e3c..000000000 --- a/GliaWidgetsTests/CallVisualizer/ScreenSharing/Mocks/ScreenSharingViewController.Mock.swift +++ /dev/null @@ -1,13 +0,0 @@ -#if DEBUG - -import UIKit - -extension CallVisualizer.ScreenSharingViewController.Props { - static func mock( - screenShareViewProps: CallVisualizer.ScreenSharingView.Props = .mock() - ) -> CallVisualizer.ScreenSharingViewController.Props { - return .init(screenSharingViewProps: screenShareViewProps) - } -} - -#endif diff --git a/GliaWidgetsTests/CallVisualizer/ScreenSharing/Mocks/ScreenSharingViewStyle+Mock.swift b/GliaWidgetsTests/CallVisualizer/ScreenSharing/Mocks/ScreenSharingViewStyle+Mock.swift index a7bead115..731cc44ae 100644 --- a/GliaWidgetsTests/CallVisualizer/ScreenSharing/Mocks/ScreenSharingViewStyle+Mock.swift +++ b/GliaWidgetsTests/CallVisualizer/ScreenSharing/Mocks/ScreenSharingViewStyle+Mock.swift @@ -4,7 +4,7 @@ import UIKit extension ScreenSharingViewStyle { static func mock( - title: String = "", + title: String = "Screen Sharing", messageTextFont: UIFont = .systemFont(ofSize: 20, weight: .medium), buttonTitleFont: UIFont = .systemFont(ofSize: 16, weight: .regular) ) -> ScreenSharingViewStyle { diff --git a/GliaWidgetsTests/CallVisualizer/ScreenSharing/ScreenSharingViewModelTests.swift b/GliaWidgetsTests/CallVisualizer/ScreenSharing/ScreenSharingViewModelTests.swift index 2ad63a3c2..772f204e4 100644 --- a/GliaWidgetsTests/CallVisualizer/ScreenSharing/ScreenSharingViewModelTests.swift +++ b/GliaWidgetsTests/CallVisualizer/ScreenSharing/ScreenSharingViewModelTests.swift @@ -3,12 +3,11 @@ import XCTest final class ScreenSharingViewModelTests: XCTestCase { - private var viewModel: CallVisualizer.ScreenSharingViewModel! + private var model: CallVisualizer.ScreenSharingView.Model! override func tearDownWithError() throws { try super.tearDownWithError() - - viewModel = nil + model = nil } func test_end_screen_sharing() throws { @@ -18,15 +17,9 @@ final class ScreenSharingViewModelTests: XCTestCase { isRunning = false } - viewModel = CallVisualizer.ScreenSharingViewModel( - style: ScreenSharingViewStyle.mock(), - environment: .init(screenShareHandler: screenShareHandlerMock) - ) - - let props = viewModel.props() - + model = .mock(screenSharingHandler: screenShareHandlerMock) XCTAssertTrue(isRunning) - props.screenSharingViewProps.endScreenSharing.tap.execute() + model.event(.endScreenShareTapped) XCTAssertFalse(isRunning) } @@ -34,20 +27,14 @@ final class ScreenSharingViewModelTests: XCTestCase { enum Call { case close } var calls: [Call] = [] - viewModel = CallVisualizer.ScreenSharingViewModel( - style: .mock(), - environment: .init(screenShareHandler: ScreenShareHandler.mock) - ) - viewModel.delegate = Command { event in + model = .mock() + model.delegate = Command { event in switch event { - case .close: + case .closeTapped: calls.append(.close) } } - let props = viewModel.props() - - props.screenSharingViewProps.endScreenSharing.tap.execute() - props.screenSharingViewProps.header.backButton?.tap() + model.event(.closeTapped) XCTAssertEqual(calls, [.close]) } } diff --git a/GliaWidgetsTests/CallVisualizer/VideoCall/Mocks/HeaderStyle.Mock.swift b/GliaWidgetsTests/CallVisualizer/VideoCall/Mocks/HeaderStyle.Mock.swift index 62e17e3ec..65a5cdb9e 100644 --- a/GliaWidgetsTests/CallVisualizer/VideoCall/Mocks/HeaderStyle.Mock.swift +++ b/GliaWidgetsTests/CallVisualizer/VideoCall/Mocks/HeaderStyle.Mock.swift @@ -26,7 +26,7 @@ extension HeaderStyle { extension HeaderButtonStyle { static func mock( - image: UIImage = .mock, + image: UIImage = Asset.back.image, color: UIColor = .white, accessibility: Accessibility = .init(label: "", hint: "") ) -> HeaderButtonStyle { diff --git a/SnapshotTests/ScreenShareViewControllerDynamicTypeFontTests.swift b/SnapshotTests/ScreenShareViewControllerDynamicTypeFontTests.swift index 4ffcbab25..1df4baf23 100644 --- a/SnapshotTests/ScreenShareViewControllerDynamicTypeFontTests.swift +++ b/SnapshotTests/ScreenShareViewControllerDynamicTypeFontTests.swift @@ -5,24 +5,10 @@ import XCTest // swiftlint:disable type_name final class ScreenShareViewControllerDynamicTypeFontTests: SnapshotTestCase { func testScreenShareViewController_extra3Large() { - let theme = Theme() - let font = theme.font - let props: CallVisualizer.ScreenSharingViewController.Props = .init( - screenSharingViewProps: .init( - style: .mock( - messageTextFont: font.header2, - buttonTitleFont: font.bodyText - ), - header: .mock( - title: L10n.CallVisualizer.ScreenSharing.title, - backButton: .init(style: .mock(image: Asset.back.image)) - ), - endScreenSharing: .mock(style: .mock(titleFont: font.bodyText)) - ) - ) - let screenShareViewController = CallVisualizer.ScreenSharingViewController(props: props) - screenShareViewController.assertSnapshot(as: .extra3LargeFont, in: .portrait) - screenShareViewController.assertSnapshot(as: .extra3LargeFont, in: .landscape) + let model: CallVisualizer.ScreenSharingView.Model = .mock() + let viewController: CallVisualizer.ScreenSharingViewController = .init(model: model) + viewController.assertSnapshot(as: .extra3LargeFont, in: .portrait) + viewController.assertSnapshot(as: .extra3LargeFont, in: .landscape) } } // swiftlint:enable type_name diff --git a/SnapshotTests/ScreenShareViewControllerLayoutTests.swift b/SnapshotTests/ScreenShareViewControllerLayoutTests.swift index dd64fab18..cd210b7f0 100644 --- a/SnapshotTests/ScreenShareViewControllerLayoutTests.swift +++ b/SnapshotTests/ScreenShareViewControllerLayoutTests.swift @@ -4,23 +4,9 @@ import XCTest final class ScreenShareViewControllerLayoutTests: SnapshotTestCase { func testScreenShareViewController() { - let theme = Theme() - let font = theme.font - let props: CallVisualizer.ScreenSharingViewController.Props = .init( - screenSharingViewProps: .init( - style: .mock( - messageTextFont: font.header2, - buttonTitleFont: font.bodyText - ), - header: .mock( - title: L10n.CallVisualizer.ScreenSharing.title, - backButton: .init(style: .mock(image: Asset.back.image)) - ), - endScreenSharing: .mock(style: .mock(titleFont: font.bodyText)) - ) - ) - let screenShareViewController = CallVisualizer.ScreenSharingViewController(props: props) - screenShareViewController.assertSnapshot(as: .image, in: .portrait) - screenShareViewController.assertSnapshot(as: .image, in: .landscape) + let model: CallVisualizer.ScreenSharingView.Model = .mock() + let viewController: CallVisualizer.ScreenSharingViewController = .init(model: model) + viewController.assertSnapshot(as: .image, in: .portrait) + viewController.assertSnapshot(as: .image, in: .landscape) } } diff --git a/SnapshotTests/ScreenShareViewControllerVoiceOverTests.swift b/SnapshotTests/ScreenShareViewControllerVoiceOverTests.swift index 5ca81ba33..b124aa601 100644 --- a/SnapshotTests/ScreenShareViewControllerVoiceOverTests.swift +++ b/SnapshotTests/ScreenShareViewControllerVoiceOverTests.swift @@ -5,22 +5,8 @@ import XCTest final class ScreenShareViewControllerVoiceOverTests: SnapshotTestCase { func testScreenShareViewController() { - let theme = Theme() - let font = theme.font - let props: CallVisualizer.ScreenSharingViewController.Props = .init( - screenSharingViewProps: .init( - style: .mock( - messageTextFont: font.header2, - buttonTitleFont: font.bodyText - ), - header: .mock( - title: L10n.CallVisualizer.ScreenSharing.title, - backButton: .init(style: .mock(image: Asset.back.image)) - ), - endScreenSharing: .mock(style: .mock(titleFont: font.bodyText)) - ) - ) - let screenShareViewController = CallVisualizer.ScreenSharingViewController(props: props) - screenShareViewController.assertSnapshot(as: .accessibilityImage) + let model: CallVisualizer.ScreenSharingView.Model = .mock() + let viewController: CallVisualizer.ScreenSharingViewController = .init(model: model) + viewController.assertSnapshot(as: .accessibilityImage) } } diff --git a/integrations/SwiftPackageManager/spm-project.yml b/integrations/SwiftPackageManager/spm-project.yml index 5299ddfee..b6df53c14 100644 --- a/integrations/SwiftPackageManager/spm-project.yml +++ b/integrations/SwiftPackageManager/spm-project.yml @@ -8,7 +8,7 @@ targets: SpmSampleApp: type: application platform: iOS - deploymentTarget: "12.0" + deploymentTarget: "13.0" info: path: Sources/Info.plist sources: [Sources]