mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-02 12:07:55 +00:00
Security and privacy part 2 (#3637)
* handling the history visibility flag * better logic to handle visibility * better handling of the visibility options state * added some copies, and the public room directory visibility state * completed the UI added also the preview tests * improved the handling of the directory visibility * added the space users case and improved handling of the access -> vsibility reaction. Also added a simple error handling for the public directory toggle * added the edit room address view but is missing its full implementation * implement the UI for the edit room address screen * implemented error checking when editing the address * updated preview tests and improved code * typo fix * Fix various issues after rebasing. * Fix build errors and broken snapshot tests * Adopt latest room privacy and canonical alias setting APIs * Add support for creating and editing the room's alias. * Add support for saving room privacy setting changes. * Fix room alias screen snapshot tests following recent changes. --------- Co-authored-by: Stefan Ceriu <stefanc@matrix.org>
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
//
|
||||
// Copyright 2022-2024 New Vector Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
// Please see LICENSE in the repository root for full details.
|
||||
//
|
||||
|
||||
import Compound
|
||||
import SwiftUI
|
||||
|
||||
struct EditRoomAddressScreen: View {
|
||||
@ObservedObject var context: EditRoomAddressScreenViewModel.Context
|
||||
|
||||
var body: some View {
|
||||
Form {
|
||||
Section {
|
||||
EditRoomAddressListRow(aliasLocalPart: $context.desiredAliasLocalPart,
|
||||
serverName: context.viewState.serverName, shouldDisplayError: context.viewState.aliasErrors.errorDescription != nil)
|
||||
.onChange(of: context.desiredAliasLocalPart) { _, newAliasLocalPart in
|
||||
context.desiredAliasLocalPart = newAliasLocalPart.lowercased()
|
||||
}
|
||||
.onSubmit {
|
||||
if context.viewState.canSave {
|
||||
context.send(viewAction: .save)
|
||||
}
|
||||
}
|
||||
} footer: {
|
||||
VStack(alignment: .leading, spacing: 12) {
|
||||
if let errorDescription = context.viewState.aliasErrors.errorDescription {
|
||||
Label(errorDescription, icon: \.error, iconSize: .xSmall, relativeTo: .compound.bodySM)
|
||||
.foregroundStyle(.compound.textCriticalPrimary)
|
||||
.font(.compound.bodySM)
|
||||
}
|
||||
Text(L10n.screenCreateRoomRoomAddressSectionFooter)
|
||||
.compoundListSectionFooter()
|
||||
.font(.compound.bodySM)
|
||||
}
|
||||
}
|
||||
}
|
||||
.compoundList()
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.navigationTitle(L10n.screenEditRoomAddressTitle)
|
||||
.toolbar { toolbar }
|
||||
}
|
||||
|
||||
@ToolbarContentBuilder
|
||||
var toolbar: some ToolbarContent {
|
||||
ToolbarItem(placement: .confirmationAction) {
|
||||
Button(L10n.actionSave) {
|
||||
context.send(viewAction: .save)
|
||||
}
|
||||
.disabled(!context.viewState.canSave)
|
||||
}
|
||||
ToolbarItem(placement: .cancellationAction) {
|
||||
Button(L10n.actionCancel) {
|
||||
context.send(viewAction: .cancel)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Previews
|
||||
|
||||
struct EditRoomAddressScreen_Previews: PreviewProvider, TestablePreview {
|
||||
static let noAliasviewModel = EditRoomAddressScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "Room Name")),
|
||||
clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org")),
|
||||
userIndicatorController: UserIndicatorControllerMock())
|
||||
|
||||
static let aliasviewModel = EditRoomAddressScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "Room Name", canonicalAlias: "#room-alias:matrix.org")),
|
||||
clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org")),
|
||||
userIndicatorController: UserIndicatorControllerMock())
|
||||
|
||||
static let invalidSymbolsViewModel = EditRoomAddressScreenViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "Room Name", canonicalAlias: "#room#-alias:matrix.org")),
|
||||
clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org")),
|
||||
userIndicatorController: UserIndicatorControllerMock())
|
||||
|
||||
static let alreadyExistingViewModel = {
|
||||
let clientProxy = ClientProxyMock(.init(userIDServerName: "matrix.org"))
|
||||
clientProxy.isAliasAvailableReturnValue = .success(false)
|
||||
return EditRoomAddressScreenViewModel(initialViewState: .init(serverName: "matrix.org",
|
||||
bindings: .init(desiredAliasLocalPart: "whatever")),
|
||||
roomProxy: JoinedRoomProxyMock(.init(name: "Room Name")),
|
||||
clientProxy: clientProxy,
|
||||
userIndicatorController: UserIndicatorControllerMock())
|
||||
}()
|
||||
|
||||
static var previews: some View {
|
||||
NavigationStack {
|
||||
EditRoomAddressScreen(context: noAliasviewModel.context)
|
||||
}
|
||||
.previewDisplayName("No alias")
|
||||
|
||||
NavigationStack {
|
||||
EditRoomAddressScreen(context: aliasviewModel.context)
|
||||
}
|
||||
.previewDisplayName("With alias")
|
||||
|
||||
NavigationStack {
|
||||
EditRoomAddressScreen(context: invalidSymbolsViewModel.context)
|
||||
}
|
||||
.snapshotPreferences(expect: invalidSymbolsViewModel.context.$viewState.map { state in
|
||||
!state.aliasErrors.isEmpty
|
||||
})
|
||||
.previewDisplayName("Invalid symbols")
|
||||
|
||||
NavigationStack {
|
||||
EditRoomAddressScreen(context: alreadyExistingViewModel.context)
|
||||
}
|
||||
.snapshotPreferences(expect: alreadyExistingViewModel.context.$viewState.map { state in
|
||||
!state.aliasErrors.isEmpty
|
||||
})
|
||||
.previewDisplayName("Already existing")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user