diff --git a/stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/FeedStateImpl.kt b/stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/FeedStateImpl.kt index eacc217c9..8d105cd31 100644 --- a/stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/FeedStateImpl.kt +++ b/stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/FeedStateImpl.kt @@ -307,10 +307,22 @@ internal class FeedStateImpl( _notificationStatus.update { notificationStatus } } - override fun onStoriesFeedUpdated(aggregatedActivities: List) { + override fun onStoriesFeedUpdated( + activities: List, + aggregatedActivities: List, + ) { + updateActivities(activities) updateAggregatedActivities(aggregatedActivities) } + private fun updateActivities(activities: List) { + val updatedMap = activities.associateBy(ActivityData::id) + + updateActivitiesWhere({ it.id in updatedMap }) { activity -> + updatedMap[activity.id]?.let(activity::update) ?: activity + } + } + private fun updateAggregatedActivities(aggregatedActivities: List) { val updatedMap = aggregatedActivities.associateBy(AggregatedActivityData::group) @@ -470,8 +482,12 @@ internal interface FeedStateUpdates { /** * Handles updates to a stories feed. * + * @param activities The list of activities that were updated in the stories feed. * @param aggregatedActivities The list of aggregated activities that were updated in the * stories feed. */ - fun onStoriesFeedUpdated(aggregatedActivities: List) + fun onStoriesFeedUpdated( + activities: List, + aggregatedActivities: List, + ) } diff --git a/stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/StateUpdateEvent.kt b/stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/StateUpdateEvent.kt index fa551c809..28f9a5080 100644 --- a/stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/StateUpdateEvent.kt +++ b/stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/StateUpdateEvent.kt @@ -36,6 +36,7 @@ import io.getstream.feeds.android.network.models.ActivityReactionAddedEvent import io.getstream.feeds.android.network.models.ActivityReactionDeletedEvent import io.getstream.feeds.android.network.models.ActivityReactionUpdatedEvent import io.getstream.feeds.android.network.models.ActivityRemovedFromFeedEvent +import io.getstream.feeds.android.network.models.ActivityResponse import io.getstream.feeds.android.network.models.ActivityUnpinnedEvent import io.getstream.feeds.android.network.models.ActivityUpdatedEvent import io.getstream.feeds.android.network.models.AggregatedActivityResponse @@ -157,6 +158,7 @@ internal sealed interface StateUpdateEvent { data class StoriesFeedUpdated( val fid: String, + val activities: List, val aggregatedActivities: List, ) : StateUpdateEvent @@ -268,6 +270,7 @@ internal fun WSEvent.toModel(): StateUpdateEvent? = is StoriesFeedUpdatedEvent -> StateUpdateEvent.StoriesFeedUpdated( fid = fid, + activities = activities?.map(ActivityResponse::toModel).orEmpty(), aggregatedActivities = aggregatedActivities?.map(AggregatedActivityResponse::toModel).orEmpty(), ) diff --git a/stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/FeedEventHandler.kt b/stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/FeedEventHandler.kt index 43cd005c9..772578708 100644 --- a/stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/FeedEventHandler.kt +++ b/stream-feeds-android-client/src/main/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/FeedEventHandler.kt @@ -191,7 +191,7 @@ internal class FeedEventHandler( is StateUpdateEvent.StoriesFeedUpdated -> { if (event.fid == fid.rawValue) { - state.onStoriesFeedUpdated(event.aggregatedActivities) + state.onStoriesFeedUpdated(event.activities, event.aggregatedActivities) } } diff --git a/stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/FeedStateImplTest.kt b/stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/FeedStateImplTest.kt index d3c562855..5c4336db5 100644 --- a/stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/FeedStateImplTest.kt +++ b/stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/FeedStateImplTest.kt @@ -518,8 +518,9 @@ internal class FeedStateImplTest { } @Test - fun `on onStoriesFeedUpdated, update matching groups`() = runTest { - val initial = + fun `on onStoriesFeedUpdated, update matching activities and groups`() = runTest { + val initialActivities = List(3) { activityData("story-$it") } + val initialAggregated = List(3) { aggregatedActivityData( activities = listOf(activityData("story-$it")), @@ -528,17 +529,18 @@ internal class FeedStateImplTest { userCount = it, ) } + setupInitialState(activities = initialActivities, aggregatedActivities = initialAggregated) - setupInitialState(aggregatedActivities = initial) - - val updated0 = + val updatedActivity0 = activityData("story-0", text = "Updated 0") + val updatedActivity2 = activityData("story-2", text = "Updated 2") + val updatedAggregated0 = aggregatedActivityData( activities = listOf(activityData("story-0-updated")), activityCount = 10, group = "story-group-0", userCount = 10, ) - val updated2 = + val updatedAggregated2 = aggregatedActivityData( activities = listOf(activityData("story-2-updated")), activityCount = 30, @@ -546,9 +548,19 @@ internal class FeedStateImplTest { userCount = 30, ) - feedState.onStoriesFeedUpdated(listOf(updated0, updated2)) + feedState.onStoriesFeedUpdated( + listOf(updatedActivity0, updatedActivity2), + listOf(updatedAggregated0, updatedAggregated2), + ) - assertEquals(listOf(updated0, initial[1], updated2), feedState.aggregatedActivities.value) + assertEquals( + listOf(updatedActivity0, initialActivities[1], updatedActivity2), + feedState.activities.value, + ) + assertEquals( + listOf(updatedAggregated0, initialAggregated[1], updatedAggregated2), + feedState.aggregatedActivities.value, + ) } // Helper functions diff --git a/stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/FeedEventHandlerTest.kt b/stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/FeedEventHandlerTest.kt index d1726dd4a..03174f046 100644 --- a/stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/FeedEventHandlerTest.kt +++ b/stream-feeds-android-client/src/test/kotlin/io/getstream/feeds/android/client/internal/state/event/handler/FeedEventHandlerTest.kt @@ -93,6 +93,7 @@ internal class FeedEventHandlerTest( private val matchingFollow = followData(sourceFid = fid.rawValue) private val nonMatchingFollow = followData(sourceFid = "other:feed", targetFid = "another:feed") + private val activities = listOf(activity) private val aggregatedActivities = listOf( AggregatedActivityData( @@ -364,12 +365,14 @@ internal class FeedEventHandlerTest( ), testParams( name = "StoriesFeedUpdated matching feed", - event = StoriesFeedUpdated(fid.rawValue, aggregatedActivities), - verifyBlock = { state -> state.onStoriesFeedUpdated(aggregatedActivities) }, + event = StoriesFeedUpdated(fid.rawValue, activities, aggregatedActivities), + verifyBlock = { state -> + state.onStoriesFeedUpdated(activities, aggregatedActivities) + }, ), testParams( name = "StoriesFeedUpdated non-matching feed", - event = StoriesFeedUpdated("group:different", aggregatedActivities), + event = StoriesFeedUpdated("group:different", activities, aggregatedActivities), verifyBlock = { state -> state wasNot called }, ), testParams(