mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-02 21:33:26 +00:00
Update history visible settings (#4861)
* Fixes #4852 - Update history visible settings * Address PR comments and move attributed strings to the view state
This commit is contained in:
@@ -125,6 +125,7 @@ final class AppSettings {
|
||||
deviceVerificationURL: URL,
|
||||
chatBackupDetailsURL: URL,
|
||||
identityPinningViolationDetailsURL: URL,
|
||||
historySharingDetailsURL: URL,
|
||||
elementWebHosts: [String],
|
||||
accountProvisioningHost: String,
|
||||
bugReportApplicationID: String,
|
||||
@@ -144,6 +145,7 @@ final class AppSettings {
|
||||
self.deviceVerificationURL = deviceVerificationURL
|
||||
self.chatBackupDetailsURL = chatBackupDetailsURL
|
||||
self.identityPinningViolationDetailsURL = identityPinningViolationDetailsURL
|
||||
self.historySharingDetailsURL = historySharingDetailsURL
|
||||
self.elementWebHosts = elementWebHosts
|
||||
self.accountProvisioningHost = accountProvisioningHost
|
||||
self.bugReportApplicationID = bugReportApplicationID
|
||||
@@ -202,6 +204,9 @@ final class AppSettings {
|
||||
private(set) var chatBackupDetailsURL: URL = "https://element.io/help#encryption5"
|
||||
/// A URL where users can go read more about identity pinning violations
|
||||
private(set) var identityPinningViolationDetailsURL: URL = "https://element.io/help#encryption18"
|
||||
/// A URL describing how history sharing works
|
||||
private(set) var historySharingDetailsURL: URL = "https://element.io/en/help#e2ee-history-sharing"
|
||||
|
||||
/// Any domains that Element web may be hosted on - used for handling links.
|
||||
private(set) var elementWebHosts = ["app.element.io", "staging.element.io", "develop.element.io"]
|
||||
/// The domain that account provisioning links will be hosted on - used for handling the links.
|
||||
|
||||
@@ -2906,13 +2906,17 @@ internal enum L10n {
|
||||
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
|
||||
/// Anyone (history is public)
|
||||
internal static var screenSecurityAndPrivacyRoomHistoryAnyoneOptionTitle: String { return L10n.tr("Localizable", "screen_security_and_privacy_room_history_anyone_option_title") }
|
||||
/// Changes won't affect past messages, only new ones. %@
|
||||
internal static func screenSecurityAndPrivacyRoomHistorySectionFooter(_ p1: Any) -> String {
|
||||
return L10n.tr("Localizable", "screen_security_and_privacy_room_history_section_footer", String(describing: p1))
|
||||
}
|
||||
/// Who can read history
|
||||
internal static var screenSecurityAndPrivacyRoomHistorySectionHeader: String { return L10n.tr("Localizable", "screen_security_and_privacy_room_history_section_header") }
|
||||
/// Members only since they were invited
|
||||
/// Members since invited
|
||||
internal static var screenSecurityAndPrivacyRoomHistorySinceInviteOptionTitle: String { return L10n.tr("Localizable", "screen_security_and_privacy_room_history_since_invite_option_title") }
|
||||
/// Members only since selecting this option
|
||||
/// Members (full history)
|
||||
internal static var screenSecurityAndPrivacyRoomHistorySinceSelectingOptionTitle: String { return L10n.tr("Localizable", "screen_security_and_privacy_room_history_since_selecting_option_title") }
|
||||
/// Room addresses are ways to find and access rooms. This also ensures you can easily share your room with others.
|
||||
/// You can choose to publish your room in your homeserver public room directory.
|
||||
|
||||
+52
-32
@@ -15,20 +15,12 @@ enum SecurityAndPrivacyScreenViewModelAction {
|
||||
}
|
||||
|
||||
struct SecurityAndPrivacyScreenViewState: BindableState {
|
||||
private static let accessSectionFooterAttributedString = {
|
||||
let linkPlaceholder = "{link}"
|
||||
var footer = AttributedString(L10n.screenSecurityAndPrivacyRoomAccessFooter(linkPlaceholder))
|
||||
var linkString = AttributedString(L10n.screenSecurityAndPrivacyRoomAccessFooterManageSpacesAction)
|
||||
// Doesn't really matter
|
||||
linkString.link = .init(stringLiteral: "action://manageSpace")
|
||||
linkString.bold()
|
||||
footer.replace(linkPlaceholder, with: linkString)
|
||||
return footer
|
||||
}()
|
||||
|
||||
let serverName: String
|
||||
|
||||
var currentSettings: SecurityAndPrivacySettings
|
||||
var bindings: SecurityAndPrivacyScreenViewStateBindings
|
||||
let strings: SecurityAndPrivacyScreenStrings
|
||||
|
||||
var canonicalAlias: String?
|
||||
var isKnockingEnabled: Bool
|
||||
var isSpaceSettingsEnabled: Bool
|
||||
@@ -38,6 +30,7 @@ struct SecurityAndPrivacyScreenViewState: BindableState {
|
||||
var canEditJoinRule = false
|
||||
var canEnableEncryption = false
|
||||
var canEditHistoryVisibility = false
|
||||
|
||||
/// The union of joined parent spaces and the joined spaces in the current access type
|
||||
var selectableJoinedSpaces: [SpaceRoomProxyProtocol] = []
|
||||
|
||||
@@ -58,13 +51,13 @@ struct SecurityAndPrivacyScreenViewState: BindableState {
|
||||
}
|
||||
|
||||
var availableVisibilityOptions: [SecurityAndPrivacyHistoryVisibility] {
|
||||
var options = [SecurityAndPrivacyHistoryVisibility.sinceSelection]
|
||||
var options = [SecurityAndPrivacyHistoryVisibility.shared]
|
||||
if !bindings.desiredSettings.isEncryptionEnabled, bindings.desiredSettings.accessType == .anyone {
|
||||
options.append(.anyone)
|
||||
options.append(.worldReadable)
|
||||
} else {
|
||||
options.append(.sinceInvite)
|
||||
options.append(.invited)
|
||||
}
|
||||
return options
|
||||
return options.sorted()
|
||||
}
|
||||
|
||||
var isSpaceMembersOptionAvailable: Bool {
|
||||
@@ -113,16 +106,14 @@ struct SecurityAndPrivacyScreenViewState: BindableState {
|
||||
}
|
||||
}
|
||||
|
||||
var accessSectionFooter: AttributedString? {
|
||||
if (bindings.desiredSettings.accessType.isSpaceMembers &&
|
||||
isSpaceMembersOptionSelectable) ||
|
||||
(bindings.desiredSettings.accessType.isAskToJoinWithSpaceMembers &&
|
||||
isAskToJoinWithSpaceMembersOptionSelectable),
|
||||
var shouldShowAccessSectionFooter: Bool {
|
||||
if (bindings.desiredSettings.accessType.isSpaceMembers && isSpaceMembersOptionSelectable) ||
|
||||
(bindings.desiredSettings.accessType.isAskToJoinWithSpaceMembers && isAskToJoinWithSpaceMembersOptionSelectable),
|
||||
case .multiple = spaceSelection {
|
||||
Self.accessSectionFooterAttributedString
|
||||
} else {
|
||||
nil
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
enum SpaceSelection {
|
||||
@@ -169,7 +160,8 @@ struct SecurityAndPrivacyScreenViewState: BindableState {
|
||||
historyVisibility: SecurityAndPrivacyHistoryVisibility,
|
||||
isSpace: Bool,
|
||||
isKnockingEnabled: Bool,
|
||||
isSpaceSettingsEnabled: Bool) {
|
||||
isSpaceSettingsEnabled: Bool,
|
||||
historySharingDetailsURL: URL) {
|
||||
self.serverName = serverName
|
||||
self.isKnockingEnabled = isKnockingEnabled
|
||||
self.isSpace = isSpace
|
||||
@@ -180,6 +172,7 @@ struct SecurityAndPrivacyScreenViewState: BindableState {
|
||||
historyVisibility: historyVisibility)
|
||||
currentSettings = settings
|
||||
bindings = SecurityAndPrivacyScreenViewStateBindings(desiredSettings: settings)
|
||||
strings = SecurityAndPrivacyScreenStrings(historySharingDetailsURL: historySharingDetailsURL)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -254,17 +247,44 @@ enum SecurityAndPrivacyScreenViewAction {
|
||||
case manageSpaces
|
||||
}
|
||||
|
||||
enum SecurityAndPrivacyHistoryVisibility {
|
||||
case sinceSelection
|
||||
case sinceInvite
|
||||
case anyone
|
||||
enum SecurityAndPrivacyHistoryVisibility: Int, Comparable {
|
||||
case invited
|
||||
case shared
|
||||
case worldReadable
|
||||
|
||||
var fallbackOption: Self {
|
||||
switch self {
|
||||
case .sinceInvite, .sinceSelection:
|
||||
return .sinceSelection
|
||||
case .anyone:
|
||||
return .sinceInvite
|
||||
case .invited, .shared:
|
||||
return .shared
|
||||
case .worldReadable:
|
||||
return .invited
|
||||
}
|
||||
}
|
||||
|
||||
static func < (lhs: SecurityAndPrivacyHistoryVisibility, rhs: SecurityAndPrivacyHistoryVisibility) -> Bool {
|
||||
lhs.rawValue < rhs.rawValue
|
||||
}
|
||||
}
|
||||
|
||||
struct SecurityAndPrivacyScreenStrings {
|
||||
let accessSectionFooterString: AttributedString
|
||||
let historySectionFooterString: AttributedString
|
||||
|
||||
init(historySharingDetailsURL: URL) {
|
||||
let linkPlaceholder = "{link}"
|
||||
|
||||
var accessFooterString = AttributedString(L10n.screenSecurityAndPrivacyRoomAccessFooter(linkPlaceholder))
|
||||
var accessLinkString = AttributedString(L10n.screenSecurityAndPrivacyRoomAccessFooterManageSpacesAction)
|
||||
accessLinkString.link = .init(stringLiteral: "action://manageSpace") // The link address doesn't matter
|
||||
accessLinkString.bold()
|
||||
accessFooterString.replace(linkPlaceholder, with: accessLinkString)
|
||||
accessSectionFooterString = accessFooterString
|
||||
|
||||
var historyFooterString = AttributedString(L10n.screenSecurityAndPrivacyRoomHistorySectionFooter(linkPlaceholder))
|
||||
var historyLinkString = AttributedString(L10n.actionLearnMore)
|
||||
historyLinkString.link = historySharingDetailsURL
|
||||
historyLinkString.bold()
|
||||
historyFooterString.replace(linkPlaceholder, with: historyLinkString)
|
||||
historySectionFooterString = historyFooterString
|
||||
}
|
||||
}
|
||||
|
||||
+8
-7
@@ -38,7 +38,8 @@ class SecurityAndPrivacyScreenViewModel: SecurityAndPrivacyScreenViewModelType,
|
||||
historyVisibility: roomProxy.infoPublisher.value.historyVisibility.toSecurityAndPrivacyHistoryVisibility,
|
||||
isSpace: roomProxy.infoPublisher.value.isSpace,
|
||||
isKnockingEnabled: appSettings.knockingEnabled,
|
||||
isSpaceSettingsEnabled: appSettings.spaceSettingsEnabled))
|
||||
isSpaceSettingsEnabled: appSettings.spaceSettingsEnabled,
|
||||
historySharingDetailsURL: appSettings.historySharingDetailsURL))
|
||||
|
||||
if let powerLevels = roomProxy.infoPublisher.value.powerLevels {
|
||||
setupPermissions(powerLevels: powerLevels)
|
||||
@@ -345,11 +346,11 @@ private extension RoomHistoryVisibility {
|
||||
var toSecurityAndPrivacyHistoryVisibility: SecurityAndPrivacyHistoryVisibility {
|
||||
switch self {
|
||||
case .joined, .invited:
|
||||
return .sinceInvite
|
||||
return .invited
|
||||
case .shared, .custom:
|
||||
return .sinceSelection
|
||||
return .shared
|
||||
case .worldReadable:
|
||||
return .anyone
|
||||
return .worldReadable
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -357,11 +358,11 @@ private extension RoomHistoryVisibility {
|
||||
private extension SecurityAndPrivacyHistoryVisibility {
|
||||
var toRoomHistoryVisibility: RoomHistoryVisibility {
|
||||
switch self {
|
||||
case .sinceSelection:
|
||||
case .shared:
|
||||
return .shared
|
||||
case .sinceInvite:
|
||||
case .invited:
|
||||
return .invited
|
||||
case .anyone:
|
||||
case .worldReadable:
|
||||
return .worldReadable
|
||||
}
|
||||
}
|
||||
|
||||
+13
-10
@@ -80,8 +80,8 @@ struct SecurityAndPrivacyScreen: View {
|
||||
Text(L10n.screenSecurityAndPrivacyRoomAccessSectionHeader)
|
||||
.compoundListSectionHeader()
|
||||
} footer: {
|
||||
if let footer = context.viewState.accessSectionFooter {
|
||||
Text(footer)
|
||||
if context.viewState.shouldShowAccessSectionFooter {
|
||||
Text(context.viewState.strings.accessSectionFooterString)
|
||||
.compoundListSectionFooter()
|
||||
.environment(\.openURL, OpenURLAction { _ in
|
||||
context.send(viewAction: .manageSpaces)
|
||||
@@ -133,20 +133,23 @@ struct SecurityAndPrivacyScreen: View {
|
||||
Section {
|
||||
ForEach(context.viewState.availableVisibilityOptions, id: \.self) { option in
|
||||
switch option {
|
||||
case .sinceSelection:
|
||||
ListRow(label: .plain(title: L10n.screenSecurityAndPrivacyRoomHistorySinceSelectingOptionTitle),
|
||||
kind: .selection(isSelected: context.desiredSettings.historyVisibility == .sinceSelection) { context.desiredSettings.historyVisibility = .sinceSelection })
|
||||
case .anyone:
|
||||
ListRow(label: .plain(title: L10n.screenSecurityAndPrivacyRoomHistoryAnyoneOptionTitle),
|
||||
kind: .selection(isSelected: context.desiredSettings.historyVisibility == .anyone) { context.desiredSettings.historyVisibility = .anyone })
|
||||
case .sinceInvite:
|
||||
case .invited:
|
||||
ListRow(label: .plain(title: L10n.screenSecurityAndPrivacyRoomHistorySinceInviteOptionTitle),
|
||||
kind: .selection(isSelected: context.desiredSettings.historyVisibility == .sinceInvite) { context.desiredSettings.historyVisibility = .sinceInvite })
|
||||
kind: .selection(isSelected: context.desiredSettings.historyVisibility == .invited) { context.desiredSettings.historyVisibility = .invited })
|
||||
case .shared:
|
||||
ListRow(label: .plain(title: L10n.screenSecurityAndPrivacyRoomHistorySinceSelectingOptionTitle),
|
||||
kind: .selection(isSelected: context.desiredSettings.historyVisibility == .shared) { context.desiredSettings.historyVisibility = .shared })
|
||||
case .worldReadable:
|
||||
ListRow(label: .plain(title: L10n.screenSecurityAndPrivacyRoomHistoryAnyoneOptionTitle),
|
||||
kind: .selection(isSelected: context.desiredSettings.historyVisibility == .worldReadable) { context.desiredSettings.historyVisibility = .worldReadable })
|
||||
}
|
||||
}
|
||||
} header: {
|
||||
Text(L10n.screenSecurityAndPrivacyRoomHistorySectionHeader)
|
||||
.compoundListSectionHeader()
|
||||
} footer: {
|
||||
Text(context.viewState.strings.historySectionFooterString)
|
||||
.compoundListSectionFooter()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -140,6 +140,7 @@ class MockScreen: Identifiable {
|
||||
deviceVerificationURL: appSettings.deviceVerificationURL,
|
||||
chatBackupDetailsURL: appSettings.chatBackupDetailsURL,
|
||||
identityPinningViolationDetailsURL: appSettings.identityPinningViolationDetailsURL,
|
||||
historySharingDetailsURL: appSettings.historySharingDetailsURL,
|
||||
elementWebHosts: appSettings.elementWebHosts,
|
||||
accountProvisioningHost: appSettings.accountProvisioningHost,
|
||||
bugReportApplicationID: appSettings.bugReportApplicationID,
|
||||
|
||||
Reference in New Issue
Block a user