Skip to content

Commit 2a9952e

Browse files
authored
Add support for PredefinedFilters for QueryChannels (#6415)
* Add 'PredefinedFilters' support in the LLC. * Add 'sort' parsing logic. * Add 'sort' parsing logic. * Propagate PredefinedFilter to QueryChannels plugins. * Add JSON -> FilterObject mapping. * Add State/DB support for PredefinedFilter. * Simplify KDocs. * Add UI support for PredefinedFilters. * Fix test. * Migrate samples to use PredefinedFilters. * Remove TODOs. * Address PR remarks. * Use copy instead of creating new object. * Revert default search mode. * Calculate fallback sort order based on predefined filter values. * Address PR remarks. * Add queryFirstPage tests. * Update default message search filters when using predefined filters. * Normalize filter/sort values.
1 parent bda64de commit 2a9952e

66 files changed

Lines changed: 4026 additions & 718 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

stream-chat-android-client-test/src/main/java/io/getstream/chat/android/client/test/Mother.kt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -662,7 +662,17 @@ public fun randomQueryChannelsSpec(
662662
filter: FilterObject = NeutralFilterObject,
663663
sort: QuerySorter<Channel> = QuerySortByField(),
664664
cids: Set<String> = emptySet(),
665-
): QueryChannelsSpec = QueryChannelsSpec(filter, sort).apply { this.cids = cids }
665+
predefinedFilterName: String? = null,
666+
predefinedFilterValues: Map<String, Any>? = null,
667+
predefinedSortValues: Map<String, Any>? = null,
668+
): QueryChannelsSpec = QueryChannelsSpec(
669+
filter = filter,
670+
querySort = sort,
671+
cids = cids,
672+
predefinedFilterName = predefinedFilterName,
673+
predefinedFilterValues = predefinedFilterValues,
674+
predefinedSortValues = predefinedSortValues,
675+
)
666676

667677
public fun randomNotificationRemovedFromChannelEvent(
668678
cid: String = randomCID(),

stream-chat-android-client/api/stream-chat-android-client.api

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -582,25 +582,45 @@ public class io/getstream/chat/android/client/api/models/QueryChannelRequest : i
582582
}
583583

