Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 73 additions & 72 deletions ElementX.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,7 @@
"soft_logout_clear_data_submit" = "Clear all data";
"soft_logout_clear_data_dialog_title" = "Clear data";
"soft_logout_clear_data_dialog_content" = "Clear all data currently stored on this device?\nSign in again to access your account data and messages.";

// MARK: - Shared history visibility

"crypto_history_visible" = "Messages you send will be shared with new members invited to this room. %1$s";
6 changes: 6 additions & 0 deletions ElementX/Sources/Application/Settings/AppSettings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ final class AppSettings {

case elementCallBaseURLOverride

case acknowledgedHistoryVisibleRooms

// Feature flags
case publicSearchEnabled
case fuzzyRoomListSearchEnabled
Expand Down Expand Up @@ -171,6 +173,10 @@ final class AppSettings {
@UserPreference(key: UserDefaultsKeys.hasSeenNewSoundBanner, defaultValue: true, storageType: .userDefaults(store))
var hasSeenNewSoundBanner

/// The Set of room identifiers that the user has acknowledged have visible history.
@UserPreference(key: UserDefaultsKeys.acknowledgedHistoryVisibleRooms, defaultValue: [], storageType: .userDefaults(store))
var acknowledgedHistoryVisibleRooms: Set<String>

/// The initial set of account providers shown to the user in the authentication flow.
///
/// Account provider is the friendly term for the server name. It should not contain an `https` prefix and should
Expand Down
4 changes: 4 additions & 0 deletions ElementX/Sources/Generated/Strings+Untranslated.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ import Foundation
// swiftlint:disable explicit_type_interface function_parameter_count identifier_name line_length
// swiftlint:disable nesting type_body_length type_name vertical_whitespace_opening_braces
internal enum UntranslatedL10n {
/// Messages you send will be shared with new members invited to this room. %1$s
internal static func cryptoHistoryVisible(_ p1: UnsafePointer<CChar>) -> String {
return UntranslatedL10n.tr("Untranslated", "crypto_history_visible", p1)
}
/// Clear all data currently stored on this device?
/// Sign in again to access your account data and messages.
internal static var softLogoutClearDataDialogContent: String { return UntranslatedL10n.tr("Untranslated", "soft_logout_clear_data_dialog_content") }
Expand Down
2 changes: 2 additions & 0 deletions ElementX/Sources/Screens/RoomScreen/RoomScreenModels.swift
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,13 @@ struct RoomScreenViewStateBindings {
enum RoomScreenFooterViewAction {
case resolvePinViolation(userID: String)
case resolveVerificationViolation(userID: String)
case dismissHistoryVisibleAlert
}

enum RoomScreenFooterViewDetails {
case pinViolation(member: RoomMemberProxyProtocol, learnMoreURL: URL)
case verificationViolation(member: RoomMemberProxyProtocol, learnMoreURL: URL)
case historyVisible(learnMoreURL: URL)
}

enum PinnedEventsBannerState: Equatable {
Expand Down
10 changes: 10 additions & 0 deletions ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
Task { await resolveIdentityPinningViolation(userID) }
case .resolveVerificationViolation(let userID):
Task { await resolveIdentityVerificationViolation(userID) }
case .dismissHistoryVisibleAlert:
appSettings.acknowledgedHistoryVisibleRooms.insert(roomProxy.id)
state.footerDetails = nil
}
case .acceptKnock(let eventID):
Task { await acceptKnock(eventID: eventID) }
Expand Down Expand Up @@ -342,6 +345,13 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
state.canDeclineKnocks = powerLevels.canOwnUserKick()
state.canBan = powerLevels.canOwnUserBan()
}

if roomInfo.historyVisibility == RoomHistoryVisibility.joined {
appSettings.acknowledgedHistoryVisibleRooms.remove(roomInfo.id)
state.footerDetails = nil
} else if roomInfo.isEncrypted, !appSettings.acknowledgedHistoryVisibleRooms.contains(roomInfo.id) {
state.footerDetails = .historyVisible(learnMoreURL: "https://element.io")
}
}

private func setupPinnedEventsTimelineItemProviderIfNeeded() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ struct RoomScreenFooterView: View {
.compound.borderInfoSubtle
case .verificationViolation:
.compound.borderCriticalSubtle
case .historyVisible:
.compound.borderInfoSubtle
case .none:
Color.compound.bgCanvasDefault
}
Expand All @@ -31,6 +33,8 @@ struct RoomScreenFooterView: View {
.compound.info
case .verificationViolation:
Gradient(colors: [.compound.bgCriticalSubtle, .clear])
case .historyVisible:
Gradient(colors: [.compound.bgInfoSubtle, .clear])
case .none:
Gradient(colors: [.clear])
}
Expand All @@ -54,6 +58,8 @@ struct RoomScreenFooterView: View {
pinViolation(member: member, learnMoreURL: learnMoreURL)
case .verificationViolation(member: let member, learnMoreURL: let learnMoreURL):
verificationViolation(member: member, learnMoreURL: learnMoreURL)
case .historyVisible(learnMoreURL: let learnMoreURL):
historyVisibleAlert(learnMoreUrl: learnMoreURL)
}
}

Expand Down Expand Up @@ -155,6 +161,34 @@ struct RoomScreenFooterView: View {
guard let localpart = userID.components(separatedBy: ":").first else { return userID }
return String(localpart.trimmingPrefix("@"))
}

private func historyVisibleAlert(learnMoreUrl: URL) -> some View {
let linkPlaceholder = "{link}"
var description = AttributedString(UntranslatedL10n.cryptoHistoryVisible(linkPlaceholder))
var linkString = AttributedString(L10n.actionLearnMore)
linkString.link = learnMoreUrl
linkString.bold()
description.replace(linkPlaceholder, with: linkString)

return VStack(spacing: 16) {
HStack(spacing: 16) {
CompoundIcon(\.info).foregroundColor(.compound.iconInfoPrimary)
Text(description)
.font(.compound.bodyMD)
.foregroundColor(.compound.textInfoPrimary)
}
Button {
callback(.dismissHistoryVisibleAlert)
} label: {
Text(L10n.actionDismiss)
.frame(maxWidth: .infinity)
}
.buttonStyle(.compound(.primary, size: .medium))
}
.padding(.top, 16)
.padding(.horizontal, 16)
.padding(.bottom, 8)
}
}

struct RoomScreenFooterView_Previews: PreviewProvider, TestablePreview {
Expand All @@ -166,12 +200,16 @@ struct RoomScreenFooterView_Previews: PreviewProvider, TestablePreview {
static let verificationViolationDetails: RoomScreenFooterViewDetails = .verificationViolation(member: RoomMemberProxyMock.mockBob,
learnMoreURL: "https://element.io/")

static let historyVisibleDetails: RoomScreenFooterViewDetails = .historyVisible(learnMoreURL: "https://element.io")

static var previews: some View {
RoomScreenFooterView(details: bobDetails, mediaProvider: MediaProviderMock(configuration: .init())) { _ in }
.previewDisplayName("With displayname")
RoomScreenFooterView(details: noNameDetails, mediaProvider: MediaProviderMock(configuration: .init())) { _ in }
.previewDisplayName("Without displayname")
RoomScreenFooterView(details: verificationViolationDetails, mediaProvider: MediaProviderMock(configuration: .init())) { _ in }
.previewDisplayName("Verification Violation")
RoomScreenFooterView(details: historyVisibleDetails, mediaProvider: MediaProviderMock(configuration: .init()))
{ _ in }.previewDisplayName("History Visible")
}
}
Loading