Skip to content

Commit

Permalink
Merge pull request #884 from GetStream/release/3.4.0
Browse files Browse the repository at this point in the history
chore(llc,core,ui,persistence,localizations): 3.4.0
  • Loading branch information
imtoori authored Feb 3, 2022
2 parents 2ea9227 + 3c6b87a commit ca4cc3c
Show file tree
Hide file tree
Showing 135 changed files with 1,474 additions and 572 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/dart_code_metrics.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
name: Dart Code Metrics

env:
flutter_version: "2.5.0"
flutter_version: "2.8.1"
folders: "lib, test"
melos_version: "1.2.0"

on:
pull_request:
Expand Down Expand Up @@ -33,7 +34,7 @@ jobs:
flutter-version: ${{ env.flutter_version }}

- name: "Install Tools"
run: flutter pub global activate melos 1.0.0-dev.10
run: flutter pub global activate melos ${{ env.melos_version }}
- name: "Bootstrap Workspace"
run: melos bootstrap

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/stream_flutter_workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ name: stream_flutter_workflow

env:
ACTIONS_ALLOW_UNSECURE_COMMANDS: 'true'
flutter_version: "2.5.1"
melos_version: "1.0.0-dev.10"
flutter_version: "2.8.1"
melos_version: "1.2.0"

on:
pull_request:
Expand Down
Empty file added melos
Empty file.
28 changes: 27 additions & 1 deletion packages/stream_chat/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,29 @@
## 3.4.0

🐞 Fixed

