Always show security and privacy, and just hide the knocking jojn rule option through the feature flag
This commit is contained in:
@@ -1346,7 +1346,8 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
private func presentSecurityAndPrivacyScreen() {
|
||||
let coordinator = SecurityAndPrivacyScreenCoordinator(parameters: .init(roomProxy: roomProxy,
|
||||
clientProxy: userSession.clientProxy,
|
||||
userIndicatorController: flowParameters.userIndicatorController))
|
||||
userIndicatorController: flowParameters.userIndicatorController,
|
||||
appSetting: flowParameters.appSettings))
|
||||
|
||||
coordinator.actionsPublisher.sink { [weak self] action in
|
||||
guard let self else { return }
|
||||
|
||||
@@ -248,7 +248,8 @@ final class SpaceSettingsFlowCoordinator: FlowCoordinatorProtocol {
|
||||
private func presentSecurityAndPrivacyScreen() {
|
||||
let coordinator = SecurityAndPrivacyScreenCoordinator(parameters: .init(roomProxy: roomProxy,
|
||||
clientProxy: flowParameters.userSession.clientProxy,
|
||||
userIndicatorController: flowParameters.userIndicatorController))
|
||||
userIndicatorController: flowParameters.userIndicatorController,
|
||||
appSetting: flowParameters.appSettings))
|
||||
|
||||
coordinator.actionsPublisher.sink { [weak self] action in
|
||||
guard let self else { return }
|
||||
|
||||
@@ -57,6 +57,7 @@ struct RoomDetailsScreenViewState: BindableState {
|
||||
var canEditRoomTopic = false
|
||||
var canEditRoomAvatar = false
|
||||
var canEditRolesOrPermissions = false
|
||||
var canEditSecurityAndPrivacy = false
|
||||
var canKickUsers = false
|
||||
var canBanUsers = false
|
||||
var notificationSettingsState: RoomDetailsNotificationSettingsState = .loading
|
||||
@@ -74,7 +75,7 @@ struct RoomDetailsScreenViewState: BindableState {
|
||||
}
|
||||
|
||||
var canSeeSecurityAndPrivacy: Bool {
|
||||
knockingEnabled && dmRecipientInfo == nil && canEditRolesOrPermissions
|
||||
dmRecipientInfo == nil && canEditSecurityAndPrivacy
|
||||
}
|
||||
|
||||
var canEditBaseInfo: Bool {
|
||||
|
||||
@@ -292,6 +292,7 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr
|
||||
state.canBanUsers = powerLevels.canOwnUserBan()
|
||||
state.canJoinCall = powerLevels.canOwnUserJoinCall()
|
||||
state.canEditRolesOrPermissions = powerLevels.canOwnUserEditRolesAndPermissions()
|
||||
state.canEditSecurityAndPrivacy = powerLevels.canOwnUserEditSecurityAndPrivacy()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ struct SecurityAndPrivacyScreenCoordinatorParameters {
|
||||
let roomProxy: JoinedRoomProxyProtocol
|
||||
let clientProxy: ClientProxyProtocol
|
||||
let userIndicatorController: UserIndicatorControllerProtocol
|
||||
let appSetting: AppSettings
|
||||
}
|
||||
|
||||
enum SecurityAndPrivacyScreenCoordinatorAction {
|
||||
@@ -32,7 +33,8 @@ final class SecurityAndPrivacyScreenCoordinator: CoordinatorProtocol {
|
||||
init(parameters: SecurityAndPrivacyScreenCoordinatorParameters) {
|
||||
viewModel = SecurityAndPrivacyScreenViewModel(roomProxy: parameters.roomProxy,
|
||||
clientProxy: parameters.clientProxy,
|
||||
userIndicatorController: parameters.userIndicatorController)
|
||||
userIndicatorController: parameters.userIndicatorController,
|
||||
appSettings: parameters.appSetting)
|
||||
}
|
||||
|
||||
func start() {
|
||||
|
||||
@@ -17,6 +17,13 @@ struct SecurityAndPrivacyScreenViewState: BindableState {
|
||||
var currentSettings: SecurityAndPrivacySettings
|
||||
var bindings: SecurityAndPrivacyScreenViewStateBindings
|
||||
var canonicalAlias: String?
|
||||
var isKnockingEnabled: Bool
|
||||
var isSpace: Bool
|
||||
|
||||
var canEditAddress = false
|
||||
var canEditJoinRule = false
|
||||
var canEnableEncryption = false
|
||||
var canEditHistoryVisibility = false
|
||||
|
||||
private var hasChanges: Bool {
|
||||
currentSettings != bindings.desiredSettings
|
||||
@@ -42,8 +49,13 @@ struct SecurityAndPrivacyScreenViewState: BindableState {
|
||||
init(serverName: String,
|
||||
accessType: SecurityAndPrivacyRoomAccessType,
|
||||
isEncryptionEnabled: Bool,
|
||||
historyVisibility: SecurityAndPrivacyHistoryVisibility) {
|
||||
historyVisibility: SecurityAndPrivacyHistoryVisibility,
|
||||
isSpace: Bool,
|
||||
isKnockingEnabled: Bool) {
|
||||
self.serverName = serverName
|
||||
self.isKnockingEnabled = isKnockingEnabled
|
||||
self.isSpace = isSpace
|
||||
|
||||
let settings = SecurityAndPrivacySettings(accessType: accessType,
|
||||
isEncryptionEnabled: isEncryptionEnabled,
|
||||
historyVisibility: historyVisibility)
|
||||
|
||||
@@ -16,6 +16,7 @@ class SecurityAndPrivacyScreenViewModel: SecurityAndPrivacyScreenViewModelType,
|
||||
private let roomProxy: JoinedRoomProxyProtocol
|
||||
private let clientProxy: ClientProxyProtocol
|
||||
private let userIndicatorController: UserIndicatorControllerProtocol
|
||||
private let appSettings: AppSettings
|
||||
|
||||
private let actionsSubject: PassthroughSubject<SecurityAndPrivacyScreenViewModelAction, Never> = .init()
|
||||
var actionsPublisher: AnyPublisher<SecurityAndPrivacyScreenViewModelAction, Never> {
|
||||
@@ -24,14 +25,23 @@ class SecurityAndPrivacyScreenViewModel: SecurityAndPrivacyScreenViewModelType,
|
||||
|
||||
init(roomProxy: JoinedRoomProxyProtocol,
|
||||
clientProxy: ClientProxyProtocol,
|
||||
userIndicatorController: UserIndicatorControllerProtocol) {
|
||||
userIndicatorController: UserIndicatorControllerProtocol,
|
||||
appSettings: AppSettings) {
|
||||
self.roomProxy = roomProxy
|
||||
self.clientProxy = clientProxy
|
||||
self.userIndicatorController = userIndicatorController
|
||||
self.appSettings = appSettings
|
||||
|
||||
super.init(initialViewState: SecurityAndPrivacyScreenViewState(serverName: clientProxy.userIDServerName ?? "",
|
||||
accessType: roomProxy.infoPublisher.value.joinRule.toSecurityAndPrivacyRoomAccessType,
|
||||
isEncryptionEnabled: roomProxy.infoPublisher.value.isEncrypted,
|
||||
historyVisibility: roomProxy.infoPublisher.value.historyVisibility.toSecurityAndPrivacyHistoryVisibility))
|
||||
historyVisibility: roomProxy.infoPublisher.value.historyVisibility.toSecurityAndPrivacyHistoryVisibility,
|
||||
isSpace: roomProxy.infoPublisher.value.isSpace,
|
||||
isKnockingEnabled: appSettings.knockingEnabled))
|
||||
|
||||
if let powerLevels = roomProxy.infoPublisher.value.powerLevels {
|
||||
setupPermissions(powerLevels: powerLevels)
|
||||
}
|
||||
|
||||
setupRoomDirectoryVisibility()
|
||||
setupSubscriptions()
|
||||
@@ -82,7 +92,8 @@ class SecurityAndPrivacyScreenViewModel: SecurityAndPrivacyScreenViewModelType,
|
||||
|
||||
let userIDServerName = clientProxy.userIDServerName
|
||||
|
||||
roomProxy.infoPublisher
|
||||
let infoPublisher = roomProxy.infoPublisher
|
||||
infoPublisher
|
||||
.compactMap { roomInfo in
|
||||
guard let userIDServerName else {
|
||||
return nil
|
||||
@@ -96,6 +107,33 @@ class SecurityAndPrivacyScreenViewModel: SecurityAndPrivacyScreenViewModelType,
|
||||
.receive(on: DispatchQueue.main)
|
||||
.weakAssign(to: \.state.canonicalAlias, on: self)
|
||||
.store(in: &cancellables)
|
||||
|
||||
infoPublisher
|
||||
.compactMap(\.powerLevels)
|
||||
.removeDuplicates { $0.userPowerLevels == $1.userPowerLevels && $0.values == $1.values }
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink { [weak self] powerLevels in
|
||||
self?.setupPermissions(powerLevels: powerLevels)
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
infoPublisher
|
||||
.map(\.isSpace)
|
||||
.removeDuplicates()
|
||||
.receive(on: DispatchQueue.main)
|
||||
.weakAssign(to: \.state.isSpace, on: self)
|
||||
.store(in: &cancellables)
|
||||
|
||||
appSettings.$knockingEnabled
|
||||
.weakAssign(to: \.state.isKnockingEnabled, on: self)
|
||||
.store(in: &cancellables)
|
||||
}
|
||||
|
||||
private func setupPermissions(powerLevels: RoomPowerLevelsProxyProtocol) {
|
||||
state.canEditAddress = powerLevels.canOwnUser(sendStateEvent: .roomAliases)
|
||||
state.canEditJoinRule = powerLevels.canOwnUser(sendStateEvent: .roomJoinRules)
|
||||
state.canEditHistoryVisibility = powerLevels.canOwnUser(sendStateEvent: .roomHistoryVisibility)
|
||||
state.canEnableEncryption = powerLevels.canOwnUser(sendStateEvent: .roomEncryption)
|
||||
}
|
||||
|
||||
private func setupRoomDirectoryVisibility() {
|
||||
|
||||
@@ -14,8 +14,11 @@ struct SecurityAndPrivacyScreen: View {
|
||||
|
||||
var body: some View {
|
||||
Form {
|
||||
roomAccessSection
|
||||
if context.desiredSettings.accessType != .inviteOnly {
|
||||
if context.viewState.canEditJoinRule {
|
||||
roomAccessSection
|
||||
}
|
||||
|
||||
if context.desiredSettings.accessType != .inviteOnly, context.viewState.canEditAddress {
|
||||
if let canonicalAlias = context.viewState.canonicalAlias {
|
||||
visibilitySection
|
||||
addressSection(canonicalAlias: canonicalAlias)
|
||||
@@ -25,8 +28,15 @@ struct SecurityAndPrivacyScreen: View {
|
||||
addAddressSection
|
||||
}
|
||||
}
|
||||
encryptionSection
|
||||
historySection
|
||||
|
||||
if !context.viewState.isSpace {
|
||||
if context.viewState.canEnableEncryption {
|
||||
encryptionSection
|
||||
}
|
||||
if context.viewState.canEditHistoryVisibility {
|
||||
historySection
|
||||
}
|
||||
}
|
||||
}
|
||||
.compoundList()
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
@@ -40,9 +50,12 @@ struct SecurityAndPrivacyScreen: View {
|
||||
ListRow(label: .plain(title: L10n.screenSecurityAndPrivacyRoomAccessInviteOnlyOptionTitle,
|
||||
description: L10n.screenSecurityAndPrivacyRoomAccessInviteOnlyOptionDescription),
|
||||
kind: .selection(isSelected: context.desiredSettings.accessType == .inviteOnly) { context.desiredSettings.accessType = .inviteOnly })
|
||||
ListRow(label: .plain(title: L10n.screenSecurityAndPrivacyAskToJoinOptionTitle,
|
||||
description: L10n.screenSecurityAndPrivacyAskToJoinOptionDescription),
|
||||
kind: .selection(isSelected: context.desiredSettings.accessType == .askToJoin) { context.desiredSettings.accessType = .askToJoin })
|
||||
if context.viewState.isKnockingEnabled || context.viewState.currentSettings.accessType == .askToJoin {
|
||||
ListRow(label: .plain(title: L10n.screenSecurityAndPrivacyAskToJoinOptionTitle,
|
||||
description: L10n.screenSecurityAndPrivacyAskToJoinOptionDescription),
|
||||
kind: .selection(isSelected: context.desiredSettings.accessType == .askToJoin) { context.desiredSettings.accessType = .askToJoin })
|
||||
.disabled(!context.viewState.isKnockingEnabled)
|
||||
}
|
||||
ListRow(label: .plain(title: L10n.screenSecurityAndPrivacyRoomAccessAnyoneOptionTitle,
|
||||
description: L10n.screenSecurityAndPrivacyRoomAccessAnyoneOptionDescription),
|
||||
kind: .selection(isSelected: context.desiredSettings.accessType == .anyone) { context.desiredSettings.accessType = .anyone })
|
||||
@@ -187,28 +200,76 @@ struct SecurityAndPrivacyScreen: View {
|
||||
// MARK: - Previews
|
||||
|
||||
struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview {
|
||||
static let inviteOnlyViewModel = SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(joinRule: .invite)),
|
||||
clientProxy: ClientProxyMock(.init()),
|
||||
userIndicatorController: UserIndicatorControllerMock())
|
||||
static let inviteOnlyViewModel = {
|
||||
AppSettings.resetAllSettings()
|
||||
return SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(members: .allMembersAsCreator,
|
||||
joinRule: .invite)),
|
||||
clientProxy: ClientProxyMock(.init()),
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
appSettings: AppSettings())
|
||||
}()
|
||||
|
||||
static let publicViewModel = SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false,
|
||||
canonicalAlias: "#room:matrix.org",
|
||||
joinRule: .public,
|
||||
isVisibleInPublicDirectory: true)),
|
||||
clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org")),
|
||||
userIndicatorController: UserIndicatorControllerMock())
|
||||
static let publicViewModel = {
|
||||
AppSettings.resetAllSettings()
|
||||
return SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false,
|
||||
canonicalAlias: "#room:matrix.org",
|
||||
members: .allMembersAsCreator,
|
||||
joinRule: .public,
|
||||
isVisibleInPublicDirectory: true)),
|
||||
clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org")),
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
appSettings: AppSettings())
|
||||
}()
|
||||
|
||||
static let publicNoAddressViewModel = SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false,
|
||||
joinRule: .public)),
|
||||
clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org")),
|
||||
userIndicatorController: UserIndicatorControllerMock())
|
||||
static let publicNoAddressViewModel = {
|
||||
AppSettings.resetAllSettings()
|
||||
return SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false,
|
||||
members: .allMembersAsCreator,
|
||||
joinRule: .public)),
|
||||
clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org")),
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
appSettings: AppSettings())
|
||||
}()
|
||||
|
||||
static let restrictedViewModel = SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false,
|
||||
canonicalAlias: "#room:matrix.org",
|
||||
joinRule: .restricted(rules: []),
|
||||
isVisibleInPublicDirectory: true)),
|
||||
clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org")),
|
||||
userIndicatorController: UserIndicatorControllerMock())
|
||||
static let restrictedViewModel = {
|
||||
AppSettings.resetAllSettings()
|
||||
return SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false,
|
||||
canonicalAlias: "#room:matrix.org",
|
||||
members: .allMembersAsCreator,
|
||||
joinRule: .restricted(rules: []),
|
||||
isVisibleInPublicDirectory: true)),
|
||||
clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org")),
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
appSettings: AppSettings())
|
||||
}()
|
||||
|
||||
static let askToJoinViewModel = {
|
||||
AppSettings.resetAllSettings()
|
||||
let appSettings = AppSettings()
|
||||
appSettings.knockingEnabled = true
|
||||
|
||||
return SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isEncrypted: false,
|
||||
canonicalAlias: "#room:matrix.org",
|
||||
members: .allMembersAsCreator,
|
||||
joinRule: .knock,
|
||||
isVisibleInPublicDirectory: true)),
|
||||
clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org")),
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
appSettings: appSettings)
|
||||
}()
|
||||
|
||||
static let publicSpaceViewModel = {
|
||||
AppSettings.resetAllSettings()
|
||||
return SecurityAndPrivacyScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(isSpace: true,
|
||||
isEncrypted: false,
|
||||
canonicalAlias: "#space:matrix.org",
|
||||
members: .allMembersAsCreator,
|
||||
joinRule: .public,
|
||||
isVisibleInPublicDirectory: true)),
|
||||
clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org")),
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
appSettings: AppSettings())
|
||||
}()
|
||||
|
||||
static var previews: some View {
|
||||
NavigationStack {
|
||||
@@ -236,5 +297,21 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview {
|
||||
state.currentSettings.isVisibileInRoomDirectory == true
|
||||
})
|
||||
.previewDisplayName("Restricted room")
|
||||
|
||||
NavigationStack {
|
||||
SecurityAndPrivacyScreen(context: askToJoinViewModel.context)
|
||||
}
|
||||
.snapshotPreferences(expect: restrictedViewModel.context.$viewState.map { state in
|
||||
state.currentSettings.isVisibileInRoomDirectory == true
|
||||
})
|
||||
.previewDisplayName("Ask to join room")
|
||||
|
||||
NavigationStack {
|
||||
SecurityAndPrivacyScreen(context: publicSpaceViewModel.context)
|
||||
}
|
||||
.snapshotPreferences(expect: restrictedViewModel.context.$viewState.map { state in
|
||||
state.currentSettings.isVisibileInRoomDirectory == true
|
||||
})
|
||||
.previewDisplayName("Public space")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,8 +40,13 @@ protocol RoomPowerLevelsProxyProtocol {
|
||||
// MARK: - Helpers
|
||||
|
||||
extension RoomPowerLevelsProxyProtocol {
|
||||
/// Can own user edit either the room name, avatar or topic
|
||||
/// Can own user edit either the room name, avatar or topic.
|
||||
func canOwnUserEditBaseInfo() -> Bool {
|
||||
canOwnUser(sendStateEvent: .roomAvatar) || canOwnUser(sendStateEvent: .roomName) || canOwnUser(sendStateEvent: .roomTopic)
|
||||
}
|
||||
|
||||
/// Can own user edit any of the security and privacy settings.
|
||||
func canOwnUserEditSecurityAndPrivacy() -> Bool {
|
||||
canOwnUser(sendStateEvent: .roomEncryption) || canOwnUser(sendStateEvent: .roomAliases) || canOwnUser(sendStateEvent: .roomJoinRules) || canOwnUser(sendStateEvent: .roomHistoryVisibility)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user