Enable fuzzy search behind a feature flag. (#1490)

This commit is contained in:
Doug
2023-08-14 17:41:41 +01:00
committed by GitHub
parent f612655d9c
commit ee430e7e2c
11 changed files with 62 additions and 17 deletions

View File

@@ -29,6 +29,8 @@ final class AppSettings {
case enableNotifications
case enableInAppNotifications
case pusherProfileTag
// Feature flags
case shouldCollapseRoomStateEvents
case userSuggestionsEnabled
case readReceiptsEnabled
@@ -36,6 +38,7 @@ final class AppSettings {
case notificationSettingsEnabled
case swiftUITimelineEnabled
case pollsInTimeline
case fuzzySearchEnabled
}
private static var suiteName: String = InfoPlistReader.main.appGroupIdentifier
@@ -225,4 +228,7 @@ final class AppSettings {
@UserPreference(key: UserDefaultsKeys.pollsInTimeline, defaultValue: false, storageType: .userDefaults(store))
var pollsInTimelineEnabled
@UserPreference(key: UserDefaultsKeys.fuzzySearchEnabled, defaultValue: true, storageType: .userDefaults(store))
var fuzzySearchEnabled
}

View File

@@ -47,6 +47,7 @@ enum HomeScreenViewAction {
case skipSessionVerification
case updateVisibleItemRange(range: Range<Int>, isScrolling: Bool)
case selectInvites
case updatedSearchQuery
}
enum HomeScreenRoomListMode: CustomStringConvertible {
@@ -79,12 +80,14 @@ struct HomeScreenViewState: BindableState {
var selectedRoomID: String?
var fuzzySearchEnabled: Bool
var visibleRooms: [HomeScreenRoom] {
if roomListMode == .skeletons {
return placeholderRooms
}
if bindings.searchQuery.isEmpty {
if fuzzySearchEnabled || bindings.searchQuery.isEmpty {
return rooms
}

View File

@@ -49,7 +49,7 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
roomSummaryProvider = userSession.clientProxy.roomSummaryProvider
inviteSummaryProvider = userSession.clientProxy.inviteSummaryProvider
super.init(initialViewState: HomeScreenViewState(userID: userSession.userID),
super.init(initialViewState: HomeScreenViewState(userID: userSession.userID, fuzzySearchEnabled: appSettings.fuzzySearchEnabled),
imageProvider: userSession.mediaProvider)
userSession.callbacks
@@ -74,6 +74,10 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
.weakAssign(to: \.state.selectedRoomID, on: self)
.store(in: &cancellables)
appSettings.$fuzzySearchEnabled
.weakAssign(to: \.state.fuzzySearchEnabled, on: self)
.store(in: &cancellables)
guard let roomSummaryProvider, let inviteSummaryProvider else {
MXLog.error("Room summary provider unavailable")
return
@@ -187,6 +191,8 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
callback?(.presentStartChatScreen)
case .selectInvites:
callback?(.presentInvitesScreen)
case .updatedSearchQuery:
roomSummaryProvider?.updateFilterPattern(state.bindings.searchQuery)
}
}

View File

@@ -80,9 +80,13 @@ struct HomeScreen: View {
updateVisibleRange()
}
.onChange(of: context.searchQuery) { searchQuery in
guard searchQuery.isEmpty else { return }
// Dispatch allows the view to update after changing the query
DispatchQueue.main.async { updateVisibleRange() }
if context.viewState.fuzzySearchEnabled {
context.send(viewAction: .updatedSearchQuery)
} else {
guard searchQuery.isEmpty else { return }
// Dispatch allows the view to update after changing the query
DispatchQueue.main.async { updateVisibleRange() }
}
}
.onReceive(scrollViewAdapter.scrollDirection) { direction in
withAnimation(.elementDefault) { lastScrollDirection = direction }

View File

@@ -49,6 +49,7 @@ protocol DeveloperOptionsProtocol: AnyObject {
var notificationSettingsEnabled: Bool { get set }
var swiftUITimelineEnabled: Bool { get set }
var pollsInTimelineEnabled: Bool { get set }
var fuzzySearchEnabled: Bool { get set }
var filterNotificationsByPushRulesEnabled: Bool { get set }
}

View File

@@ -37,6 +37,13 @@ struct DeveloperOptionsScreen: View {
Text("Resets on reboot")
}
}
Section("Room list") {
Toggle(isOn: $context.fuzzySearchEnabled) {
Text("Fuzzy search")
Text("Requires app reboot")
}
}
Section("Notifications") {
Toggle(isOn: $context.notificationSettingsEnabled) {

View File

@@ -414,11 +414,13 @@ class ClientProxy: ClientProxyProtocol {
let eventStringBuilder = RoomEventStringBuilder(stateEventStringBuilder: RoomStateEventStringBuilder(userID: userID))
roomSummaryProvider = RoomSummaryProvider(roomListService: roomListService,
eventStringBuilder: eventStringBuilder,
name: "AllRooms")
name: "AllRooms",
appSettings: appSettings)
try await roomSummaryProvider?.setRoomList(roomListService.allRooms())
inviteSummaryProvider = RoomSummaryProvider(roomListService: roomListService,
eventStringBuilder: eventStringBuilder,
name: "Invites")
name: "Invites",
appSettings: appSettings)
self.syncService = syncService
self.roomListService = roomListService

View File

@@ -45,6 +45,8 @@ class MockRoomSummaryProvider: RoomSummaryProviderProtocol {
func setRoomList(_ roomList: RoomList) { }
func updateVisibleRange(_ range: Range<Int>) { }
func updateFilterPattern(_ pattern: String?) { }
}
extension Array where Element == RoomSummary {

View File

@@ -22,12 +22,14 @@ class RoomSummaryProvider: RoomSummaryProviderProtocol {
private let roomListService: RoomListServiceProtocol
private let eventStringBuilder: RoomEventStringBuilder
private let name: String
private var appSettings: AppSettings
private let serialDispatchQueue: DispatchQueue
private var roomList: RoomListProtocol?
private var cancellables = Set<AnyCancellable>()
private var listUpdatesSubscriptionResult: RoomListEntriesWithDynamicFilterResult?
private var listUpdatesTaskHandle: TaskHandle?
private var stateUpdatesTaskHandle: TaskHandle?
@@ -53,11 +55,13 @@ class RoomSummaryProvider: RoomSummaryProviderProtocol {
init(roomListService: RoomListServiceProtocol,
eventStringBuilder: RoomEventStringBuilder,
name: String) {
name: String,
appSettings: AppSettings) {
self.roomListService = roomListService
serialDispatchQueue = DispatchQueue(label: "io.element.elementx.roomsummaryprovider", qos: .utility)
self.eventStringBuilder = eventStringBuilder
self.name = name
self.appSettings = appSettings
diffsPublisher
.receive(on: serialDispatchQueue)
@@ -73,21 +77,17 @@ class RoomSummaryProvider: RoomSummaryProviderProtocol {
self.roomList = roomList
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 }
MXLog.info("\(name): Received list update")
diffsPublisher.send(updates)
})
listUpdatesTaskHandle = listUpdatesSubscriptionResult.entriesStream
rooms = listUpdatesSubscriptionResult.entries.map { roomListEntry in
buildSummaryForRoomListEntry(roomListEntry)
}
// Manually call it here as the didSet doesn't work from constructors
roomListSubject.send(rooms)
listUpdatesTaskHandle = listUpdatesSubscriptionResult?.entriesStream
// Forces the listener above to be called with the current state
updateFilterPattern(nil)
let stateUpdatesSubscriptionResult = try roomList.loadingState(listener: RoomListStateObserver { [weak self] state in
guard let self else { return }
MXLog.info("\(name): Received state update: \(state)")
@@ -113,6 +113,17 @@ 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
fileprivate func updateRoomsWithDiffs(_ diffs: [RoomListEntriesUpdate]) {

View File

@@ -99,4 +99,6 @@ protocol RoomSummaryProviderProtocol {
func setRoomList(_ roomList: RoomList)
func updateVisibleRange(_ range: Range<Int>)
func updateFilterPattern(_ pattern: String?)
}

View File

@@ -0,0 +1 @@
Allow fuzzy searching for room list rooms