Skip to content

Commit d63b14c

Browse files
authored
feat(llc): handle missing events (#71)
1 parent 2390fe4 commit d63b14c

File tree

72 files changed

+12248
-3365
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

72 files changed

+12248
-3365
lines changed

melos.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ command:
4848
shared_preferences: ^2.5.3
4949
state_notifier: ^1.0.0
5050
stream_feeds: ^0.5.0
51-
stream_core: ^0.3.2
51+
stream_core: ^0.3.3
5252
video_player: ^2.10.0
5353
uuid: ^4.5.1
5454

packages/stream_feeds/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
## Upcoming
2+
- Added missing state updates for the websocket events.
3+
14
## 0.5.0
25
- [BREAKING] Unified `ThreadedCommentData` into `CommentData` to handle both flat and threaded comments.
36
- [BREAKING] Renamed `ActivitiesFilterField.type` to `ActivitiesFilterField.activityType`.
Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
tags:
2-
feed:
3-
feed-list:
42
activity:
3+
activity-comment-list:
54
activity-list:
6-
bookmark-list:
5+
activity-reaction-list:
76
bookmark-folder-list:
7+
bookmark-list:
88
comment-list:
9+
comment-reaction-list:
10+
comment-reply-list:
11+
feed:
12+
feed-list:
913
follow-list:
14+
member-list:
15+
moderation-config-list:
1016
poll-list:
1117
poll-vote-list:

packages/stream_feeds/lib/src/client/feeds_client_impl.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,7 @@ class StreamFeedsClientImpl implements StreamFeedsClient {
388388
query: query,
389389
commentsRepository: _commentsRepository,
390390
eventsEmitter: events,
391+
currentUserId: user.id,
391392
);
392393
}
393394

@@ -444,6 +445,7 @@ class StreamFeedsClientImpl implements StreamFeedsClient {
444445
query: query,
445446
pollsRepository: _pollsRepository,
446447
eventsEmitter: events,
448+
currentUserId: user.id,
447449
);
448450
}
449451

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

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,22 @@ extension ActivityDataMutations on ActivityData {
341341
);
342342
}
343343

344+
/// Conditionally updates this activity based on a filter.
345+
///
346+
/// If [filter] returns true for this activity, applies the [update] function
347+
/// to produce a new updated activity. Otherwise, returns this activity unchanged.
348+
///
349+
/// This is useful for applying updates only when certain conditions are met.
350+
///
351+
/// Returns a new [ActivityData] instance, either updated or unchanged.
352+
ActivityData updateIf({
353+
required bool Function(ActivityData) filter,
354+
required ActivityData Function(ActivityData) update,
355+
}) {
356+
if (!filter(this)) return this;
357+
return update(this);
358+
}
359+
344360
/// Adds or updates a comment in this activity.
345361
///
346362
/// Updates the comments list by adding or updating [comment]. If the comment already
@@ -381,6 +397,75 @@ extension ActivityDataMutations on ActivityData {
381397
);
382398
}
383399

