mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 16:10:20 +00:00
Surface search set query errors with an error indicator
This commit is contained in:
@@ -97,7 +97,8 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
if flowParameters.appSettings.globalSearchEnabled, #available(iOS 26.0, *) {
|
if flowParameters.appSettings.globalSearchEnabled, #available(iOS 26.0, *) {
|
||||||
let searchCoordinator = SearchScreenCoordinator(parameters: .init(roomSummaryProvider: flowParameters.userSession.clientProxy.alternateRoomSummaryProvider,
|
let searchCoordinator = SearchScreenCoordinator(parameters: .init(roomSummaryProvider: flowParameters.userSession.clientProxy.alternateRoomSummaryProvider,
|
||||||
clientProxy: flowParameters.userSession.clientProxy,
|
clientProxy: flowParameters.userSession.clientProxy,
|
||||||
mediaProvider: flowParameters.userSession.mediaProvider))
|
mediaProvider: flowParameters.userSession.mediaProvider,
|
||||||
|
userIndicatorController: flowParameters.userIndicatorController))
|
||||||
let searchStackCoordinator = NavigationStackCoordinator()
|
let searchStackCoordinator = NavigationStackCoordinator()
|
||||||
searchStackCoordinator.setRootCoordinator(searchCoordinator)
|
searchStackCoordinator.setRootCoordinator(searchCoordinator)
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ struct SearchScreenCoordinatorParameters {
|
|||||||
let roomSummaryProvider: RoomSummaryProviderProtocol
|
let roomSummaryProvider: RoomSummaryProviderProtocol
|
||||||
let clientProxy: ClientProxyProtocol
|
let clientProxy: ClientProxyProtocol
|
||||||
let mediaProvider: MediaProviderProtocol
|
let mediaProvider: MediaProviderProtocol
|
||||||
|
let userIndicatorController: UserIndicatorControllerProtocol
|
||||||
}
|
}
|
||||||
|
|
||||||
enum SearchScreenCoordinatorAction {
|
enum SearchScreenCoordinatorAction {
|
||||||
@@ -32,7 +33,8 @@ final class SearchScreenCoordinator: CoordinatorProtocol {
|
|||||||
init(parameters: SearchScreenCoordinatorParameters) {
|
init(parameters: SearchScreenCoordinatorParameters) {
|
||||||
viewModel = SearchScreenViewModel(roomSummaryProvider: parameters.roomSummaryProvider,
|
viewModel = SearchScreenViewModel(roomSummaryProvider: parameters.roomSummaryProvider,
|
||||||
clientProxy: parameters.clientProxy,
|
clientProxy: parameters.clientProxy,
|
||||||
mediaProvider: parameters.mediaProvider)
|
mediaProvider: parameters.mediaProvider,
|
||||||
|
userIndicatorController: parameters.userIndicatorController)
|
||||||
}
|
}
|
||||||
|
|
||||||
func start() {
|
func start() {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ typealias SearchScreenViewModelType = StateStoreViewModelV2<SearchScreenViewStat
|
|||||||
class SearchScreenViewModel: SearchScreenViewModelType, SearchScreenViewModelProtocol {
|
class SearchScreenViewModel: SearchScreenViewModelType, SearchScreenViewModelProtocol {
|
||||||
private let roomSummaryProvider: RoomSummaryProviderProtocol
|
private let roomSummaryProvider: RoomSummaryProviderProtocol
|
||||||
private let searchService: SearchServiceProxyProtocol
|
private let searchService: SearchServiceProxyProtocol
|
||||||
|
private let userIndicatorController: UserIndicatorControllerProtocol
|
||||||
private var searchQueryObservationTask: Task<Void, Never>?
|
private var searchQueryObservationTask: Task<Void, Never>?
|
||||||
private var loadingObservationTask: Task<Void, Never>?
|
private var loadingObservationTask: Task<Void, Never>?
|
||||||
private var setQueryTask: Task<Void, Never>?
|
private var setQueryTask: Task<Void, Never>?
|
||||||
@@ -26,10 +27,12 @@ class SearchScreenViewModel: SearchScreenViewModelType, SearchScreenViewModelPro
|
|||||||
init(roomSummaryProvider: RoomSummaryProviderProtocol,
|
init(roomSummaryProvider: RoomSummaryProviderProtocol,
|
||||||
clientProxy: ClientProxyProtocol,
|
clientProxy: ClientProxyProtocol,
|
||||||
mediaProvider: MediaProviderProtocol,
|
mediaProvider: MediaProviderProtocol,
|
||||||
|
userIndicatorController: UserIndicatorControllerProtocol,
|
||||||
initialSearchQuery: String = "",
|
initialSearchQuery: String = "",
|
||||||
initialSearchMode: SearchScreenMode = .rooms) {
|
initialSearchMode: SearchScreenMode = .rooms) {
|
||||||
self.roomSummaryProvider = roomSummaryProvider
|
self.roomSummaryProvider = roomSummaryProvider
|
||||||
searchService = clientProxy.searchService
|
searchService = clientProxy.searchService
|
||||||
|
self.userIndicatorController = userIndicatorController
|
||||||
|
|
||||||
super.init(initialViewState: SearchScreenViewState(bindings: .init(searchQuery: initialSearchQuery, searchMode: initialSearchMode)),
|
super.init(initialViewState: SearchScreenViewState(bindings: .init(searchQuery: initialSearchQuery, searchMode: initialSearchMode)),
|
||||||
mediaProvider: mediaProvider)
|
mediaProvider: mediaProvider)
|
||||||
@@ -133,8 +136,10 @@ class SearchScreenViewModel: SearchScreenViewModelType, SearchScreenViewModelPro
|
|||||||
} else {
|
} else {
|
||||||
roomSummaryProvider.setFilter(.search(query: searchQuery))
|
roomSummaryProvider.setFilter(.search(query: searchQuery))
|
||||||
setQueryTask = Task { [weak self] in
|
setQueryTask = Task { [weak self] in
|
||||||
// TODO: @stefanceriu Surface set query errors
|
guard let self else { return }
|
||||||
_ = await self?.searchService.setQuery(searchQuery)
|
if case .failure = await searchService.setQuery(searchQuery), !Task.isCancelled {
|
||||||
|
userIndicatorController.submitIndicator(.init(title: L10n.errorUnknown))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -467,23 +467,28 @@ private final class KeyNavigatingSearchTextField: UISearchTextField {
|
|||||||
struct SearchScreen_Previews: PreviewProvider, TestablePreview {
|
struct SearchScreen_Previews: PreviewProvider, TestablePreview {
|
||||||
static let emptyViewModel = SearchScreenViewModel(roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded([]))),
|
static let emptyViewModel = SearchScreenViewModel(roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded([]))),
|
||||||
clientProxy: makeClientProxy(),
|
clientProxy: makeClientProxy(),
|
||||||
mediaProvider: MediaProviderMock(.init()))
|
mediaProvider: MediaProviderMock(.init()),
|
||||||
|
userIndicatorController: UserIndicatorControllerMock())
|
||||||
static let noResultsViewModel = SearchScreenViewModel(roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded([]))),
|
static let noResultsViewModel = SearchScreenViewModel(roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded([]))),
|
||||||
clientProxy: makeClientProxy(),
|
clientProxy: makeClientProxy(),
|
||||||
mediaProvider: MediaProviderMock(.init()),
|
mediaProvider: MediaProviderMock(.init()),
|
||||||
|
userIndicatorController: UserIndicatorControllerMock(),
|
||||||
initialSearchQuery: "John Doe")
|
initialSearchQuery: "John Doe")
|
||||||
static let roomsViewModel = SearchScreenViewModel(roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(.mockRooms))),
|
static let roomsViewModel = SearchScreenViewModel(roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(.mockRooms))),
|
||||||
clientProxy: makeClientProxy(),
|
clientProxy: makeClientProxy(),
|
||||||
mediaProvider: MediaProviderMock(.init()),
|
mediaProvider: MediaProviderMock(.init()),
|
||||||
|
userIndicatorController: UserIndicatorControllerMock(),
|
||||||
initialSearchQuery: "Foundation")
|
initialSearchQuery: "Foundation")
|
||||||
static let messagesViewModel = SearchScreenViewModel(roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded([]))),
|
static let messagesViewModel = SearchScreenViewModel(roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded([]))),
|
||||||
clientProxy: makeClientProxy(searchService: makeSearchService(results: .mockResults)),
|
clientProxy: makeClientProxy(searchService: makeSearchService(results: .mockResults)),
|
||||||
mediaProvider: MediaProviderMock(.init()),
|
mediaProvider: MediaProviderMock(.init()),
|
||||||
|
userIndicatorController: UserIndicatorControllerMock(),
|
||||||
initialSearchQuery: "Foundation",
|
initialSearchQuery: "Foundation",
|
||||||
initialSearchMode: .messages)
|
initialSearchMode: .messages)
|
||||||
static let loadingMessagesViewModel = SearchScreenViewModel(roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded([]))),
|
static let loadingMessagesViewModel = SearchScreenViewModel(roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded([]))),
|
||||||
clientProxy: makeClientProxy(searchService: makeSearchService(paginationState: .loading)),
|
clientProxy: makeClientProxy(searchService: makeSearchService(paginationState: .loading)),
|
||||||
mediaProvider: MediaProviderMock(.init()),
|
mediaProvider: MediaProviderMock(.init()),
|
||||||
|
userIndicatorController: UserIndicatorControllerMock(),
|
||||||
initialSearchQuery: "Foundation",
|
initialSearchQuery: "Foundation",
|
||||||
initialSearchMode: .messages)
|
initialSearchMode: .messages)
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,8 @@ struct SearchScreenViewModelTests {
|
|||||||
|
|
||||||
viewModel = SearchScreenViewModel(roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(.mockRooms))),
|
viewModel = SearchScreenViewModel(roomSummaryProvider: RoomSummaryProviderMock(.init(state: .loaded(.mockRooms))),
|
||||||
clientProxy: clientProxy,
|
clientProxy: clientProxy,
|
||||||
mediaProvider: MediaProviderMock(.init()))
|
mediaProvider: MediaProviderMock(.init()),
|
||||||
|
userIndicatorController: UserIndicatorControllerMock())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in New Issue
Block a user