Fix Suggestion Pattern when text is empty (#1943)

* fix + debounce improvement

* comment

* improved existing function to be more generic
This commit is contained in:
Mauro 2023-10-23 17:52:10 +02:00 committed by GitHub
parent 2f57fbc77d
commit 4c84878f88
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 45 additions and 10 deletions

View File

@ -25,16 +25,23 @@ extension Publisher where Self.Failure == Never {
}
}
extension Publisher where Output == String, Failure == Never {
/// Debounce text queries and remove duplicates.
/// Clearing the text publishes the update immediately.
func debounceAndRemoveDuplicates() -> AnyPublisher<String, Never> {
extension Publisher where Output: Equatable, Failure == Never {
func debounceAndRemoveDuplicates<S: Scheduler>(on scheduler: S, delay: @escaping (Output) -> S.SchedulerTimeType.Stride) -> AnyPublisher<Output, Never> {
map { query in
let milliseconds = query.isEmpty ? 0 : 250
return Just(query).delay(for: .milliseconds(milliseconds), scheduler: DispatchQueue.main)
Just(query).delay(for: delay(query), scheduler: scheduler)
}
.switchToLatest()
.removeDuplicates()
.eraseToAnyPublisher()
}
}
extension Publisher where Output == String, Failure == Never {
/// Debounce text queries and remove duplicates.
/// Clearing the text publishes the update immediately.
func debounceTextQueriesAndRemoveDuplicates() -> AnyPublisher<String, Never> {
debounceAndRemoveDuplicates(on: DispatchQueue.main) { query in
query.isEmpty ? .milliseconds(0) : .milliseconds(250)
}
}
}

View File

@ -55,8 +55,10 @@ final class CompletionSuggestionService: CompletionSuggestionServiceProtocol {
return membersSuggestion
}
}
.debounce(for: 0.5, scheduler: DispatchQueue.main)
.eraseToAnyPublisher()
// We only debounce if the suggestion is nil
.debounceAndRemoveDuplicates(on: DispatchQueue.main) { [weak self] _ in
self?.suggestionTriggerSubject.value != nil ? .milliseconds(500) : .milliseconds(0)
}
Task {
switch await roomProxy.canUserTriggerRoomNotification(userID: roomProxy.ownUserID) {
@ -73,6 +75,10 @@ final class CompletionSuggestionService: CompletionSuggestionServiceProtocol {
}
private static func isIncluded(searchText: String, userID: String, displayName: String?) -> Bool {
// If the search text is empty give back all the results
guard !searchText.isEmpty else {
return true
}
let containedInUserID = userID.localizedStandardContains(searchText.lowercased())
let containedInDisplayName: Bool

View File

@ -95,7 +95,7 @@ class InviteUsersScreenViewModel: InviteUsersScreenViewModelType, InviteUsersScr
private func setupSubscriptions(selectedUsers: CurrentValuePublisher<[UserProfileProxy], Never>) {
context.$viewState
.map(\.bindings.searchQuery)
.debounceAndRemoveDuplicates()
.debounceTextQueriesAndRemoveDuplicates()
.sink { [weak self] _ in
self?.fetchUsers()
}

View File

@ -92,7 +92,7 @@ class StartChatScreenViewModel: StartChatScreenViewModelType, StartChatScreenVie
private func setupBindings() {
context.$viewState
.map(\.bindings.searchQuery)
.debounceAndRemoveDuplicates()
.debounceTextQueriesAndRemoveDuplicates()
.sink { [weak self] _ in
self?.fetchUsers()
}

View File

@ -87,4 +87,26 @@ final class CompletionSuggestionServiceTests: XCTestCase {
service.setSuggestionTrigger(.init(type: .user, text: "every"))
try await deferred.fulfill()
}
func testUserSuggestionsWithEmptyText() async throws {
let alice: RoomMemberProxyMock = .mockAlice
let bob: RoomMemberProxyMock = .mockBob
let members: [RoomMemberProxyMock] = [alice, bob, .mockMe]
let roomProxyMock = RoomProxyMock(with: .init(displayName: "test", members: members, canUserTriggerRoomNotification: true))
let service = CompletionSuggestionService(roomProxy: roomProxyMock, areSuggestionsEnabled: true)
var deferred = deferFulfillment(service.suggestionsPublisher) { suggestions in
suggestions == []
}
try await deferred.fulfill()
deferred = deferFulfillment(service.suggestionsPublisher) { suggestions in
suggestions == [.user(item: .init(id: alice.userID, displayName: alice.displayName, avatarURL: alice.avatarURL)),
.user(item: .init(id: bob.userID, displayName: bob.displayName, avatarURL: bob.avatarURL)),
.allUsers(item: .allUsersMention(roomAvatar: nil))]
}
service.setSuggestionTrigger(.init(type: .user, text: ""))
try await deferred.fulfill()
}
}