Skip to content

Commit 6b47a72

Browse files
authored
feat(llc, samples): basic stories implementation (#50)
1 parent 11b075c commit 6b47a72

File tree

16 files changed

+815
-88
lines changed

16 files changed

+815
-88
lines changed

packages/stream_feeds/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
## unreleased
22
- Update follower and following counts on the feed state when receiving follow websocket events.
33
- Fix FeedsReactionData id for updating reactions in the feed state.
4+
- Improvement for stories and minor updates to other AggregatedActivity state updates.
45

56
## 0.3.1
67
- Update API client with renaming `addReaction` to `addActivityReaction` and `deleteReaction` to `deleteActivityReaction`.

packages/stream_feeds/lib/src/models/activity_data.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class ActivityData with _$ActivityData {
3838
this.filterTags = const [],
3939
required this.id,
4040
this.interestTags = const [],
41+
this.isWatched,
4142
this.latestReactions = const [],
4243
this.location,
4344
this.mentionedUsers = const [],
@@ -114,6 +115,10 @@ class ActivityData with _$ActivityData {
114115
@override
115116
final List<String> interestTags;
116117

118+
/// Whether the activity was watched by the current user. Relevant for stories.
119+
@override
120+
final bool? isWatched;
121+
117122
/// The most recent reactions added to the activity.
118123
@override
119124
final List<FeedsReactionData> latestReactions;
@@ -254,6 +259,7 @@ extension ActivityResponseMapper on ActivityResponse {
254259
filterTags: filterTags,
255260
id: id,
256261
interestTags: interestTags,
262+
isWatched: isWatched,
257263
latestReactions: [...latestReactions.map((r) => r.toModel())],
258264
location: location,
259265
mentionedUsers: [...mentionedUsers.map((u) => u.toModel())],

packages/stream_feeds/lib/src/models/activity_data.freezed.dart

Lines changed: 11 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/stream_feeds/lib/src/state/event/feed_event_handler.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,14 @@ class FeedEventHandler with FeedCapabilitiesMixin implements StateEventHandler {
204204
if (event is api.FeedMemberRemovedEvent) return;
205205
if (event is api.FeedMemberUpdatedEvent) return;
206206

207+
if (event is api.StoriesFeedUpdatedEvent) {
208+
if (event.fid != fid.rawValue) return;
209+
210+
return state.onAggregatedActivitiesUpdated(
211+
event.aggregatedActivities?.map((it) => it.toModel()).toList(),
212+
);
213+
}
214+
207215
// Handle other events if necessary
208216
}
209217
}

packages/stream_feeds/lib/src/state/feed.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,7 @@ class Feed with Disposable {
451451
(feedData) {
452452
_stateNotifier.onQueryMoreActivities(
453453
feedData.activities,
454+
feedData.aggregatedActivities,
454455
feedData.activitiesQueryConfig,
455456
);
456457

packages/stream_feeds/lib/src/state/feed_state.dart

Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,21 +83,27 @@ class FeedStateNotifier extends StateNotifier<FeedState> {
8383

8484
/// Handles the result of a query for more activities.
8585
void onQueryMoreActivities(
86-
PaginationResult<ActivityData> result,
86+
PaginationResult<ActivityData> activities,
87+
List<AggregatedActivityData> aggregatedActivities,
8788
QueryConfiguration<ActivityData> queryConfig,
8889
) {
8990
_activitiesQueryConfig = queryConfig;
9091

9192
// Merge the new activities with the existing ones
9293
final updatedActivities = state.activities.merge(
93-
result.items,
94+
activities.items,
9495
key: (it) => it.id,
9596
compare: activitiesSort.compare,
9697
);
98+
final updatedAggregatedActivities = state.aggregatedActivities.merge(
99+
aggregatedActivities,
100+
key: (it) => it.group,
101+
);
97102

98103
state = state.copyWith(
99104
activities: updatedActivities,
100-
activitiesPagination: result.pagination,
105+
aggregatedActivities: updatedAggregatedActivities,
106+
activitiesPagination: activities.pagination,
101107
);
102108
}
103109

@@ -188,6 +194,8 @@ class FeedStateNotifier extends StateNotifier<FeedState> {
188194
markRead: (read) => _markRead(read, state),
189195
// If markSeen contains specific IDs, mark those as seen
190196
markSeen: (seen) => _markSeen(seen, state),
197+
// If markWatched contains specific IDs, mark those as watched
198+
markWatched: (watched) => _markWatched(watched, state),
191199
// For other cases, return the current state without changes
192200
orElse: (MarkActivityData data) => state,
193201
);
@@ -199,14 +207,27 @@ class FeedStateNotifier extends StateNotifier<FeedState> {
199207
NotificationStatusResponse? notificationStatus,
200208
) {
201209
// Update the aggregated activities and notification status in the state
202-
final updatedAggregatedActivities = [...?aggregatedActivities];
210+
final updatedAggregatedActivities = state.aggregatedActivities.merge(
211+
aggregatedActivities ?? [],
212+
key: (it) => it.group,
213+
);
203214

204215
state = state.copyWith(
205216
aggregatedActivities: updatedAggregatedActivities,
206217
notificationStatus: notificationStatus,
207218
);
208219
}
209220

221+
void onAggregatedActivitiesUpdated(
222+
List<AggregatedActivityData>? aggregatedActivities,
223+
) {
224+
final updatedAggregatedActivities = state.aggregatedActivities.merge(
225+
aggregatedActivities ?? [],
226+
key: (it) => it.group,
227+
);
228+
state = state.copyWith(aggregatedActivities: updatedAggregatedActivities);
229+
}
230+
210231
/// Handles updates to the feed state when a bookmark is added or removed.
211232
void onBookmarkAdded(BookmarkData bookmark) {
212233
// Add or update the bookmark in the activity
@@ -477,6 +498,37 @@ class FeedStateNotifier extends StateNotifier<FeedState> {
477498
return state.copyWith(notificationStatus: updatedNotificationStatus);
478499
}
479500

501+
FeedState _markWatched(Set<String> watchedIds, FeedState state) {
502+
final activities = _markWatchedActivities(watchedIds, state.activities);
503+
504+
final aggregatedActivities =
505+
state.aggregatedActivities.map((aggregatedActivity) {
506+
return aggregatedActivity.copyWith(
507+
activities: _markWatchedActivities(
508+
watchedIds,
509+
aggregatedActivity.activities,
510+
),
511+
);
512+
}).toList();
513+
514+
return state.copyWith(
515+
activities: activities,
516+
aggregatedActivities: aggregatedActivities,
517+
);
518+
}
519+
520+
List<ActivityData> _markWatchedActivities(
521+
Set<String> watchedIds,
522+
List<ActivityData> activities,
523+
) {
524+
return activities.map((activity) {
525+
if (watchedIds.contains(activity.id)) {
526+
return activity.copyWith(isWatched: true);
527+
}
528+
return activity;
529+
}).toList();
530+
}
531+
480532
@override
481533
void dispose() {
482534
_removeMemberListListener?.call();
@@ -549,7 +601,7 @@ class FeedState with _$FeedState {
549601
@override
550602
final NotificationStatusResponse? notificationStatus;
551603

552-
/// Pagination information for activities queries.
604+
/// Pagination information for [activities] and [aggregatedActivities] queries.
553605
@override
554606
final PaginationData? activitiesPagination;
555607

0 commit comments

Comments
 (0)