Remove message pinning FF (#3318)

This commit is contained in:
Mauro
2024-09-30 14:32:35 +02:00
committed by GitHub
parent 5d35a74fb6
commit 5f4c2890f6
13 changed files with 21 additions and 72 deletions
@@ -271,9 +271,6 @@ final class AppSettings {
@UserPreference(key: UserDefaultsKeys.fuzzyRoomListSearchEnabled, defaultValue: false, storageType: .userDefaults(store)) @UserPreference(key: UserDefaultsKeys.fuzzyRoomListSearchEnabled, defaultValue: false, storageType: .userDefaults(store))
var fuzzyRoomListSearchEnabled var fuzzyRoomListSearchEnabled
@UserPreference(key: UserDefaultsKeys.pinningEnabled, defaultValue: true, storageType: .userDefaults(store))
var pinningEnabled
enum SlidingSyncDiscovery: Codable { case proxy, native, forceNative } enum SlidingSyncDiscovery: Codable { case proxy, native, forceNative }
@UserPreference(key: UserDefaultsKeys.slidingSyncDiscovery, defaultValue: .native, storageType: .userDefaults(store)) @UserPreference(key: UserDefaultsKeys.slidingSyncDiscovery, defaultValue: .native, storageType: .userDefaults(store))
var slidingSyncDiscovery: SlidingSyncDiscovery var slidingSyncDiscovery: SlidingSyncDiscovery
@@ -44,7 +44,6 @@ struct RoomDetailsScreenViewState: BindableState {
var canEditRolesOrPermissions = false var canEditRolesOrPermissions = false
var notificationSettingsState: RoomDetailsNotificationSettingsState = .loading var notificationSettingsState: RoomDetailsNotificationSettingsState = .loading
var canJoinCall = false var canJoinCall = false
var isPinningEnabled = false
var pinnedEventsActionState = RoomDetailsScreenPinnedEventsActionState.loading var pinnedEventsActionState = RoomDetailsScreenPinnedEventsActionState.loading
var canEdit: Bool { var canEdit: Bool {
@@ -75,13 +75,8 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr
bindings: .init()), bindings: .init()),
mediaProvider: mediaProvider) mediaProvider: mediaProvider)
appSettings.$pinningEnabled appMediator.networkMonitor.reachabilityPublisher
.weakAssign(to: \.state.isPinningEnabled, on: self) .filter { $0 == .reachable }
.store(in: &cancellables)
appSettings.$pinningEnabled
.combineLatest(appMediator.networkMonitor.reachabilityPublisher)
.filter { $0.0 && $0.1 == .reachable }
.receive(on: DispatchQueue.main) .receive(on: DispatchQueue.main)
.sink { [weak self] _ in .sink { [weak self] _ in
self?.setupPinnedEventsTimelineProviderIfNeeded() self?.setupPinnedEventsTimelineProviderIfNeeded()
@@ -189,15 +189,13 @@ struct RoomDetailsScreen: View {
context.send(viewAction: .toggleFavourite(isFavourite: newValue)) context.send(viewAction: .toggleFavourite(isFavourite: newValue))
} }
if context.viewState.isPinningEnabled { ListRow(label: .default(title: L10n.screenRoomDetailsPinnedEventsRowTitle,
ListRow(label: .default(title: L10n.screenRoomDetailsPinnedEventsRowTitle, icon: \.pin),
icon: \.pin), details: context.viewState.pinnedEventsActionState.isLoading ? .isWaiting(true) : .title(context.viewState.pinnedEventsActionState.count),
details: context.viewState.pinnedEventsActionState.isLoading ? .isWaiting(true) : .title(context.viewState.pinnedEventsActionState.count), kind: context.viewState.pinnedEventsActionState.isLoading ? .label : .navigationLink(action: {
kind: context.viewState.pinnedEventsActionState.isLoading ? .label : .navigationLink(action: { context.send(viewAction: .processTapPinnedEvents)
context.send(viewAction: .processTapPinnedEvents) }))
})) .disabled(context.viewState.pinnedEventsActionState.isLoading)
.disabled(context.viewState.pinnedEventsActionState.isLoading)
}
if context.viewState.canEditRolesOrPermissions, context.viewState.dmRecipient == nil { if context.viewState.canEditRolesOrPermissions, context.viewState.dmRecipient == nil {
ListRow(label: .default(title: L10n.screenRoomDetailsRolesAndPermissions, ListRow(label: .default(title: L10n.screenRoomDetailsRolesAndPermissions,
@@ -320,8 +318,6 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview {
var notificationSettingsProxyMockConfiguration = NotificationSettingsProxyMockConfiguration() var notificationSettingsProxyMockConfiguration = NotificationSettingsProxyMockConfiguration()
notificationSettingsProxyMockConfiguration.roomMode.isDefault = false notificationSettingsProxyMockConfiguration.roomMode.isDefault = false
let notificationSettingsProxy = NotificationSettingsProxyMock(with: notificationSettingsProxyMockConfiguration) let notificationSettingsProxy = NotificationSettingsProxyMock(with: notificationSettingsProxyMockConfiguration)
let appSettings = AppSettings()
appSettings.pinningEnabled = true
return RoomDetailsScreenViewModel(roomProxy: roomProxy, return RoomDetailsScreenViewModel(roomProxy: roomProxy,
clientProxy: ClientProxyMock(.init()), clientProxy: ClientProxyMock(.init()),
@@ -331,7 +327,7 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview {
notificationSettingsProxy: notificationSettingsProxy, notificationSettingsProxy: notificationSettingsProxy,
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()), attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()),
appMediator: AppMediatorMock.default, appMediator: AppMediatorMock.default,
appSettings: appSettings) appSettings: ServiceLocator.shared.settings)
}() }()
static let dmRoomViewModel = { static let dmRoomViewModel = {
@@ -348,8 +344,6 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview {
canonicalAlias: "#alias:domain.com", canonicalAlias: "#alias:domain.com",
members: members)) members: members))
let notificationSettingsProxy = NotificationSettingsProxyMock(with: .init()) let notificationSettingsProxy = NotificationSettingsProxyMock(with: .init())
let appSettings = AppSettings()
appSettings.pinningEnabled = true
return RoomDetailsScreenViewModel(roomProxy: roomProxy, return RoomDetailsScreenViewModel(roomProxy: roomProxy,
clientProxy: ClientProxyMock(.init()), clientProxy: ClientProxyMock(.init()),
@@ -359,7 +353,7 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview {
notificationSettingsProxy: notificationSettingsProxy, notificationSettingsProxy: notificationSettingsProxy,
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()), attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()),
appMediator: AppMediatorMock.default, appMediator: AppMediatorMock.default,
appSettings: appSettings) appSettings: ServiceLocator.shared.settings)
}() }()
static let simpleRoomViewModel = { static let simpleRoomViewModel = {
@@ -375,8 +369,6 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview {
isEncrypted: false, isEncrypted: false,
members: members)) members: members))
let notificationSettingsProxy = NotificationSettingsProxyMock(with: .init()) let notificationSettingsProxy = NotificationSettingsProxyMock(with: .init())
let appSettings = AppSettings()
appSettings.pinningEnabled = true
return RoomDetailsScreenViewModel(roomProxy: roomProxy, return RoomDetailsScreenViewModel(roomProxy: roomProxy,
clientProxy: ClientProxyMock(.init()), clientProxy: ClientProxyMock(.init()),
@@ -386,7 +378,7 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview {
notificationSettingsProxy: notificationSettingsProxy, notificationSettingsProxy: notificationSettingsProxy,
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()), attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()),
appMediator: AppMediatorMock.default, appMediator: AppMediatorMock.default,
appSettings: appSettings) appSettings: ServiceLocator.shared.settings)
}() }()
static var previews: some View { static var previews: some View {
@@ -28,11 +28,10 @@ struct RoomScreenViewState: BindableState {
var roomAvatar: RoomAvatar var roomAvatar: RoomAvatar
var lastScrollDirection: ScrollDirection? var lastScrollDirection: ScrollDirection?
var isPinningEnabled = false
// This is used to control the banner // This is used to control the banner
var pinnedEventsBannerState: PinnedEventsBannerState = .loading(numbersOfEvents: 0) var pinnedEventsBannerState: PinnedEventsBannerState = .loading(numbersOfEvents: 0)
var shouldShowPinnedEventsBanner: Bool { var shouldShowPinnedEventsBanner: Bool {
isPinningEnabled && !pinnedEventsBannerState.isEmpty && lastScrollDirection != .top !pinnedEventsBannerState.isEmpty && lastScrollDirection != .top
} }
var canJoinCall = false var canJoinCall = false
@@ -124,15 +124,8 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
} }
.store(in: &cancellables) .store(in: &cancellables)
let pinningEnabledPublisher = appSettings.$pinningEnabled appMediator.networkMonitor.reachabilityPublisher
.filter { $0 == .reachable }
pinningEnabledPublisher
.weakAssign(to: \.state.isPinningEnabled, on: self)
.store(in: &cancellables)
pinningEnabledPublisher
.combineLatest(appMediator.networkMonitor.reachabilityPublisher)
.filter { $0.0 && $0.1 == .reachable }
.receive(on: DispatchQueue.main) .receive(on: DispatchQueue.main)
.sink { [weak self] _ in .sink { [weak self] _ in
self?.setupPinnedEventsTimelineProviderIfNeeded() self?.setupPinnedEventsTimelineProviderIfNeeded()
@@ -46,7 +46,6 @@ protocol DeveloperOptionsProtocol: AnyObject {
var hideUnreadMessagesBadge: Bool { get set } var hideUnreadMessagesBadge: Bool { get set }
var elementCallBaseURLOverride: URL? { get set } var elementCallBaseURLOverride: URL? { get set }
var fuzzyRoomListSearchEnabled: Bool { get set } var fuzzyRoomListSearchEnabled: Bool { get set }
var pinningEnabled: Bool { get set }
var enableOnlySignedDeviceIsolationMode: Bool { get set } var enableOnlySignedDeviceIsolationMode: Bool { get set }
} }
@@ -35,13 +35,6 @@ struct DeveloperOptionsScreen: View {
Text(context.viewState.slidingSyncFooter) Text(context.viewState.slidingSyncFooter)
} }
Section("Message Pinning") {
Toggle(isOn: $context.pinningEnabled) {
Text("Enable message pinning")
Text("Requires app reboot")
}
}
Section("Room List") { Section("Room List") {
Toggle(isOn: $context.hideUnreadMessagesBadge) { Toggle(isOn: $context.hideUnreadMessagesBadge) {
Text("Hide grey dots") Text("Hide grey dots")
@@ -336,8 +336,7 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol {
state.canCurrentUserRedactSelf = false state.canCurrentUserRedactSelf = false
} }
if appSettings.pinningEnabled, if case let .success(value) = await roomProxy.canUserPinOrUnpin(userID: roomProxy.ownUserID) {
case let .success(value) = await roomProxy.canUserPinOrUnpin(userID: roomProxy.ownUserID) {
state.canCurrentUserPin = value state.canCurrentUserPin = value
} else { } else {
state.canCurrentUserPin = false state.canCurrentUserPin = false
@@ -444,9 +443,7 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol {
} }
private func updatePinnedEventIDs() async { private func updatePinnedEventIDs() async {
if appSettings.pinningEnabled { state.pinnedEventIDs = await roomProxy.pinnedEventIDs
state.pinnedEventIDs = await roomProxy.pinnedEventIDs
}
} }
private func setupDirectRoomSubscriptionsIfNeeded() { private func setupDirectRoomSubscriptionsIfNeeded() {
@@ -355,8 +355,6 @@ private extension View {
struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview { struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview {
static let viewModel = TimelineViewModel.mock static let viewModel = TimelineViewModel.mock
static let viewModelWithPins: TimelineViewModel = { static let viewModelWithPins: TimelineViewModel = {
var settings = AppSettings()
settings.pinningEnabled = true
let roomProxy = JoinedRoomProxyMock(.init(name: "Preview Room", pinnedEventIDs: [""])) let roomProxy = JoinedRoomProxyMock(.init(name: "Preview Room", pinnedEventIDs: [""]))
return TimelineViewModel(roomProxy: roomProxy, return TimelineViewModel(roomProxy: roomProxy,
focussedEventID: nil, focussedEventID: nil,
@@ -366,7 +364,7 @@ struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview
voiceMessageMediaManager: VoiceMessageMediaManagerMock(), voiceMessageMediaManager: VoiceMessageMediaManagerMock(),
userIndicatorController: ServiceLocator.shared.userIndicatorController, userIndicatorController: ServiceLocator.shared.userIndicatorController,
appMediator: AppMediatorMock.default, appMediator: AppMediatorMock.default,
appSettings: settings, appSettings: ServiceLocator.shared.settings,
analyticsService: ServiceLocator.shared.analytics) analyticsService: ServiceLocator.shared.analytics)
}() }()
@@ -384,7 +382,7 @@ struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview
.previewDisplayName("Encryption Indicators") .previewDisplayName("Encryption Indicators")
pinned pinned
.previewDisplayName("Pinned messages") .previewDisplayName("Pinned messages")
.snapshotPreferences(delay: 1.0) .snapshotPreferences(delay: 2.0)
} }
// These always include a reply // These always include a reply
@@ -816,12 +816,13 @@ class ClientProxy: ClientProxyProtocol {
}) })
} }
private lazy var eventFilters: TimelineEventTypeFilter = { private let eventFilters: TimelineEventTypeFilter = {
var stateEventFilters: [StateEventType] = [.roomAliases, var stateEventFilters: [StateEventType] = [.roomAliases,
.roomCanonicalAlias, .roomCanonicalAlias,
.roomGuestAccess, .roomGuestAccess,
.roomHistoryVisibility, .roomHistoryVisibility,
.roomJoinRules, .roomJoinRules,
.roomPinnedEvents,
.roomPowerLevels, .roomPowerLevels,
.roomServerAcl, .roomServerAcl,
.roomTombstone, .roomTombstone,
@@ -830,12 +831,6 @@ class ClientProxy: ClientProxyProtocol {
.policyRuleRoom, .policyRuleRoom,
.policyRuleServer, .policyRuleServer,
.policyRuleUser] .policyRuleUser]
// Reminder: once the feature flag is not required anymore, change the lazy var back to a let
if !appSettings.pinningEnabled {
stateEventFilters.append(.roomPinnedEvents)
}
return .exclude(eventTypes: stateEventFilters.map { FilterTimelineEventType.state(eventType: $0) }) return .exclude(eventTypes: stateEventFilters.map { FilterTimelineEventType.state(eventType: $0) })
}() }()
@@ -23,7 +23,6 @@ class RoomScreenViewModelTests: XCTestCase {
} }
func testPinnedEventsBanner() async throws { func testPinnedEventsBanner() async throws {
ServiceLocator.shared.settings.pinningEnabled = true
let timelineSubject = PassthroughSubject<TimelineProxyProtocol, Never>() let timelineSubject = PassthroughSubject<TimelineProxyProtocol, Never>()
let updateSubject = PassthroughSubject<JoinedRoomProxyAction, Never>() let updateSubject = PassthroughSubject<JoinedRoomProxyAction, Never>()
let roomProxyMock = JoinedRoomProxyMock(.init()) let roomProxyMock = JoinedRoomProxyMock(.init())
@@ -101,7 +100,6 @@ class RoomScreenViewModelTests: XCTestCase {
} }
func testPinnedEventsBannerSelection() async throws { func testPinnedEventsBannerSelection() async throws {
ServiceLocator.shared.settings.pinningEnabled = true
let roomProxyMock = JoinedRoomProxyMock(.init()) let roomProxyMock = JoinedRoomProxyMock(.init())
// setup a way to inject the mock of the pinned events timeline // setup a way to inject the mock of the pinned events timeline
let pinnedTimelineMock = TimelineProxyMock() let pinnedTimelineMock = TimelineProxyMock()
@@ -346,9 +346,6 @@ class TimelineViewModelTests: XCTestCase {
// MARK: - Pins // MARK: - Pins
func testPinnedEvents() async throws { func testPinnedEvents() async throws {
ServiceLocator.shared.settings.pinningEnabled = true
// Note: We need to start the test with a non-default value so we know the view model has finished the Task.
let roomProxyMock = JoinedRoomProxyMock(.init(name: "", let roomProxyMock = JoinedRoomProxyMock(.init(name: "",
pinnedEventIDs: .init(["test1"]))) pinnedEventIDs: .init(["test1"])))
let actionsSubject = PassthroughSubject<JoinedRoomProxyAction, Never>() let actionsSubject = PassthroughSubject<JoinedRoomProxyAction, Never>()
@@ -378,9 +375,6 @@ class TimelineViewModelTests: XCTestCase {
} }
func testCanUserPinEvents() async throws { func testCanUserPinEvents() async throws {
ServiceLocator.shared.settings.pinningEnabled = true
// Note: We need to start the test with the non-default value so we know the view model has finished the Task.
let roomProxyMock = JoinedRoomProxyMock(.init(name: "", canUserPin: true)) let roomProxyMock = JoinedRoomProxyMock(.init(name: "", canUserPin: true))
let actionsSubject = PassthroughSubject<JoinedRoomProxyAction, Never>() let actionsSubject = PassthroughSubject<JoinedRoomProxyAction, Never>()
roomProxyMock.underlyingActionsPublisher = actionsSubject.eraseToAnyPublisher() roomProxyMock.underlyingActionsPublisher = actionsSubject.eraseToAnyPublisher()