Merge pull request #1212 from GetStream/feature/newMessageLabel

feat(ui,localization): add unread messages label
This commit is contained in:
Salvatore Giordano
2022-06-17 12:22:15 +02:00
committed by GitHub
15 changed files with 173 additions and 7 deletions
@@ -14,6 +14,8 @@
- [[#1011]](https://github.com/GetStream/stream-chat-flutter/issues/1011) Animate the background - [[#1011]](https://github.com/GetStream/stream-chat-flutter/issues/1011) Animate the background
color of pinned messages. color of pinned messages.
- Added unread messages divider in `StreamMessageListView`.
- Added `StreamMessageListView.unreadMessagesSeparatorBuilder`.
## 4.2.0 ## 4.2.0
@@ -59,5 +59,7 @@
<key>NSMicrophoneUsageDescription</key> <key>NSMicrophoneUsageDescription</key>
<string>Explain why your app uses the mic</string> <string>Explain why your app uses the mic</string>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
</dict> </dict>
</plist> </plist>
@@ -77,6 +77,10 @@ abstract class Translations {
/// contains a parent message /// contains a parent message
String threadSeparatorText(int replyCount); String threadSeparatorText(int replyCount);
/// The text for showing the unread messages count
/// in the [StreamMessageListView]
String unreadMessagesSeparatorText(int unreadCount);
/// The label for "connected" in [StreamConnectionStatusBuilder] /// The label for "connected" in [StreamConnectionStatusBuilder]
String get connectedLabel; String get connectedLabel;
@@ -711,4 +715,12 @@ Attachment limit exceeded: it's not possible to add more than $limit attachments
@override @override
String get linkDisabledError => 'Links are disabled'; String get linkDisabledError => 'Links are disabled';
@override
String unreadMessagesSeparatorText(int unreadCount) {
if (unreadCount == 1) {
return '1 unread message';
}
return '$unreadCount unread messages';
}
} }
@@ -200,6 +200,7 @@ class StreamMessageListView extends StatefulWidget {
this.onSystemMessageTap, this.onSystemMessageTap,
this.showFloatingDateDivider = true, this.showFloatingDateDivider = true,
this.threadSeparatorBuilder, this.threadSeparatorBuilder,
this.unreadMessagesSeparatorBuilder,
this.messageListController, this.messageListController,
this.reverse = true, this.reverse = true,
this.paginationLimit = 20, this.paginationLimit = 20,
@@ -337,6 +338,10 @@ class StreamMessageListView extends StatefulWidget {
/// Builder used to build the thread separator in case it's a thread view /// Builder used to build the thread separator in case it's a thread view
final WidgetBuilder? threadSeparatorBuilder; final WidgetBuilder? threadSeparatorBuilder;
/// Builder used to build the unread message separator
final Widget Function(BuildContext context, int unreadCount)?
unreadMessagesSeparatorBuilder;
/// A [MessageListController] allows pagination. /// A [MessageListController] allows pagination.
/// Use [ChannelListController.paginateData] pagination. /// Use [ChannelListController.paginateData] pagination.
final MessageListController? messageListController; final MessageListController? messageListController;
@@ -363,6 +368,7 @@ class _StreamMessageListViewState extends State<StreamMessageListView> {
StreamChannelState? streamChannel; StreamChannelState? streamChannel;
late StreamChatThemeData _streamTheme; late StreamChatThemeData _streamTheme;
late List<String> _userPermissions; late List<String> _userPermissions;
late int unreadCount;
int get _initialIndex { int get _initialIndex {
final initialScrollIndex = widget.initialScrollIndex; final initialScrollIndex = widget.initialScrollIndex;
@@ -596,9 +602,12 @@ class _StreamMessageListViewState extends State<StreamMessageListView> {
return const SizedBox(height: 8); return const SizedBox(height: 8);
} }
if (i == 1 || i == itemCount - 4) return const Offstage(); if (i == 1 || i == itemCount - 4) {
return const Offstage();
}
late final Message message, nextMessage; late final Message message, nextMessage;
late Widget separator;
if (widget.reverse) { if (widget.reverse) {
message = messages[i - 1]; message = messages[i - 1];
nextMessage = messages[i - 2]; nextMessage = messages[i - 2];
@@ -611,7 +620,7 @@ class _StreamMessageListViewState extends State<StreamMessageListView> {
nextMessage.createdAt.toLocal(), nextMessage.createdAt.toLocal(),
Units.DAY, Units.DAY,
)) { )) {
return _buildDateDivider(nextMessage); separator = _buildDateDivider(nextMessage);
} }
final timeDiff = final timeDiff =
Jiffy(nextMessage.createdAt.toLocal()).diff( Jiffy(nextMessage.createdAt.toLocal()).diff(
@@ -644,13 +653,52 @@ class _StreamMessageListViewState extends State<StreamMessageListView> {
} }
if (spacingRules.isNotEmpty) { if (spacingRules.isNotEmpty) {
return widget.spacingWidgetBuilder separator = widget.spacingWidgetBuilder
?.call(context, spacingRules) ?? ?.call(context, spacingRules) ??
const SizedBox(height: 8); const SizedBox(height: 8);
} }
return widget.spacingWidgetBuilder separator = widget.spacingWidgetBuilder
?.call(context, [SpacingType.defaultSpacing]) ?? ?.call(context, [SpacingType.defaultSpacing]) ??
const SizedBox(height: 2); const SizedBox(height: 2);
if (!isThread && unreadCount > 0 && unreadCount == i - 1) {
final unreadMessagesSeparator = widget
.unreadMessagesSeparatorBuilder
?.call(context, unreadCount);
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
separator,
unreadMessagesSeparator ??
Padding(
padding:
const EdgeInsets.symmetric(vertical: 8),
child: DecoratedBox(
decoration: BoxDecoration(
gradient:
_streamTheme.colorTheme.bgGradient,
),
child: Padding(
padding: const EdgeInsets.all(8),
child: Text(
context.translations
.unreadMessagesSeparatorText(
unreadCount,
),
textAlign: TextAlign.center,
style:
StreamChannelHeaderTheme.of(context)
.subtitleStyle,
),
),
),
),
],
);
}
return separator;
}, },
itemBuilder: (context, i) { itemBuilder: (context, i) {
if (i == itemCount - 1) { if (i == itemCount - 1) {
@@ -880,6 +928,7 @@ class _StreamMessageListViewState extends State<StreamMessageListView> {
} }
Future<void> scrollToBottomDefaultTapAction(int unreadCount) async { Future<void> scrollToBottomDefaultTapAction(int unreadCount) async {
this.unreadCount = unreadCount;
if (unreadCount > 0) { if (unreadCount > 0) {
streamChannel!.channel.markRead(); streamChannel!.channel.markRead();
} }
@@ -890,11 +939,11 @@ class _StreamMessageListViewState extends State<StreamMessageListView> {
await streamChannel!.reloadChannel(); await streamChannel!.reloadChannel();
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
_scrollController!.jumpTo(index: 0); _scrollController!.jumpTo(index: unreadCount);
}); });
} else { } else {
_scrollController!.scrollTo( _scrollController!.scrollTo(
index: 0, index: unreadCount,
duration: const Duration(seconds: 1), duration: const Duration(seconds: 1),
curve: Curves.easeInOut, curve: Curves.easeInOut,
); );
@@ -1335,18 +1384,28 @@ class _StreamMessageListViewState extends State<StreamMessageListView> {
if (event.message?.parentId == widget.parentMessage?.id && if (event.message?.parentId == widget.parentMessage?.id &&
event.message!.user!.id == event.message!.user!.id ==
streamChannel!.channel.client.state.currentUser!.id) { streamChannel!.channel.client.state.currentUser!.id) {
setState(() {
unreadCount = 0;
});
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
_scrollController?.scrollTo( _scrollController?.scrollTo(
index: 0, index: 0,
duration: const Duration(seconds: 1), duration: const Duration(seconds: 1),
); );
}); });
} else if (streamChannel?.channel.state?.unreadCount != 0) {
setState(() {
unreadCount = unreadCount + 1;
});
} }
}); });
if (_isThreadConversation) { if (_isThreadConversation) {
streamChannel!.getReplies(widget.parentMessage!.id); streamChannel!.getReplies(widget.parentMessage!.id);
} }
unreadCount = streamChannel?.channel.state?.unreadCount ?? 0;
} }
super.didChangeDependencies(); super.didChangeDependencies();
@@ -1,3 +1,9 @@
## Upcoming
✅ Added
* Added support for `unreadMessagesSeparatorText` translation.
## 3.1.0 ## 3.1.0
* Added support for [German](https://github.com/GetStream/stream-chat-flutter/blob/master/packages/stream_chat_localizations/lib/src/stream_chat_localizations_de.dart) locale. * Added support for [German](https://github.com/GetStream/stream-chat-flutter/blob/master/packages/stream_chat_localizations/lib/src/stream_chat_localizations_de.dart) locale.
@@ -405,6 +405,14 @@ class NnStreamChatLocalizations extends GlobalStreamChatLocalizations {
@override @override
String get viewLibrary => 'View library'; String get viewLibrary => 'View library';
@override
String unreadMessagesSeparatorText(int unreadCount) {
if (unreadCount == 1) {
return '1 unread message';
}
return '$unreadCount unread messages';
}
} }
void main() async { void main() async {
@@ -381,4 +381,12 @@ class StreamChatLocalizationsDe extends GlobalStreamChatLocalizations {
@override @override
String get viewLibrary => 'Bibliothek öffnen'; String get viewLibrary => 'Bibliothek öffnen';
@override
String unreadMessagesSeparatorText(int unreadCount) {
if (unreadCount == 1) {
return '1 ungelesene Nachricht';
}
return '$unreadCount ungelesene Nachrichten';
}
} }
@@ -381,4 +381,12 @@ class StreamChatLocalizationsEn extends GlobalStreamChatLocalizations {
@override @override
String get viewLibrary => 'View library'; String get viewLibrary => 'View library';
@override
String unreadMessagesSeparatorText(int unreadCount) {
if (unreadCount == 1) {
return '1 unread message';
}
return '$unreadCount unread messages';
}
} }
@@ -387,4 +387,12 @@ No es posible añadir más de $limit archivos adjuntos
@override @override
String get linkDisabledError => 'Los enlaces están deshabilitados'; String get linkDisabledError => 'Los enlaces están deshabilitados';
@override
String unreadMessagesSeparatorText(int unreadCount) {
if (unreadCount == 1) {
return '1 mensaje no leído';
}
return '$unreadCount mensajes no leídos';
}
} }
@@ -386,4 +386,12 @@ Limite de pièces jointes dépassée : il n'est pas possible d'ajouter plus de $
@override @override
String get linkDisabledError => 'Les liens sont désactivés'; String get linkDisabledError => 'Les liens sont désactivés';
@override
String unreadMessagesSeparatorText(int unreadCount) {
if (unreadCount == 1) {
return '1 message non lu';
}
return '$unreadCount messages non lus';
}
} }
@@ -380,4 +380,12 @@ class StreamChatLocalizationsHi extends GlobalStreamChatLocalizations {
@override @override
String get linkDisabledError => 'लिंक भेजना प्रतिबंधित'; String get linkDisabledError => 'लिंक भेजना प्रतिबंधित';
@override
String unreadMessagesSeparatorText(int unreadCount) {
if (unreadCount == 1) {
return '1 अपठित संदेश';
}
return '$unreadCount अपठित संदेश';
}
} }
@@ -40,7 +40,12 @@ class StreamChatLocalizationsIt extends GlobalStreamChatLocalizations {
String get onlyVisibleToYouText => 'Visible solo a te'; String get onlyVisibleToYouText => 'Visible solo a te';
@override @override
String threadReplyCountText(int count) => '$count risposte al thread'; String threadReplyCountText(int count) {
if (count == 1) {
return '1 risposta al thread';
}
return '$count risposte al thread';
}
@override @override
String attachmentsUploadProgressText({ String attachmentsUploadProgressText({
@@ -383,4 +388,12 @@ Attenzione: il limite massimo di $limit file è stato superato.
@override @override
String get linkDisabledError => 'I links sono disattivati'; String get linkDisabledError => 'I links sono disattivati';
@override
String unreadMessagesSeparatorText(int unreadCount) {
if (unreadCount == 1) {
return '1 messaggio non letto';
}
return '$unreadCount messaggi non letti';
}
} }
@@ -365,4 +365,12 @@ class StreamChatLocalizationsJa extends GlobalStreamChatLocalizations {
@override @override
String get linkDisabledError => 'リンクが無効になっています'; String get linkDisabledError => 'リンクが無効になっています';
@override
String unreadMessagesSeparatorText(int unreadCount) {
if (unreadCount == 1) {
return '未読メッセージ1通';
}
return '$unreadCountつの未読メッセージ';
}
} }
@@ -366,4 +366,12 @@ class StreamChatLocalizationsKo extends GlobalStreamChatLocalizations {
@override @override
String get linkDisabledError => '링크가 비활성화되었습니다.'; String get linkDisabledError => '링크가 비활성화되었습니다.';
@override
String unreadMessagesSeparatorText(int unreadCount) {
if (unreadCount == 1) {
return '읽지 않은 메시지 1개';
}
return '읽지 않은 메시지 $unreadCount개';
}
} }
@@ -384,4 +384,12 @@ Não é possível adicionar mais de $limit arquivos de uma vez
@override @override
String get viewLibrary => 'Ver biblioteca'; String get viewLibrary => 'Ver biblioteca';
@override
String unreadMessagesSeparatorText(int unreadCount) {
if (unreadCount == 1) {
return '1 mensagem não lida';
}
return '$unreadCount mensagens não lidas';
}
} }