security and privacy redesign for spaces.

This commit is contained in:
Mauro Romito
2025-11-12 18:34:35 +01:00
committed by Mauro
parent f32921ce70
commit c3f31a9e23
87 changed files with 461 additions and 353 deletions
+15 -11
View File
@@ -1632,9 +1632,9 @@ internal enum L10n {
internal static var screenEditProfileTitle: String { return L10n.tr("Localizable", "screen_edit_profile_title") }
/// Updating profile…
internal static var screenEditProfileUpdatingDetails: String { return L10n.tr("Localizable", "screen_edit_profile_updating_details") }
/// You’ll need a room address in order to make it visible in the directory.
/// You’ll need an address in order to make it visible in the public directory.
internal static var screenEditRoomAddressRoomAddressSectionFooter: String { return L10n.tr("Localizable", "screen_edit_room_address_room_address_section_footer") }
/// Room address
/// Edit address
internal static var screenEditRoomAddressTitle: String { return L10n.tr("Localizable", "screen_edit_room_address_title") }
/// Continue reset
internal static var screenEncryptionResetActionContinueReset: String { return L10n.tr("Localizable", "screen_encryption_reset_action_continue_reset") }
@@ -2376,7 +2376,7 @@ internal enum L10n {
internal static var screenRoomDetailsBadgeNotEncrypted: String { return L10n.tr("Localizable", "screen_room_details_badge_not_encrypted") }
/// Public room
internal static var screenRoomDetailsBadgePublic: String { return L10n.tr("Localizable", "screen_room_details_badge_public") }
/// Edit Room
/// Edit details
internal static var screenRoomDetailsEditRoomTitle: String { return L10n.tr("Localizable", "screen_room_details_edit_room_title") }
/// There was an unknown error and the information couldn't be changed.
internal static var screenRoomDetailsEditionError: String { return L10n.tr("Localizable", "screen_room_details_edition_error") }
@@ -2732,7 +2732,7 @@ internal enum L10n {
internal static var screenRoomlistTombstonedRoomDescription: String { return L10n.tr("Localizable", "screen_roomlist_tombstoned_room_description") }
/// Add room address
internal static var screenSecurityAndPrivacyAddRoomAddressAction: String { return L10n.tr("Localizable", "screen_security_and_privacy_add_room_address_action") }
/// Anyone can ask to join the room but an administrator or moderator will have to accept the request.
/// Anyone can request access but an administrator must accept the request.
internal static var screenSecurityAndPrivacyAskToJoinOptionDescription: String { return L10n.tr("Localizable", "screen_security_and_privacy_ask_to_join_option_description") }
/// Ask to join
internal static var screenSecurityAndPrivacyAskToJoinOptionTitle: String { return L10n.tr("Localizable", "screen_security_and_privacy_ask_to_join_option_title") }
@@ -2750,29 +2750,33 @@ internal enum L10n {
internal static var screenSecurityAndPrivacyEncryptionSectionHeader: String { return L10n.tr("Localizable", "screen_security_and_privacy_encryption_section_header") }
/// Enable end-to-end encryption
internal static var screenSecurityAndPrivacyEncryptionToggleTitle: String { return L10n.tr("Localizable", "screen_security_and_privacy_encryption_toggle_title") }
/// Anyone can find and join
/// Anyone can join.
internal static var screenSecurityAndPrivacyRoomAccessAnyoneOptionDescription: String { return L10n.tr("Localizable", "screen_security_and_privacy_room_access_anyone_option_description") }
/// Anyone
/// Public
internal static var screenSecurityAndPrivacyRoomAccessAnyoneOptionTitle: String { return L10n.tr("Localizable", "screen_security_and_privacy_room_access_anyone_option_title") }
/// People can only join if they are invited
/// Only invited people can join.
internal static var screenSecurityAndPrivacyRoomAccessInviteOnlyOptionDescription: String { return L10n.tr("Localizable", "screen_security_and_privacy_room_access_invite_only_option_description") }
/// Invite only
/// Private
internal static var screenSecurityAndPrivacyRoomAccessInviteOnlyOptionTitle: String { return L10n.tr("Localizable", "screen_security_and_privacy_room_access_invite_only_option_title") }
/// Room access
/// Access
internal static var screenSecurityAndPrivacyRoomAccessSectionHeader: String { return L10n.tr("Localizable", "screen_security_and_privacy_room_access_section_header") }
/// Spaces are not currently supported
internal static var screenSecurityAndPrivacyRoomAccessSpaceMembersOptionDescription: String { return L10n.tr("Localizable", "screen_security_and_privacy_room_access_space_members_option_description") }
/// Space members
internal static var screenSecurityAndPrivacyRoomAccessSpaceMembersOptionTitle: String { return L10n.tr("Localizable", "screen_security_and_privacy_room_access_space_members_option_title") }
/// You’ll need an address in order to make it visible in the public directory.
internal static var screenSecurityAndPrivacyRoomAddressDescription: String { return L10n.tr("Localizable", "screen_security_and_privacy_room_address_description") }
/// You’ll need a room address in order to make it visible in the room directory.
internal static var screenSecurityAndPrivacyRoomAddressSectionFooter: String { return L10n.tr("Localizable", "screen_security_and_privacy_room_address_section_footer") }
/// Room address
/// Published address
internal static var screenSecurityAndPrivacyRoomAddressSectionHeader: String { return L10n.tr("Localizable", "screen_security_and_privacy_room_address_section_header") }
/// Allow for this room to be found by searching %1$@ public room directory
internal static func screenSecurityAndPrivacyRoomDirectoryVisibilitySectionFooter(_ p1: Any) -> String {
return L10n.tr("Localizable", "screen_security_and_privacy_room_directory_visibility_section_footer", String(describing: p1))
}
/// Visible in public room directory
/// Allow to be found by searching the public directory.
internal static var screenSecurityAndPrivacyRoomDirectoryVisibilityToggleDescription: String { return L10n.tr("Localizable", "screen_security_and_privacy_room_directory_visibility_toggle_description") }
/// Visible in public directory
internal static var screenSecurityAndPrivacyRoomDirectoryVisibilityToggleTitle: String { return L10n.tr("Localizable", "screen_security_and_privacy_room_directory_visibility_toggle_title") }
/// Anyone
internal static var screenSecurityAndPrivacyRoomHistoryAnyoneOptionTitle: String { return L10n.tr("Localizable", "screen_security_and_privacy_room_history_anyone_option_title") }
@@ -32,7 +32,7 @@ struct EditRoomAddressScreen: View {
.foregroundStyle(.compound.textCriticalPrimary)
.font(.compound.bodySM)
}
Text(L10n.screenCreateRoomRoomAddressSectionFooter)
Text(L10n.screenEditRoomAddressRoomAddressSectionFooter)
.compoundListSectionFooter()
.font(.compound.bodySM)
}
@@ -20,9 +20,7 @@ struct SecurityAndPrivacyScreen: View {
if context.desiredSettings.accessType != .inviteOnly, context.viewState.canEditAddress {
if let canonicalAlias = context.viewState.canonicalAlias {
visibilitySection
addressSection(canonicalAlias: canonicalAlias)
roomDirectoryVisibilitySection
} else {
publishingSection
addAddressSection
@@ -47,26 +45,31 @@ struct SecurityAndPrivacyScreen: View {
private var roomAccessSection: some View {
Section {
ListRow(label: .plain(title: L10n.screenSecurityAndPrivacyRoomAccessInviteOnlyOptionTitle,
description: L10n.screenSecurityAndPrivacyRoomAccessInviteOnlyOptionDescription),
kind: .selection(isSelected: context.desiredSettings.accessType == .inviteOnly) { context.desiredSettings.accessType = .inviteOnly })
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.isKnockingEnabled || context.viewState.currentSettings.accessType == .askToJoin {
ListRow(label: .plain(title: L10n.screenSecurityAndPrivacyAskToJoinOptionTitle,
description: L10n.screenSecurityAndPrivacyAskToJoinOptionDescription),
ListRow(label: .default(title: L10n.screenSecurityAndPrivacyAskToJoinOptionTitle,
description: L10n.screenSecurityAndPrivacyAskToJoinOptionDescription,
icon: \.userAdd),
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 })
if context.viewState.currentSettings.accessType == .spaceUsers {
ListRow(label: .plain(title: L10n.screenSecurityAndPrivacyRoomAccessSpaceMembersOptionTitle,
description: L10n.screenSecurityAndPrivacyRoomAccessSpaceMembersOptionDescription),
ListRow(label: .default(title: L10n.screenSecurityAndPrivacyRoomAccessSpaceMembersOptionTitle,
description: L10n.screenSecurityAndPrivacyRoomAccessSpaceMembersOptionDescription,
icon: \.space),
kind: .selection(isSelected: context.desiredSettings.accessType == .spaceUsers) { })
// This is not supported so it will always be disabled and has no handler
.disabled(true)
}
ListRow(label: .default(title: L10n.screenSecurityAndPrivacyRoomAccessInviteOnlyOptionTitle,
description: L10n.screenSecurityAndPrivacyRoomAccessInviteOnlyOptionDescription,
icon: \.lock),
kind: .selection(isSelected: context.desiredSettings.accessType == .inviteOnly) { context.desiredSettings.accessType = .inviteOnly })
} header: {
Text(L10n.screenSecurityAndPrivacyRoomAccessSectionHeader)
.compoundListSectionHeader()
@@ -116,27 +119,15 @@ struct SecurityAndPrivacyScreen: View {
}
}
private var visibilitySection: some View {
Section {
EmptyView()
} header: {
Text(L10n.screenSecurityAndPrivacyRoomVisibilitySectionHeader)
.compoundListSectionHeader()
} footer: {
Text(L10n.screenSecurityAndPrivacyRoomVisibilitySectionFooter(context.viewState.serverName))
.compoundListSectionFooter()
}
}
private func addressSection(canonicalAlias: String) -> some View {
Section {
ListRow(label: .plain(title: canonicalAlias), kind: .navigationLink { context.send(viewAction: .editAddress) })
ListRow(label: .plain(title: canonicalAlias,
description: L10n.screenSecurityAndPrivacyRoomAddressDescription),
kind: .navigationLink { context.send(viewAction: .editAddress) })
roomDirectoryVisibilityRow
} header: {
Text(L10n.screenSecurityAndPrivacyRoomAddressSectionHeader)
.compoundListSectionHeader()
} footer: {
Text(L10n.screenSecurityAndPrivacyRoomAddressSectionFooter)
.compoundListSectionFooter()
}
}
@@ -168,22 +159,16 @@ struct SecurityAndPrivacyScreen: View {
}
@ViewBuilder
private var roomDirectoryVisibilitySection: some View {
private var roomDirectoryVisibilityRow: some View {
let binding = Binding<Bool>(get: {
context.desiredSettings.isVisibileInRoomDirectory ?? false
}, set: { newValue in
context.desiredSettings.isVisibileInRoomDirectory = newValue
})
Section {
ListRow(label: .plain(title: L10n.screenSecurityAndPrivacyRoomDirectoryVisibilityToggleTitle),
details:
context.desiredSettings.isVisibileInRoomDirectory == nil ? .isWaiting(true) : nil,
kind: context.desiredSettings.isVisibileInRoomDirectory == nil ? .label : .toggle(binding))
} footer: {
Text(L10n.screenSecurityAndPrivacyRoomDirectoryVisibilitySectionFooter(context.viewState.serverName))
.compoundListSectionFooter()
}
ListRow(label: .plain(title: L10n.screenSecurityAndPrivacyRoomDirectoryVisibilityToggleTitle,
description: L10n.screenSecurityAndPrivacyRoomDirectoryVisibilityToggleDescription),
details: context.desiredSettings.isVisibileInRoomDirectory == nil ? .isWaiting(true) : nil,
kind: context.desiredSettings.isVisibileInRoomDirectory == nil ? .label : .toggle(binding))
}
@ToolbarContentBuilder