Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add pagination options to queryUsers #288

Merged
merged 1 commit into from May 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `Filter.custom` to be able to use new operators before our SDK is updated [#285](https://github.com/GetStream/stream-chat-swift/issues/285)
Please make sure to provide a valid operator.
Example: `.custom("contains", key: "teams", value: "red")`
- `queryUsers` now supports `Pagination.limit` and `Pagination.offset` [#288](https://github.com/GetStream/stream-chat-swift/issues/288)

# [2.2.1](https://github.com/GetStream/stream-chat-swift/releases/tag/2.2.1)
_May 19, 2020_
Expand Down
4 changes: 3 additions & 1 deletion Sources/Client/Client/Client+User.swift
Expand Up @@ -16,14 +16,16 @@ public extension Client {
/// - Parameters:
/// - filter: a users filter.
/// - sort: a sorting.
/// - pagination: Pagination for query. Only supports `.limit` and `.offset`
/// - options: a query options.
/// - completion: a completion block with `[User]`.
@discardableResult
func queryUsers(filter: Filter,
sort: Sorting? = nil,
pagination: Pagination = [.usersPageSize],
options: QueryOptions = [],
_ completion: @escaping Client.Completion<[User]>) -> Cancellable {
queryUsers(query: .init(filter: filter, sort: sort, options: options), completion)
queryUsers(query: .init(filter: filter, sort: sort, pagination: pagination, options: options), completion)
}

/// Requests users with a given query (see `UsersQuery`).
Expand Down
2 changes: 2 additions & 0 deletions Sources/Client/Model/Pagination.swift
Expand Up @@ -44,6 +44,8 @@ public extension KeyedEncodingContainer {
/// let pagination = Pagination.limit(50) + .lessThan("some_id")
/// ```
public enum PaginationOption: Encodable, Hashable {
/// Default queryUsers page size
public static let usersPageSize: Self = .limit(25)
/// A default channels page size.
public static let channelsPageSize: Self = .limit(20)
/// A default channels page sizefor the next page.
Expand Down
28 changes: 26 additions & 2 deletions Sources/Client/Model/User/UsersQuery.swift
Expand Up @@ -13,12 +13,16 @@ public struct UsersQuery: Encodable {
private enum CodingKeys: String, CodingKey {
case filter = "filter_conditions"
case sort
case limit
case offset
}

/// Filter conditions.
public let filter: Filter
/// Sort options, e.g. `.init("last_active", isAscending: false)`
public let sort: Sorting?
/// Used for paginating response.
public let pagination: Pagination
/// Query options, e.g. .presence
public let options: QueryOptions

Expand All @@ -27,17 +31,37 @@ public struct UsersQuery: Encodable {
/// - Parameters:
/// - filter: filter conditions, e.g. `"name".equal(to: "rover_curiosity")`
/// - sort: sort options, e.g. `.init("last_active", isAscending: false)`
/// - pagination: Pagination for query. Only supports `.limit` and `.offset`
/// - options: Query options, e.g. `.presence`
public init(filter: Filter, sort: Sorting? = nil, options: QueryOptions = []) {
public init(filter: Filter, sort: Sorting? = nil, pagination: Pagination = [.usersPageSize], options: QueryOptions = []) {
self.filter = filter
self.sort = sort
self.pagination = pagination
self.options = options

let invalidPaginations = pagination.filter({
switch $0 {
case .limit, .offset:
return false
default:
return true
}
})
if !invalidPaginations.isEmpty {
ClientLogger.log("⚠️",
level: .debug,
"queryUsers only supports .limit and .offset paginations. "
+ "You've supplied invalid paginations \(invalidPaginations) "
+ "These paginations will not take effect. "
+ "Break on \(#file) \(#line) to catch this issue.")
}
}

public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(filter, forKey: .filter)
try container.encodeIfPresent(sort, forKey: .sort)
try container.encodeIfPresent(pagination.limit, forKey: .limit)
try container.encodeIfPresent(pagination.offset, forKey: .offset)
try options.encode(to: encoder)
}
}
4 changes: 3 additions & 1 deletion Sources/Core/Client/Client+RxUser.swift
Expand Up @@ -18,11 +18,13 @@ public extension Reactive where Base == Client {
/// - Parameters:
/// - filter: a user filter.
/// - sort: a sorting.
/// - pagination: Pagination for query. Only supports `.limit` and `.offset`
/// - options: a query options.
func queryUsers(filter: Filter,
sort: Sorting? = nil,
pagination: Pagination = [.usersPageSize],
options: QueryOptions = []) -> Observable<[User]> {
queryUsers(query: .init(filter: filter, sort: sort, options: options))
queryUsers(query: .init(filter: filter, sort: sort, pagination: pagination, options: options))
}

/// Requests users with a given query (see `UsersQuery`).
Expand Down
3 changes: 2 additions & 1 deletion Tests/Client/Unit Tests/QueryEncodingTests.swift
Expand Up @@ -60,9 +60,10 @@ final class QueryEncodingTests: XCTestCase {
func testUsersQueryEncoding() {
let query = { UsersQuery(filter: self.complexFilter,
sort: .init("name", isAscending: true),
pagination: self.mediumPagination(),
options: .all) }

let expectedString = #"{"presence":true,"state":true,"watch":true,"sort":{"field":"name","direction":1},"filter_conditions":{"$and":[{"members":{"$in":["john"]}},{"unread_count":0},{"$or":[{"id":{"$gt":42}},{"$and":[{"avatar":{"$ne":"null"}},{"name":{"$autocomplete":"ro"}}]}]}]}}"#
let expectedString = #"{"filter_conditions":{"$and":[{"members":{"$in":["john"]}},{"unread_count":0},{"$or":[{"id":{"$gt":42}},{"$and":[{"avatar":{"$ne":"null"}},{"name":{"$autocomplete":"ro"}}]}]}]},"presence":true,"state":true,"offset":20,"watch":true,"limit":10}"#

AssertJSONEqual(Data(expectedString.utf8), try encode(query()))
}
Expand Down