Skip to content

Commit ec653d0

Browse files
authored
feat(llc, persistence): add reaction groups to Message (#2255)
1 parent 988bd27 commit ec653d0

29 files changed

+4089
-1038
lines changed

packages/stream_chat/CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1+
## Upcoming
2+
3+
✅ Added
4+
5+
- Added `reactionGroups` to the `Message` model. This field is a map of reaction types to their
6+
respective counts and scores and additional metadata such as the first and last reaction
7+
timestamps.
8+
9+
🔄 Changed
10+
11+
- Deprecated `message.reactionCounts`, `message.reactionScores` in favor of
12+
`message.reactionGroups`.
13+
114
## 9.10.0
215

316
🐞 Fixed

packages/stream_chat/lib/src/client/channel.dart

Lines changed: 23 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// ignore_for_file: avoid_redundant_argument_values
22

33
import 'dart:async';
4-
import 'dart:math';
4+
import 'dart:math' as math;
55

66
import 'package:collection/collection.dart';
77
import 'package:rxdart/rxdart.dart';
@@ -303,7 +303,7 @@ class Channel {
303303
final currentTime = DateTime.timestamp();
304304
final elapsedTime = currentTime.difference(userLastMessageAt).inSeconds;
305305

306-
return max(0, cooldownDuration - elapsedTime);
306+
return math.max(0, cooldownDuration - elapsedTime);
307307
}
308308

309309
/// Stores time at which cooldown was started
@@ -1303,59 +1303,37 @@ class Channel {
13031303
bool enforceUnique = false,
13041304
}) async {
13051305
_checkInitialized();
1306-
final messageId = message.id;
1307-
final now = DateTime.now();
1308-
final user = _client.state.currentUser;
1309-
1310-
var latestReactions = [...message.latestReactions ?? <Reaction>[]];
1311-
if (enforceUnique) {
1312-
latestReactions.removeWhere((it) => it.userId == user!.id);
1306+
final currentUser = _client.state.currentUser;
1307+
if (currentUser == null) {
1308+
throw StateError(
1309+
'Cannot send reaction: current user is not available. '
1310+
'Ensure the client is connected and a user is set.',
1311+
);
13131312
}
13141313

1315-
final newReaction = Reaction(
1316-
messageId: messageId,
1317-
createdAt: now,
1314+
final messageId = message.id;
1315+
final reaction = Reaction(
13181316
type: type,
1319-
user: user,
1317+
messageId: messageId,
1318+
user: currentUser,
13201319
score: score,
1320+
createdAt: DateTime.timestamp(),
13211321
extraData: extraData,
13221322
);
13231323

1324-
latestReactions = (latestReactions
1325-
// Inserting at the 0th index as it's the latest reaction
1326-
..insert(0, newReaction))
1327-
.take(10)
1328-
.toList();
1329-
final ownReactions = enforceUnique
1330-
? <Reaction>[newReaction]
1331-
: <Reaction>[
1332-
...message.ownReactions ?? [],
1333-
newReaction,
1334-
];
1335-
1336-
final newMessage = message.copyWith(
1337-
reactionCounts: {...message.reactionCounts ?? <String, int>{}}
1338-
..update(type, (value) {
1339-
if (enforceUnique) return value;
1340-
return value + 1;
1341-
}, ifAbsent: () => 1), // ignore: prefer-trailing-comma
1342-
reactionScores: {...message.reactionScores ?? <String, int>{}}
1343-
..update(type, (value) {
1344-
if (enforceUnique) return value;
1345-
return value + 1;
1346-
}, ifAbsent: () => 1), // ignore: prefer-trailing-comma
1347-
latestReactions: latestReactions,
1348-
ownReactions: ownReactions,
1324+
final updatedMessage = message.addMyReaction(
1325+
reaction,
1326+
enforceUnique: enforceUnique,
13491327
);
13501328

1351-
state?.updateMessage(newMessage);
1329+
state?.updateMessage(updatedMessage);
13521330

13531331
try {
13541332
final reactionResp = await _client.sendReaction(
13551333
messageId,
1356-
type,
1357-
score: score,
1358-
extraData: extraData,
1334+
reaction.type,
1335+
score: reaction.score,
1336+
extraData: reaction.extraData,
13591337
enforceUnique: enforceUnique,
13601338
);
13611339
return reactionResp;
@@ -1371,35 +1349,11 @@ class Channel {
13711349
Message message,
13721350
Reaction reaction,
13731351
) async {
1374-
final type = reaction.type;
1375-
1376-
final reactionCounts = {...?message.reactionCounts};
1377-
if (reactionCounts.containsKey(type)) {
1378-
reactionCounts.update(type, (value) => value - 1);
1379-
}
1380-
final reactionScores = {...?message.reactionScores};
1381-
if (reactionScores.containsKey(type)) {
1382-
reactionScores.update(type, (value) => value - 1);
1383-
}
1384-
1385-
final latestReactions = [...?message.latestReactions]..removeWhere((r) =>
1386-
r.userId == reaction.userId &&
1387-
r.type == reaction.type &&
1388-
r.messageId == reaction.messageId);
1389-
1390-
final ownReactions = [...?message.ownReactions]..removeWhere((r) =>
1391-
r.userId == reaction.userId &&
1392-
r.type == reaction.type &&
1393-
r.messageId == reaction.messageId);
1394-
1395-
final newMessage = message.copyWith(
1396-
reactionCounts: reactionCounts..removeWhere((_, value) => value == 0),
1397-
reactionScores: reactionScores..removeWhere((_, value) => value == 0),
1398-
latestReactions: latestReactions,
1399-
ownReactions: ownReactions,
1352+
final updatedMessage = message.deleteMyReaction(
1353+
reactionType: reaction.type,
14001354
);
14011355

1402-
state?.updateMessage(newMessage);
1356+
state?.updateMessage(updatedMessage);
14031357

14041358
try {
14051359
final deleteResponse = await _client.deleteReaction(

0 commit comments

Comments
 (0)