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
+2 -1
View File
@@ -4,11 +4,12 @@ schemes:
- IntegrationTests - IntegrationTests
- UITests - UITests
- UnitTests - UnitTests
- PreviewTests
targets: targets:
- ElementX - ElementX
- IntegrationTests - IntegrationTests
- NSE - NSE
# - NCE - PreviewTests
- UITests - UITests
- UnitTests - UnitTests
report_exclude: report_exclude:
@@ -275,21 +275,6 @@ final class AppSettings {
// MARK: - Feature Flags // MARK: - Feature Flags
@UserPreference(key: UserDefaultsKeys.userSuggestionsEnabled, defaultValue: false, storageType: .volatile)
var userSuggestionsEnabled
@UserPreference(key: UserDefaultsKeys.mentionsBadgeEnabled, defaultValue: true, storageType: .userDefaults(store))
var mentionsBadgeEnabled
@UserPreference(key: UserDefaultsKeys.roomListFiltersEnabled, defaultValue: false, storageType: .userDefaults(store))
var roomListFiltersEnabled
@UserPreference(key: UserDefaultsKeys.markAsUnreadEnabled, defaultValue: false, storageType: .userDefaults(store))
var markAsUnreadEnabled
@UserPreference(key: UserDefaultsKeys.markAsFavouriteEnabled, defaultValue: false, storageType: .userDefaults(store))
var markAsFavouriteEnabled
@UserPreference(key: UserDefaultsKeys.roomModerationEnabled, defaultValue: false, storageType: .userDefaults(store)) @UserPreference(key: UserDefaultsKeys.roomModerationEnabled, defaultValue: false, storageType: .userDefaults(store))
var roomModerationEnabled var roomModerationEnabled
@@ -3787,23 +3787,6 @@ class UserDiscoveryServiceMock: UserDiscoveryServiceProtocol {
return searchProfilesWithReturnValue return searchProfilesWithReturnValue
} }
} }
//MARK: - fetchSuggestions
var fetchSuggestionsCallsCount = 0
var fetchSuggestionsCalled: Bool {
return fetchSuggestionsCallsCount > 0
}
var fetchSuggestionsReturnValue: Result<[UserProfileProxy], UserDiscoveryErrorType>!
var fetchSuggestionsClosure: (() async -> Result<[UserProfileProxy], UserDiscoveryErrorType>)?
func fetchSuggestions() async -> Result<[UserProfileProxy], UserDiscoveryErrorType> {
fetchSuggestionsCallsCount += 1
if let fetchSuggestionsClosure = fetchSuggestionsClosure {
return await fetchSuggestionsClosure()
} else {
return fetchSuggestionsReturnValue
}
}
} }
class UserIndicatorControllerMock: UserIndicatorControllerProtocol { class UserIndicatorControllerMock: UserIndicatorControllerProtocol {
var window: UIWindow? var window: UIWindow?
@@ -22,18 +22,9 @@ struct BlockedUsersScreenCoordinatorParameters {
let userIndicatorController: UserIndicatorControllerProtocol let userIndicatorController: UserIndicatorControllerProtocol
} }
enum BlockedUsersScreenCoordinatorAction { }
final class BlockedUsersScreenCoordinator: CoordinatorProtocol { final class BlockedUsersScreenCoordinator: CoordinatorProtocol {
private let viewModel: BlockedUsersScreenViewModelProtocol 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) { init(parameters: BlockedUsersScreenCoordinatorParameters) {
viewModel = BlockedUsersScreenViewModel(clientProxy: parameters.clientProxy, viewModel = BlockedUsersScreenViewModel(clientProxy: parameters.clientProxy,
userIndicatorController: parameters.userIndicatorController) userIndicatorController: parameters.userIndicatorController)
@@ -16,8 +16,6 @@
import Foundation import Foundation
enum BlockedUsersScreenViewModelAction { }
struct BlockedUsersScreenViewState: BindableState { struct BlockedUsersScreenViewState: BindableState {
var blockedUsers: [String] var blockedUsers: [String]
var processingUserID: String? var processingUserID: String?
@@ -22,11 +22,6 @@ typealias BlockedUsersScreenViewModelType = StateStoreViewModel<BlockedUsersScre
class BlockedUsersScreenViewModel: BlockedUsersScreenViewModelType, BlockedUsersScreenViewModelProtocol { class BlockedUsersScreenViewModel: BlockedUsersScreenViewModelType, BlockedUsersScreenViewModelProtocol {
let clientProxy: ClientProxyProtocol let clientProxy: ClientProxyProtocol
let userIndicatorController: UserIndicatorControllerProtocol let userIndicatorController: UserIndicatorControllerProtocol
private let actionsSubject: PassthroughSubject<BlockedUsersScreenViewModelAction, Never> = .init()
var actionsPublisher: AnyPublisher<BlockedUsersScreenViewModelAction, Never> {
actionsSubject.eraseToAnyPublisher()
}
init(clientProxy: ClientProxyProtocol, init(clientProxy: ClientProxyProtocol,
userIndicatorController: UserIndicatorControllerProtocol) { userIndicatorController: UserIndicatorControllerProtocol) {
@@ -18,7 +18,6 @@ import Combine
@MainActor @MainActor
protocol BlockedUsersScreenViewModelProtocol { protocol BlockedUsersScreenViewModelProtocol {
var actionsPublisher: AnyPublisher<BlockedUsersScreenViewModelAction, Never> { get }
var context: BlockedUsersScreenViewModelType.Context { get } var context: BlockedUsersScreenViewModelType.Context { get }
func stop() func stop()
@@ -89,10 +89,6 @@ struct HomeScreenViewState: BindableState {
var rooms: [HomeScreenRoom] = [] var rooms: [HomeScreenRoom] = []
var roomListMode: HomeScreenRoomListMode = .skeletons var roomListMode: HomeScreenRoomListMode = .skeletons
var areFiltersEnabled = false
var markAsUnreadEnabled = false
var markAsFavouriteEnabled = false
var hasPendingInvitations = false var hasPendingInvitations = false
var hasUnreadPendingInvitations = false var hasUnreadPendingInvitations = false
@@ -120,11 +116,7 @@ struct HomeScreenViewState: BindableState {
} }
var shouldShowEmptyFilterState: Bool { var shouldShowEmptyFilterState: Bool {
shouldShowFilters && bindings.filtersState.isFiltering && visibleRooms.isEmpty !bindings.isSearchFieldFocused && bindings.filtersState.isFiltering && visibleRooms.isEmpty
}
var shouldShowFilters: Bool {
areFiltersEnabled && !bindings.isSearchFieldFocused
} }
} }
@@ -100,28 +100,6 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
.weakAssign(to: \.state.selectedRoomID, on: self) .weakAssign(to: \.state.selectedRoomID, on: self)
.store(in: &cancellables) .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 appSettings.$hideUnreadMessagesBadge
.sink { [weak self] _ in self?.updateRooms() } .sink { [weak self] _ in self?.updateRooms() }
.store(in: &cancellables) .store(in: &cancellables)
@@ -235,7 +213,7 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
if state.bindings.isSearchFieldFocused { if state.bindings.isSearchFieldFocused {
roomSummaryProvider?.setFilter(.search(query: state.bindings.searchQuery)) roomSummaryProvider?.setFilter(.search(query: state.bindings.searchQuery))
} else { } 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 return availableFilters.elements
} }
var orderedFilters: [RoomListFilter] {
activeFilters.elements + availableFilters
}
var isFiltering: Bool { var isFiltering: Bool {
!activeFilters.isEmpty !activeFilters.isEmpty
} }
@@ -53,36 +53,24 @@ struct HomeScreenContent: View {
.layoutPriority(1) .layoutPriority(1)
} }
case .rooms: case .rooms:
if context.viewState.areFiltersEnabled { // Showing empty views in pinned headers makes the room list spasm when reaching the top
// Showing empty views in pinned headers makes the room list spasm when reaching the top LazyVStack(spacing: 0, pinnedViews: [.sectionHeaders]) {
LazyVStack(spacing: 0, pinnedViews: [.sectionHeaders]) { Section {
Section { if context.viewState.shouldShowEmptyFilterState {
if context.viewState.shouldShowEmptyFilterState { RoomListFiltersEmptyStateView(state: context.filtersState)
RoomListFiltersEmptyStateView(state: context.filtersState) .frame(height: geometry.size.height - topSectionFrame.height)
.frame(height: geometry.size.height - topSectionFrame.height) } else {
} else { HomeScreenRoomList(context: context)
HomeScreenRoomList(context: context)
}
} header: {
topSection
.readFrame($topSectionFrame)
} }
} 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: case .migration:
EmptyView() EmptyView()
} }
@@ -121,7 +109,7 @@ struct HomeScreenContent: View {
/// The session verification banner and invites button if either are needed. /// The session verification banner and invites button if either are needed.
private var topSection: some View { private var topSection: some View {
VStack(spacing: 0) { VStack(spacing: 0) {
if context.viewState.shouldShowFilters { if !context.isSearchFieldFocused {
filters filters
} }
@@ -39,35 +39,31 @@ struct HomeScreenRoomList: View {
HomeScreenRoomCell(room: room, context: context, isSelected: isSelected) HomeScreenRoomCell(room: room, context: context, isSelected: isSelected)
.contextMenu { .contextMenu {
if context.viewState.markAsUnreadEnabled { if room.badges.isDotShown {
if room.badges.isDotShown { Button {
Button { context.send(viewAction: .markRoomAsRead(roomIdentifier: room.id))
context.send(viewAction: .markRoomAsRead(roomIdentifier: room.id)) } label: {
} label: { Text(L10n.screenRoomlistMarkAsRead)
Text(L10n.screenRoomlistMarkAsRead) }
} } else {
} else { Button {
Button { context.send(viewAction: .markRoomAsUnread(roomIdentifier: room.id))
context.send(viewAction: .markRoomAsUnread(roomIdentifier: room.id)) } label: {
} label: { Text(L10n.screenRoomlistMarkAsUnread)
Text(L10n.screenRoomlistMarkAsUnread)
}
} }
} }
if context.viewState.markAsFavouriteEnabled { if room.isFavourite {
if room.isFavourite { Button {
Button { context.send(viewAction: .markRoomAsFavourite(roomIdentifier: room.id, isFavourite: false))
context.send(viewAction: .markRoomAsFavourite(roomIdentifier: room.id, isFavourite: false)) } label: {
} label: { Label(L10n.commonFavourited, icon: \.favouriteSolid)
Label(L10n.commonFavourited, icon: \.favouriteSolid) }
} } else {
} else { Button {
Button { context.send(viewAction: .markRoomAsFavourite(roomIdentifier: room.id, isFavourite: true))
context.send(viewAction: .markRoomAsFavourite(roomIdentifier: room.id, isFavourite: true)) } label: {
} label: { Label(L10n.commonFavourite, icon: \.favourite)
Label(L10n.commonFavourite, icon: \.favourite)
}
} }
} }
@@ -46,7 +46,6 @@ final class InviteUsersScreenCoordinator: CoordinatorProtocol {
roomType: parameters.roomType, roomType: parameters.roomType,
mediaProvider: parameters.mediaProvider, mediaProvider: parameters.mediaProvider,
userDiscoveryService: parameters.userDiscoveryService, userDiscoveryService: parameters.userDiscoveryService,
appSettings: ServiceLocator.shared.settings,
userIndicatorController: parameters.userIndicatorController) userIndicatorController: parameters.userIndicatorController)
} }
@@ -23,7 +23,6 @@ typealias InviteUsersScreenViewModelType = StateStoreViewModel<InviteUsersScreen
class InviteUsersScreenViewModel: InviteUsersScreenViewModelType, InviteUsersScreenViewModelProtocol { class InviteUsersScreenViewModel: InviteUsersScreenViewModelType, InviteUsersScreenViewModelProtocol {
private let roomType: InviteUsersScreenRoomType private let roomType: InviteUsersScreenRoomType
private let userDiscoveryService: UserDiscoveryServiceProtocol private let userDiscoveryService: UserDiscoveryServiceProtocol
private let appSettings: AppSettings
private let userIndicatorController: UserIndicatorControllerProtocol private let userIndicatorController: UserIndicatorControllerProtocol
private let actionsSubject: PassthroughSubject<InviteUsersScreenViewModelAction, Never> = .init() private let actionsSubject: PassthroughSubject<InviteUsersScreenViewModelAction, Never> = .init()
@@ -36,11 +35,9 @@ class InviteUsersScreenViewModel: InviteUsersScreenViewModelType, InviteUsersScr
roomType: InviteUsersScreenRoomType, roomType: InviteUsersScreenRoomType,
mediaProvider: MediaProviderProtocol, mediaProvider: MediaProviderProtocol,
userDiscoveryService: UserDiscoveryServiceProtocol, userDiscoveryService: UserDiscoveryServiceProtocol,
appSettings: AppSettings,
userIndicatorController: UserIndicatorControllerProtocol) { userIndicatorController: UserIndicatorControllerProtocol) {
self.roomType = roomType self.roomType = roomType
self.userDiscoveryService = userDiscoveryService self.userDiscoveryService = userDiscoveryService
self.appSettings = appSettings
self.userIndicatorController = userIndicatorController self.userIndicatorController = userIndicatorController
super.init(initialViewState: InviteUsersScreenViewState(selectedUsers: selectedUsers.value, isCreatingRoom: roomType.isCreatingRoom), imageProvider: mediaProvider) super.init(initialViewState: InviteUsersScreenViewState(selectedUsers: selectedUsers.value, isCreatingRoom: roomType.isCreatingRoom), imageProvider: mediaProvider)
@@ -130,7 +127,7 @@ class InviteUsersScreenViewModel: InviteUsersScreenViewModelType, InviteUsersScr
private func fetchUsers() { private func fetchUsers() {
guard searchQuery.count >= 3 else { guard searchQuery.count >= 3 else {
fetchSuggestions() state.usersSection = .init(type: .suggestions, users: [])
return 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>) { private func handleResult(for sectionType: UserDiscoverySectionType, result: Result<[UserProfileProxy], UserDiscoveryErrorType>) {
state.isSearching = false state.isSearching = false
@@ -159,13 +159,11 @@ struct InviteUsersScreen: View {
struct InviteUsersScreen_Previews: PreviewProvider, TestablePreview { struct InviteUsersScreen_Previews: PreviewProvider, TestablePreview {
static let viewModel = { static let viewModel = {
let userDiscoveryService = UserDiscoveryServiceMock() let userDiscoveryService = UserDiscoveryServiceMock()
userDiscoveryService.fetchSuggestionsReturnValue = .success([.mockAlice])
userDiscoveryService.searchProfilesWithReturnValue = .success([.mockAlice]) userDiscoveryService.searchProfilesWithReturnValue = .success([.mockAlice])
return InviteUsersScreenViewModel(selectedUsers: .init([]), return InviteUsersScreenViewModel(selectedUsers: .init([]),
roomType: .draft, roomType: .draft,
mediaProvider: MockMediaProvider(), mediaProvider: MockMediaProvider(),
userDiscoveryService: userDiscoveryService, userDiscoveryService: userDiscoveryService,
appSettings: ServiceLocator.shared.settings,
userIndicatorController: UserIndicatorControllerMock()) userIndicatorController: UserIndicatorControllerMock())
}() }()
@@ -47,15 +47,8 @@ protocol DeveloperOptionsProtocol: AnyObject {
var logLevel: TracingConfiguration.LogLevel { get set } var logLevel: TracingConfiguration.LogLevel { get set }
var otlpTracingEnabled: Bool { get set } var otlpTracingEnabled: Bool { get set }
var shouldCollapseRoomStateEvents: 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 hideUnreadMessagesBadge: Bool { get set }
var markAsUnreadEnabled: Bool { get set }
var markAsFavouriteEnabled: Bool { get set }
var roomModerationEnabled: Bool { get set } var roomModerationEnabled: Bool { get set }
var elementCallBaseURL: URL { 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") { 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) { Toggle(isOn: $context.hideUnreadMessagesBadge) {
Text("Hide grey dots") Text("Hide grey dots")
} }
@@ -54,7 +54,6 @@ final class StartChatScreenCoordinator: CoordinatorProtocol {
self.parameters = parameters self.parameters = parameters
viewModel = StartChatScreenViewModel(userSession: parameters.userSession, viewModel = StartChatScreenViewModel(userSession: parameters.userSession,
userSuggestionsEnabled: ServiceLocator.shared.settings.userSuggestionsEnabled,
analytics: ServiceLocator.shared.analytics, analytics: ServiceLocator.shared.analytics,
userIndicatorController: parameters.userIndicatorController, userIndicatorController: parameters.userIndicatorController,
userDiscoveryService: parameters.userDiscoveryService) userDiscoveryService: parameters.userDiscoveryService)
@@ -21,7 +21,6 @@ typealias StartChatScreenViewModelType = StateStoreViewModel<StartChatScreenView
class StartChatScreenViewModel: StartChatScreenViewModelType, StartChatScreenViewModelProtocol { class StartChatScreenViewModel: StartChatScreenViewModelType, StartChatScreenViewModelProtocol {
private let userSession: UserSessionProtocol private let userSession: UserSessionProtocol
private let userSuggestionsEnabled: Bool
private let analytics: AnalyticsService private let analytics: AnalyticsService
private let userIndicatorController: UserIndicatorControllerProtocol private let userIndicatorController: UserIndicatorControllerProtocol
private let userDiscoveryService: UserDiscoveryServiceProtocol private let userDiscoveryService: UserDiscoveryServiceProtocol
@@ -33,12 +32,10 @@ class StartChatScreenViewModel: StartChatScreenViewModelType, StartChatScreenVie
} }
init(userSession: UserSessionProtocol, init(userSession: UserSessionProtocol,
userSuggestionsEnabled: Bool,
analytics: AnalyticsService, analytics: AnalyticsService,
userIndicatorController: UserIndicatorControllerProtocol, userIndicatorController: UserIndicatorControllerProtocol,
userDiscoveryService: UserDiscoveryServiceProtocol) { userDiscoveryService: UserDiscoveryServiceProtocol) {
self.userSession = userSession self.userSession = userSession
self.userSuggestionsEnabled = userSuggestionsEnabled
self.analytics = analytics self.analytics = analytics
self.userIndicatorController = userIndicatorController self.userIndicatorController = userIndicatorController
self.userDiscoveryService = userDiscoveryService self.userDiscoveryService = userDiscoveryService
@@ -105,7 +102,7 @@ class StartChatScreenViewModel: StartChatScreenViewModelType, StartChatScreenVie
private func fetchUsers() { private func fetchUsers() {
guard searchQuery.count >= 3 else { guard searchQuery.count >= 3 else {
fetchSuggestions() state.usersSection = .init(type: .suggestions, users: [])
return return
} }
fetchUsersTask = Task { 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>) { private func handleResult(for sectionType: UserDiscoverySectionType, result: Result<[UserProfileProxy], UserDiscoveryErrorType>) {
switch result { switch result {
case .success(let users): case .success(let users):
@@ -133,10 +133,8 @@ struct StartChatScreen_Previews: PreviewProvider, TestablePreview {
mediaProvider: MockMediaProvider(), mediaProvider: MockMediaProvider(),
voiceMessageMediaManager: VoiceMessageMediaManagerMock()) voiceMessageMediaManager: VoiceMessageMediaManagerMock())
let userDiscoveryService = UserDiscoveryServiceMock() let userDiscoveryService = UserDiscoveryServiceMock()
userDiscoveryService.fetchSuggestionsReturnValue = .success([.mockAlice])
userDiscoveryService.searchProfilesWithReturnValue = .success([.mockAlice]) userDiscoveryService.searchProfilesWithReturnValue = .success([.mockAlice])
let viewModel = StartChatScreenViewModel(userSession: userSession, let viewModel = StartChatScreenViewModel(userSession: userSession,
userSuggestionsEnabled: true,
analytics: ServiceLocator.shared.analytics, analytics: ServiceLocator.shared.analytics,
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
userDiscoveryService: userDiscoveryService) userDiscoveryService: userDiscoveryService)
@@ -575,25 +575,19 @@ class ClientProxy: ClientProxyProtocol {
eventStringBuilder: eventStringBuilder, eventStringBuilder: eventStringBuilder,
name: "AllRooms", name: "AllRooms",
shouldUpdateVisibleRange: true, shouldUpdateVisibleRange: true,
notificationSettings: notificationSettings, notificationSettings: notificationSettings)
backgroundTaskService: backgroundTaskService,
appSettings: appSettings)
try await roomSummaryProvider?.setRoomList(roomListService.allRooms()) try await roomSummaryProvider?.setRoomList(roomListService.allRooms())
alternateRoomSummaryProvider = RoomSummaryProvider(roomListService: roomListService, alternateRoomSummaryProvider = RoomSummaryProvider(roomListService: roomListService,
eventStringBuilder: eventStringBuilder, eventStringBuilder: eventStringBuilder,
name: "MessageForwarding", name: "MessageForwarding",
notificationSettings: notificationSettings, notificationSettings: notificationSettings)
backgroundTaskService: backgroundTaskService,
appSettings: appSettings)
try await alternateRoomSummaryProvider?.setRoomList(roomListService.allRooms()) try await alternateRoomSummaryProvider?.setRoomList(roomListService.allRooms())
inviteSummaryProvider = RoomSummaryProvider(roomListService: roomListService, inviteSummaryProvider = RoomSummaryProvider(roomListService: roomListService,
eventStringBuilder: eventStringBuilder, eventStringBuilder: eventStringBuilder,
name: "Invites", name: "Invites",
notificationSettings: notificationSettings, notificationSettings: notificationSettings)
backgroundTaskService: backgroundTaskService,
appSettings: appSettings)
try await inviteSummaryProvider?.setRoomList(roomListService.invites()) try await inviteSummaryProvider?.setRoomList(roomListService.invites())
self.syncService = syncService self.syncService = syncService
@@ -18,16 +18,9 @@ import Foundation
import MatrixRustSDK import MatrixRustSDK
final class RoomMemberProxy: RoomMemberProxyProtocol { final class RoomMemberProxy: RoomMemberProxyProtocol {
private let backgroundTaskService: BackgroundTaskServiceProtocol
private let member: RoomMember private let member: RoomMember
private let backgroundAccountDataTaskName = "SendAccountDataEvent" init(member: RoomMember) {
private var sendAccountDataEventBackgroundTask: BackgroundTaskProtocol?
private let userInitiatedDispatchQueue = DispatchQueue(label: "io.element.elementx.roommemberproxy.userinitiated", qos: .userInitiated)
init(member: RoomMember, backgroundTaskService: BackgroundTaskServiceProtocol) {
self.backgroundTaskService = backgroundTaskService
self.member = member self.member = member
} }
@@ -17,11 +17,6 @@
import Foundation import Foundation
import MatrixRustSDK import MatrixRustSDK
enum RoomMemberProxyError: Error {
case ignoreUserFailed
case unignoreUserFailed
}
// sourcery: AutoMockable // sourcery: AutoMockable
protocol RoomMemberProxyProtocol: AnyObject { protocol RoomMemberProxyProtocol: AnyObject {
var userID: String { get } var userID: String { get }
@@ -195,9 +195,7 @@ class RoomProxy: RoomProxyProtocol {
do { do {
let membersNoSyncIterator = try await room.membersNoSync() let membersNoSyncIterator = try await room.membersNoSync()
if let members = membersNoSyncIterator.nextChunk(chunkSize: membersNoSyncIterator.len()) { if let members = membersNoSyncIterator.nextChunk(chunkSize: membersNoSyncIterator.len()) {
membersSubject.value = members.map { membersSubject.value = members.map(RoomMemberProxy.init)
RoomMemberProxy(member: $0, backgroundTaskService: self.backgroundTaskService)
}
} }
} catch { } catch {
MXLog.error("[RoomProxy] Failed to update members using no sync API: \(error)") MXLog.error("[RoomProxy] Failed to update members using no sync API: \(error)")
@@ -207,9 +205,7 @@ class RoomProxy: RoomProxyProtocol {
// Then we update members using the sync API, this is slower but will get us the latest members // Then we update members using the sync API, this is slower but will get us the latest members
let membersIterator = try await room.members() let membersIterator = try await room.members()
if let members = membersIterator.nextChunk(chunkSize: membersIterator.len()) { if let members = membersIterator.nextChunk(chunkSize: membersIterator.len()) {
membersSubject.value = members.map { membersSubject.value = members.map(RoomMemberProxy.init)
RoomMemberProxy(member: $0, backgroundTaskService: self.backgroundTaskService)
}
} }
} catch { } catch {
MXLog.error("[RoomProxy] Failed to update members using sync API: \(error)") MXLog.error("[RoomProxy] Failed to update members using sync API: \(error)")
@@ -228,7 +224,7 @@ class RoomProxy: RoomProxyProtocol {
do { do {
let member = try await room.member(userId: userID) let member = try await room.member(userId: userID)
return .success(RoomMemberProxy(member: member, backgroundTaskService: backgroundTaskService)) return .success(RoomMemberProxy(member: member))
} catch { } catch {
return .failure(.failedRetrievingMember) return .failure(.failedRetrievingMember)
} }
@@ -21,7 +21,6 @@ import MatrixRustSDK
enum RoomProxyError: Error, Equatable { enum RoomProxyError: Error, Equatable {
case failedRedactingEvent case failedRedactingEvent
case failedReportingContent case failedReportingContent
case failedIgnoringUser
case failedRetrievingMember case failedRetrievingMember
case failedLeavingRoom case failedLeavingRoom
case failedAcceptingInvite case failedAcceptingInvite
@@ -24,9 +24,7 @@ class RoomSummaryProvider: RoomSummaryProviderProtocol {
private let name: String private let name: String
private let shouldUpdateVisibleRange: Bool private let shouldUpdateVisibleRange: Bool
private let notificationSettings: NotificationSettingsProxyProtocol private let notificationSettings: NotificationSettingsProxyProtocol
private let backgroundTaskService: BackgroundTaskServiceProtocol
private let appSettings: AppSettings
private let roomListPageSize = 200 private let roomListPageSize = 200
private let serialDispatchQueue: DispatchQueue private let serialDispatchQueue: DispatchQueue
@@ -67,17 +65,13 @@ class RoomSummaryProvider: RoomSummaryProviderProtocol {
eventStringBuilder: RoomEventStringBuilder, eventStringBuilder: RoomEventStringBuilder,
name: String, name: String,
shouldUpdateVisibleRange: Bool = false, shouldUpdateVisibleRange: Bool = false,
notificationSettings: NotificationSettingsProxyProtocol, notificationSettings: NotificationSettingsProxyProtocol) {
backgroundTaskService: BackgroundTaskServiceProtocol,
appSettings: AppSettings) {
self.roomListService = roomListService self.roomListService = roomListService
serialDispatchQueue = DispatchQueue(label: "io.element.elementx.roomsummaryprovider", qos: .default) serialDispatchQueue = DispatchQueue(label: "io.element.elementx.roomsummaryprovider", qos: .default)
self.eventStringBuilder = eventStringBuilder self.eventStringBuilder = eventStringBuilder
self.name = name self.name = name
self.shouldUpdateVisibleRange = shouldUpdateVisibleRange self.shouldUpdateVisibleRange = shouldUpdateVisibleRange
self.notificationSettings = notificationSettings self.notificationSettings = notificationSettings
self.backgroundTaskService = backgroundTaskService
self.appSettings = appSettings
diffsPublisher diffsPublisher
.receive(on: serialDispatchQueue) .receive(on: serialDispatchQueue)
@@ -240,7 +234,7 @@ class RoomSummaryProvider: RoomSummaryProviderProtocol {
var inviterProxy: RoomMemberProxyProtocol? var inviterProxy: RoomMemberProxyProtocol?
if let inviter = roomInfo.inviter { if let inviter = roomInfo.inviter {
inviterProxy = RoomMemberProxy(member: inviter, backgroundTaskService: backgroundTaskService) inviterProxy = RoomMemberProxy(member: inviter)
} }
let notificationMode = roomInfo.userDefinedNotificationMode.flatMap { RoomNotificationModeProxy.from(roomNotificationMode: $0) } let notificationMode = roomInfo.userDefinedNotificationMode.flatMap { RoomNotificationModeProxy.from(roomNotificationMode: $0) }
@@ -251,14 +245,14 @@ class RoomSummaryProvider: RoomSummaryProviderProtocol {
avatarURL: roomInfo.avatarUrl.flatMap(URL.init(string:)), avatarURL: roomInfo.avatarUrl.flatMap(URL.init(string:)),
lastMessage: attributedLastMessage, lastMessage: attributedLastMessage,
lastMessageFormattedTimestamp: lastMessageFormattedTimestamp, lastMessageFormattedTimestamp: lastMessageFormattedTimestamp,
unreadMessagesCount: appSettings.mentionsBadgeEnabled ? UInt(roomInfo.numUnreadMessages) : 0, unreadMessagesCount: UInt(roomInfo.numUnreadMessages),
unreadMentionsCount: appSettings.mentionsBadgeEnabled ? UInt(roomInfo.numUnreadMentions) : 0, unreadMentionsCount: UInt(roomInfo.numUnreadMentions),
unreadNotificationsCount: appSettings.mentionsBadgeEnabled ? UInt(roomInfo.numUnreadNotifications) : UInt(roomInfo.notificationCount), unreadNotificationsCount: UInt(roomInfo.numUnreadNotifications),
notificationMode: notificationMode, notificationMode: notificationMode,
canonicalAlias: roomInfo.canonicalAlias, canonicalAlias: roomInfo.canonicalAlias,
inviter: inviterProxy, inviter: inviterProxy,
hasOngoingCall: roomInfo.hasRoomCall, hasOngoingCall: roomInfo.hasRoomCall,
isMarkedUnread: appSettings.markAsUnreadEnabled ? roomInfo.isMarkedUnread : false, isMarkedUnread: roomInfo.isMarkedUnread,
isFavourite: roomInfo.isFavourite) isFavourite: roomInfo.isFavourite)
return invalidated ? .invalidated(details: details) : .filled(details: details) return invalidated ? .invalidated(details: details) : .filled(details: details)
@@ -23,10 +23,6 @@ final class UserDiscoveryService: UserDiscoveryServiceProtocol {
self.clientProxy = clientProxy self.clientProxy = clientProxy
} }
func fetchSuggestions() async -> Result<[UserProfileProxy], UserDiscoveryErrorType> {
.success(filterAccountOwner([.mockAlice, .mockBob, .mockCharlie]))
}
func searchProfiles(with searchQuery: String) async -> Result<[UserProfileProxy], UserDiscoveryErrorType> { func searchProfiles(with searchQuery: String) async -> Result<[UserProfileProxy], UserDiscoveryErrorType> {
async let queriedProfile = profileIfPossible(with: searchQuery) async let queriedProfile = profileIfPossible(with: searchQuery)
@@ -23,5 +23,4 @@ enum UserDiscoveryErrorType: Error {
// sourcery: AutoMockable // sourcery: AutoMockable
protocol UserDiscoveryServiceProtocol { protocol UserDiscoveryServiceProtocol {
func searchProfiles(with searchQuery: String) async -> Result<[UserProfileProxy], UserDiscoveryErrorType> func searchProfiles(with searchQuery: String) async -> Result<[UserProfileProxy], UserDiscoveryErrorType>
func fetchSuggestions() async -> Result<[UserProfileProxy], UserDiscoveryErrorType>
} }
@@ -743,10 +743,8 @@ class MockScreen: Identifiable {
navigationStackCoordinator.setRootCoordinator(coordinator) navigationStackCoordinator.setRootCoordinator(coordinator)
return navigationStackCoordinator return navigationStackCoordinator
case .startChat: case .startChat:
ServiceLocator.shared.settings.userSuggestionsEnabled = true
let navigationStackCoordinator = NavigationStackCoordinator() let navigationStackCoordinator = NavigationStackCoordinator()
let userDiscoveryMock = UserDiscoveryServiceMock() let userDiscoveryMock = UserDiscoveryServiceMock()
userDiscoveryMock.fetchSuggestionsReturnValue = .success([.mockAlice, .mockBob, .mockCharlie])
userDiscoveryMock.searchProfilesWithReturnValue = .success([]) userDiscoveryMock.searchProfilesWithReturnValue = .success([])
let userSession = MockUserSession(clientProxy: ClientProxyMock(.init(userID: "@mock:client.com")), let userSession = MockUserSession(clientProxy: ClientProxyMock(.init(userID: "@mock:client.com")),
mediaProvider: MockMediaProvider(), mediaProvider: MockMediaProvider(),
@@ -763,7 +761,6 @@ class MockScreen: Identifiable {
let navigationStackCoordinator = NavigationStackCoordinator() let navigationStackCoordinator = NavigationStackCoordinator()
let clientProxy = ClientProxyMock(.init(userID: "@mock:client.com")) let clientProxy = ClientProxyMock(.init(userID: "@mock:client.com"))
let userDiscoveryMock = UserDiscoveryServiceMock() let userDiscoveryMock = UserDiscoveryServiceMock()
userDiscoveryMock.fetchSuggestionsReturnValue = .success([])
userDiscoveryMock.searchProfilesWithReturnValue = .success([.mockBob, .mockBobby]) userDiscoveryMock.searchProfilesWithReturnValue = .success([.mockBob, .mockBobby])
let userSession = MockUserSession(clientProxy: clientProxy, mediaProvider: MockMediaProvider(), voiceMessageMediaManager: VoiceMessageMediaManagerMock()) let userSession = MockUserSession(clientProxy: clientProxy, mediaProvider: MockMediaProvider(), voiceMessageMediaManager: VoiceMessageMediaManagerMock())
let coordinator = StartChatScreenCoordinator(parameters: .init(orientationManager: OrientationManagerMock(), let coordinator = StartChatScreenCoordinator(parameters: .init(orientationManager: OrientationManagerMock(),
@@ -862,15 +859,13 @@ class MockScreen: Identifiable {
let coordinator = InvitesScreenCoordinator(parameters: .init(userSession: MockUserSession(clientProxy: clientProxy, mediaProvider: MockMediaProvider(), voiceMessageMediaManager: VoiceMessageMediaManagerMock()))) let coordinator = InvitesScreenCoordinator(parameters: .init(userSession: MockUserSession(clientProxy: clientProxy, mediaProvider: MockMediaProvider(), voiceMessageMediaManager: VoiceMessageMediaManagerMock())))
navigationStackCoordinator.setRootCoordinator(coordinator) navigationStackCoordinator.setRootCoordinator(coordinator)
return navigationStackCoordinator return navigationStackCoordinator
case .inviteUsers, .inviteUsersInRoom, .inviteUsersInRoomExistingMembers: case .inviteUsers:
ServiceLocator.shared.settings.userSuggestionsEnabled = true
let navigationStackCoordinator = NavigationStackCoordinator() let navigationStackCoordinator = NavigationStackCoordinator()
let userDiscoveryMock = UserDiscoveryServiceMock() let userDiscoveryMock = UserDiscoveryServiceMock()
userDiscoveryMock.fetchSuggestionsReturnValue = .success([.mockAlice, .mockBob, .mockCharlie])
userDiscoveryMock.searchProfilesWithReturnValue = .success([]) userDiscoveryMock.searchProfilesWithReturnValue = .success([])
let mediaProvider = MockMediaProvider() let mediaProvider = MockMediaProvider()
let usersSubject = CurrentValueSubject<[UserProfileProxy], Never>([]) let usersSubject = CurrentValueSubject<[UserProfileProxy], Never>([])
let members: [RoomMemberProxyMock] = id == .inviteUsersInRoomExistingMembers ? [.mockInvitedAlice, .mockBob] : [] let members: [RoomMemberProxyMock] = []
let roomProxy = RoomProxyMock(with: .init(name: "test", members: members)) let roomProxy = RoomProxyMock(with: .init(name: "test", members: members))
let roomType: InviteUsersScreenRoomType = id == .inviteUsers ? .draft : .room(roomProxy: roomProxy) let roomType: InviteUsersScreenRoomType = id == .inviteUsers ? .draft : .room(roomProxy: roomProxy)
let coordinator = InviteUsersScreenCoordinator(parameters: .init(selectedUsers: usersSubject.asCurrentValuePublisher(), let coordinator = InviteUsersScreenCoordinator(parameters: .init(selectedUsers: usersSubject.asCurrentValuePublisher(),
@@ -80,8 +80,6 @@ enum UITestsScreenIdentifier: String {
case invitesWithBadges case invitesWithBadges
case invitesNoInvites case invitesNoInvites
case inviteUsers case inviteUsers
case inviteUsersInRoom
case inviteUsersInRoomExistingMembers
case createRoom case createRoom
case createRoomNoUsers case createRoomNoUsers
case createPoll case createPoll
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:82fb6aa4a6fbe1bec12bcdcfe2ef10ef0c76ba077e7cbb069f7c3e96e6e870d5 oid sha256:3fa48b92d820d0c1e9fb6a8a597208bb2e80cf304de5f083609feafe7723061a
size 103016 size 117380
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:ad4d46806bc06ac24b11f3dfed1b7490e7d1cf83f7e348a00a114d611bfca211 oid sha256:8a38db286014a40b855c6db7c6b4a7517822f76e7f110543178c36c3812e7648
size 296045 size 307743
@@ -22,22 +22,4 @@ class InviteUsersScreenUITests: XCTestCase {
let app = Application.launch(.inviteUsers) let app = Application.launch(.inviteUsers)
try await app.assertScreenshot(.inviteUsers) try await app.assertScreenshot(.inviteUsers)
} }
func testSelectedUsers() async throws {
let app = Application.launch(.inviteUsers)
app.buttons[A11yIdentifiers.inviteUsersScreen.userProfile].firstMatch.tap()
try await app.assertScreenshot(.inviteUsers, step: 1)
}
func testInviteUsers() async throws {
let app = Application.launch(.inviteUsersInRoom)
app.buttons[A11yIdentifiers.inviteUsersScreen.userProfile].firstMatch.tap()
try await app.assertScreenshot(.inviteUsersInRoom, step: 1)
}
func testInviteUserExistingMembers() async throws {
let app = Application.launch(.inviteUsersInRoomExistingMembers)
app.buttons[A11yIdentifiers.inviteUsersScreen.userProfile].firstMatch.tap()
try await app.assertScreenshot(.inviteUsersInRoomExistingMembers, step: 1)
}
} }
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7df4611bd9e2f673e236f0b5f70df91b0060e1ecec94d67e2abffbc2b8fe5ba0
size 105433
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:6caae22557a376372cc80a520f574dad25d0a3ffe9bc4015f0b95b96fd186e13 oid sha256:00c267f37fb0d9d5e85ad941231292d88f879ab20973cb244454f6d07a70a09f
size 95699 size 63815
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c3f8cd03eb57875402afe6320915fe247e33205e24cdffd99334ca6c7d017215
size 107065
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:4380762f5d2ecfebe278deaad65dbc1e4a5b40ff5936db9425bb0087b6701cb7
size 95503
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:5bbc69959f073b4d5c074cc3effa07912bcbefaa43b0ed775457491806e16e3c oid sha256:29f6060cadaac23418128a8f087c96a9a5940a6d486b7fd9ed79de9e8a04b4c2
size 103078 size 75467
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:16ae9dccde16a9758470b038971566c6a60c5553bb0feca695bdb2acd1476f08 oid sha256:96c8f8de1bdb21df00fad7b6cc1c619852eec6c12a36ffb171293e9a268e8e81
size 305283 size 312945
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:866d817857162852477d835ccecab7b6af398316e6aad9278e7bb09d3d263161 oid sha256:8554038e51fae2d8a89610e4e8749142a403e2628d3cf60b4f158189fe04771e
size 434773 size 441950
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:3b28aaf9d6d73d52b8e4f43e8246b7a471b5d9ea6ee716baf466f9b3f62c5cc6 oid sha256:2d08bd0a8f3f914a6de2714cc5b82b6d5f054ab1b15b28dbb8c9ecb6302bc574
size 676109 size 684885
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:abc0d764c74dbf4a1424bfb0ebf22d30e481a395efedca489f4eea01d4dcf561
size 125908
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:3376eeab4934aabd2520774eb489ab40d81cfa803de49851141cd05bf54662ae oid sha256:edecf983c382b401860ce0958cdce8f0b45aec90c60b6a019d4a82e342b8ecbb
size 111448 size 65453
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:95fa99a10f32b2bd70ed9f547c6b5e6904799d197653376f61155fc7a737245f
size 128675
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:5d49688083fd896d8f60a437a657e5b047b9e2eea5746910380e141b961ff739
size 111576
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:da7ed614bc6c00574ab7959a351c070b84ee17ecaaf6afa7bfe1ee50b22faf86 oid sha256:17803f2dadd6f43345c867e595143d52cf25637e8da9490f72b5de0b74c5d7d9
size 125770 size 83582
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:d6f94120d6bbdfb19d471f9fb6156443d6e94892485e79d31afc88d018626140 oid sha256:891aaa3e12fd0999b5c588ebecba20fdf655252eaf622d44ef3e1b241d20fd3f
size 289879 size 300038
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:fc3acdd6447da268ef587596cbce65a616b1b77d70ef1d503fdf9389e4292340 oid sha256:20ba7a152fddecb6d0fc8f850f16ef4badaee1671aef57babd2a7ada30f45f1e
size 328755 size 328845
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:7b1f41291345f1454f9bf773e4efb7b96f370a68185710796a5f3675d4e672d2 oid sha256:71a804e4f618655897c9e34d214a909f101f1592ae89efa1fded5d1456045f57
size 768475 size 768561
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:4e2ea9cb24ceeccbc3989999704a5ecd8c07b35cd81b00945407c37730b9b361
size 109114
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:baf46e031df4ca38e250d145ba251d5dff0151521173faa72144fd04e30ae541 oid sha256:ce5b799ce30d00f674e1b2275b2053348d122e1aa47c23543347d515109aabe0
size 99541 size 65938
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:9c0f3eed1c78e3b734c787fa6d47ea09347303dc132289b993a72c9d823332e0
size 111097
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:1fcde6c5a8783a21d5f0683b850fbb8c95c88bc6e3ca5994fd4e769e92ccec36
size 102638
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:2c1d4c40717ad7c7291009d0458b4737d93d77c404e7f88cf9445148f9bcbfe9 oid sha256:51ae2109aa903b1bb3cd92b1a37a65089ff35df1edf08dbcd0d109c557179506
size 111160 size 80801
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:4b7bf00a08472a91457ede8325bd9593c54292f595d9132cc7df9065132ffd40 oid sha256:fd9376c0ec4981d72e8e495ccfdb3634fec84b1771d41e1e0ba25432ded73f70
size 306877 size 314081
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:ae69d26c82628764ae5254f4a180a95fb2a69abe2cc113ee4c4f03531b3b221a oid sha256:8dceab7ecd50de0ec4c4dbbdaa7484a2dc142b418477b03d7cd5ebe60de2e7e8
size 436822 size 443420
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:1a34893148141ab6925e4875d90404a46085f5440dac2a1a694861b18d75a7a4 oid sha256:c17fade4c6cc4422518b6aa1c4ceac9a6c62f957c40f89877da6b95bc1180153
size 709895 size 719640
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:23889a3f018de42f1d43672488a99d82c379356b93c64e2b464e6dc8e301579d
size 132289
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:b95cf05146a78f0300fce52071c14cd1a7e22ac77b73242b6979fe6742029da1 oid sha256:8b0dda025aa247f05356fced96f8a1c54323fcd31bf1e40b0780b6d3049d7c51
size 113297 size 69006
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:683d1b9b97925e38e99eb1484b1b60fb8dd8a966a843338f2930d46b37869f63
size 134683
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ec7e0d2f7a28ea69ce3f79abe7b46044626a38b9d2d9c36a2d9a4a9b27c53327
size 116295
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:facd745ec4ffb852684629d6d2a3283a04e5de896e2e87952b6a4e9e487ea82b oid sha256:a04e624edc5379a57499b3136f533da3ce13fbe36a76de0f04951bd0f7693227
size 135609 size 91906
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:1f2700dece05d0b7bba51d1b71b31a4eba6b64ef622c83badd55ae30822c5deb oid sha256:14e6f0339d1a5b4bfe56ee9f0c5a6b409cac25f1fffcb733c6674f73c42a9bd7
size 292792 size 301482
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:7659f0d89a39f3a88863af13afb8e5f84112b9a20043d7baaea51720f39c5995 oid sha256:8ccd7c2b6588ebf5f5867a3e5978d66742ac3a99652a89748eab6a9cdca80bfd
size 313332 size 313225
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:90f8ed29ba91fd9d39da5211c1fc86c819015f1287db78f7b3405a408a3528bc oid sha256:116b1934f9d3bb70bb2f39101a3ec7e71bfe6bcbddfd1c9a0859209a8ed84454
size 809223 size 809116
@@ -28,7 +28,6 @@ class HomeScreenViewModelTests: XCTestCase {
var roomSummaryProvider: RoomSummaryProviderMock! var roomSummaryProvider: RoomSummaryProviderMock!
override func setUpWithError() throws { override func setUpWithError() throws {
ServiceLocator.shared.settings.roomListFiltersEnabled = true
cancellables.removeAll() cancellables.removeAll()
roomSummaryProvider = RoomSummaryProviderMock(.init(state: .loaded(.mockRooms))) roomSummaryProvider = RoomSummaryProviderMock(.init(state: .loaded(.mockRooms)))
clientProxy = ClientProxyMock(.init(userID: "@mock:client.com", roomSummaryProvider: roomSummaryProvider)) clientProxy = ClientProxyMock(.init(userID: "@mock:client.com", roomSummaryProvider: roomSummaryProvider))
@@ -179,7 +178,6 @@ class HomeScreenViewModelTests: XCTestCase {
try await Task.sleep(for: .milliseconds(100)) try await Task.sleep(for: .milliseconds(100))
XCTAssertEqual(roomSummaryProvider.roomListPublisher.value.first?.name, "Prelude to Foundation") XCTAssertEqual(roomSummaryProvider.roomListPublisher.value.first?.name, "Prelude to Foundation")
XCTAssertEqual(roomSummaryProvider.roomListPublisher.value.count, 1) XCTAssertEqual(roomSummaryProvider.roomListPublisher.value.count, 1)
XCTAssertFalse(context.viewState.shouldShowFilters)
} }
func testFiltersEmptyState() async throws { func testFiltersEmptyState() async throws {
@@ -96,13 +96,11 @@ class InviteUsersScreenViewModelTests: XCTestCase {
private func setupWithRoomType(roomType: InviteUsersScreenRoomType) { private func setupWithRoomType(roomType: InviteUsersScreenRoomType) {
let usersSubject = CurrentValueSubject<[UserProfileProxy], Never>([]) let usersSubject = CurrentValueSubject<[UserProfileProxy], Never>([])
userDiscoveryService = UserDiscoveryServiceMock() userDiscoveryService = UserDiscoveryServiceMock()
userDiscoveryService.fetchSuggestionsReturnValue = .success([])
userDiscoveryService.searchProfilesWithReturnValue = .success([]) userDiscoveryService.searchProfilesWithReturnValue = .success([])
usersSubject.send([]) usersSubject.send([])
let viewModel = InviteUsersScreenViewModel(selectedUsers: usersSubject.asCurrentValuePublisher(), let viewModel = InviteUsersScreenViewModel(selectedUsers: usersSubject.asCurrentValuePublisher(),
roomType: roomType, mediaProvider: MockMediaProvider(), roomType: roomType, mediaProvider: MockMediaProvider(),
userDiscoveryService: userDiscoveryService, userDiscoveryService: userDiscoveryService,
appSettings: ServiceLocator.shared.settings,
userIndicatorController: UserIndicatorControllerMock()) userIndicatorController: UserIndicatorControllerMock())
viewModel.state.usersSection = .init(type: .suggestions, users: [.mockAlice, .mockBob, .mockCharlie]) viewModel.state.usersSection = .init(type: .suggestions, users: [.mockAlice, .mockBob, .mockCharlie])
self.viewModel = viewModel self.viewModel = viewModel
@@ -31,13 +31,11 @@ class StartChatScreenViewModelTests: XCTestCase {
override func setUpWithError() throws { override func setUpWithError() throws {
clientProxy = .init(.init(userID: "")) clientProxy = .init(.init(userID: ""))
userDiscoveryService = UserDiscoveryServiceMock() userDiscoveryService = UserDiscoveryServiceMock()
userDiscoveryService.fetchSuggestionsReturnValue = .success([])
userDiscoveryService.searchProfilesWithReturnValue = .success([]) userDiscoveryService.searchProfilesWithReturnValue = .success([])
let userSession = MockUserSession(clientProxy: clientProxy, let userSession = MockUserSession(clientProxy: clientProxy,
mediaProvider: MockMediaProvider(), mediaProvider: MockMediaProvider(),
voiceMessageMediaManager: VoiceMessageMediaManagerMock()) voiceMessageMediaManager: VoiceMessageMediaManagerMock())
viewModel = StartChatScreenViewModel(userSession: userSession, viewModel = StartChatScreenViewModel(userSession: userSession,
userSuggestionsEnabled: true,
analytics: ServiceLocator.shared.analytics, analytics: ServiceLocator.shared.analytics,
userIndicatorController: UserIndicatorControllerMock(), userIndicatorController: UserIndicatorControllerMock(),
userDiscoveryService: userDiscoveryService) userDiscoveryService: userDiscoveryService)
@@ -46,7 +44,6 @@ class StartChatScreenViewModelTests: XCTestCase {
func testQueryShowingNoResults() async throws { func testQueryShowingNoResults() async throws {
await search(query: "A") await search(query: "A")
XCTAssertEqual(context.viewState.usersSection.type, .suggestions) XCTAssertEqual(context.viewState.usersSection.type, .suggestions)
XCTAssertTrue(userDiscoveryService.fetchSuggestionsCalled)
await search(query: "AA") await search(query: "AA")
XCTAssertEqual(context.viewState.usersSection.type, .suggestions) XCTAssertEqual(context.viewState.usersSection.type, .suggestions)
+1
View File
@@ -0,0 +1 @@
The features: Filters, Mark as Read/Unread/Favourites are now available.