Merge branch 'develop' of https://github.com/GetStream/stream-chat-flutter into cds-189
This commit is contained in:
@@ -45,6 +45,7 @@ breakdown:
|
||||
🐞 Fixed
|
||||
|
||||
- Fixed `MessageInput` textField case where `input` is not enabled if the file picked from the camera is null.
|
||||
- Fixed date dividers position/alignment in non reversed `MessageListView`.
|
||||
|
||||
## 2.1.2
|
||||
|
||||
|
||||
@@ -584,11 +584,16 @@ class _ChannelListViewState extends State<ChannelListView> {
|
||||
),
|
||||
],
|
||||
child: widget.channelPreviewBuilder?.call(context, channel) ??
|
||||
ChannelPreview(
|
||||
onLongPress: widget.onChannelLongPress,
|
||||
channel: channel,
|
||||
onImageTap: () => widget.onImageTap?.call(channel),
|
||||
onTap: (channel) => onTap(channel, widget.channelWidget),
|
||||
DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
color: chatThemeData.channelListViewTheme.backgroundColor,
|
||||
),
|
||||
child: ChannelPreview(
|
||||
onLongPress: widget.onChannelLongPress,
|
||||
channel: channel,
|
||||
onImageTap: () => widget.onImageTap?.call(channel),
|
||||
onTap: (channel) => onTap(channel, widget.channelWidget),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -132,7 +132,7 @@ class ChannelPreview extends StatelessWidget {
|
||||
message: lastMessage!,
|
||||
size: channelPreviewTheme.indicatorIconSize,
|
||||
isMessageRead: channel.state!.read
|
||||
?.where((element) =>
|
||||
.where((element) =>
|
||||
element.user.id !=
|
||||
channel
|
||||
.client.state.currentUser!.id)
|
||||
|
||||
@@ -142,9 +142,9 @@ class _GalleryFooterState extends State<GalleryFooter> {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
'${widget.currentPage + 1} '
|
||||
'${context.translations.ofText} '
|
||||
'${widget.totalPages}',
|
||||
context.translations.galleryPaginationText(
|
||||
currentPage: widget.currentPage,
|
||||
totalPages: widget.totalPages),
|
||||
style: galleryFooterThemeData.titleTextStyle,
|
||||
),
|
||||
],
|
||||
|
||||
@@ -299,8 +299,9 @@ abstract class Translations {
|
||||
/// The text shown for "You"
|
||||
String get youText;
|
||||
|
||||
/// The text shown for "Of"
|
||||
String get ofText;
|
||||
/// Gallery footer pagination text
|
||||
String galleryPaginationText(
|
||||
{required int currentPage, required int totalPages});
|
||||
|
||||
/// The text shown for "File"
|
||||
String get fileText;
|
||||
@@ -660,7 +661,9 @@ class DefaultTranslations implements Translations {
|
||||
String get youText => 'You';
|
||||
|
||||
@override
|
||||
String get ofText => 'of';
|
||||
String galleryPaginationText(
|
||||
{required int currentPage, required int totalPages}) =>
|
||||
'${currentPage + 1} of $totalPages';
|
||||
|
||||
@override
|
||||
String get fileText => 'File';
|
||||
|
||||
@@ -505,8 +505,14 @@ class _MessageListViewState extends State<MessageListView> {
|
||||
|
||||
if (i == 1 || i == itemCount - 4) return const Offstage();
|
||||
|
||||
final message = messages[i - 1];
|
||||
final nextMessage = messages[i - 2];
|
||||
late final Message message, nextMessage;
|
||||
if (widget.reverse) {
|
||||
message = messages[i - 1];
|
||||
nextMessage = messages[i - 2];
|
||||
} else {
|
||||
message = messages[i - 2];
|
||||
nextMessage = messages[i - 1];
|
||||
}
|
||||
if (!Jiffy(message.createdAt.toLocal()).isSame(
|
||||
nextMessage.createdAt.toLocal(),
|
||||
Units.DAY,
|
||||
@@ -636,8 +642,7 @@ class _MessageListViewState extends State<MessageListView> {
|
||||
}
|
||||
|
||||
Positioned _buildFloatingDateDivider(int itemCount) => Positioned(
|
||||
top: widget.reverse ? 20 : null,
|
||||
bottom: widget.reverse ? null : 20,
|
||||
top: 20,
|
||||
left: 0,
|
||||
right: 0,
|
||||
child: BetterStreamBuilder<Iterable<ItemPosition>>(
|
||||
@@ -647,19 +652,36 @@ class _MessageListViewState extends State<MessageListView> {
|
||||
if (a == null || b == null) {
|
||||
return false;
|
||||
}
|
||||
final aTop = _getTopElementIndex(a);
|
||||
final bTop = _getTopElementIndex(b);
|
||||
return aTop == bTop;
|
||||
if (widget.reverse) {
|
||||
final aTop = _getTopElementIndex(a);
|
||||
final bTop = _getTopElementIndex(b);
|
||||
return aTop == bTop;
|
||||
} else {
|
||||
final aBottom = _getBottomElementIndex(a);
|
||||
final bBottom = _getBottomElementIndex(b);
|
||||
return aBottom == bBottom;
|
||||
}
|
||||
},
|
||||
builder: (context, values) {
|
||||
if (values.isEmpty || messages.isEmpty) {
|
||||
return const Offstage();
|
||||
}
|
||||
|
||||
final index = _getTopElementIndex(values);
|
||||
int? index;
|
||||
if (widget.reverse) {
|
||||
index = _getTopElementIndex(values);
|
||||
} else {
|
||||
index = _getBottomElementIndex(values);
|
||||
}
|
||||
|
||||
if (index == null || index <= 2 || index >= itemCount - 3) {
|
||||
return const Offstage();
|
||||
if (index == null) return const Offstage();
|
||||
|
||||
if (index <= 2 || index >= itemCount - 3) {
|
||||
if (widget.reverse) {
|
||||
index = itemCount - 4;
|
||||
} else {
|
||||
index = 2;
|
||||
}
|
||||
}
|
||||
|
||||
final message = messages[index - 2];
|
||||
@@ -685,6 +707,15 @@ class _MessageListViewState extends State<MessageListView> {
|
||||
.index;
|
||||
}
|
||||
|
||||
int? _getBottomElementIndex(Iterable<ItemPosition> values) {
|
||||
final inView = values.where((position) => position.itemLeadingEdge < 1);
|
||||
if (inView.isEmpty) return null;
|
||||
return inView
|
||||
.reduce((min, position) =>
|
||||
position.itemLeadingEdge < min.itemLeadingEdge ? position : min)
|
||||
.index;
|
||||
}
|
||||
|
||||
Widget _buildScrollToBottom() => StreamBuilder<Tuple2<bool, int>>(
|
||||
stream: Rx.combineLatest2(
|
||||
streamChannel!.channel.state!.isUpToDateStream.distinct(),
|
||||
@@ -915,7 +946,7 @@ class _MessageListViewState extends State<MessageListView> {
|
||||
}
|
||||
|
||||
final channel = streamChannel!.channel;
|
||||
final readList = channel.state?.read?.where((read) {
|
||||
final readList = channel.state?.read.where((read) {
|
||||
if (read.user.id == userId) return false;
|
||||
return read.lastRead.isAfter(message.createdAt) ||
|
||||
read.lastRead.isAtSameMomentAs(message.createdAt);
|
||||
@@ -1203,8 +1234,7 @@ class _MessageListViewState extends State<MessageListView> {
|
||||
MaterialPageRoute(
|
||||
builder: (_) => BetterStreamBuilder<Message>(
|
||||
stream: streamChannel!.channel.state!.messagesStream.map(
|
||||
(messages) =>
|
||||
messages!.firstWhere((m) => m.id == message.id)),
|
||||
(messages) => messages.firstWhere((m) => m.id == message.id)),
|
||||
initialData: message,
|
||||
builder: (_, data) => StreamChannel(
|
||||
channel: streamChannel!.channel,
|
||||
|
||||
@@ -21,6 +21,8 @@ void main() {
|
||||
when(() => clientState.currentUser).thenReturn(user);
|
||||
when(() => clientState.currentUserStream)
|
||||
.thenAnswer((_) => Stream.value(user));
|
||||
when(() => channel.lastMessageAtStream)
|
||||
.thenAnswer((_) => Stream.value(lastMessageAt));
|
||||
when(() => channel.lastMessageAt).thenReturn(lastMessageAt);
|
||||
when(() => channel.state).thenReturn(channelState);
|
||||
when(() => channel.client).thenReturn(client);
|
||||
|
||||
@@ -167,7 +167,7 @@ void main() {
|
||||
expect(translations.withText, isNotNull);
|
||||
expect(translations.inText, isNotNull);
|
||||
expect(translations.youText, isNotNull);
|
||||
expect(translations.ofText, isNotNull);
|
||||
expect(translations.galleryPaginationText, isNotNull);
|
||||
expect(translations.fileText, isNotNull);
|
||||
expect(translations.replyToMessageLabel, isNotNull);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user