diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index 47b91696b..f6a4261ae 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -1083,6 +1083,7 @@ A6F345328CCC5C9B0DAE2257 /* LogViewerScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BB05221D7D941CC82DC8480 /* LogViewerScreenViewModel.swift */; }; A6FFC4C5154C446BAD6B40D8 /* TimelineItemProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8520AFD6680CBAD388F6D927 /* TimelineItemProvider.swift */; }; A722F426FD81FC67706BB1E0 /* CustomLayoutLabelStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42236480CF0431535EBE8387 /* CustomLayoutLabelStyle.swift */; }; + A73D1EC3D092E5A768F5F500 /* CreateRoomScreenHook.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F374C789B4BD1C597394987 /* CreateRoomScreenHook.swift */; }; A74438ED16F8683A4B793E6A /* AnalyticsSettingsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BCE3FAF40932AC7C7639AC4 /* AnalyticsSettingsScreenViewModel.swift */; }; A7C0BA4E23E3650B155749D2 /* landscape_test_video.mov in Resources */ = {isa = PBXBuildFile; fileRef = 59AD88B11514D6725F22AE78 /* landscape_test_video.mov */; }; A7D48E44D485B143AADDB77D /* Strings+Untranslated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A18F6CE4D694D21E4EA9B25 /* Strings+Untranslated.swift */; }; @@ -1407,6 +1408,7 @@ DDFBDEE1DC32BDD5488F898C /* ClientProxyMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2F96CCBEAAA7F2185BFA354 /* ClientProxyMock.swift */; }; DE3BF0ED68E56BF625591D49 /* LinkNewDeviceScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 72C4A2D279386A811BDC6DAE /* LinkNewDeviceScreen.swift */; }; DE4F8C4E0F1DB4832F09DE97 /* HomeScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31D6764D6976D235926FE5FC /* HomeScreenViewModel.swift */; }; + DE5102C95985AFB3F63E807B /* SecurityAndPrivacyScreenHook.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00C4628208584D251CCDAC0A /* SecurityAndPrivacyScreenHook.swift */; }; DEDBD3E9CFCC9F20CAC79881 /* JoinRoomScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 136F80A613B55BDD071DCEA5 /* JoinRoomScreenModels.swift */; }; DF004A5B2EABBD0574D06A04 /* SplashScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 854BCEAF2A832176FAACD2CB /* SplashScreenCoordinator.swift */; }; DF05F9C9D3D977EB77E13692 /* Macros in Frameworks */ = {isa = PBXBuildFile; productRef = E9170427ACFD3E9F67EB7116 /* Macros */; }; @@ -1764,6 +1766,7 @@ 007C16779FDCF10DA4F1A510 /* LinkNewDeviceService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkNewDeviceService.swift; sourceTree = ""; }; 008D864B3F51B41DF483B860 /* RoomThreadListScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomThreadListScreenViewModelProtocol.swift; sourceTree = ""; }; 00AFC5F08734C2EA4EE79C59 /* IdentityConfirmationScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityConfirmationScreen.swift; sourceTree = ""; }; + 00C4628208584D251CCDAC0A /* SecurityAndPrivacyScreenHook.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecurityAndPrivacyScreenHook.swift; sourceTree = ""; }; 00E5B2CBEF8F96424F095508 /* RoomDetailsEditScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsEditScreenViewModelTests.swift; sourceTree = ""; }; 011AFA4990C585D157829679 /* DeclineAndBlockScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeclineAndBlockScreenViewModel.swift; sourceTree = ""; }; 012A284622B32052015F1F89 /* ReadMarkerRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadMarkerRoomTimelineView.swift; sourceTree = ""; }; @@ -2062,6 +2065,7 @@ 2E11E7C396ED06A154CF6DF3 /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/SAS.strings; sourceTree = ""; }; 2F06F70B9C433BAD4BC6B9F5 /* EncryptedRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptedRoomTimelineView.swift; sourceTree = ""; }; 2F36C5D9B37E50915ECBD3EE /* RoomMemberProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberProxy.swift; sourceTree = ""; }; + 2F374C789B4BD1C597394987 /* CreateRoomScreenHook.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateRoomScreenHook.swift; sourceTree = ""; }; 2F65178687F725E8924B723C /* TimelineFixtures.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineFixtures.swift; sourceTree = ""; }; 2F926D08EB3D622A480BCA71 /* TimelineEventContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineEventContent.swift; sourceTree = ""; }; 2FCD606155B7B4AFC06B7635 /* ManualClockTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManualClockTests.swift; sourceTree = ""; }; @@ -4013,6 +4017,7 @@ 25586C0ADB814FEE9897DCAA /* BugReportHook.swift */, B3561843E139EA7CDAED0933 /* ClientFactoryHook.swift */, 8B89D6C760E8CAE29CA28FB1 /* CompoundHook.swift */, + 2F374C789B4BD1C597394987 /* CreateRoomScreenHook.swift */, 0F60FDB3AEFC60830BD289FE /* DeveloperOptionsScreenHook.swift */, 04CAC77224E949D8E758E2E3 /* OAuthPresenterHook.swift */, 7AE97AD18893E2D8120F559D /* RecoveryKeyScreenHook.swift */, @@ -4020,6 +4025,7 @@ 3674212CAB6C5143DD437AC4 /* RoomDetailsScreenHook.swift */, 99EB08B2C8B01F3BFE4B0CEC /* RoomMemberDetailsScreenHook.swift */, B343C5255FB408DDE853CFDF /* RoomScreenHook.swift */, + 00C4628208584D251CCDAC0A /* SecurityAndPrivacyScreenHook.swift */, 2A95C9B8299A36A6495DECA6 /* TracingHook.swift */, 8B35734F3743563566413C9A /* UserProfileScreenHook.swift */, E9773983346838AABFAA914D /* UserSessionHook.swift */, @@ -8840,6 +8846,7 @@ 633501761094E09DFBEBFFAD /* CopyTextButton.swift in Sources */, CE8296D4AD30DDC6D0C67A74 /* CreateRoomScreen.swift in Sources */, D38E59C48BE5499A48D12031 /* CreateRoomScreenCoordinator.swift in Sources */, + A73D1EC3D092E5A768F5F500 /* CreateRoomScreenHook.swift in Sources */, 9DBF6524DFD8143A4D6A17F0 /* CreateRoomScreenModels.swift in Sources */, A7DB75E090542331F6668A23 /* CreateRoomScreenViewModel.swift in Sources */, DB01FDD050A43B72C5425549 /* CreateRoomScreenViewModelProtocol.swift in Sources */, @@ -9481,6 +9488,7 @@ AC90434798E7894370E80E66 /* SecureBackupScreenViewModelProtocol.swift in Sources */, 7254FB2EFDD43BC8BB7A1213 /* SecurityAndPrivacyScreen.swift in Sources */, 611BEE29B8B622204E1E6B04 /* SecurityAndPrivacyScreenCoordinator.swift in Sources */, + DE5102C95985AFB3F63E807B /* SecurityAndPrivacyScreenHook.swift in Sources */, 6B80C24A52411EAF10E06E96 /* SecurityAndPrivacyScreenModels.swift in Sources */, 7C545FFEC9930F7247352593 /* SecurityAndPrivacyScreenViewModel.swift in Sources */, 0D617A152D099D94271D3BA8 /* SecurityAndPrivacyScreenViewModelProtocol.swift in Sources */, diff --git a/ElementX/Sources/AppHooks/AppHooks.swift b/ElementX/Sources/AppHooks/AppHooks.swift index 580e6aabb..20d9c4e3d 100644 --- a/ElementX/Sources/AppHooks/AppHooks.swift +++ b/ElementX/Sources/AppHooks/AppHooks.swift @@ -48,6 +48,12 @@ final nonisolated class AppHooks: AppHooksProtocol { @AppHook(default: DefaultRecoveryKeyScreenHook()) var recoveryKeyScreenHook: RecoveryKeyScreenHookProtocol + + @AppHook(default: DefaultCreateRoomScreenHook()) + var createRoomScreenHook: CreateRoomScreenHookProtocol + + @AppHook(default: DefaultSecurityAndPrivacyScreenHook()) + var securityAndPrivacyScreenHook: SecurityAndPrivacyScreenHookProtocol #endif @AppHook(default: DefaultTracingHook()) diff --git a/ElementX/Sources/AppHooks/Hooks/CreateRoomScreenHook.swift b/ElementX/Sources/AppHooks/Hooks/CreateRoomScreenHook.swift new file mode 100644 index 000000000..c9ea03d7f --- /dev/null +++ b/ElementX/Sources/AppHooks/Hooks/CreateRoomScreenHook.swift @@ -0,0 +1,18 @@ +// +// Copyright 2026 Element Creations Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. +// Please see LICENSE files in the repository root for full details. +// + +import Foundation + +nonisolated protocol CreateRoomScreenHookProtocol: Sendable { + @MainActor func update(_ viewState: CreateRoomScreenViewState, homeserver: String) -> CreateRoomScreenViewState +} + +struct DefaultCreateRoomScreenHook: CreateRoomScreenHookProtocol { + func update(_ viewState: CreateRoomScreenViewState, homeserver: String) -> CreateRoomScreenViewState { + viewState + } +} diff --git a/ElementX/Sources/AppHooks/Hooks/SecurityAndPrivacyScreenHook.swift b/ElementX/Sources/AppHooks/Hooks/SecurityAndPrivacyScreenHook.swift new file mode 100644 index 000000000..8ef0614f5 --- /dev/null +++ b/ElementX/Sources/AppHooks/Hooks/SecurityAndPrivacyScreenHook.swift @@ -0,0 +1,18 @@ +// +// Copyright 2026 Element Creations Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. +// Please see LICENSE files in the repository root for full details. +// + +import Foundation + +nonisolated protocol SecurityAndPrivacyScreenHookProtocol: Sendable { + @MainActor func update(_ viewState: SecurityAndPrivacyScreenViewState, homeserver: String) -> SecurityAndPrivacyScreenViewState +} + +struct DefaultSecurityAndPrivacyScreenHook: SecurityAndPrivacyScreenHookProtocol { + func update(_ viewState: SecurityAndPrivacyScreenViewState, homeserver: String) -> SecurityAndPrivacyScreenViewState { + viewState + } +} diff --git a/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift index 0ec42f31d..80d3d51fb 100644 --- a/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift @@ -1420,7 +1420,8 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { let coordinator = SecurityAndPrivacyScreenCoordinator(parameters: .init(roomProxy: roomProxy, clientProxy: userSession.clientProxy, userIndicatorController: flowParameters.userIndicatorController, - appSetting: flowParameters.userSettings)) + appSetting: flowParameters.userSettings, + appHooks: flowParameters.appHooks)) coordinator.actionsPublisher.sink { [weak self] action in guard let self else { return } diff --git a/ElementX/Sources/FlowCoordinators/SpaceSettingsFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/SpaceSettingsFlowCoordinator.swift index 906448fe8..84d250c2a 100644 --- a/ElementX/Sources/FlowCoordinators/SpaceSettingsFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/SpaceSettingsFlowCoordinator.swift @@ -278,7 +278,8 @@ final class SpaceSettingsFlowCoordinator: FlowCoordinatorProtocol { let coordinator = SecurityAndPrivacyScreenCoordinator(parameters: .init(roomProxy: roomProxy, clientProxy: flowParameters.userSession.clientProxy, userIndicatorController: flowParameters.userIndicatorController, - appSetting: flowParameters.userSettings)) + appSetting: flowParameters.userSettings, + appHooks: flowParameters.appHooks)) coordinator.actionsPublisher.sink { [weak self] action in guard let self else { return } diff --git a/ElementX/Sources/FlowCoordinators/StartChatFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/StartChatFlowCoordinator.swift index 2d339d9bc..8b26ad51e 100644 --- a/ElementX/Sources/FlowCoordinators/StartChatFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/StartChatFlowCoordinator.swift @@ -215,7 +215,8 @@ class StartChatFlowCoordinator: FlowCoordinatorProtocol { userSession: flowParameters.userSession, userIndicatorController: flowParameters.userIndicatorController, userSettings: flowParameters.userSettings, - analytics: flowParameters.analytics) + analytics: flowParameters.analytics, + appHooks: flowParameters.appHooks) let coordinator = CreateRoomScreenCoordinator(parameters: createParameters) coordinator.actions.sink { [weak self] action in guard let self else { return } diff --git a/ElementX/Sources/Screens/CreateRoomScreen/CreateRoomScreenCoordinator.swift b/ElementX/Sources/Screens/CreateRoomScreen/CreateRoomScreenCoordinator.swift index 26bd998aa..f3fe00890 100644 --- a/ElementX/Sources/Screens/CreateRoomScreen/CreateRoomScreenCoordinator.swift +++ b/ElementX/Sources/Screens/CreateRoomScreen/CreateRoomScreenCoordinator.swift @@ -17,6 +17,7 @@ struct CreateRoomScreenCoordinatorParameters { let userIndicatorController: UserIndicatorControllerProtocol let userSettings: UserSettings let analytics: AnalyticsServiceProtocol + let appHooks: AppHooks } enum CreateRoomScreenCoordinatorAction { @@ -41,7 +42,8 @@ final class CreateRoomScreenCoordinator: CoordinatorProtocol { userSession: parameters.userSession, analytics: parameters.analytics, userIndicatorController: parameters.userIndicatorController, - userSettings: parameters.userSettings) + userSettings: parameters.userSettings, + appHooks: parameters.appHooks) } func start() { diff --git a/ElementX/Sources/Screens/CreateRoomScreen/CreateRoomScreenModels.swift b/ElementX/Sources/Screens/CreateRoomScreen/CreateRoomScreenModels.swift index 0765760bc..92bf16a85 100644 --- a/ElementX/Sources/Screens/CreateRoomScreen/CreateRoomScreenModels.swift +++ b/ElementX/Sources/Screens/CreateRoomScreen/CreateRoomScreenModels.swift @@ -31,6 +31,7 @@ struct CreateRoomScreenViewState: BindableState { var roomName: String let serverName: String let isKnockingFeatureEnabled: Bool + var isPublicAccessAllowed = true let canSelectSpace: Bool var aliasLocalPart: String var editableSpaces: [SpaceServiceRoom] = [] @@ -69,6 +70,11 @@ struct CreateRoomScreenViewState: BindableState { } } availableAccessTypes.append(.private) + + if !isPublicAccessAllowed { + availableAccessTypes.removeAll { $0 == .public } + } + return availableAccessTypes } diff --git a/ElementX/Sources/Screens/CreateRoomScreen/CreateRoomScreenViewModel.swift b/ElementX/Sources/Screens/CreateRoomScreen/CreateRoomScreenViewModel.swift index 913e5473a..207684def 100644 --- a/ElementX/Sources/Screens/CreateRoomScreen/CreateRoomScreenViewModel.swift +++ b/ElementX/Sources/Screens/CreateRoomScreen/CreateRoomScreenViewModel.swift @@ -33,7 +33,8 @@ class CreateRoomScreenViewModel: CreateRoomScreenViewModelType, CreateRoomScreen userSession: UserSessionProtocol, analytics: AnalyticsServiceProtocol, userIndicatorController: UserIndicatorControllerProtocol, - userSettings: UserSettings) { + userSettings: UserSettings, + appHooks: AppHooks) { self.userSession = userSession mediaUploadingPreprocessor = MediaUploadingPreprocessor(userSettings: userSettings) self.analytics = analytics @@ -59,14 +60,16 @@ class CreateRoomScreenViewModel: CreateRoomScreenViewModelType, CreateRoomScreen selectedAccessType: selectedAccessType, selectedSpace: selectedSpace) - super.init(initialViewState: CreateRoomScreenViewState(isSpace: isSpace, - shouldShowCancelButton: shouldShowCancelButton, - roomName: "", - serverName: userSession.clientProxy.userIDServerName ?? "", - isKnockingFeatureEnabled: userSettings.knockingEnabled, - canSelectSpace: canSelectSpace, - aliasLocalPart: roomAliasNameFromRoomDisplayName(roomName: ""), - bindings: bindings), + let viewState = CreateRoomScreenViewState(isSpace: isSpace, + shouldShowCancelButton: shouldShowCancelButton, + roomName: "", + serverName: userSession.clientProxy.userIDServerName ?? "", + isKnockingFeatureEnabled: userSettings.knockingEnabled, + canSelectSpace: canSelectSpace, + aliasLocalPart: roomAliasNameFromRoomDisplayName(roomName: ""), + bindings: bindings) + + super.init(initialViewState: appHooks.createRoomScreenHook.update(viewState, homeserver: userSession.clientProxy.homeserver), mediaProvider: userSession.mediaProvider) setupBindings() diff --git a/ElementX/Sources/Screens/CreateRoomScreen/View/CreateRoomScreen.swift b/ElementX/Sources/Screens/CreateRoomScreen/View/CreateRoomScreen.swift index 968eb155a..5039dfc7a 100644 --- a/ElementX/Sources/Screens/CreateRoomScreen/View/CreateRoomScreen.swift +++ b/ElementX/Sources/Screens/CreateRoomScreen/View/CreateRoomScreen.swift @@ -467,6 +467,7 @@ struct CreateRoom_Previews: PreviewProvider, TestablePreview { userSession: userSession, analytics: AnalyticsServiceMock(.init()), userIndicatorController: UserIndicatorControllerMock(), - userSettings: userSettings) + userSettings: userSettings, + appHooks: AppHooks()) } } diff --git a/ElementX/Sources/Screens/CreateRoomScreen/View/CreateRoomSpaceSelectionSheet.swift b/ElementX/Sources/Screens/CreateRoomScreen/View/CreateRoomSpaceSelectionSheet.swift index e3f39bd07..ad258afdf 100644 --- a/ElementX/Sources/Screens/CreateRoomScreen/View/CreateRoomSpaceSelectionSheet.swift +++ b/ElementX/Sources/Screens/CreateRoomScreen/View/CreateRoomSpaceSelectionSheet.swift @@ -73,7 +73,8 @@ struct CreateRoomSpaceSelectionSheet_Previews: PreviewProvider, TestablePreview userSession: userSession, analytics: AnalyticsServiceMock(.init()), userIndicatorController: UserIndicatorControllerMock(), - userSettings: userSettings) + userSettings: userSettings, + appHooks: AppHooks()) }() static var previews: some View { diff --git a/ElementX/Sources/Screens/SecurityAndPrivacyScreen/SecurityAndPrivacyScreenCoordinator.swift b/ElementX/Sources/Screens/SecurityAndPrivacyScreen/SecurityAndPrivacyScreenCoordinator.swift index cae3edaf9..7d9947b2c 100644 --- a/ElementX/Sources/Screens/SecurityAndPrivacyScreen/SecurityAndPrivacyScreenCoordinator.swift +++ b/ElementX/Sources/Screens/SecurityAndPrivacyScreen/SecurityAndPrivacyScreenCoordinator.swift @@ -14,6 +14,7 @@ struct SecurityAndPrivacyScreenCoordinatorParameters { let clientProxy: ClientProxyProtocol let userIndicatorController: UserIndicatorControllerProtocol let appSetting: UserSettings + let appHooks: AppHooks } enum SecurityAndPrivacyScreenCoordinatorAction { @@ -36,7 +37,8 @@ final class SecurityAndPrivacyScreenCoordinator: CoordinatorProtocol { viewModel = SecurityAndPrivacyScreenViewModel(roomProxy: parameters.roomProxy, clientProxy: parameters.clientProxy, userIndicatorController: parameters.userIndicatorController, - userSettings: parameters.appSetting) + userSettings: parameters.appSetting, + appHooks: parameters.appHooks) } func start() { diff --git a/ElementX/Sources/Screens/SecurityAndPrivacyScreen/SecurityAndPrivacyScreenModels.swift b/ElementX/Sources/Screens/SecurityAndPrivacyScreen/SecurityAndPrivacyScreenModels.swift index e0b01de3e..8af1012cb 100644 --- a/ElementX/Sources/Screens/SecurityAndPrivacyScreen/SecurityAndPrivacyScreenModels.swift +++ b/ElementX/Sources/Screens/SecurityAndPrivacyScreen/SecurityAndPrivacyScreenModels.swift @@ -21,6 +21,7 @@ struct SecurityAndPrivacyScreenViewState: BindableState { var canonicalAlias: String? var isKnockingEnabled: Bool + var isPublicAccessAllowed = true var isSpace: Bool var canEditAddress = false @@ -57,6 +58,11 @@ struct SecurityAndPrivacyScreenViewState: BindableState { return options.sorted() } + /// Keeps the option visible on rooms that are already public so the current state is shown. + var isAnyoneOptionAvailable: Bool { + currentSettings.accessType == .anyone || isPublicAccessAllowed + } + var isSpaceMembersOptionAvailable: Bool { currentSettings.accessType.isSpaceMembers || isSpaceMembersOptionSelectable } diff --git a/ElementX/Sources/Screens/SecurityAndPrivacyScreen/SecurityAndPrivacyScreenViewModel.swift b/ElementX/Sources/Screens/SecurityAndPrivacyScreen/SecurityAndPrivacyScreenViewModel.swift index b8cada92a..6af6cf906 100644 --- a/ElementX/Sources/Screens/SecurityAndPrivacyScreen/SecurityAndPrivacyScreenViewModel.swift +++ b/ElementX/Sources/Screens/SecurityAndPrivacyScreen/SecurityAndPrivacyScreenViewModel.swift @@ -26,18 +26,21 @@ class SecurityAndPrivacyScreenViewModel: SecurityAndPrivacyScreenViewModelType, init(roomProxy: JoinedRoomProxyProtocol, clientProxy: ClientProxyProtocol, userIndicatorController: UserIndicatorControllerProtocol, - userSettings: UserSettings) { + userSettings: UserSettings, + appHooks: AppHooks) { self.roomProxy = roomProxy self.clientProxy = clientProxy self.userIndicatorController = userIndicatorController self.userSettings = userSettings - super.init(initialViewState: SecurityAndPrivacyScreenViewState(accessType: roomProxy.infoPublisher.value.joinRule.toSecurityAndPrivacyRoomAccessType, - isEncryptionEnabled: roomProxy.infoPublisher.value.isEncrypted, - historyVisibility: roomProxy.infoPublisher.value.historyVisibility.toSecurityAndPrivacyHistoryVisibility, - isSpace: roomProxy.infoPublisher.value.isSpace, - isKnockingEnabled: userSettings.knockingEnabled, - historySharingDetailsURL: userSettings.historySharingDetailsURL)) + let viewState = SecurityAndPrivacyScreenViewState(accessType: roomProxy.infoPublisher.value.joinRule.toSecurityAndPrivacyRoomAccessType, + isEncryptionEnabled: roomProxy.infoPublisher.value.isEncrypted, + historyVisibility: roomProxy.infoPublisher.value.historyVisibility.toSecurityAndPrivacyHistoryVisibility, + isSpace: roomProxy.infoPublisher.value.isSpace, + isKnockingEnabled: userSettings.knockingEnabled, + historySharingDetailsURL: userSettings.historySharingDetailsURL) + + super.init(initialViewState: appHooks.securityAndPrivacyScreenHook.update(viewState, homeserver: clientProxy.homeserver)) if let powerLevels = roomProxy.infoPublisher.value.powerLevels { setupPermissions(powerLevels: powerLevels) diff --git a/ElementX/Sources/Screens/SecurityAndPrivacyScreen/View/SecurityAndPrivacyScreen.swift b/ElementX/Sources/Screens/SecurityAndPrivacyScreen/View/SecurityAndPrivacyScreen.swift index c7fffd1c7..2e896e7c8 100644 --- a/ElementX/Sources/Screens/SecurityAndPrivacyScreen/View/SecurityAndPrivacyScreen.swift +++ b/ElementX/Sources/Screens/SecurityAndPrivacyScreen/View/SecurityAndPrivacyScreen.swift @@ -46,10 +46,12 @@ struct SecurityAndPrivacyScreen: View { private var roomAccessSection: some View { Section { - ListRow(label: .default(title: L10n.screenSecurityAndPrivacyRoomAccessAnyoneOptionTitle, - description: L10n.screenSecurityAndPrivacyRoomAccessAnyoneOptionDescription, - icon: \.public), - kind: .selection(isSelected: context.desiredSettings.accessType == .anyone) { context.desiredSettings.accessType = .anyone }) + if context.viewState.isAnyoneOptionAvailable { + ListRow(label: .default(title: L10n.screenSecurityAndPrivacyRoomAccessAnyoneOptionTitle, + description: L10n.screenSecurityAndPrivacyRoomAccessAnyoneOptionDescription, + icon: \.public), + kind: .selection(isSelected: context.desiredSettings.accessType == .anyone) { context.desiredSettings.accessType = .anyone }) + } if context.viewState.isSpaceMembersOptionAvailable { ListRow(label: .default(title: L10n.screenSecurityAndPrivacyRoomAccessSpaceMembersOptionTitle, @@ -233,7 +235,8 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview { joinRule: .invite)), clientProxy: ClientProxyMock(.init()), userIndicatorController: UserIndicatorControllerMock(), - userSettings: .volatile()) + userSettings: .volatile(), + appHooks: AppHooks()) static let publicViewModel = SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false, canonicalAlias: "#room:matrix.org", @@ -242,14 +245,16 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview { isVisibleInPublicDirectory: true)), clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org")), userIndicatorController: UserIndicatorControllerMock(), - userSettings: .volatile()) + userSettings: .volatile(), + appHooks: AppHooks()) static let publicNoAddressViewModel = SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false, members: .allMembersAsCreator, joinRule: .public)), clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org")), userIndicatorController: UserIndicatorControllerMock(), - userSettings: .volatile()) + userSettings: .volatile(), + appHooks: AppHooks()) static let singleSpaceMembersViewModel = { let userSettings = UserSettings.volatile() @@ -264,7 +269,8 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview { clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org", spaceServiceConfiguration: .init(joinedParentSpaces: [space]))), userIndicatorController: UserIndicatorControllerMock(), - userSettings: userSettings) + userSettings: userSettings, + appHooks: AppHooks()) }() static let multipleSpacesMembersViewModel = { @@ -280,7 +286,8 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview { clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org", spaceServiceConfiguration: .init(joinedParentSpaces: spaces))), userIndicatorController: UserIndicatorControllerMock(), - userSettings: userSettings) + userSettings: userSettings, + appHooks: AppHooks()) }() static let askToJoinViewModel = { @@ -294,7 +301,8 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview { isVisibleInPublicDirectory: true)), clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org")), userIndicatorController: UserIndicatorControllerMock(), - userSettings: userSettings) + userSettings: userSettings, + appHooks: AppHooks()) }() static let singleAskToJoinSpaceMembersViewModel = { @@ -311,7 +319,8 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview { clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org", spaceServiceConfiguration: .init(joinedParentSpaces: [space]))), userIndicatorController: UserIndicatorControllerMock(), - userSettings: userSettings) + userSettings: userSettings, + appHooks: AppHooks()) }() static let multipleAskToJoinSpacesMembersViewModel = { @@ -328,7 +337,8 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview { clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org", spaceServiceConfiguration: .init(joinedParentSpaces: spaces))), userIndicatorController: UserIndicatorControllerMock(), - userSettings: userSettings) + userSettings: userSettings, + appHooks: AppHooks()) }() static let publicSpaceViewModel = SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isSpace: true, @@ -339,7 +349,8 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview { isVisibleInPublicDirectory: true)), clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org")), userIndicatorController: UserIndicatorControllerMock(), - userSettings: .volatile()) + userSettings: .volatile(), + appHooks: AppHooks()) static var previews: some View { ElementNavigationStack { diff --git a/Enterprise b/Enterprise index 44949031c..4c72bf375 160000 --- a/Enterprise +++ b/Enterprise @@ -1 +1 @@ -Subproject commit 44949031c7dfcb6ba0c9ad0f690fe824a280cc0a +Subproject commit 4c72bf3758485fae2e5251e7f283f07a85569111 diff --git a/UnitTests/Sources/CreateRoomViewModelTests.swift b/UnitTests/Sources/CreateRoomViewModelTests.swift index 5dc7c6199..6dcc32e5a 100644 --- a/UnitTests/Sources/CreateRoomViewModelTests.swift +++ b/UnitTests/Sources/CreateRoomViewModelTests.swift @@ -92,7 +92,8 @@ final class CreateRoomScreenViewModelTests { userSession: userSession, analytics: AnalyticsServiceMock(.init()), userIndicatorController: UserIndicatorControllerMock(), - userSettings: userSettings) + userSettings: userSettings, + appHooks: AppHooks()) self.viewModel = viewModel // Given a form with a blank topic. @@ -342,7 +343,8 @@ final class CreateRoomScreenViewModelTests { userSession: userSession, analytics: AnalyticsServiceMock(.init()), userIndicatorController: UserIndicatorControllerMock(), - userSettings: userSettings) + userSettings: userSettings, + appHooks: AppHooks()) self.viewModel = viewModel } } diff --git a/UnitTests/Sources/SecurityAndPrivacyScreenViewModelTests.swift b/UnitTests/Sources/SecurityAndPrivacyScreenViewModelTests.swift index 770a8b62a..42819743c 100644 --- a/UnitTests/Sources/SecurityAndPrivacyScreenViewModelTests.swift +++ b/UnitTests/Sources/SecurityAndPrivacyScreenViewModelTests.swift @@ -473,6 +473,7 @@ final class SecurityAndPrivacyScreenViewModelTests { spaceServiceConfiguration: .init(topLevelSpaces: topLevelSpaces, joinedParentSpaces: joinedParentSpaces))), userIndicatorController: UserIndicatorControllerMock(), - userSettings: userSettings) + userSettings: userSettings, + appHooks: AppHooks()) } }