- [[#857]](https://github.com/GetStream/stream-chat-flutter/issues/857) Channel now listens for member ban/unban and
updates the channel state with the latest data.
- [[#748]](https://github.com/GetStream/stream-chat-flutter/issues/748) `Message.user` is now also included while saving users in persistence.
- [[#871]](https://github.com/GetStream/stream-chat-flutter/issues/871) Fixed thread message deletion.
- [[#846]](https://github.com/GetStream/stream-chat-flutter/issues/846) Fixed `message.ownReactions` getting truncated when receiving a reaction event.
- Add check for invalid image URLs
- Fix `channelState.pinnedMessagesStream` getting reset to `0` after a channel update.
- Fixed `unreadCount` after removing user from a channel.

🔄 Changed

- `client.location` is now deprecated in favor of the
new [edge server](https://getstream.io/blog/chat-edge-infrastructure) and will be removed in v4.0.0.
- `channel.banUser`, `channel.unbanUser` is now deprecated in favor of the new `channel.banMember`
and `channel.unbanMember`. These deprecated methods will be removed in v4.0.0.
- Added `banExpires` property of type `DateTime` on the `Member`, `OwnUser`, and `User` models.

✅ Added

- Added `client.enrichUrl` endpoint for enriching URLs with metadata.
- Added `client.queryBannedUsers`, `channel.queryBannedUsers` endpoint for querying banned users.

## 3.3.1

🐞 Fixed
Expand Down Expand Up @@ -748,4 +774,4 @@

## 0.0.2

- first beta version
- first beta version
171 changes: 138 additions & 33 deletions packages/stream_chat/lib/src/client/channel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,9 @@ import 'dart:math';
import 'package:collection/collection.dart'
show IterableExtension, ListEquality;
import 'package:dio/dio.dart';
import 'package:rate_limiter/rate_limiter.dart';
import 'package:rxdart/rxdart.dart';
import 'package:stream_chat/src/client/retry_queue.dart';
import 'package:stream_chat/src/core/error/error.dart';
import 'package:stream_chat/src/core/models/attachment_file.dart';
import 'package:stream_chat/src/core/models/channel_state.dart';
import 'package:stream_chat/src/core/models/user.dart';
import 'package:stream_chat/src/core/util/utils.dart';
import 'package:stream_chat/src/event_type.dart';
import 'package:stream_chat/stream_chat.dart';

/// Class that manages a specific channel.
Expand Down Expand Up @@ -825,7 +819,7 @@ class Channel {
final now = DateTime.now();
final user = _client.state.currentUser;

final latestReactions = [...message.latestReactions ?? <Reaction>[]];
var latestReactions = [...message.latestReactions ?? <Reaction>[]];
if (enforceUnique) {
latestReactions.removeWhere((it) => it.userId == user!.id);
}
Expand All @@ -839,10 +833,17 @@ class Channel {
extraData: extraData,
);

// Inserting at the 0th index as it's the latest reaction
latestReactions.insert(0, newReaction);
final ownReactions = [...latestReactions]
..removeWhere((it) => it.userId != user!.id);
latestReactions = (latestReactions
// Inserting at the 0th index as it's the latest reaction
..insert(0, newReaction))
.take(10)
.toList();
final ownReactions = enforceUnique
? <Reaction>[newReaction]
: <Reaction>[
...message.ownReactions ?? [],
newReaction,
];

final newMessage = message.copyWith(
reactionCounts: {...message.reactionCounts ?? <String, int>{}}
Expand Down Expand Up @@ -882,7 +883,6 @@ class Channel {
Reaction reaction,
) async {
final type = reaction.type;
final user = _client.state.currentUser;

final reactionCounts = {...message.reactionCounts ?? <String, int>{}};
if (reactionCounts.containsKey(type)) {
Expand All @@ -899,8 +899,11 @@ class Channel {
r.type == reaction.type &&
r.messageId == reaction.messageId);

final ownReactions = [...latestReactions]
..removeWhere((it) => it.userId != user!.id);
final ownReactions = message.ownReactions
?..removeWhere((r) =>
r.userId == reaction.userId &&
r.type == reaction.type &&
r.messageId == reaction.messageId);

final newMessage = message.copyWith(
reactionCounts: reactionCounts..removeWhere((_, value) => value == 0),
Expand Down Expand Up @@ -1268,6 +1271,21 @@ class Channel {
pagination: pagination,
);

/// Query channel banned users.
Future<QueryBannedUsersResponse> queryBannedUsers({
Filter? filter,
List<SortOption>? sort,
PaginationParams? pagination,
}) {
_checkInitialized();
filter ??= Filter.equal('channel_cid', cid!);
return _client.queryBannedUsers(
filter: filter,
sort: sort,
pagination: pagination,
);
}

/// Mutes the channel.
Future<EmptyResponse> mute({Duration? expiration}) {
_checkInitialized();
Expand All @@ -1281,9 +1299,17 @@ class Channel {
}

/// Bans the user with given [userID] from the channel.
@Deprecated("Use 'banMember' instead. This method will be removed in v4.0.0")
Future<EmptyResponse> banUser(
String userID,
Map<String, dynamic> options,
) =>
banMember(userID, options);

/// Bans the member with given [userID] from the channel.
Future<EmptyResponse> banMember(
String userID,
Map<String, dynamic> options,
) async {
_checkInitialized();
final opts = Map<String, dynamic>.from(options)
Expand All @@ -1295,7 +1321,12 @@ class Channel {
}

/// Remove the ban for the user with given [userID] in the channel.
Future<EmptyResponse> unbanUser(String userID) async {
@Deprecated(
"Use 'unbanMember' instead. This method will be removed in v4.0.0")
Future<EmptyResponse> unbanUser(String userID) => unbanMember(userID);

/// Remove the ban for the member with given [userID] in the channel.
Future<EmptyResponse> unbanMember(String userID) async {
_checkInitialized();
return _client.unbanUser(userID, {
'type': type,
Expand Down Expand Up @@ -1466,6 +1497,10 @@ class ChannelClientState {

_listenMemberRemoved();

_listenMemberBanned();

_listenMemberUnbanned();

_startCleaning();

_startCleaningPinnedMessages();
Expand Down Expand Up @@ -1498,16 +1533,21 @@ class ChannelClientState {
if (url == null || !url.contains('')) {
return false;
}
final uri = Uri.parse(url);
if (!uri.host.endsWith('stream-io-cdn.com') ||
uri.queryParameters['Expires'] == null) {
try {
final uri = Uri.parse(url);
if (!uri.host.endsWith('stream-io-cdn.com') ||
uri.queryParameters['Expires'] == null) {
return false;
}
final secondsFromEpoch =
int.parse(uri.queryParameters['Expires']!);
final expiration = DateTime.fromMillisecondsSinceEpoch(
secondsFromEpoch * 1000,
);
return expiration.isBefore(DateTime.now());
} catch (_) {
return false;
}
final secondsFromEpoch =
int.parse(uri.queryParameters['Expires']!);
final expiration =
DateTime.fromMillisecondsSinceEpoch(secondsFromEpoch * 1000);
return expiration.isBefore(DateTime.now());
}))
.map((e) => e.id)
.toList();
Expand Down Expand Up @@ -1538,6 +1578,7 @@ class ChannelClientState {
members: List.from(
channelState.members..removeWhere((m) => m.userId == user!.id),
),
read: channelState.read..removeWhere((r) => r.user.id == user!.id),
));
}));
}
Expand All @@ -1563,6 +1604,54 @@ class ChannelClientState {
}));
}

void _listenMemberBanned() {
_subscriptions.add(_channel
.on(EventType.userBanned)
.where((it) => it.cid != null) // filters channel ban from app ban
.listen(
(event) async {
final user = event.user!;
final member = await _channel
.queryMembers(filter: Filter.equal('id', user.id))
.then((it) => it.members.first);

_updateMember(member);
},
));
}

void _listenMemberUnbanned() {
_subscriptions.add(_channel
.on(EventType.userUnbanned)
.where((it) => it.cid != null) // filters channel ban from app ban
.listen(
(event) async {
final user = event.user!;
final member = await _channel
.queryMembers(filter: Filter.equal('id', user.id))
.then((it) => it.members.first);

_updateMember(member);
},
));
}

void _updateMember(Member member) {
final currentMembers = [...members];
final memberIndex = currentMembers.indexWhere(
(m) => m.userId == member.userId,
);

if (memberIndex == -1) return;
currentMembers[memberIndex] = member;

updateChannelState(
channelState.copyWith(
members: currentMembers,
),
);
}

/// Flag which indicates if [ChannelClientState] contain latest/recent messages or not.
///
/// This flag should be managed by UI sdks.
Expand Down Expand Up @@ -1604,21 +1693,30 @@ class ChannelClientState {

void _listenReactionDeleted() {
_subscriptions.add(_channel.on(EventType.reactionDeleted).listen((event) {
final userId = _channel.client.state.currentUser!.id;
final oldMessage =
messages.firstWhereOrNull((it) => it.id == event.message?.id);
final reaction = event.reaction;
final ownReactions = oldMessage?.ownReactions
?.whereNot((it) =>
it.type == reaction?.type &&
it.score == reaction?.score &&
it.messageId == reaction?.messageId &&
it.userId == reaction?.userId &&
it.extraData == reaction?.extraData)
.toList(growable: false);
final message = event.message!.copyWith(
ownReactions: [...event.message!.latestReactions!]
..removeWhere((it) => it.userId != userId),
ownReactions: ownReactions,
);
addMessage(message);
}));
}

void _listenReactions() {
_subscriptions.add(_channel.on(EventType.reactionNew).listen((event) {
final userId = _channel.client.state.currentUser!.id;
final oldMessage =
messages.firstWhereOrNull((it) => it.id == event.message?.id);
final message = event.message!.copyWith(
ownReactions: [...event.message!.latestReactions!]
..removeWhere((it) => it.userId != userId),
ownReactions: oldMessage?.ownReactions,
);
addMessage(message);
}));
Expand All @@ -1631,10 +1729,11 @@ class ChannelClientState {
EventType.reactionUpdated,
)
.listen((event) {
final userId = _channel.client.state.currentUser!.id;
final oldMessage =
messages.firstWhereOrNull((it) => it.id == event.message?.id);

final message = event.message!.copyWith(
ownReactions: [...event.message!.latestReactions!]
..removeWhere((it) => it.userId != userId),
ownReactions: oldMessage?.ownReactions,
);
addMessage(message);

Expand Down Expand Up @@ -1729,7 +1828,13 @@ class ChannelClientState {
if (replyCount == null || replyCount == 0) return;

addMessage(parentMessage.copyWith(replyCount: replyCount - 1));
updateThreadInfo(parentId, threads[parentId]!..remove(message));
updateThreadInfo(
parentId,
threads[parentId]!
..removeWhere(
(e) => e.id == message.id,
),
);
} else {
// Remove regular message
final allMessages = [...messages];
Expand Down
Loading

0 comments on commit ca4cc3c

Please sign in to comment.