400+
/// Adds or updates a reaction in a comment within this activity with unique enforcement.
401+
///
402+
/// Updates the own reactions list of the comment by adding or updating [reaction]. Only adds reactions
403+
/// that belong to [currentUserId]. When unique enforcement is enabled, replaces any
404+
/// existing reaction from the same user.
405+
///
406+
/// Returns a new [ActivityData] instance with the updated comment reactions.
407+
ActivityData upsertUniqueCommentReaction(
408+
CommentData updatedComment,
409+
FeedsReactionData reaction,
410+
String currentUserId,
411+
) {
412+
return upsertCommentReaction(
413+
updatedComment,
414+
reaction,
415+
currentUserId,
416+
enforceUnique: true,
417+
);
418+
}
419+
420+
/// Adds or updates a reaction in a comment within this activity.
421+
///
422+
/// Updates the own reactions list of the comment by adding or updating [reaction]. Only adds reactions
423+
/// that belong to [currentUserId]. When [enforceUnique] is true, replaces any existing
424+
/// reaction from the same user; otherwise, allows multiple reactions from the same user.
425+
///
426+
/// Returns a new [ActivityData] instance with the updated comment reactions.
427+
ActivityData upsertCommentReaction(
428+
CommentData updatedComment,
429+
FeedsReactionData reaction,
430+
String currentUserId, {
431+
bool enforceUnique = false,
432+
}) {
433+
final updatedComments = comments.updateWhere(
434+
(it) => it.id == updatedComment.id,
435+
update: (it) => it.upsertReaction(
436+
updatedComment,
437+
reaction,
438+
currentUserId,
439+
enforceUnique: enforceUnique,
440+
),
441+
);
442+
443+
return copyWith(comments: updatedComments);
444+
}
445+
446+
/// Removes a reaction from a comment within this activity.
447+
///
448+
/// Updates the own reactions list of the comment by removing [reaction]. Only removes reactions
449+
/// that belong to [currentUserId].
450+
///
451+
/// Returns a new [ActivityData] instance with the updated comment reactions.
452+
ActivityData removeCommentReaction(
453+
CommentData updatedComment,
454+
FeedsReactionData reaction,
455+
String currentUserId,
456+
) {
457+
final updatedComments = comments.updateWhere(
458+
(it) => it.id == updatedComment.id,
459+
update: (it) => it.removeReaction(
460+
updatedComment,
461+
reaction,
462+
currentUserId,
463+
),
464+
);
465+
466+
return copyWith(comments: updatedComments);
467+
}
468+
384469
/// Adds or updates a bookmark in this activity.
385470
///
386471
/// Updates the own bookmarks list by adding or updating [bookmark]. Only adds bookmarks

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ class MarkActivityData with _$MarkActivityData {
4545
final List<String>? markWatched;
4646
}
4747

