Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
<a name="2.2.2"></a>
# [2.2.6](https://github.com/GetStream/stream-swift/releases/tag/2.2.3) - 16 Nov 2022

### ✅ Added
- Add `ActivityReactionsOptions` in `Client.get<T: ActivityProtocol>`. Enable ability to get activities with reaction data.

# [2.2.2](https://github.com/GetStream/stream-swift/releases/tag/2.2.2) - 24 Feb 2020

### 🐞 Fixed
Expand Down
57 changes: 52 additions & 5 deletions Sources/Core/Activity/ActivityEndpoint.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import Moya
public typealias Properties = [String: Encodable]

enum ActivityEndpoint<T: ActivityProtocol> {
case getByIds(_ enrich: Bool, _ activitiesIds: [String])
case getByIds(_ enrich: Bool, _ activitiesIds: [String], _ reactionsOptions: ActivityReactionsOptions)
case get(_ enrich: Bool, foreignIds: [String], times: [Date])
case update(_ activities: [T])
case updateActivityById(setProperties: Properties?, unsetPropertiesNames: [String]?, activityId: String)
Expand All @@ -27,7 +27,7 @@ extension ActivityEndpoint: StreamTargetType {

var path: String {
switch self {
case .getByIds(let enrich, _), .get(let enrich, _, _):
case .getByIds(let enrich, _, _), .get(let enrich, _, _):
return "\(enrich ? "enrich/" : "")activities/"
case .update:
return "activities/"
Expand All @@ -48,9 +48,25 @@ extension ActivityEndpoint: StreamTargetType {

var task: Task {
switch self {
case .getByIds(_, let ids):
case .getByIds(_, let ids, let reactionsOptions):
let ids = ids.map { $0 }.joined(separator: ",")
return .requestParameters(parameters: ["ids" : ids], encoding: URLEncoding.default)
var parameters: [String: Any] = [
ActivityEndpointParameters.ids.rawValue: ids
]

if reactionsOptions.contains(.own) {
parameters[ActivityEndpointParameters.withOwnReactions.rawValue] = true
}

if reactionsOptions.contains(.latest) {
parameters[ActivityEndpointParameters.withRecentReactions.rawValue] = true
}

if reactionsOptions.contains(.counts) {
parameters[ActivityEndpointParameters.withReactionCounts.rawValue] = true
}

return .requestParameters(parameters: parameters, encoding: URLEncoding.default)

case let .get(_, foreignIds: foreignIds, times: times):
return .requestParameters(parameters: idParameters(with: foreignIds, times: times), encoding: URLEncoding.default)
Expand All @@ -72,7 +88,7 @@ extension ActivityEndpoint: StreamTargetType {

var sampleJSON: String {
switch self {
case let .getByIds(enrich, activitiesIds):
case let .getByIds(enrich, activitiesIds, _):
let actorJSON = enrich
? "{\"id\":\"eric\",\"data\":{\"name\":\"Eric\"},\"updated_at\":\"2019-04-15T17:55:53.425\",\"created_at\":\"2019-04-15T17:55:53.425\"}"
: "\"eric\""
Expand Down Expand Up @@ -187,3 +203,34 @@ extension ActivityEndpoint {
return ["foreign_ids": foreignIds, "timestamps": times]
}
}

enum ActivityEndpointParameters: String {
case ids
case withRecentReactions
case withOwnReactions
case withReactionCounts
}

// MARK: - Reactions Option

/// A activity reaction options to include reaction for activities.
/// - Available options:
/// - `includeOwn`: include reactions added by current user to all activities.
/// - `includeRecent`: include recent reactions to activities.
/// - `includeCounts`: include reaction counts to activities.
public struct ActivityReactionsOptions: OptionSet {
public let rawValue: Int

public init(rawValue: Int) {
self.rawValue = rawValue
}

/// Include reactions added by current user to all activities.
public static let own = ActivityReactionsOptions(rawValue: 1 << 0)
/// Include recent reactions to activities.
public static let latest = ActivityReactionsOptions(rawValue: 1 << 1)
/// Include reaction counts to activities.
public static let counts = ActivityReactionsOptions(rawValue: 1 << 2)
/// Include all reactions options to activities.
public static let all: ActivityReactionsOptions = [.own, .latest, .counts]
}
10 changes: 8 additions & 2 deletions Sources/Core/Activity/Client+Activity.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,20 @@ public typealias ActivitiesCompletion<T: Decodable> = (_ result: Result<Response
extension Client {

/// Receive activities by activity ids with a custom activity type.
///
/// - Parameters:
/// - enrich: when using collections, you can request to enrich activities to include them.
/// - typeOf: custom activity type to decode to
/// - activityIds: activity ids
/// - reactionsOptions: options to include reactions to activities. Check options in docs for `ActivityReactionsOptions`
/// - completion: a completion handler with an array of the `Activity` type.
/// - Note: A maximum length of list of activityIds is 100.
@discardableResult
public func get<T: ActivityProtocol>(enrich: Bool = true,
typeOf type: T.Type,
activityIds: [String],
includeReactions reactionsOptions: ActivityReactionsOptions = [],
completion: @escaping ActivitiesCompletion<T>) -> Cancellable {
return request(endpoint: ActivityEndpoint<T>.getByIds(enrich, activityIds)) { [weak self] result in
return request(endpoint: ActivityEndpoint<T>.getByIds(enrich, activityIds, reactionsOptions)) { [weak self] result in
if let self = self {
result.parse(self.callbackQueue, completion)
}
Expand Down
37 changes: 36 additions & 1 deletion Tests/Core/ClientTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,45 @@ final class ClientTests: TestCase {
}

func testActivityBaseURL() {
let endpoint = ActivityEndpoint<SimpleActivity>.getByIds(true, [.test1])
let endpoint = ActivityEndpoint<SimpleActivity>.getByIds(true, [.test1], [])
XCTAssertEqual(endpoint.baseURL, BaseURL.placeholderURL)
}

func testActivityWithReactionOption() {
var endpoint = ActivityEndpoint<SimpleActivity>.getByIds(true, [.test1], [.all])
switch endpoint.task {
case .requestParameters(let parameter, _):
XCTAssertEqual(parameter[ActivityEndpointParameters.ids.rawValue] as? String, .test1)
XCTAssertEqual(parameter[ActivityEndpointParameters.withRecentReactions.rawValue] as? Bool, true)
XCTAssertEqual(parameter[ActivityEndpointParameters.withOwnReactions.rawValue] as? Bool, true)
XCTAssertEqual(parameter[ActivityEndpointParameters.withReactionCounts.rawValue] as? Bool, true)
default:
XCTFail("Should be request parameter")
}

endpoint = ActivityEndpoint<SimpleActivity>.getByIds(true, [.test1], [.counts])
switch endpoint.task {
case .requestParameters(let parameter, _):
XCTAssertEqual(parameter[ActivityEndpointParameters.ids.rawValue] as? String, .test1)
XCTAssertNil(parameter[ActivityEndpointParameters.withRecentReactions.rawValue])
XCTAssertNil(parameter[ActivityEndpointParameters.withOwnReactions.rawValue] )
XCTAssertEqual(parameter[ActivityEndpointParameters.withReactionCounts.rawValue] as? Bool, true)
default:
XCTFail("Should be request parameter")
}

endpoint = ActivityEndpoint<SimpleActivity>.getByIds(true, [.test1], [.counts, .latest])
switch endpoint.task {
case .requestParameters(let parameter, _):
XCTAssertEqual(parameter[ActivityEndpointParameters.ids.rawValue] as? String, .test1)
XCTAssertEqual(parameter[ActivityEndpointParameters.withRecentReactions.rawValue] as? Bool, true)
XCTAssertNil(parameter[ActivityEndpointParameters.withOwnReactions.rawValue])
XCTAssertEqual(parameter[ActivityEndpointParameters.withReactionCounts.rawValue] as? Bool, true)
default:
XCTFail("Should be request parameter")
}
}

func testClientActivityGetByIds() {
expect("get an enriched activity by id") { test in
Client.shared.get(enrich: true, typeOf: Activity.self, activityIds: [.test1, .test2]) { result in
Expand Down