Revert "Remove fuzzy searching entirely because of performance issues"

This reverts commit e86f65ad2d.
This commit is contained in:
Stefan Ceriu
2023-08-21 16:21:09 +03:00
committed by Stefan Ceriu
parent 65256bf4ab
commit ff074e3fae
9 changed files with 54 additions and 11 deletions
@@ -38,6 +38,7 @@ final class AppSettings {
case notificationSettingsEnabled case notificationSettingsEnabled
case swiftUITimelineEnabled case swiftUITimelineEnabled
case pollsInTimeline case pollsInTimeline
case fuzzySearchEnabled
} }
private static var suiteName: String = InfoPlistReader.main.appGroupIdentifier private static var suiteName: String = InfoPlistReader.main.appGroupIdentifier
@@ -223,4 +224,7 @@ final class AppSettings {
@UserPreference(key: UserDefaultsKeys.pollsInTimeline, defaultValue: false, storageType: .userDefaults(store)) @UserPreference(key: UserDefaultsKeys.pollsInTimeline, defaultValue: false, storageType: .userDefaults(store))
var pollsInTimelineEnabled var pollsInTimelineEnabled
@UserPreference(key: UserDefaultsKeys.fuzzySearchEnabled, defaultValue: true, storageType: .userDefaults(store))
var fuzzySearchEnabled
} }
@@ -79,12 +79,14 @@ struct HomeScreenViewState: BindableState {
var selectedRoomID: String? var selectedRoomID: String?
var fuzzySearchEnabled: Bool
var visibleRooms: [HomeScreenRoom] { var visibleRooms: [HomeScreenRoom] {
if roomListMode == .skeletons { if roomListMode == .skeletons {
return placeholderRooms return placeholderRooms
} }
if bindings.searchQuery.isEmpty { if fuzzySearchEnabled || bindings.searchQuery.isEmpty {
return rooms return rooms
} }
@@ -49,7 +49,7 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
roomSummaryProvider = userSession.clientProxy.roomSummaryProvider roomSummaryProvider = userSession.clientProxy.roomSummaryProvider
inviteSummaryProvider = userSession.clientProxy.inviteSummaryProvider inviteSummaryProvider = userSession.clientProxy.inviteSummaryProvider
super.init(initialViewState: HomeScreenViewState(userID: userSession.userID), super.init(initialViewState: HomeScreenViewState(userID: userSession.userID, fuzzySearchEnabled: appSettings.fuzzySearchEnabled),
imageProvider: userSession.mediaProvider) imageProvider: userSession.mediaProvider)
userSession.callbacks userSession.callbacks
@@ -74,6 +74,19 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
.weakAssign(to: \.state.selectedRoomID, on: self) .weakAssign(to: \.state.selectedRoomID, on: self)
.store(in: &cancellables) .store(in: &cancellables)
appSettings.$fuzzySearchEnabled
.weakAssign(to: \.state.fuzzySearchEnabled, on: self)
.store(in: &cancellables)
context.$viewState
.filter { _ in appSettings.fuzzySearchEnabled }
.map(\.bindings.searchQuery)
.debounceAndRemoveDuplicates()
.sink { [weak self] searchQuery in
self?.roomSummaryProvider?.updateFilterPattern(searchQuery)
}
.store(in: &cancellables)
setupRoomSummaryProviderSubscriptions() setupRoomSummaryProviderSubscriptions()
updateRooms() updateRooms()
@@ -49,6 +49,7 @@ protocol DeveloperOptionsProtocol: AnyObject {
var notificationSettingsEnabled: Bool { get set } var notificationSettingsEnabled: Bool { get set }
var swiftUITimelineEnabled: Bool { get set } var swiftUITimelineEnabled: Bool { get set }
var pollsInTimelineEnabled: Bool { get set } var pollsInTimelineEnabled: Bool { get set }
var fuzzySearchEnabled: Bool { get set }
} }
extension AppSettings: DeveloperOptionsProtocol { } extension AppSettings: DeveloperOptionsProtocol { }
@@ -38,6 +38,13 @@ struct DeveloperOptionsScreen: View {
} }
} }
Section("Room list") {
Toggle(isOn: $context.fuzzySearchEnabled) {
Text("Fuzzy search")
Text("Requires app reboot")
}
}
Section("Notifications") { Section("Notifications") {
Toggle(isOn: $context.notificationSettingsEnabled) { Toggle(isOn: $context.notificationSettingsEnabled) {
Text("Show notification settings") Text("Show notification settings")
@@ -399,11 +399,13 @@ class ClientProxy: ClientProxyProtocol {
roomSummaryProvider = RoomSummaryProvider(roomListService: roomListService, roomSummaryProvider = RoomSummaryProvider(roomListService: roomListService,
eventStringBuilder: eventStringBuilder, eventStringBuilder: eventStringBuilder,
name: "AllRooms", name: "AllRooms",
appSettings: appSettings,
backgroundTaskService: backgroundTaskService) backgroundTaskService: backgroundTaskService)
try await roomSummaryProvider?.setRoomList(roomListService.allRooms()) try await roomSummaryProvider?.setRoomList(roomListService.allRooms())
inviteSummaryProvider = RoomSummaryProvider(roomListService: roomListService, inviteSummaryProvider = RoomSummaryProvider(roomListService: roomListService,
eventStringBuilder: eventStringBuilder, eventStringBuilder: eventStringBuilder,
name: "Invites", name: "Invites",
appSettings: appSettings,
backgroundTaskService: backgroundTaskService) backgroundTaskService: backgroundTaskService)
self.syncService = syncService self.syncService = syncService
@@ -45,6 +45,8 @@ class MockRoomSummaryProvider: RoomSummaryProviderProtocol {
func setRoomList(_ roomList: RoomList) { } func setRoomList(_ roomList: RoomList) { }
func updateVisibleRange(_ range: Range<Int>) { } func updateVisibleRange(_ range: Range<Int>) { }
func updateFilterPattern(_ pattern: String?) { }
} }
extension Array where Element == RoomSummary { extension Array where Element == RoomSummary {
@@ -22,6 +22,7 @@ class RoomSummaryProvider: RoomSummaryProviderProtocol {
private let roomListService: RoomListServiceProtocol private let roomListService: RoomListServiceProtocol
private let eventStringBuilder: RoomEventStringBuilder private let eventStringBuilder: RoomEventStringBuilder
private let name: String private let name: String
private var appSettings: AppSettings
private let backgroundTaskService: BackgroundTaskServiceProtocol private let backgroundTaskService: BackgroundTaskServiceProtocol
private let serialDispatchQueue: DispatchQueue private let serialDispatchQueue: DispatchQueue
@@ -29,6 +30,7 @@ class RoomSummaryProvider: RoomSummaryProviderProtocol {
private var roomList: RoomListProtocol? private var roomList: RoomListProtocol?
private var cancellables = Set<AnyCancellable>() private var cancellables = Set<AnyCancellable>()
private var listUpdatesSubscriptionResult: RoomListEntriesWithDynamicFilterResult?
private var listUpdatesTaskHandle: TaskHandle? private var listUpdatesTaskHandle: TaskHandle?
private var stateUpdatesTaskHandle: TaskHandle? private var stateUpdatesTaskHandle: TaskHandle?
@@ -55,11 +57,13 @@ class RoomSummaryProvider: RoomSummaryProviderProtocol {
init(roomListService: RoomListServiceProtocol, init(roomListService: RoomListServiceProtocol,
eventStringBuilder: RoomEventStringBuilder, eventStringBuilder: RoomEventStringBuilder,
name: String, name: String,
appSettings: AppSettings,
backgroundTaskService: BackgroundTaskServiceProtocol) { backgroundTaskService: BackgroundTaskServiceProtocol) {
self.roomListService = roomListService self.roomListService = roomListService
serialDispatchQueue = DispatchQueue(label: "io.element.elementx.roomsummaryprovider", qos: .utility) serialDispatchQueue = DispatchQueue(label: "io.element.elementx.roomsummaryprovider", qos: .utility)
self.eventStringBuilder = eventStringBuilder self.eventStringBuilder = eventStringBuilder
self.name = name self.name = name
self.appSettings = appSettings
self.backgroundTaskService = backgroundTaskService self.backgroundTaskService = backgroundTaskService
diffsPublisher diffsPublisher
@@ -76,20 +80,16 @@ class RoomSummaryProvider: RoomSummaryProviderProtocol {
self.roomList = roomList self.roomList = roomList
do { do {
let listUpdatesSubscriptionResult = roomList.entries(listener: RoomListEntriesListenerProxy { [weak self] updates in listUpdatesSubscriptionResult = roomList.entriesWithDynamicFilter(listener: RoomListEntriesListenerProxy { [weak self] updates in
guard let self else { return } guard let self else { return }
MXLog.info("\(name): Received list update") MXLog.info("\(name): Received list update")
diffsPublisher.send(updates) diffsPublisher.send(updates)
}) })
listUpdatesTaskHandle = listUpdatesSubscriptionResult.entriesStream listUpdatesTaskHandle = listUpdatesSubscriptionResult?.entriesStream
rooms = listUpdatesSubscriptionResult.entries.map { roomListEntry in
buildSummaryForRoomListEntry(roomListEntry)
}
// Manually call it here as the didSet doesn't work from constructors // Forces the listener above to be called with the current state
roomListSubject.send(rooms) updateFilterPattern(nil)
let stateUpdatesSubscriptionResult = try roomList.loadingState(listener: RoomListStateObserver { [weak self] state in let stateUpdatesSubscriptionResult = try roomList.loadingState(listener: RoomListStateObserver { [weak self] state in
guard let self else { return } guard let self else { return }
@@ -100,7 +100,6 @@ class RoomSummaryProvider: RoomSummaryProviderProtocol {
stateUpdatesTaskHandle = stateUpdatesSubscriptionResult.stateStream stateUpdatesTaskHandle = stateUpdatesSubscriptionResult.stateStream
stateSubject.send(RoomSummaryProviderState(roomListState: stateUpdatesSubscriptionResult.state)) stateSubject.send(RoomSummaryProviderState(roomListState: stateUpdatesSubscriptionResult.state))
} catch { } catch {
MXLog.error("Failed setting up room list entry listener with error: \(error)") MXLog.error("Failed setting up room list entry listener with error: \(error)")
} }
@@ -116,7 +115,18 @@ class RoomSummaryProvider: RoomSummaryProviderProtocol {
} }
} }
} }
func updateFilterPattern(_ pattern: String?) {
guard let pattern, !pattern.isEmpty else {
_ = listUpdatesSubscriptionResult?.dynamicFilter.set(kind: .all)
return
}
guard appSettings.fuzzySearchEnabled else { return }
_ = listUpdatesSubscriptionResult?.dynamicFilter.set(kind: .fuzzyMatchRoomName(pattern: pattern.lowercased()))
}
// MARK: - Private // MARK: - Private
fileprivate func updateRoomsWithDiffs(_ diffs: [RoomListEntriesUpdate]) { fileprivate func updateRoomsWithDiffs(_ diffs: [RoomListEntriesUpdate]) {
@@ -99,4 +99,6 @@ protocol RoomSummaryProviderProtocol {
func setRoomList(_ roomList: RoomList) func setRoomList(_ roomList: RoomList)
func updateVisibleRange(_ range: Range<Int>) func updateVisibleRange(_ range: Range<Int>)
func updateFilterPattern(_ pattern: String?)
} }