From 4312e3133b2ba9ce832fe5e43fd5c0f14c88c858 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 19 May 2020 12:57:07 +0200 Subject: [PATCH] add system messages --- example/lib/main.dart | 6 +- lib/src/giphy_attachment.dart | 42 +++++++------- lib/src/image_attachment.dart | 59 +++++++++---------- lib/src/message_list_view.dart | 7 +++ lib/src/system_message.dart | 100 +++++++++++++++++++++++++++++++++ lib/src/utils.dart | 5 -- lib/stream_chat_flutter.dart | 1 + pubspec.yaml | 3 +- 8 files changed, 160 insertions(+), 63 deletions(-) create mode 100644 lib/src/system_message.dart diff --git a/example/lib/main.dart b/example/lib/main.dart index 51784e02..701b1759 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -79,16 +79,16 @@ void main() async { ); // final client = Client( -// 'qk4nn7rpcn75', +// '892s22ypvt6m', // logLevel: Level.INFO, // showLocalNotification: Platform.isAndroid ? showLocalNotification : null, // persistenceEnabled: true, -// baseURL: '127.0.0.1:3030', +// baseURL: '10.0.2.2:3030', // ); // // await client.setUser( // User(id: 'super-band-9'), -// 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoic3VwZXItdHJhbXAtOSJ9.BbcxsR3FsK9c1q1ijhbBWvlXRwRpZ1RoHMKscKWZklk', +// 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoic3VwZXItYmFuZC05In0.MfmkavyPRSztKxcxpOk8Wud3WrzQ4YdNfXqoVjtIoRM', // ); _initNotifications(client); diff --git a/lib/src/giphy_attachment.dart b/lib/src/giphy_attachment.dart index d5e6bb78..62de980b 100644 --- a/lib/src/giphy_attachment.dart +++ b/lib/src/giphy_attachment.dart @@ -6,7 +6,6 @@ import '../stream_chat_flutter.dart'; import 'attachment_error.dart'; import 'attachment_title.dart'; import 'full_screen_image.dart'; -import 'utils.dart'; class GiphyAttachment extends StatelessWidget { final Attachment attachment; @@ -48,29 +47,26 @@ class GiphyAttachment extends StatelessWidget { ); })); }, - child: Hero( - tag: getAttachmentHeroTag(message, attachment), - child: CachedNetworkImage( - height: size?.height, - width: size?.width, - placeholder: (_, __) { - return Container( - width: size?.width, - height: size?.height, - child: Center( - child: CircularProgressIndicator(), - ), - ); - }, - imageUrl: attachment.thumbUrl ?? - attachment.imageUrl ?? - attachment.assetUrl, - errorWidget: (context, url, error) => AttachmentError( - attachment: attachment, - size: size, - ), - fit: BoxFit.cover, + child: CachedNetworkImage( + height: size?.height, + width: size?.width, + placeholder: (_, __) { + return Container( + width: size?.width, + height: size?.height, + child: Center( + child: CircularProgressIndicator(), + ), + ); + }, + imageUrl: attachment.thumbUrl ?? + attachment.imageUrl ?? + attachment.assetUrl, + errorWidget: (context, url, error) => AttachmentError( + attachment: attachment, + size: size, ), + fit: BoxFit.cover, ), ), ], diff --git a/lib/src/image_attachment.dart b/lib/src/image_attachment.dart index f8ac69af..a4bd1a0f 100644 --- a/lib/src/image_attachment.dart +++ b/lib/src/image_attachment.dart @@ -37,39 +37,36 @@ class ImageAttachment extends StatelessWidget { Column( children: [ Expanded( - child: Hero( - tag: getAttachmentHeroTag(message, attachment), - child: GestureDetector( - onTap: () { - Navigator.push(context, MaterialPageRoute(builder: (_) { - return FullScreenImage( - url: attachment.imageUrl ?? - attachment.assetUrl ?? - attachment.thumbUrl, - ); - })); + child: GestureDetector( + onTap: () { + Navigator.push(context, MaterialPageRoute(builder: (_) { + return FullScreenImage( + url: attachment.imageUrl ?? + attachment.assetUrl ?? + attachment.thumbUrl, + ); + })); + }, + child: CachedNetworkImage( + height: size?.height, + width: size?.width, + placeholder: (_, __) { + return Container( + width: size?.width, + height: size?.height, + child: Center( + child: CircularProgressIndicator(), + ), + ); }, - child: CachedNetworkImage( - height: size?.height, - width: size?.width, - placeholder: (_, __) { - return Container( - width: size?.width, - height: size?.height, - child: Center( - child: CircularProgressIndicator(), - ), - ); - }, - imageUrl: attachment.thumbUrl ?? - attachment.imageUrl ?? - attachment.assetUrl, - errorWidget: (context, url, error) => AttachmentError( - attachment: attachment, - size: size, - ), - fit: BoxFit.cover, + imageUrl: attachment.thumbUrl ?? + attachment.imageUrl ?? + attachment.assetUrl, + errorWidget: (context, url, error) => AttachmentError( + attachment: attachment, + size: size, ), + fit: BoxFit.cover, ), ), ), diff --git a/lib/src/message_list_view.dart b/lib/src/message_list_view.dart index 5750a8a2..85a1b0b0 100644 --- a/lib/src/message_list_view.dart +++ b/lib/src/message_list_view.dart @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import 'package:jiffy/jiffy.dart'; import 'package:stream_chat/stream_chat.dart'; import 'package:stream_chat_flutter/src/message_widget.dart'; +import 'package:stream_chat_flutter/src/system_message.dart'; import 'package:visibility_detector/visibility_detector.dart'; import '../stream_chat_flutter.dart'; @@ -412,6 +413,12 @@ class _MessageListViewState extends State { List messages, int index, ) { + if (message.type == 'system' && message.text?.isNotEmpty == true) { + return SystemMessage( + message: message, + ); + } + final isMyMessage = message.user.id == StreamChat.of(context).user.id; final isLastUser = index + 1 < messages.length && message.user.id == messages[index + 1]?.user?.id; diff --git a/lib/src/system_message.dart b/lib/src/system_message.dart new file mode 100644 index 00000000..7454b0ee --- /dev/null +++ b/lib/src/system_message.dart @@ -0,0 +1,100 @@ +import 'package:flutter/material.dart'; +import 'package:jiffy/jiffy.dart'; +import 'package:stream_chat_flutter/stream_chat_flutter.dart'; + +/// It shows a date divider depending on the date difference +class SystemMessage extends StatelessWidget { + final Message message; + + const SystemMessage({ + Key key, + @required this.message, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + final divider = Expanded( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 8.0), + child: Divider(), + ), + ); + + final createdAt = Jiffy(message.createdAt.toLocal()); + final now = DateTime.now(); + final hourInfo = createdAt.format('h:mm a'); + + String dayInfo; + if (Jiffy(createdAt).isSame(now, Units.DAY)) { + dayInfo = 'TODAY'; + } else if (Jiffy(createdAt) + .isSame(now.subtract(Duration(days: 1)), Units.DAY)) { + dayInfo = 'YESTERDAY'; + } else if (Jiffy(createdAt).isAfter( + now.subtract(Duration(days: 7)), + Units.DAY, + )) { + dayInfo = createdAt.format('EEEE').toUpperCase(); + } else if (Jiffy(createdAt).isAfter( + Jiffy(now).subtract(years: 1), + Units.DAY, + )) { + dayInfo = createdAt.format('dd/MM').toUpperCase(); + } else { + dayInfo = createdAt.format('dd/MM/yyyy').toUpperCase(); + } + + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + divider, + Padding( + padding: const EdgeInsets.symmetric(horizontal: 32.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text( + message.text, + style: TextStyle( + fontSize: 10, + color: Theme.of(context) + .textTheme + .headline6 + .color + .withOpacity(.5), + fontWeight: FontWeight.bold, + ), + ), + Text.rich( + TextSpan( + children: [ + TextSpan( + text: dayInfo, + style: TextStyle( + fontWeight: FontWeight.bold, + ), + ), + TextSpan(text: ' AT'), + TextSpan(text: ' $hourInfo'), + ], + style: TextStyle( + fontWeight: FontWeight.normal, + ), + ), + style: TextStyle( + fontSize: 10, + color: Theme.of(context) + .textTheme + .headline6 + .color + .withOpacity(.5), + ), + ), + ], + ), + ), + divider, + ], + ); + } +} diff --git a/lib/src/utils.dart b/lib/src/utils.dart index 0b9af1e3..c427099b 100644 --- a/lib/src/utils.dart +++ b/lib/src/utils.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'package:url_launcher/url_launcher.dart'; Future launchURL(BuildContext context, String url) async { @@ -13,7 +12,3 @@ Future launchURL(BuildContext context, String url) async { ); } } - -String getAttachmentHeroTag(Message message, Attachment attachment) { - return '${message.id}-${attachment.imageUrl ?? attachment.assetUrl ?? attachment.thumbUrl ?? attachment.ogScrapeUrl}'; -} diff --git a/lib/stream_chat_flutter.dart b/lib/stream_chat_flutter.dart index 9411aea1..3000a503 100644 --- a/lib/stream_chat_flutter.dart +++ b/lib/stream_chat_flutter.dart @@ -22,6 +22,7 @@ export 'src/sending_indicator.dart'; export 'src/stream_channel.dart'; export 'src/stream_chat.dart'; export 'src/stream_chat_theme.dart'; +export 'src/system_message.dart'; export 'src/thread_header.dart'; export 'src/typing_indicator.dart'; export 'src/user_avatar.dart'; diff --git a/pubspec.yaml b/pubspec.yaml index 45b87120..3640ef69 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -21,7 +21,8 @@ dependencies: file_picker: ^1.9.0+1 image_picker: ^0.6.6+1 flutter_keyboard_visibility: ^2.0.0 - stream_chat: ^0.2.0-alpha+15 + stream_chat: + path: ../stream_chat_dart mime: ^0.9.6+3 visibility_detector: ^0.1.5 http_parser: ^3.1.4