This reverts commit 1e0bbce3c4.
This commit is contained in:
@@ -32,7 +32,6 @@ final class AppSettings {
|
||||
case seenInvites
|
||||
case hasSeenSpacesAnnouncement
|
||||
case hasSeenNewSoundBanner
|
||||
case acknowledgedHistoryVisibleRooms
|
||||
case appLockNumberOfPINAttempts
|
||||
case appLockNumberOfBiometricAttempts
|
||||
case timelineStyle
|
||||
@@ -126,7 +125,6 @@ final class AppSettings {
|
||||
deviceVerificationURL: URL,
|
||||
chatBackupDetailsURL: URL,
|
||||
identityPinningViolationDetailsURL: URL,
|
||||
historyVisibleDetailsURL: URL,
|
||||
elementWebHosts: [String],
|
||||
accountProvisioningHost: String,
|
||||
bugReportApplicationID: String,
|
||||
@@ -146,7 +144,6 @@ final class AppSettings {
|
||||
self.deviceVerificationURL = deviceVerificationURL
|
||||
self.chatBackupDetailsURL = chatBackupDetailsURL
|
||||
self.identityPinningViolationDetailsURL = identityPinningViolationDetailsURL
|
||||
self.historyVisibleDetailsURL = historyVisibleDetailsURL
|
||||
self.elementWebHosts = elementWebHosts
|
||||
self.accountProvisioningHost = accountProvisioningHost
|
||||
self.bugReportApplicationID = bugReportApplicationID
|
||||
@@ -174,10 +171,6 @@ 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
|
||||
@@ -209,8 +202,6 @@ 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 where users can go to read more about room history sharing.
|
||||
private(set) var historyVisibleDetailsURL: 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.
|
||||
|
||||
@@ -93,13 +93,11 @@ 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 {
|
||||
|
||||
@@ -101,9 +101,6 @@ 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) }
|
||||
@@ -345,16 +342,6 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
state.canDeclineKnocks = powerLevels.canOwnUserKick()
|
||||
state.canBan = powerLevels.canOwnUserBan()
|
||||
}
|
||||
|
||||
// Whever the user opens a room with joined history visibility, we clear the dismiss flag to ensure that the banner is displayed again if the history is made visible in the future.
|
||||
if roomInfo.historyVisibility == RoomHistoryVisibility.joined {
|
||||
appSettings.acknowledgedHistoryVisibleRooms.remove(roomInfo.id)
|
||||
state.footerDetails = nil
|
||||
}
|
||||
// Whenever the user opens an encrypted room with non-join history visbility, we show them a warning banner if they have not already dismissed it.
|
||||
else if roomInfo.isEncrypted, !appSettings.acknowledgedHistoryVisibleRooms.contains(roomInfo.id) {
|
||||
state.footerDetails = .historyVisible(learnMoreURL: appSettings.historyVisibleDetailsURL)
|
||||
}
|
||||
}
|
||||
|
||||
private func setupPinnedEventsTimelineItemProviderIfNeeded() {
|
||||
|
||||
@@ -16,7 +16,7 @@ struct RoomScreenFooterView: View {
|
||||
|
||||
private var borderColor: Color {
|
||||
switch details {
|
||||
case .pinViolation, .historyVisible:
|
||||
case .pinViolation:
|
||||
.compound.borderInfoSubtle
|
||||
case .verificationViolation:
|
||||
.compound.borderCriticalSubtle
|
||||
@@ -27,7 +27,7 @@ struct RoomScreenFooterView: View {
|
||||
|
||||
private var gradient: Gradient {
|
||||
switch details {
|
||||
case .pinViolation, .historyVisible:
|
||||
case .pinViolation:
|
||||
.compound.info
|
||||
case .verificationViolation:
|
||||
Gradient(colors: [.compound.bgCriticalSubtle, .clear])
|
||||
@@ -54,8 +54,6 @@ 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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,43 +151,10 @@ struct RoomScreenFooterView: View {
|
||||
return description
|
||||
}
|
||||
|
||||
private func historyVisibleAlertDescriptionWithLearnMoreLink(learnMoreURL: URL) -> AttributedString {
|
||||
let linkPlaceholder = "{link}"
|
||||
var description = AttributedString(L10n.cryptoHistoryVisible(linkPlaceholder))
|
||||
var linkString = AttributedString(L10n.actionLearnMore)
|
||||
linkString.link = learnMoreURL
|
||||
linkString.bold()
|
||||
description.replace(linkPlaceholder, with: linkString)
|
||||
return description
|
||||
}
|
||||
|
||||
private func fallbackDisplayName(_ userID: String) -> String {
|
||||
guard let localpart = userID.components(separatedBy: ":").first else { return userID }
|
||||
return String(localpart.trimmingPrefix("@"))
|
||||
}
|
||||
|
||||
private func historyVisibleAlert(learnMoreURL: URL) -> some View {
|
||||
let description = historyVisibleAlertDescriptionWithLearnMoreLink(learnMoreURL: learnMoreURL)
|
||||
|
||||
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 {
|
||||
@@ -201,8 +166,6 @@ 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")
|
||||
@@ -210,6 +173,5 @@ struct RoomScreenFooterView_Previews: PreviewProvider, TestablePreview {
|
||||
.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")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,7 +140,6 @@ class MockScreen: Identifiable {
|
||||
deviceVerificationURL: appSettings.deviceVerificationURL,
|
||||
chatBackupDetailsURL: appSettings.chatBackupDetailsURL,
|
||||
identityPinningViolationDetailsURL: appSettings.identityPinningViolationDetailsURL,
|
||||
historyVisibleDetailsURL: appSettings.historyVisibleDetailsURL,
|
||||
elementWebHosts: appSettings.elementWebHosts,
|
||||
accountProvisioningHost: appSettings.accountProvisioningHost,
|
||||
bugReportApplicationID: appSettings.bugReportApplicationID,
|
||||
|
||||
Submodule Enterprise updated: 6fafddc467...e2c37065c6
@@ -172,7 +172,6 @@ class AuthenticationStartScreenViewModelTests: XCTestCase {
|
||||
deviceVerificationURL: appSettings.deviceVerificationURL,
|
||||
chatBackupDetailsURL: appSettings.chatBackupDetailsURL,
|
||||
identityPinningViolationDetailsURL: appSettings.identityPinningViolationDetailsURL,
|
||||
historyVisibleDetailsURL: appSettings.historyVisibleDetailsURL,
|
||||
elementWebHosts: appSettings.elementWebHosts,
|
||||
accountProvisioningHost: appSettings.accountProvisioningHost,
|
||||
bugReportApplicationID: appSettings.bugReportApplicationID,
|
||||
|
||||
@@ -438,118 +438,4 @@ class RoomScreenViewModelTests: XCTestCase {
|
||||
}
|
||||
try await deferred.fulfill()
|
||||
}
|
||||
|
||||
// MARK: History Sharing
|
||||
|
||||
func testHistoryVisibleBannerDoesNotAppearIfNotEncrypted() async throws {
|
||||
let roomProxyMock = JoinedRoomProxyMock(.init(isEncrypted: false))
|
||||
|
||||
let viewModel = RoomScreenViewModel(userSession: UserSessionMock(.init()),
|
||||
roomProxy: roomProxyMock,
|
||||
initialSelectedPinnedEventID: nil,
|
||||
ongoingCallRoomIDPublisher: .init(.init(nil)),
|
||||
appSettings: ServiceLocator.shared.settings,
|
||||
appHooks: AppHooks(),
|
||||
analyticsService: ServiceLocator.shared.analytics,
|
||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
||||
|
||||
self.viewModel = viewModel
|
||||
|
||||
let deferred = deferFulfillment(viewModel.context.$viewState) { state in
|
||||
state.footerDetails == nil
|
||||
}
|
||||
try await deferred.fulfill()
|
||||
}
|
||||
|
||||
func testHistoryVisibleBannerDoesNotAppearIfJoined() async throws {
|
||||
let configuration = JoinedRoomProxyMockConfiguration(isEncrypted: false)
|
||||
let roomProxyMock = JoinedRoomProxyMock(configuration)
|
||||
|
||||
let roomInfoProxyMock = RoomInfoProxyMock(configuration)
|
||||
roomInfoProxyMock.historyVisibility = .joined
|
||||
|
||||
let infoSubject = CurrentValueSubject<RoomInfoProxyProtocol, Never>(roomInfoProxyMock)
|
||||
roomProxyMock.underlyingInfoPublisher = infoSubject.asCurrentValuePublisher()
|
||||
|
||||
let viewModel = RoomScreenViewModel(userSession: UserSessionMock(.init()),
|
||||
roomProxy: roomProxyMock,
|
||||
initialSelectedPinnedEventID: nil,
|
||||
ongoingCallRoomIDPublisher: .init(.init(nil)),
|
||||
appSettings: ServiceLocator.shared.settings,
|
||||
appHooks: AppHooks(),
|
||||
analyticsService: ServiceLocator.shared.analytics,
|
||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
||||
|
||||
self.viewModel = viewModel
|
||||
|
||||
let deferred = deferFulfillment(viewModel.context.$viewState) { state in
|
||||
state.footerDetails == nil
|
||||
}
|
||||
try await deferred.fulfill()
|
||||
}
|
||||
|
||||
func testHistoryVisibleBannerDoesNotAppearIfAcknowledged() async throws {
|
||||
ServiceLocator.shared.settings.acknowledgedHistoryVisibleRooms.insert("$room:example.com")
|
||||
|
||||
let configuration = JoinedRoomProxyMockConfiguration(id: "$room:example.com", isEncrypted: false)
|
||||
let roomProxyMock = JoinedRoomProxyMock(configuration)
|
||||
|
||||
let roomInfoProxyMock = RoomInfoProxyMock(configuration)
|
||||
roomInfoProxyMock.historyVisibility = .shared
|
||||
|
||||
let infoSubject = CurrentValueSubject<RoomInfoProxyProtocol, Never>(roomInfoProxyMock)
|
||||
roomProxyMock.underlyingInfoPublisher = infoSubject.asCurrentValuePublisher()
|
||||
|
||||
let viewModel = RoomScreenViewModel(userSession: UserSessionMock(.init()),
|
||||
roomProxy: roomProxyMock,
|
||||
initialSelectedPinnedEventID: nil,
|
||||
ongoingCallRoomIDPublisher: .init(.init(nil)),
|
||||
appSettings: ServiceLocator.shared.settings,
|
||||
appHooks: AppHooks(),
|
||||
analyticsService: ServiceLocator.shared.analytics,
|
||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
||||
|
||||
self.viewModel = viewModel
|
||||
|
||||
let deferred = deferFulfillment(viewModel.context.$viewState) { state in
|
||||
state.footerDetails == nil
|
||||
}
|
||||
try await deferred.fulfill()
|
||||
}
|
||||
|
||||
func testHistoryVisibleBannerAppearsThenDisappearsOnAcknowledge() async throws {
|
||||
let configuration = JoinedRoomProxyMockConfiguration(id: "$room:example.com", isEncrypted: true)
|
||||
let roomProxyMock = JoinedRoomProxyMock(configuration)
|
||||
|
||||
let roomInfoProxyMock = RoomInfoProxyMock(configuration)
|
||||
roomInfoProxyMock.historyVisibility = .shared
|
||||
|
||||
let infoSubject = CurrentValueSubject<RoomInfoProxyProtocol, Never>(roomInfoProxyMock)
|
||||
roomProxyMock.underlyingInfoPublisher = infoSubject.asCurrentValuePublisher()
|
||||
|
||||
let viewModel = RoomScreenViewModel(userSession: UserSessionMock(.init()),
|
||||
roomProxy: roomProxyMock,
|
||||
initialSelectedPinnedEventID: nil,
|
||||
ongoingCallRoomIDPublisher: .init(.init(nil)),
|
||||
appSettings: ServiceLocator.shared.settings,
|
||||
appHooks: AppHooks(),
|
||||
analyticsService: ServiceLocator.shared.analytics,
|
||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
||||
|
||||
self.viewModel = viewModel
|
||||
|
||||
var deferred = deferFulfillment(viewModel.context.$viewState) { state in
|
||||
state.footerDetails != nil
|
||||
}
|
||||
try await deferred.fulfill()
|
||||
|
||||
deferred = deferFulfillment(viewModel.context.$viewState) { state in
|
||||
state.footerDetails == nil
|
||||
}
|
||||
|
||||
ServiceLocator.shared.settings.acknowledgedHistoryVisibleRooms.insert("$room:example.com")
|
||||
viewModel.context.send(viewAction: .footerViewAction(RoomScreenFooterViewAction.dismissHistoryVisibleAlert))
|
||||
|
||||
try await deferred.fulfill()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -324,7 +324,6 @@ class ServerConfirmationScreenViewModelTests: XCTestCase {
|
||||
deviceVerificationURL: appSettings.deviceVerificationURL,
|
||||
chatBackupDetailsURL: appSettings.chatBackupDetailsURL,
|
||||
identityPinningViolationDetailsURL: appSettings.identityPinningViolationDetailsURL,
|
||||
historyVisibleDetailsURL: appSettings.historyVisibleDetailsURL,
|
||||
elementWebHosts: appSettings.elementWebHosts,
|
||||
accountProvisioningHost: appSettings.accountProvisioningHost,
|
||||
bugReportApplicationID: appSettings.bugReportApplicationID,
|
||||
|
||||
Reference in New Issue
Block a user