Skip to content

Commit 374ff78

Browse files
authored
Handle stories_feed.updated & change handling of notification_feed.updated (#113)
1 parent 519dc03 commit 374ff78

File tree

6 files changed

+124
-18
lines changed

6 files changed

+124
-18
lines changed

stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/FeedStateImpl.kt

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -298,10 +298,20 @@ internal class FeedStateImpl(
298298
aggregatedActivities: List<AggregatedActivityData>,
299299
notificationStatus: NotificationStatusResponse?,
300300
) {
301-
_aggregatedActivities.update { aggregatedActivities }
301+
updateAggregatedActivities(aggregatedActivities)
302302
_notificationStatus.update { notificationStatus }
303303
}
304304

305+
override fun onStoriesFeedUpdated(aggregatedActivities: List<AggregatedActivityData>) {
306+
updateAggregatedActivities(aggregatedActivities)
307+
}
308+
309+
private fun updateAggregatedActivities(aggregatedActivities: List<AggregatedActivityData>) {
310+
val updatedMap = aggregatedActivities.associateBy(AggregatedActivityData::group)
311+
312+
_aggregatedActivities.update { current -> current.map { updatedMap[it.group] ?: it } }
313+
}
314+
305315
private fun addFollow(follow: FollowData) {
306316
if (follow.isFollowRequest) {
307317
_followRequests.update { it.upsert(follow, FollowData::id) }
@@ -438,11 +448,20 @@ internal interface FeedStateUpdates {
438448
/**
439449
* Handles updates to a notification feed.
440450
*
441-
* @param aggregatedActivities The list of aggregated activities in the notification feed.
451+
* @param aggregatedActivities The list of aggregated activities that were updated in the
452+
* notification feed.
442453
* @param notificationStatus The current notification status.
443454
*/
444455
fun onNotificationFeedUpdated(
445456
aggregatedActivities: List<AggregatedActivityData>,
446457
notificationStatus: NotificationStatusResponse?,
447458
)
459+
460+
/**
461+
* Handles updates to a stories feed.
462+
*
463+
* @param aggregatedActivities The list of aggregated activities that were updated in the
464+
* stories feed.
465+
*/
466+
fun onStoriesFeedUpdated(aggregatedActivities: List<AggregatedActivityData>)
448467
}

stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/StateUpdateEvent.kt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ import io.getstream.feeds.android.network.models.PollUpdatedFeedEvent
6666
import io.getstream.feeds.android.network.models.PollVoteCastedFeedEvent
6767
import io.getstream.feeds.android.network.models.PollVoteChangedFeedEvent
6868
import io.getstream.feeds.android.network.models.PollVoteRemovedFeedEvent
69+
import io.getstream.feeds.android.network.models.StoriesFeedUpdatedEvent
6970
import io.getstream.feeds.android.network.models.WSEvent
7071

7172
/**
@@ -161,6 +162,11 @@ internal sealed interface StateUpdateEvent {
161162
val notificationStatus: NotificationStatusResponse?,
162163
) : StateUpdateEvent
163164

165+
data class StoriesFeedUpdated(
166+
val fid: String,
167+
val aggregatedActivities: List<AggregatedActivityData>,
168+
) : StateUpdateEvent
169+
164170
data class PollDeleted(val fid: String, val pollId: String) : StateUpdateEvent
165171

166172
data class PollUpdated(val fid: String, val poll: PollData) : StateUpdateEvent
@@ -244,6 +250,13 @@ internal fun WSEvent.toModel(): StateUpdateEvent? =
244250
notificationStatus = notificationStatus,
245251
)
246252

253+
is StoriesFeedUpdatedEvent ->
254+
StateUpdateEvent.StoriesFeedUpdated(
255+
fid = fid,
256+
aggregatedActivities =
257+
aggregatedActivities?.map(AggregatedActivityResponse::toModel).orEmpty(),
258+
)
259+
247260
is FeedMemberAddedEvent -> StateUpdateEvent.FeedMemberAdded(fid, member.toModel())
248261

249262
is FeedMemberRemovedEvent -> StateUpdateEvent.FeedMemberRemoved(fid, memberId)

stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/FeedEventHandler.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,12 @@ internal class FeedEventHandler(private val fid: FeedId, private val state: Feed
180180
}
181181
}
182182

183+
is StateUpdateEvent.StoriesFeedUpdated -> {
184+
if (event.fid == fid.rawValue) {
185+
state.onStoriesFeedUpdated(event.aggregatedActivities)
186+
}
187+
}
188+
183189
is StateUpdateEvent.PollDeleted -> {
184190
if (event.fid == fid.rawValue) {
185191
state.onPollDeleted(event.pollId)

stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/FeedStateImplTest.kt

Lines changed: 63 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package io.getstream.feeds.android.client.internal.state
1818
import io.getstream.android.core.api.filter.equal
1919
import io.getstream.feeds.android.client.api.model.ActivityData
2020
import io.getstream.feeds.android.client.api.model.ActivityPinData
21+
import io.getstream.feeds.android.client.api.model.AggregatedActivityData
2122
import io.getstream.feeds.android.client.api.model.FeedData
2223
import io.getstream.feeds.android.client.api.model.FeedId
2324
import io.getstream.feeds.android.client.api.model.FollowData
@@ -570,24 +571,67 @@ internal class FeedStateImplTest {
570571
}
571572

572573
@Test
573-
fun `on onNotificationFeedUpdated, update aggregated activities and notification status`() =
574-
runTest {
575-
val aggregatedActivities =
576-
listOf(
577-
aggregatedActivityData(
578-
activities = listOf(activityData("activity-1")),
579-
activityCount = 2,
580-
group = "group-1",
581-
userCount = 2,
582-
)
574+
fun `on onNotificationFeedUpdated, update matching groups and notification status`() = runTest {
575+
val initial =
576+
List(3) {
577+
aggregatedActivityData(
578+
activities = listOf(activityData("activity-$it")),
579+
activityCount = it,
580+
group = "group-$it",
581+
userCount = it,
583582
)
584-
val notificationStatus = NotificationStatusResponse(unread = 5, unseen = 3)
583+
}
585584

586-
feedState.onNotificationFeedUpdated(aggregatedActivities, notificationStatus)
585+
setupInitialState(aggregatedActivities = initial)
587586

588-
assertEquals(aggregatedActivities, feedState.aggregatedActivities.value)
589-
assertEquals(notificationStatus, feedState.notificationStatus.value)
590-
}
587+
val updated =
588+
aggregatedActivityData(
589+
activities = listOf(activityData("activity-1-updated")),
590+
activityCount = 5,
591+
group = "group-1",
592+
userCount = 5,
593+
)
594+
val notificationStatus = NotificationStatusResponse(unread = 5, unseen = 3)
595+
596+
feedState.onNotificationFeedUpdated(listOf(updated), notificationStatus)
597+
598+
assertEquals(listOf(initial[0], updated, initial[2]), feedState.aggregatedActivities.value)
599+
assertEquals(notificationStatus, feedState.notificationStatus.value)
600+
}
601+
602+
@Test
603+
fun `on onStoriesFeedUpdated, update matching groups`() = runTest {
604+
val initial =
605+
List(3) {
606+
aggregatedActivityData(
607+
activities = listOf(activityData("story-$it")),
608+
activityCount = it,
609+
group = "story-group-$it",
610+
userCount = it,
611+
)
612+
}
613+
614+
setupInitialState(aggregatedActivities = initial)
615+
616+
val updated0 =
617+
aggregatedActivityData(
618+
activities = listOf(activityData("story-0-updated")),
619+
activityCount = 10,
620+
group = "story-group-0",
621+
userCount = 10,
622+
)
623+
val updated2 =
624+
aggregatedActivityData(
625+
activities = listOf(activityData("story-2-updated")),
626+
activityCount = 30,
627+
group = "story-group-2",
628+
userCount = 30,
629+
)
630+
631+
feedState.onStoriesFeedUpdated(listOf(updated0, updated2))
632+
633+
assertEquals(listOf(updated0, initial[1], updated2), feedState.aggregatedActivities.value)
634+
}
591635

592636
// Helper functions
593637
private fun setupInitialState(
@@ -597,6 +641,7 @@ internal class FeedStateImplTest {
597641
followers: List<FollowData> = emptyList(),
598642
following: List<FollowData> = emptyList(),
599643
followRequests: List<FollowData> = emptyList(),
644+
aggregatedActivities: List<AggregatedActivityData> = emptyList(),
600645
) {
601646
val result =
602647
createGetOrCreateInfo(
@@ -606,6 +651,7 @@ internal class FeedStateImplTest {
606651
followers = followers,
607652
following = following,
608653
followRequests = followRequests,
654+
aggregatedActivities = aggregatedActivities,
609655
)
610656
feedState.onQueryFeed(result)
611657
}
@@ -617,6 +663,7 @@ internal class FeedStateImplTest {
617663
following: List<FollowData> = emptyList(),
618664
followRequests: List<FollowData> = emptyList(),
619665
pinnedActivities: List<ActivityPinData> = emptyList(),
666+
aggregatedActivities: List<AggregatedActivityData> = emptyList(),
620667
): GetOrCreateInfo {
621668
val paginationResult =
622669
PaginationResult(
@@ -633,7 +680,7 @@ internal class FeedStateImplTest {
633680
following = following,
634681
followRequests = followRequests,
635682
pinnedActivities = pinnedActivities,
636-
aggregatedActivities = emptyList(),
683+
aggregatedActivities = aggregatedActivities,
637684
notificationStatus = null,
638685
members =
639686
PaginationResult(

stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/StateUpdateEventToModelTest.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ import io.getstream.feeds.android.network.models.PollUpdatedFeedEvent
5050
import io.getstream.feeds.android.network.models.PollVoteCastedFeedEvent
5151
import io.getstream.feeds.android.network.models.PollVoteChangedFeedEvent
5252
import io.getstream.feeds.android.network.models.PollVoteRemovedFeedEvent
53+
import io.getstream.feeds.android.network.models.StoriesFeedUpdatedEvent
5354
import io.getstream.feeds.android.network.models.WSEvent
5455
import java.util.Date
5556
import kotlin.reflect.KClass
@@ -103,6 +104,7 @@ internal class StateUpdateEventToModelTest(
103104
followUpdated().shouldMapTo<StateUpdateEvent.FollowUpdated>(),
104105
followDeleted().shouldMapTo<StateUpdateEvent.FollowDeleted>(),
105106
notificationFeedUpdated().shouldMapTo<StateUpdateEvent.NotificationFeedUpdated>(),
107+
storiesFeedUpdated().shouldMapTo<StateUpdateEvent.StoriesFeedUpdated>(),
106108
feedMemberAdded().shouldMapTo<StateUpdateEvent.FeedMemberAdded>(),
107109
feedMemberRemoved().shouldMapTo<StateUpdateEvent.FeedMemberRemoved>(),
108110
feedMemberUpdated().shouldMapTo<StateUpdateEvent.FeedMemberUpdated>(),
@@ -306,6 +308,14 @@ internal class StateUpdateEventToModelTest(
306308
type = "notification_feed.updated",
307309
)
308310

311+
private fun storiesFeedUpdated() =
312+
StoriesFeedUpdatedEvent(
313+
createdAt = Date(1000),
314+
fid = "group:feed",
315+
aggregatedActivities = emptyList(),
316+
type = "stories_feed.updated",
317+
)
318+
309319
private fun feedMemberAdded() =
310320
FeedMemberAddedEvent(
311321
createdAt = Date(1000),

stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/FeedEventHandlerTest.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ import io.getstream.feeds.android.client.internal.state.event.StateUpdateEvent.P
4848
import io.getstream.feeds.android.client.internal.state.event.StateUpdateEvent.PollVoteCasted
4949
import io.getstream.feeds.android.client.internal.state.event.StateUpdateEvent.PollVoteChanged
5050
import io.getstream.feeds.android.client.internal.state.event.StateUpdateEvent.PollVoteRemoved
51+
import io.getstream.feeds.android.client.internal.state.event.StateUpdateEvent.StoriesFeedUpdated
5152
import io.getstream.feeds.android.client.internal.test.TestData.activityData
5253
import io.getstream.feeds.android.client.internal.test.TestData.activityPin
5354
import io.getstream.feeds.android.client.internal.test.TestData.bookmarkData
@@ -359,6 +360,16 @@ internal class FeedEventHandlerTest(
359360
),
360361
verifyBlock = { state -> state wasNot called },
361362
),
363+
testParams<FeedStateUpdates>(
364+
name = "StoriesFeedUpdated matching feed",
365+
event = StoriesFeedUpdated(fid.rawValue, aggregatedActivities),
366+
verifyBlock = { state -> state.onStoriesFeedUpdated(aggregatedActivities) },
367+
),
368+
testParams<FeedStateUpdates>(
369+
name = "StoriesFeedUpdated non-matching feed",
370+
event = StoriesFeedUpdated("group:different", aggregatedActivities),
371+
verifyBlock = { state -> state wasNot called },
372+
),
362373
testParams<FeedStateUpdates>(
363374
name = "PollDeleted matching feed",
364375
event = PollDeleted(fid.rawValue, pollId),

0 commit comments

Comments
 (0)