48-
extension MarkActivityDataHandler<R> on MarkActivityData {
49-
R handle({
48+
extension MarkActivityDataHandler on MarkActivityData {
49+
R handle<R>({
5050
R Function()? markAllRead,
5151
R Function()? markAllSeen,
5252
R Function(Set<String> read)? markRead,

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

Lines changed: 76 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -176,10 +176,10 @@ extension PollDataMutations on PollData {
176176
/// exists (by ID), it will be updated.
177177
///
178178
/// Returns a new [PollData] instance with the updated options.
179-
PollData addOption(PollOptionData option) {
179+
PollData upsertOption(PollOptionData option) {
180180
final updatedOptions = options.upsert(
181181
option,
182-
key: (it) => it.id == option.id,
182+
key: (it) => it.id,
183183
);
184184

185185
return copyWith(options: updatedOptions);
@@ -191,44 +191,97 @@ extension PollDataMutations on PollData {
191191
///
192192
/// Returns a new [PollData] instance with the updated options.
193193
PollData removeOption(String optionId) {
194-
final updatedOptions = options.where((it) => it.id != optionId).toList();
194+
final updatedOptions = options.where((it) {
195+
return it.id != optionId;
196+
}).toList();
195197

196198
return copyWith(options: updatedOptions);
197199
}
198200

199-
/// Updates an existing option in this poll.
201+
/// Adds or updates a vote in this poll.
200202
///
201-
/// Updates the options list by replacing the option with the same ID as [option]
202-
/// with the new [option] data.
203+
/// Updates the own votes and answers list by adding or updating [vote]. Only adds votes
204+
/// that belong to [currentUserId].
203205
///
204-
/// Returns a new [PollData] instance with the updated options.
205-
PollData updateOption(PollOptionData option) {
206-
final updatedOptions = options.map((it) {
207-
if (it.id != option.id) return it;
208-
return option;
209-
}).toList();
206+
/// Returns a new [PollData] instance with the updated own votes and answers.
207+
PollData upsertVote(
208+
PollData updatedPoll,
209+
PollVoteData vote,
210+
String currentUserId,
211+
) {
212+
final updatedOwnVotesAndAnswers = ownVotesAndAnswers.let((it) {
213+
if (vote.userId != currentUserId) return it;
214+
return it.upsert(vote, key: (it) => it.id);
215+
});
210216

211-
return copyWith(options: updatedOptions);
217+
return updateWith(
218+
updatedPoll,
219+
ownVotesAndAnswers: updatedOwnVotesAndAnswers,
220+
);
212221
}
213222

214-
/// Casts an answer to this poll.
223+
/// Adds or updates an answer in this poll.
215224
///
216-
/// Updates the latest answers and own votes/answers lists by adding or updating [answer].
217-
/// Only adds answers that belong to [currentUserId] to the own votes/answers list.
225+
/// Updates the own votes and answers list by adding or updating [answer]. Only adds answers
226+
/// that belong to [currentUserId].
218227
///
219-
/// Returns a new [PollData] instance with the updated answers.
220-
PollData castAnswer(PollVoteData answer, String currentUserId) {
221-
final updatedLatestAnswers = latestAnswers.let((it) {
222-
return it.upsert(answer, key: (it) => it.id == answer.id);
228+
/// Returns a new [PollData] instance with the updated own votes and answers.
229+
PollData upsertAnswer(
230+
PollData updatedPoll,
231+
PollVoteData answer,
232+
String currentUserId,
233+
) {
234+
final updatedOwnVotesAndAnswers = ownVotesAndAnswers.let((it) {
235+
if (answer.userId != currentUserId) return it;
236+
return it.upsert(answer, key: (it) => it.id);
223237
});
224238

239+
return updateWith(
240+
updatedPoll,
241+
ownVotesAndAnswers: updatedOwnVotesAndAnswers,
242+
);
243+
}
244+
245+
/// Removes a vote from this poll.
246+
///
247+
/// Updates the own votes and answers list by removing [vote]. Only removes votes
248+
/// that belong to [currentUserId].
249+
///
250+
/// Returns a new [PollData] instance with the updated own votes and answers.
251+
PollData removeVote(
252+
PollData updatedPoll,
253+
PollVoteData vote,
254+
String currentUserId,
255+
) {
256+
final updatedOwnVotesAndAnswers = ownVotesAndAnswers.let((it) {
257+
if (vote.userId != currentUserId) return it;
258+
return it.where((it) => it.id != vote.id).toList();
259+
});
260+
261+
return updateWith(
262+
updatedPoll,
263+
ownVotesAndAnswers: updatedOwnVotesAndAnswers,
264+
);
265+
}
266+
267+
/// Removes an answer from this poll.
268+
///
269+
/// Updates the own votes and answers list by removing [answer]. Only removes answers
270+
/// that belong to [currentUserId].
271+
///
272+
/// Returns a new [PollData] instance with the updated own votes and answers.
273+
PollData removeAnswer(
274+
PollData updatedPoll,
275+
PollVoteData answer,
276+
String currentUserId,
277+
) {
225278
final updatedOwnVotesAndAnswers = ownVotesAndAnswers.let((it) {
226279
if (answer.userId != currentUserId) return it;
227-
return it.upsert(answer, key: (it) => it.id == answer.id);
280+
return it.where((it) => it.id != answer.id).toList();
228281
});
229282

230-
return copyWith(
231-
latestAnswers: updatedLatestAnswers,
283+
return updateWith(
284+
updatedPoll,
232285
ownVotesAndAnswers: updatedOwnVotesAndAnswers,
233286
);
234287
}

packages/stream_feeds/lib/src/repository/polls_repository.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ class PollsRepository {
3333
const request = api.UpdatePollPartialRequest(
3434
set: {'is_closed': true},
3535
);
36+
3637
final result = await _api.updatePollPartial(
3738
pollId: pollId,
3839
updatePollPartialRequest: request,

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ class Activity with Disposable {
5757

5858
final initialActivityState = ActivityState(
5959
activity: initialActivityData,
60-
poll: initialActivityData?.poll,
6160
);
6261

6362
_stateNotifier = ActivityStateNotifier(
@@ -110,7 +109,7 @@ class Activity with Disposable {
110109
final result = await activitiesRepository.getActivity(activityId);
111110

112111
result.onSuccess((activity) {
113-
_stateNotifier.onActivityUpdated(activity);
112+
_stateNotifier.onActivityGet(activity);
114113
if (activity.currentFeed case final feed?) {
115114
capabilitiesRepository.cacheCapabilitiesForFeeds([feed]);
116115
}

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,14 @@ class ActivityCommentListStateNotifier
4545
);
4646
}
4747

48+
/// Handles the deletion of the activity.
49+
void onActivityDeleted() {
50+
state = state.copyWith(
51+
comments: [], // Clear all comments when the activity is deleted
52+
pagination: null,
53+
);
54+
}
55+
4856
/// Handles the addition of a new comment.
4957
void onCommentAdded(CommentData comment) {
5058
final parentId = comment.parentId;

0 commit comments

Comments
 (0)