584584
public final class io/getstream/chat/android/client/api/models/QueryChannelsRequest : io/getstream/chat/android/client/api/models/ChannelRequest {
585+
public fun <init> (Lio/getstream/chat/android/models/FilterObject;I)V
586+
public fun <init> (Lio/getstream/chat/android/models/FilterObject;II)V
587+
public fun <init> (Lio/getstream/chat/android/models/FilterObject;IILio/getstream/chat/android/models/querysort/QuerySorter;)V
588+
public fun <init> (Lio/getstream/chat/android/models/FilterObject;IILio/getstream/chat/android/models/querysort/QuerySorter;Ljava/lang/Integer;)V
585589
public fun <init> (Lio/getstream/chat/android/models/FilterObject;IILio/getstream/chat/android/models/querysort/QuerySorter;Ljava/lang/Integer;Ljava/lang/Integer;)V
586-
public synthetic fun <init> (Lio/getstream/chat/android/models/FilterObject;IILio/getstream/chat/android/models/querysort/QuerySorter;Ljava/lang/Integer;Ljava/lang/Integer;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
590+
public fun <init> (Lio/getstream/chat/android/models/FilterObject;IILio/getstream/chat/android/models/querysort/QuerySorter;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/String;)V
591+
public fun <init> (Lio/getstream/chat/android/models/FilterObject;IILio/getstream/chat/android/models/querysort/QuerySorter;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/String;Ljava/util/Map;)V
592+
public fun <init> (Lio/getstream/chat/android/models/FilterObject;IILio/getstream/chat/android/models/querysort/QuerySorter;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)V
593+
public synthetic fun <init> (Lio/getstream/chat/android/models/FilterObject;IILio/getstream/chat/android/models/querysort/QuerySorter;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
594+
public fun <init> (Ljava/lang/String;I)V
595+
public fun <init> (Ljava/lang/String;ILjava/util/Map;)V
596+
public fun <init> (Ljava/lang/String;ILjava/util/Map;Ljava/util/Map;)V
597+
public fun <init> (Ljava/lang/String;ILjava/util/Map;Ljava/util/Map;I)V
598+
public fun <init> (Ljava/lang/String;ILjava/util/Map;Ljava/util/Map;ILjava/lang/Integer;)V
599+
public fun <init> (Ljava/lang/String;ILjava/util/Map;Ljava/util/Map;ILjava/lang/Integer;Ljava/lang/Integer;)V
600+
public synthetic fun <init> (Ljava/lang/String;ILjava/util/Map;Ljava/util/Map;ILjava/lang/Integer;Ljava/lang/Integer;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
587601
public final fun component1 ()Lio/getstream/chat/android/models/FilterObject;
588602
public final fun component2 ()I
589603
public final fun component3 ()I
590604
public final fun component4 ()Lio/getstream/chat/android/models/querysort/QuerySorter;
591605
public final fun component5 ()Ljava/lang/Integer;
592606
public final fun component6 ()Ljava/lang/Integer;
593-
public final fun copy (Lio/getstream/chat/android/models/FilterObject;IILio/getstream/chat/android/models/querysort/QuerySorter;Ljava/lang/Integer;Ljava/lang/Integer;)Lio/getstream/chat/android/client/api/models/QueryChannelsRequest;
594-
public static synthetic fun copy$default (Lio/getstream/chat/android/client/api/models/QueryChannelsRequest;Lio/getstream/chat/android/models/FilterObject;IILio/getstream/chat/android/models/querysort/QuerySorter;Ljava/lang/Integer;Ljava/lang/Integer;ILjava/lang/Object;)Lio/getstream/chat/android/client/api/models/QueryChannelsRequest;
607+
public final fun component7 ()Ljava/lang/String;
608+
public final fun component8 ()Ljava/util/Map;
609+
public final fun component9 ()Ljava/util/Map;
610+
public final fun copy (Lio/getstream/chat/android/models/FilterObject;IILio/getstream/chat/android/models/querysort/QuerySorter;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)Lio/getstream/chat/android/client/api/models/QueryChannelsRequest;
611+
public static synthetic fun copy$default (Lio/getstream/chat/android/client/api/models/QueryChannelsRequest;Lio/getstream/chat/android/models/FilterObject;IILio/getstream/chat/android/models/querysort/QuerySorter;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;ILjava/lang/Object;)Lio/getstream/chat/android/client/api/models/QueryChannelsRequest;
595612
public fun equals (Ljava/lang/Object;)Z
596613
public final fun getFilter ()Lio/getstream/chat/android/models/FilterObject;
614+
public final fun getFilterValues ()Ljava/util/Map;
597615
public final fun getLimit ()I
598616
public final fun getMemberLimit ()Ljava/lang/Integer;
599617
public final fun getMessageLimit ()Ljava/lang/Integer;
600618
public final fun getOffset ()I
619+
public final fun getPredefinedFilter ()Ljava/lang/String;
601620
public fun getPresence ()Z
602621
public final fun getQuerySort ()Lio/getstream/chat/android/models/querysort/QuerySorter;
603622
public final fun getSort ()Ljava/util/List;
623+
public final fun getSortValues ()Ljava/util/Map;
604624
public fun getState ()Z
605625
public fun getWatch ()Z
606626
public fun hashCode ()I
@@ -3051,6 +3071,34 @@ public final class io/getstream/chat/android/client/internal/offline/repository/
30513071
public fun toString ()Ljava/lang/String;
30523072
}
30533073

3074+
public final class io/getstream/chat/android/client/internal/state/plugin/QueryChannelsIdentifier$Predefined : io/getstream/chat/android/client/internal/state/plugin/QueryChannelsIdentifier {
3075+
public fun <init> (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)V
3076+
public final fun component1 ()Ljava/lang/String;
3077+
public final fun component2 ()Ljava/util/Map;
3078+
public final fun component3 ()Ljava/util/Map;
3079+
public final fun copy (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)Lio/getstream/chat/android/client/internal/state/plugin/QueryChannelsIdentifier$Predefined;
3080+
public static synthetic fun copy$default (Lio/getstream/chat/android/client/internal/state/plugin/QueryChannelsIdentifier$Predefined;Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;ILjava/lang/Object;)Lio/getstream/chat/android/client/internal/state/plugin/QueryChannelsIdentifier$Predefined;
3081+
public fun equals (Ljava/lang/Object;)Z
3082+
public final fun getFilterValues ()Ljava/util/Map;
3083+
public final fun getName ()Ljava/lang/String;
3084+
public final fun getSortValues ()Ljava/util/Map;
3085+
public fun hashCode ()I
3086+
public fun toString ()Ljava/lang/String;
3087+
}
3088+
3089+
public final class io/getstream/chat/android/client/internal/state/plugin/QueryChannelsIdentifier$Standard : io/getstream/chat/android/client/internal/state/plugin/QueryChannelsIdentifier {
3090+
public fun <init> (Lio/getstream/chat/android/models/FilterObject;Lio/getstream/chat/android/models/querysort/QuerySorter;)V
3091+
public final fun component1 ()Lio/getstream/chat/android/models/FilterObject;
3092+
public final fun component2 ()Lio/getstream/chat/android/models/querysort/QuerySorter;
3093+
public final fun copy (Lio/getstream/chat/android/models/FilterObject;Lio/getstream/chat/android/models/querysort/QuerySorter;)Lio/getstream/chat/android/client/internal/state/plugin/QueryChannelsIdentifier$Standard;
3094+
public static synthetic fun copy$default (Lio/getstream/chat/android/client/internal/state/plugin/QueryChannelsIdentifier$Standard;Lio/getstream/chat/android/models/FilterObject;Lio/getstream/chat/android/models/querysort/QuerySorter;ILjava/lang/Object;)Lio/getstream/chat/android/client/internal/state/plugin/QueryChannelsIdentifier$Standard;
3095+
public fun equals (Ljava/lang/Object;)Z
3096+
public final fun getFilter ()Lio/getstream/chat/android/models/FilterObject;
3097+
public final fun getSort ()Lio/getstream/chat/android/models/querysort/QuerySorter;
3098+
public fun hashCode ()I
3099+
public fun toString ()Ljava/lang/String;
3100+
}
3101+
30543102
public final class io/getstream/chat/android/client/logger/ChatLogLevel : java/lang/Enum {
30553103
public static final field ALL Lio/getstream/chat/android/client/logger/ChatLogLevel;
30563104
public static final field DEBUG Lio/getstream/chat/android/client/logger/ChatLogLevel;
@@ -3275,13 +3323,24 @@ public final class io/getstream/chat/android/client/query/CreateChannelParams {
32753323

32763324
public final class io/getstream/chat/android/client/query/QueryChannelsSpec {
32773325
public fun <init> (Lio/getstream/chat/android/models/FilterObject;Lio/getstream/chat/android/models/querysort/QuerySorter;)V
3326+
public fun <init> (Lio/getstream/chat/android/models/FilterObject;Lio/getstream/chat/android/models/querysort/QuerySorter;Ljava/util/Set;Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)V
3327+
public synthetic fun <init> (Lio/getstream/chat/android/models/FilterObject;Lio/getstream/chat/android/models/querysort/QuerySorter;Ljava/util/Set;Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
32783328
public final fun component1 ()Lio/getstream/chat/android/models/FilterObject;
32793329
public final fun component2 ()Lio/getstream/chat/android/models/querysort/QuerySorter;
3330+
public final fun component3 ()Ljava/util/Set;
3331+
public final fun component4 ()Ljava/lang/String;
3332+
public final fun component5 ()Ljava/util/Map;
3333+
public final fun component6 ()Ljava/util/Map;
32803334
public final fun copy (Lio/getstream/chat/android/models/FilterObject;Lio/getstream/chat/android/models/querysort/QuerySorter;)Lio/getstream/chat/android/client/query/QueryChannelsSpec;
3335+
public final fun copy (Lio/getstream/chat/android/models/FilterObject;Lio/getstream/chat/android/models/querysort/QuerySorter;Ljava/util/Set;Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)Lio/getstream/chat/android/client/query/QueryChannelsSpec;
32813336
public static synthetic fun copy$default (Lio/getstream/chat/android/client/query/QueryChannelsSpec;Lio/getstream/chat/android/models/FilterObject;Lio/getstream/chat/android/models/querysort/QuerySorter;ILjava/lang/Object;)Lio/getstream/chat/android/client/query/QueryChannelsSpec;
3337+
public static synthetic fun copy$default (Lio/getstream/chat/android/client/query/QueryChannelsSpec;Lio/getstream/chat/android/models/FilterObject;Lio/getstream/chat/android/models/querysort/QuerySorter;Ljava/util/Set;Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;ILjava/lang/Object;)Lio/getstream/chat/android/client/query/QueryChannelsSpec;
32823338
public fun equals (Ljava/lang/Object;)Z
32833339
public final fun getCids ()Ljava/util/Set;
32843340
public final fun getFilter ()Lio/getstream/chat/android/models/FilterObject;
3341+
public final fun getPredefinedFilterName ()Ljava/lang/String;
3342+
public final fun getPredefinedFilterValues ()Ljava/util/Map;
3343+
public final fun getPredefinedSortValues ()Ljava/util/Map;
32853344
public final fun getQuerySort ()Lio/getstream/chat/android/models/querysort/QuerySorter;
32863345
public fun hashCode ()I
32873346
public final fun setCids (Ljava/util/Set;)V

stream-chat-android-client/src/main/java/io/getstream/chat/android/client/ChatClient.kt

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import io.getstream.chat.android.client.api.models.GetThreadOptions
3535
import io.getstream.chat.android.client.api.models.PinnedMessagesPagination
3636
import io.getstream.chat.android.client.api.models.QueryChannelRequest
3737
import io.getstream.chat.android.client.api.models.QueryChannelsRequest
38+
import io.getstream.chat.android.client.api.models.QueryChannelsResult
3839
import io.getstream.chat.android.client.api.models.QueryThreadsRequest
3940
import io.getstream.chat.android.client.api.models.QueryUsersRequest
4041
import io.getstream.chat.android.client.api.models.SendActionRequest
@@ -2973,7 +2974,7 @@ internal constructor(
29732974
*/
29742975
@CheckResult
29752976
@InternalStreamChatApi
2976-
public fun queryChannelsInternal(request: QueryChannelsRequest): Call<List<Channel>> {
2977+
public fun queryChannelsInternal(request: QueryChannelsRequest): Call<QueryChannelsResult> {
29772978
return api.queryChannels(request)
29782979
}
29792980

@@ -3001,7 +3002,7 @@ internal constructor(
30013002
this.watch = false
30023003
this.state = state
30033004
}
3004-
when (val result = api.queryChannels(request).await()) {
3005+
when (val result = api.queryChannels(request).map { it.channels }.await()) {
30053006
is Result.Success -> {
30063007
val channels = result.value
30073008
if (channels.isEmpty()) {
@@ -3112,7 +3113,7 @@ internal constructor(
31123113
@CheckResult
31133114
public fun queryChannels(request: QueryChannelsRequest): Call<List<Channel>> {
31143115
logger.d { "[queryChannels] offset: ${request.offset}, limit: ${request.limit}" }
3115-
return queryChannelsInternal(request = request).doOnStart(userScope) {
3116+
return api.queryChannels(request).doOnStart(userScope) {
31163117
plugins.forEach { listener ->
31173118
logger.v { "[queryChannels] #doOnStart; plugin: ${listener::class.qualifiedName}" }
31183119
listener.onQueryChannelsRequest(request)
@@ -3124,6 +3125,8 @@ internal constructor(
31243125
}
31253126
}.precondition(plugins) {
31263127
onQueryChannelsPrecondition(request)
3128+
}.map {
3129+
it.channels
31273130
}.share(userScope) {
31283131
QueryChannelsIdentifier(request)
31293132
}

stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api/ChatApi.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import io.getstream.chat.android.client.api.models.GetThreadOptions
2121
import io.getstream.chat.android.client.api.models.PinnedMessagesPagination
2222
import io.getstream.chat.android.client.api.models.QueryChannelRequest
2323
import io.getstream.chat.android.client.api.models.QueryChannelsRequest
24+
import io.getstream.chat.android.client.api.models.QueryChannelsResult
2425
import io.getstream.chat.android.client.api.models.QueryThreadsRequest
2526
import io.getstream.chat.android.client.api.models.QueryUsersRequest
2627
import io.getstream.chat.android.client.api.models.SendActionRequest
@@ -285,7 +286,7 @@ internal interface ChatApi {
285286
): Call<List<Message>>
286287

287288
@CheckResult
288-
fun queryChannels(query: QueryChannelsRequest): Call<List<Channel>>
289+
fun queryChannels(query: QueryChannelsRequest): Call<QueryChannelsResult>
289290

290291
@CheckResult
291292
fun updateUsers(users: List<User>): Call<List<User>>

stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api/internal/DistinctChatApi.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import io.getstream.chat.android.client.api.ChatApi
2020
import io.getstream.chat.android.client.api.models.PinnedMessagesPagination
2121
import io.getstream.chat.android.client.api.models.QueryChannelRequest
2222
import io.getstream.chat.android.client.api.models.QueryChannelsRequest
23+
import io.getstream.chat.android.client.api.models.QueryChannelsResult
2324
import io.getstream.chat.android.client.api2.optimisation.hash.ChannelQueryKey
2425
import io.getstream.chat.android.client.api2.optimisation.hash.GetNewerRepliesHash
2526
import io.getstream.chat.android.client.api2.optimisation.hash.GetPinnedMessagesHash
@@ -133,7 +134,7 @@ internal class DistinctChatApi(
133134
}
134135
}
135136

136-
override fun queryChannels(query: QueryChannelsRequest): Call<List<Channel>> {
137+
override fun queryChannels(query: QueryChannelsRequest): Call<QueryChannelsResult> {
137138
val uniqueKey = query.hashCode()
138139
StreamLog.d(TAG) { "[queryChannels] query: $query, uniqueKey: $uniqueKey" }
139140
return getOrCreate(uniqueKey) {

stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api/internal/DistinctChatApiEnabler.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import io.getstream.chat.android.client.api.ChatApi
2020
import io.getstream.chat.android.client.api.models.PinnedMessagesPagination
2121
import io.getstream.chat.android.client.api.models.QueryChannelRequest
2222
import io.getstream.chat.android.client.api.models.QueryChannelsRequest
23+
import io.getstream.chat.android.client.api.models.QueryChannelsResult
2324
import io.getstream.chat.android.models.BannedUser
2425
import io.getstream.chat.android.models.BannedUsersSort
2526
import io.getstream.chat.android.models.Channel
@@ -77,7 +78,7 @@ internal class DistinctChatApiEnabler(
7778
return getApi().getPinnedMessages(channelType, channelId, limit, sort, pagination)
7879
}
7980

80-
override fun queryChannels(query: QueryChannelsRequest): Call<List<Channel>> {
81+
override fun queryChannels(query: QueryChannelsRequest): Call<QueryChannelsResult> {
8182
return getApi().queryChannels(query)
8283
}
8384

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright (c) 2014-2026 Stream.io Inc. All rights reserved.
3+
*
4+
* Licensed under the Stream License;
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://github.com/GetStream/stream-chat-android/blob/main/LICENSE
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.getstream.chat.android.client.api.models
18+
19+
import io.getstream.chat.android.core.internal.InternalStreamChatApi
20+
import io.getstream.chat.android.models.Channel
21+
import io.getstream.chat.android.models.FilterObject
22+
import io.getstream.chat.android.models.querysort.QuerySorter
23+
24+
/**
25+
* Represents a predefined filter parsed by the backend.
26+
*
27+
* @param filter The parsed filter specification.
28+
* @param sort The parsed sort specification, or locally calculated fallback if null.
29+
*/
30+
@InternalStreamChatApi
31+
public data class PredefinedFilter(
32+
val filter: FilterObject,
33+
val sort: QuerySorter<Channel>,
34+
)

0 commit comments

Comments
 (0)