Filters, Mark Unread/Read/Favourites FF removals + code and tests clean up (#2541)

This commit is contained in:
Mauro
2024-03-07 17:56:09 +01:00
committed by GitHub
parent da0fcfe052
commit c66ddfb71e
69 changed files with 105 additions and 374 deletions
@@ -22,18 +22,9 @@ struct BlockedUsersScreenCoordinatorParameters {
let userIndicatorController: UserIndicatorControllerProtocol
}
enum BlockedUsersScreenCoordinatorAction { }
final class BlockedUsersScreenCoordinator: CoordinatorProtocol {
private let viewModel: BlockedUsersScreenViewModelProtocol
private var cancellables = Set<AnyCancellable>()
private let actionsSubject: PassthroughSubject<BlockedUsersScreenCoordinatorAction, Never> = .init()
var actionsPublisher: AnyPublisher<BlockedUsersScreenCoordinatorAction, Never> {
actionsSubject.eraseToAnyPublisher()
}
init(parameters: BlockedUsersScreenCoordinatorParameters) {
viewModel = BlockedUsersScreenViewModel(clientProxy: parameters.clientProxy,
userIndicatorController: parameters.userIndicatorController)
@@ -16,8 +16,6 @@
import Foundation
enum BlockedUsersScreenViewModelAction { }
struct BlockedUsersScreenViewState: BindableState {
var blockedUsers: [String]
var processingUserID: String?
@@ -22,11 +22,6 @@ typealias BlockedUsersScreenViewModelType = StateStoreViewModel<BlockedUsersScre
class BlockedUsersScreenViewModel: BlockedUsersScreenViewModelType, BlockedUsersScreenViewModelProtocol {
let clientProxy: ClientProxyProtocol
let userIndicatorController: UserIndicatorControllerProtocol
private let actionsSubject: PassthroughSubject<BlockedUsersScreenViewModelAction, Never> = .init()
var actionsPublisher: AnyPublisher<BlockedUsersScreenViewModelAction, Never> {
actionsSubject.eraseToAnyPublisher()
}
init(clientProxy: ClientProxyProtocol,
userIndicatorController: UserIndicatorControllerProtocol) {
@@ -18,7 +18,6 @@ import Combine
@MainActor
protocol BlockedUsersScreenViewModelProtocol {
var actionsPublisher: AnyPublisher<BlockedUsersScreenViewModelAction, Never> { get }
var context: BlockedUsersScreenViewModelType.Context { get }
func stop()
@@ -89,10 +89,6 @@ struct HomeScreenViewState: BindableState {
var rooms: [HomeScreenRoom] = []
var roomListMode: HomeScreenRoomListMode = .skeletons
var areFiltersEnabled = false
var markAsUnreadEnabled = false
var markAsFavouriteEnabled = false
var hasPendingInvitations = false
var hasUnreadPendingInvitations = false
@@ -120,11 +116,7 @@ struct HomeScreenViewState: BindableState {
}
var shouldShowEmptyFilterState: Bool {
shouldShowFilters && bindings.filtersState.isFiltering && visibleRooms.isEmpty
}
var shouldShowFilters: Bool {
areFiltersEnabled && !bindings.isSearchFieldFocused
!bindings.isSearchFieldFocused && bindings.filtersState.isFiltering && visibleRooms.isEmpty
}
}
@@ -100,28 +100,6 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
.weakAssign(to: \.state.selectedRoomID, on: self)
.store(in: &cancellables)
appSettings.$roomListFiltersEnabled
.sink { [weak self] value in
guard let self else {
return
}
if !value {
state.areFiltersEnabled = false
state.bindings.filtersState.clearFilters()
} else {
state.areFiltersEnabled = true
}
}
.store(in: &cancellables)
appSettings.$markAsUnreadEnabled
.weakAssign(to: \.state.markAsUnreadEnabled, on: self)
.store(in: &cancellables)
appSettings.$markAsFavouriteEnabled
.weakAssign(to: \.state.markAsFavouriteEnabled, on: self)
.store(in: &cancellables)
appSettings.$hideUnreadMessagesBadge
.sink { [weak self] _ in self?.updateRooms() }
.store(in: &cancellables)
@@ -235,7 +213,7 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
if state.bindings.isSearchFieldFocused {
roomSummaryProvider?.setFilter(.search(query: state.bindings.searchQuery))
} else {
roomSummaryProvider?.setFilter(.all(filters: state.areFiltersEnabled ? state.bindings.filtersState.activeFilters.set : []))
roomSummaryProvider?.setFilter(.all(filters: state.bindings.filtersState.activeFilters.set))
}
}
}
@@ -89,10 +89,6 @@ struct RoomListFiltersState {
return availableFilters.elements
}
var orderedFilters: [RoomListFilter] {
activeFilters.elements + availableFilters
}
var isFiltering: Bool {
!activeFilters.isEmpty
}
@@ -53,36 +53,24 @@ struct HomeScreenContent: View {
.layoutPriority(1)
}
case .rooms:
if context.viewState.areFiltersEnabled {
// Showing empty views in pinned headers makes the room list spasm when reaching the top
LazyVStack(spacing: 0, pinnedViews: [.sectionHeaders]) {
Section {
if context.viewState.shouldShowEmptyFilterState {
RoomListFiltersEmptyStateView(state: context.filtersState)
.frame(height: geometry.size.height - topSectionFrame.height)
} else {
HomeScreenRoomList(context: context)
}
} header: {
topSection
.readFrame($topSectionFrame)
// Showing empty views in pinned headers makes the room list spasm when reaching the top
LazyVStack(spacing: 0, pinnedViews: [.sectionHeaders]) {
Section {
if context.viewState.shouldShowEmptyFilterState {
RoomListFiltersEmptyStateView(state: context.filtersState)
.frame(height: geometry.size.height - topSectionFrame.height)
} else {
HomeScreenRoomList(context: context)
}
} header: {
topSection
.readFrame($topSectionFrame)
}
.isSearching($context.isSearchFieldFocused)
.searchable(text: $context.searchQuery)
.compoundSearchField()
.disableAutocorrection(true)
} else {
topSection
LazyVStack(spacing: 0) {
HomeScreenRoomList(context: context)
.isSearching($context.isSearchFieldFocused)
}
.searchable(text: $context.searchQuery)
.compoundSearchField()
.disableAutocorrection(true)
}
.isSearching($context.isSearchFieldFocused)
.searchable(text: $context.searchQuery)
.compoundSearchField()
.disableAutocorrection(true)
case .migration:
EmptyView()
}
@@ -121,7 +109,7 @@ struct HomeScreenContent: View {
/// The session verification banner and invites button if either are needed.
private var topSection: some View {
VStack(spacing: 0) {
if context.viewState.shouldShowFilters {
if !context.isSearchFieldFocused {
filters
}
@@ -39,35 +39,31 @@ struct HomeScreenRoomList: View {
HomeScreenRoomCell(room: room, context: context, isSelected: isSelected)
.contextMenu {
if context.viewState.markAsUnreadEnabled {
if room.badges.isDotShown {
Button {
context.send(viewAction: .markRoomAsRead(roomIdentifier: room.id))
} label: {
Text(L10n.screenRoomlistMarkAsRead)
}
} else {
Button {
context.send(viewAction: .markRoomAsUnread(roomIdentifier: room.id))
} label: {
Text(L10n.screenRoomlistMarkAsUnread)
}
if room.badges.isDotShown {
Button {
context.send(viewAction: .markRoomAsRead(roomIdentifier: room.id))
} label: {
Text(L10n.screenRoomlistMarkAsRead)
}
} else {
Button {
context.send(viewAction: .markRoomAsUnread(roomIdentifier: room.id))
} label: {
Text(L10n.screenRoomlistMarkAsUnread)
}
}
if context.viewState.markAsFavouriteEnabled {
if room.isFavourite {
Button {
context.send(viewAction: .markRoomAsFavourite(roomIdentifier: room.id, isFavourite: false))
} label: {
Label(L10n.commonFavourited, icon: \.favouriteSolid)
}
} else {
Button {
context.send(viewAction: .markRoomAsFavourite(roomIdentifier: room.id, isFavourite: true))
} label: {
Label(L10n.commonFavourite, icon: \.favourite)
}
if room.isFavourite {
Button {
context.send(viewAction: .markRoomAsFavourite(roomIdentifier: room.id, isFavourite: false))
} label: {
Label(L10n.commonFavourited, icon: \.favouriteSolid)
}
} else {
Button {
context.send(viewAction: .markRoomAsFavourite(roomIdentifier: room.id, isFavourite: true))
} label: {
Label(L10n.commonFavourite, icon: \.favourite)
}
}
@@ -46,7 +46,6 @@ final class InviteUsersScreenCoordinator: CoordinatorProtocol {
roomType: parameters.roomType,
mediaProvider: parameters.mediaProvider,
userDiscoveryService: parameters.userDiscoveryService,
appSettings: ServiceLocator.shared.settings,
userIndicatorController: parameters.userIndicatorController)
}
@@ -23,7 +23,6 @@ typealias InviteUsersScreenViewModelType = StateStoreViewModel<InviteUsersScreen
class InviteUsersScreenViewModel: InviteUsersScreenViewModelType, InviteUsersScreenViewModelProtocol {
private let roomType: InviteUsersScreenRoomType
private let userDiscoveryService: UserDiscoveryServiceProtocol
private let appSettings: AppSettings
private let userIndicatorController: UserIndicatorControllerProtocol
private let actionsSubject: PassthroughSubject<InviteUsersScreenViewModelAction, Never> = .init()
@@ -36,11 +35,9 @@ class InviteUsersScreenViewModel: InviteUsersScreenViewModelType, InviteUsersScr
roomType: InviteUsersScreenRoomType,
mediaProvider: MediaProviderProtocol,
userDiscoveryService: UserDiscoveryServiceProtocol,
appSettings: AppSettings,
userIndicatorController: UserIndicatorControllerProtocol) {
self.roomType = roomType
self.userDiscoveryService = userDiscoveryService
self.appSettings = appSettings
self.userIndicatorController = userIndicatorController
super.init(initialViewState: InviteUsersScreenViewState(selectedUsers: selectedUsers.value, isCreatingRoom: roomType.isCreatingRoom), imageProvider: mediaProvider)
@@ -130,7 +127,7 @@ class InviteUsersScreenViewModel: InviteUsersScreenViewModelType, InviteUsersScr
private func fetchUsers() {
guard searchQuery.count >= 3 else {
fetchSuggestions()
state.usersSection = .init(type: .suggestions, users: [])
return
}
@@ -142,20 +139,6 @@ class InviteUsersScreenViewModel: InviteUsersScreenViewModelType, InviteUsersScr
}
}
private func fetchSuggestions() {
guard appSettings.userSuggestionsEnabled else {
state.usersSection = .init(type: .suggestions, users: [])
return
}
state.isSearching = true
fetchUsersTask = Task {
let result = await userDiscoveryService.fetchSuggestions()
guard !Task.isCancelled else { return }
handleResult(for: .suggestions, result: result)
}
}
private func handleResult(for sectionType: UserDiscoverySectionType, result: Result<[UserProfileProxy], UserDiscoveryErrorType>) {
state.isSearching = false
@@ -159,13 +159,11 @@ struct InviteUsersScreen: View {
struct InviteUsersScreen_Previews: PreviewProvider, TestablePreview {
static let viewModel = {
let userDiscoveryService = UserDiscoveryServiceMock()
userDiscoveryService.fetchSuggestionsReturnValue = .success([.mockAlice])
userDiscoveryService.searchProfilesWithReturnValue = .success([.mockAlice])
return InviteUsersScreenViewModel(selectedUsers: .init([]),
roomType: .draft,
mediaProvider: MockMediaProvider(),
userDiscoveryService: userDiscoveryService,
appSettings: ServiceLocator.shared.settings,
userIndicatorController: UserIndicatorControllerMock())
}()
@@ -47,15 +47,8 @@ protocol DeveloperOptionsProtocol: AnyObject {
var logLevel: TracingConfiguration.LogLevel { get set }
var otlpTracingEnabled: Bool { get set }
var shouldCollapseRoomStateEvents: Bool { get set }
var userSuggestionsEnabled: Bool { get set }
var mentionsBadgeEnabled: Bool { get set }
var roomListFiltersEnabled: Bool { get set }
var hideUnreadMessagesBadge: Bool { get set }
var markAsUnreadEnabled: Bool { get set }
var markAsFavouriteEnabled: Bool { get set }
var roomModerationEnabled: Bool { get set }
var elementCallBaseURL: URL { get set }
}
@@ -41,32 +41,7 @@ struct DeveloperOptionsScreen: View {
}
}
Section("Room creation") {
Toggle(isOn: $context.userSuggestionsEnabled) {
Text("User suggestions")
}
}
Section("Mentions") {
Toggle(isOn: $context.mentionsBadgeEnabled) {
Text("Mentions badge")
Text("Requires app reboot")
}
}
Section("Room List") {
Toggle(isOn: $context.roomListFiltersEnabled) {
Text("Show filters")
}
Toggle(isOn: $context.markAsUnreadEnabled) {
Text("Mark as unread")
}
Toggle(isOn: $context.markAsFavouriteEnabled) {
Text("Mark as favourite")
}
Toggle(isOn: $context.hideUnreadMessagesBadge) {
Text("Hide grey dots")
}
@@ -54,7 +54,6 @@ final class StartChatScreenCoordinator: CoordinatorProtocol {
self.parameters = parameters
viewModel = StartChatScreenViewModel(userSession: parameters.userSession,
userSuggestionsEnabled: ServiceLocator.shared.settings.userSuggestionsEnabled,
analytics: ServiceLocator.shared.analytics,
userIndicatorController: parameters.userIndicatorController,
userDiscoveryService: parameters.userDiscoveryService)
@@ -21,7 +21,6 @@ typealias StartChatScreenViewModelType = StateStoreViewModel<StartChatScreenView
class StartChatScreenViewModel: StartChatScreenViewModelType, StartChatScreenViewModelProtocol {
private let userSession: UserSessionProtocol
private let userSuggestionsEnabled: Bool
private let analytics: AnalyticsService
private let userIndicatorController: UserIndicatorControllerProtocol
private let userDiscoveryService: UserDiscoveryServiceProtocol
@@ -33,12 +32,10 @@ class StartChatScreenViewModel: StartChatScreenViewModelType, StartChatScreenVie
}
init(userSession: UserSessionProtocol,
userSuggestionsEnabled: Bool,
analytics: AnalyticsService,
userIndicatorController: UserIndicatorControllerProtocol,
userDiscoveryService: UserDiscoveryServiceProtocol) {
self.userSession = userSession
self.userSuggestionsEnabled = userSuggestionsEnabled
self.analytics = analytics
self.userIndicatorController = userIndicatorController
self.userDiscoveryService = userDiscoveryService
@@ -105,7 +102,7 @@ class StartChatScreenViewModel: StartChatScreenViewModelType, StartChatScreenVie
private func fetchUsers() {
guard searchQuery.count >= 3 else {
fetchSuggestions()
state.usersSection = .init(type: .suggestions, users: [])
return
}
fetchUsersTask = Task {
@@ -115,18 +112,6 @@ class StartChatScreenViewModel: StartChatScreenViewModelType, StartChatScreenVie
}
}
private func fetchSuggestions() {
guard userSuggestionsEnabled else {
state.usersSection = .init(type: .suggestions, users: [])
return
}
fetchUsersTask = Task {
let result = await userDiscoveryService.fetchSuggestions()
guard !Task.isCancelled else { return }
handleResult(for: .suggestions, result: result)
}
}
private func handleResult(for sectionType: UserDiscoverySectionType, result: Result<[UserProfileProxy], UserDiscoveryErrorType>) {
switch result {
case .success(let users):
@@ -133,10 +133,8 @@ struct StartChatScreen_Previews: PreviewProvider, TestablePreview {
mediaProvider: MockMediaProvider(),
voiceMessageMediaManager: VoiceMessageMediaManagerMock())
let userDiscoveryService = UserDiscoveryServiceMock()
userDiscoveryService.fetchSuggestionsReturnValue = .success([.mockAlice])
userDiscoveryService.searchProfilesWithReturnValue = .success([.mockAlice])
let viewModel = StartChatScreenViewModel(userSession: userSession,
userSuggestionsEnabled: true,
analytics: ServiceLocator.shared.analytics,
userIndicatorController: UserIndicatorControllerMock(),
userDiscoveryService: userDiscoveryService)