From bb58e1341ccea9d86e1d09f0c05c37fc6916a706 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Thu, 16 Apr 2020 10:33:37 +0200 Subject: [PATCH 01/17] fix dependencies errors --- CHANGELOG.md | 2 +- lib/src/message_input.dart | 1 + pubspec.yaml | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 445788e7..d4ce73a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## 0.1.24 +## 0.1.25 - Fx overflow in mentions overlay diff --git a/lib/src/message_input.dart b/lib/src/message_input.dart index 8d3f4f1d..cff17a5f 100644 --- a/lib/src/message_input.dart +++ b/lib/src/message_input.dart @@ -4,6 +4,7 @@ import 'package:file_picker/file_picker.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart'; +import 'package:http_parser/http_parser.dart'; import 'package:image_picker/image_picker.dart'; import 'package:mime/mime.dart'; import 'package:stream_chat/stream_chat.dart'; diff --git a/pubspec.yaml b/pubspec.yaml index 20f3a29c..1d45d21d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: stream_chat_flutter homepage: https://github.com/GetStream/stream-chat-flutter description: Stream Chat official Flutter SDK. Build your own chat experience using Dart and Flutter. -version: 0.1.24 +version: 0.1.25 environment: sdk: ">=2.3.0 <3.0.0" From d81d2f63cd8cffda808df3e021e038649199f807 Mon Sep 17 00:00:00 2001 From: vishtree Date: Sun, 19 Apr 2020 17:25:21 +0200 Subject: [PATCH 02/17] Adding support for one-on-one conversation to channel preview --- lib/src/channel_image.dart | 13 +++++++++++-- lib/src/channel_name.dart | 15 +++++++++++---- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/lib/src/channel_image.dart b/lib/src/channel_image.dart index 8f624bf0..0cc4c16b 100644 --- a/lib/src/channel_image.dart +++ b/lib/src/channel_image.dart @@ -57,11 +57,20 @@ class ChannelImage extends StatelessWidget { @override Widget build(BuildContext context) { + final client = StreamChat.of(context); final channel = this.channel ?? StreamChannel.of(context).channel; return StreamBuilder>( stream: channel.extraDataStream, initialData: channel.extraData, builder: (context, snapshot) { + var image = ''; + if (snapshot.data?.containsKey('image') ?? false) { + image = snapshot.data['image']; + } else if (channel.state.members.length == 2) { + final otherMemberIndex = channel.state.members[0].user.id == client.user.id ? 1 : 0; + image = channel.state.members[otherMemberIndex].user.image; + } + return ClipRRect( borderRadius: StreamChatTheme.of(context) .channelPreviewTheme @@ -75,9 +84,9 @@ class ChannelImage extends StatelessWidget { decoration: BoxDecoration( color: StreamChatTheme.of(context).accentColor, ), - child: snapshot.data?.containsKey('image') ?? false + child: image != '' ? CachedNetworkImage( - imageUrl: snapshot.data['image'], + imageUrl: image, errorWidget: (_, __, ___) { return Center( child: Text( diff --git a/lib/src/channel_name.dart b/lib/src/channel_name.dart index f2f27244..137fdc6b 100644 --- a/lib/src/channel_name.dart +++ b/lib/src/channel_name.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:stream_chat/stream_chat.dart'; +import '../stream_chat_flutter.dart'; import 'stream_channel.dart'; /// It shows the current [Channel] name using a [Text] widget. @@ -21,15 +22,21 @@ class ChannelName extends StatelessWidget { @override Widget build(BuildContext context) { + final client = StreamChat.of(context); final channel = this.channel ?? StreamChannel.of(context).channel; return StreamBuilder>( stream: channel.extraDataStream, initialData: channel.extraData, builder: (context, snapshot) { - return Text( - snapshot.data != null - ? (snapshot.data['name'] ?? channel.cid) - : channel.cid, + var title; + if (snapshot.data['name'] == null && channel.state.members.length == 2) { + final otherMemberIndex = channel.state.members[0].user.id == client.user.id ? 1 : 0; + title = channel.state.members[otherMemberIndex].user.name; + } else { + title = snapshot.data['name'] ?? channel.id; + } + + return Text(title, style: textStyle, ); }, From 3ff6a1922948468019b4b943329dff9a317909fe Mon Sep 17 00:00:00 2001 From: vishtree Date: Sun, 19 Apr 2020 22:23:48 +0200 Subject: [PATCH 03/17] Code cleanup for finding other member of direct conversation --- lib/src/channel_image.dart | 8 +++++--- lib/src/channel_name.dart | 6 ++++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/src/channel_image.dart b/lib/src/channel_image.dart index 0cc4c16b..45363064 100644 --- a/lib/src/channel_image.dart +++ b/lib/src/channel_image.dart @@ -64,11 +64,13 @@ class ChannelImage extends StatelessWidget { initialData: channel.extraData, builder: (context, snapshot) { var image = ''; - if (snapshot.data?.containsKey('image') ?? false) { + if (snapshot.data?.containsKey('image') == true) { image = snapshot.data['image']; } else if (channel.state.members.length == 2) { - final otherMemberIndex = channel.state.members[0].user.id == client.user.id ? 1 : 0; - image = channel.state.members[otherMemberIndex].user.image; + final otherMember = channel.state.members.firstWhere( + (member) => member.user.id != client.user.id + ); + image = otherMember.user.image; } return ClipRRect( diff --git a/lib/src/channel_name.dart b/lib/src/channel_name.dart index 137fdc6b..ce563804 100644 --- a/lib/src/channel_name.dart +++ b/lib/src/channel_name.dart @@ -30,8 +30,10 @@ class ChannelName extends StatelessWidget { builder: (context, snapshot) { var title; if (snapshot.data['name'] == null && channel.state.members.length == 2) { - final otherMemberIndex = channel.state.members[0].user.id == client.user.id ? 1 : 0; - title = channel.state.members[otherMemberIndex].user.name; + final otherMember = channel.state.members.firstWhere( + (member) => member.user.id != client.user.id + ); + title = otherMember.user.name; } else { title = snapshot.data['name'] ?? channel.id; } From 3e8d34a622fb8836fe990fcf6d00b7a5ceb94195 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Sun, 19 Apr 2020 23:37:18 +0200 Subject: [PATCH 04/17] fix channel image and user avatar widget size --- lib/src/channel_image.dart | 26 +++++++++++++------------- lib/src/channel_name.dart | 13 +++++++------ lib/src/user_avatar.dart | 6 +++--- 3 files changed, 23 insertions(+), 22 deletions(-) diff --git a/lib/src/channel_image.dart b/lib/src/channel_image.dart index 45363064..6ecbc861 100644 --- a/lib/src/channel_image.dart +++ b/lib/src/channel_image.dart @@ -38,7 +38,7 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart'; /// The widget uses a [StreamBuilder] to render the channel information image as soon as it updates. /// /// By default the widget radius size is 40x40 pixels. -/// Set the property [size] to set a custom dimension. +/// Set the property [constraints] to set a custom dimension. /// /// The widget renders the ui based on the first ancestor of type [StreamChatTheme]. /// Modify it to change the widget appearance. @@ -46,14 +46,14 @@ class ChannelImage extends StatelessWidget { const ChannelImage({ Key key, this.channel, - this.size = 40, + this.constraints, }) : super(key: key); /// The channel to show the image of final Channel channel; /// The diameter of the image - final double size; + final BoxConstraints constraints; @override Widget build(BuildContext context) { @@ -63,14 +63,13 @@ class ChannelImage extends StatelessWidget { stream: channel.extraDataStream, initialData: channel.extraData, builder: (context, snapshot) { - var image = ''; + String image; if (snapshot.data?.containsKey('image') == true) { image = snapshot.data['image']; } else if (channel.state.members.length == 2) { - final otherMember = channel.state.members.firstWhere( - (member) => member.user.id != client.user.id - ); - image = otherMember.user.image; + final otherMember = channel.state.members + .firstWhere((member) => member.user.id != client.user.id); + image = otherMember.user.extraData['image']; } return ClipRRect( @@ -79,14 +78,15 @@ class ChannelImage extends StatelessWidget { .avatarTheme .borderRadius, child: Container( - constraints: StreamChatTheme.of(context) - .channelPreviewTheme - .avatarTheme - .constraints, + constraints: constraints ?? + StreamChatTheme.of(context) + .channelPreviewTheme + .avatarTheme + .constraints, decoration: BoxDecoration( color: StreamChatTheme.of(context).accentColor, ), - child: image != '' + child: image != null ? CachedNetworkImage( imageUrl: image, errorWidget: (_, __, ___) { diff --git a/lib/src/channel_name.dart b/lib/src/channel_name.dart index ce563804..2200b351 100644 --- a/lib/src/channel_name.dart +++ b/lib/src/channel_name.dart @@ -28,17 +28,18 @@ class ChannelName extends StatelessWidget { stream: channel.extraDataStream, initialData: channel.extraData, builder: (context, snapshot) { - var title; - if (snapshot.data['name'] == null && channel.state.members.length == 2) { - final otherMember = channel.state.members.firstWhere( - (member) => member.user.id != client.user.id - ); + String title; + if (snapshot.data['name'] == null && + channel.state.members.length == 2) { + final otherMember = channel.state.members + .firstWhere((member) => member.user.id != client.user.id); title = otherMember.user.name; } else { title = snapshot.data['name'] ?? channel.id; } - return Text(title, + return Text( + title, style: textStyle, ); }, diff --git a/lib/src/user_avatar.dart b/lib/src/user_avatar.dart index 478ae3b3..aaaa6a27 100644 --- a/lib/src/user_avatar.dart +++ b/lib/src/user_avatar.dart @@ -8,11 +8,11 @@ class UserAvatar extends StatelessWidget { const UserAvatar({ Key key, @required this.user, - this.radius = 16, + this.constraints, }) : super(key: key); final User user; - final double radius; + final BoxConstraints constraints; @override Widget build(BuildContext context) { @@ -20,7 +20,7 @@ class UserAvatar extends StatelessWidget { borderRadius: StreamChatTheme.of(context).ownMessageTheme.avatarTheme.borderRadius, child: Container( - constraints: + constraints: constraints ?? StreamChatTheme.of(context).ownMessageTheme.avatarTheme.constraints, decoration: BoxDecoration( color: StreamChatTheme.of(context).accentColor, From 1b8875d2eaabda7d890f146910a9e6f57462fce0 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Sun, 19 Apr 2020 23:40:22 +0200 Subject: [PATCH 05/17] version bump --- CHANGELOG.md | 4 ++++ pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d4ce73a7..3c12fbe9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.26 + +- Show other member user's name and image in one to one channels + ## 0.1.25 - Fx overflow in mentions overlay diff --git a/pubspec.yaml b/pubspec.yaml index 1d45d21d..3aafdac9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: stream_chat_flutter homepage: https://github.com/GetStream/stream-chat-flutter description: Stream Chat official Flutter SDK. Build your own chat experience using Dart and Flutter. -version: 0.1.25 +version: 0.1.26 environment: sdk: ">=2.3.0 <3.0.0" From a21319d88e815f1d65069b51100adfdf9e1ad3f8 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Sun, 19 Apr 2020 23:50:24 +0200 Subject: [PATCH 06/17] update dependencies --- CHANGELOG.md | 2 +- lib/src/message_input.dart | 28 ++++++++++++++-------------- pubspec.yaml | 10 +++++----- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c12fbe9..13377276 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## 0.1.26 +## 0.1.27 - Show other member user's name and image in one to one channels diff --git a/lib/src/message_input.dart b/lib/src/message_input.dart index cff17a5f..5c725e8b 100644 --- a/lib/src/message_input.dart +++ b/lib/src/message_input.dart @@ -1,3 +1,4 @@ +import 'dart:async'; import 'dart:io'; import 'package:file_picker/file_picker.dart'; @@ -760,7 +761,7 @@ class _MessageInputState extends State { }); } - int _keyboardListener; + StreamSubscription _keyboardListener; @override void initState() { @@ -768,16 +769,8 @@ class _MessageInputState extends State { StreamChannel.of(context).queryMembersAndWatchers(); - _keyboardListener = KeyboardVisibilityNotification().addNewListener( - onHide: () { - if (_commandsOverlay != null) { - _commandsOverlay.remove(); - } - if (_mentionsOverlay != null) { - _mentionsOverlay.remove(); - } - }, - onShow: () { + _keyboardListener = KeyboardVisibility.onChange.listen((visible) { + if (visible) { if (_commandsOverlay != null) { if (_textController.text.startsWith('/')) { WidgetsBinding.instance.addPostFrameCallback((_) { @@ -795,8 +788,15 @@ class _MessageInputState extends State { }); } } - }, - ); + } else { + if (_commandsOverlay != null) { + _commandsOverlay.remove(); + } + if (_mentionsOverlay != null) { + _mentionsOverlay.remove(); + } + } + }); if (widget.editMessage != null) { _textController = TextEditingController(text: widget.editMessage.text); @@ -837,7 +837,7 @@ class _MessageInputState extends State { void dispose() { _commandsOverlay?.remove(); _mentionsOverlay?.remove(); - KeyboardVisibilityNotification().removeListener(_keyboardListener); + _keyboardListener.cancel(); super.dispose(); } diff --git a/pubspec.yaml b/pubspec.yaml index 3aafdac9..e1f09feb 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: stream_chat_flutter homepage: https://github.com/GetStream/stream-chat-flutter description: Stream Chat official Flutter SDK. Build your own chat experience using Dart and Flutter. -version: 0.1.26 +version: 0.1.27 environment: sdk: ">=2.3.0 <3.0.0" @@ -9,16 +9,16 @@ environment: dependencies: flutter: sdk: flutter - rxdart: ^0.23.1 + rxdart: ^0.24.0 jiffy: ^3.0.1 cached_network_image: ^2.1.0+1 - flutter_markdown: ^0.3.4 + flutter_markdown: ^0.3.5 url_launcher: ^5.4.2 video_player: ^0.10.8+1 chewie: ^0.9.10 - file_picker: ^1.6.2 + file_picker: ^1.6.3+1 image_picker: ^0.6.5 - flutter_keyboard_visibility: ^0.8.0 + flutter_keyboard_visibility: ^2.0.0 stream_chat: ^0.1.21 mime: ^0.9.6+3 visibility_detector: ^0.1.4 From b304979866e788d6e74a5c45c519721d9d00a582 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Mon, 20 Apr 2020 11:49:42 +0200 Subject: [PATCH 07/17] refs #35: add title on tap --- lib/src/channel_header.dart | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/lib/src/channel_header.dart b/lib/src/channel_header.dart index ae68bcb7..3d55c429 100644 --- a/lib/src/channel_header.dart +++ b/lib/src/channel_header.dart @@ -57,11 +57,15 @@ class ChannelHeader extends StatelessWidget implements PreferredSizeWidget { /// By default it calls [Navigator.pop] final VoidCallback onBackPressed; + /// Callback to call when pressing the header is tapped. + final VoidCallback onTitleTap; + /// Creates a channel header ChannelHeader({ Key key, this.showBackButton = true, this.onBackPressed, + this.onTitleTap, }) : preferredSize = Size.fromHeight(kToolbarHeight), super(key: key); @@ -86,17 +90,25 @@ class ChannelHeader extends StatelessWidget implements PreferredSizeWidget { ), ], centerTitle: true, - title: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - ChannelName( - textStyle: StreamChatTheme.of(context) - .channelTheme - .channelHeaderTheme - .title, + title: InkWell( + onTap: () {}, + child: Container( + height: preferredSize.height, + width: preferredSize.width, + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ChannelName( + textStyle: StreamChatTheme.of(context) + .channelTheme + .channelHeaderTheme + .title, + ), + _buildLastActive(context, channel), + ], ), - _buildLastActive(context, channel), - ], + ), ), ); } From 9ad7d56217b0eabcaea0453d879e7897b512884d Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Mon, 20 Apr 2020 12:11:59 +0200 Subject: [PATCH 08/17] add image on tap --- lib/src/channel_header.dart | 18 +++++++------ lib/src/channel_image.dart | 53 ++++++++++++++++++++++++------------- 2 files changed, 44 insertions(+), 27 deletions(-) diff --git a/lib/src/channel_header.dart b/lib/src/channel_header.dart index 3d55c429..659a24eb 100644 --- a/lib/src/channel_header.dart +++ b/lib/src/channel_header.dart @@ -57,15 +57,19 @@ class ChannelHeader extends StatelessWidget implements PreferredSizeWidget { /// By default it calls [Navigator.pop] final VoidCallback onBackPressed; - /// Callback to call when pressing the header is tapped. + /// Callback to call when the header is tapped. final VoidCallback onTitleTap; + /// Callback to call when the image is tapped. + final VoidCallback onImageTap; + /// Creates a channel header ChannelHeader({ Key key, this.showBackButton = true, this.onBackPressed, this.onTitleTap, + this.onImageTap, }) : preferredSize = Size.fromHeight(kToolbarHeight), super(key: key); @@ -80,18 +84,16 @@ class ChannelHeader extends StatelessWidget implements PreferredSizeWidget { actions: [ Padding( padding: const EdgeInsets.only(right: 10.0), - child: Stack( - children: [ - Center( - child: ChannelImage(), - ), - ], + child: Center( + child: ChannelImage( + onTap: onImageTap, + ), ), ), ], centerTitle: true, title: InkWell( - onTap: () {}, + onTap: onTitleTap, child: Container( height: preferredSize.height, width: preferredSize.width, diff --git a/lib/src/channel_image.dart b/lib/src/channel_image.dart index 6ecbc861..7d674ac1 100644 --- a/lib/src/channel_image.dart +++ b/lib/src/channel_image.dart @@ -47,6 +47,7 @@ class ChannelImage extends StatelessWidget { Key key, this.channel, this.constraints, + this.onTap, }) : super(key: key); /// The channel to show the image of @@ -55,6 +56,9 @@ class ChannelImage extends StatelessWidget { /// The diameter of the image final BoxConstraints constraints; + /// The function called when the image is tapped + final VoidCallback onTap; + @override Widget build(BuildContext context) { final client = StreamChat.of(context); @@ -86,25 +90,36 @@ class ChannelImage extends StatelessWidget { decoration: BoxDecoration( color: StreamChatTheme.of(context).accentColor, ), - child: image != null - ? CachedNetworkImage( - imageUrl: image, - errorWidget: (_, __, ___) { - return Center( - child: Text( - snapshot.data?.containsKey('name') ?? false - ? snapshot.data['name'][0] - : '', - style: TextStyle( - color: Colors.white, - fontWeight: FontWeight.bold, - ), - ), - ); - }, - fit: BoxFit.cover, - ) - : SizedBox(), + child: Stack( + fit: StackFit.expand, + children: [ + image != null + ? CachedNetworkImage( + imageUrl: image, + errorWidget: (_, __, ___) { + return Center( + child: Text( + snapshot.data?.containsKey('name') ?? false + ? snapshot.data['name'][0] + : '', + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + ), + ), + ); + }, + fit: BoxFit.cover, + ) + : SizedBox(), + Material( + color: Colors.transparent, + child: InkWell( + onTap: onTap, + ), + ), + ], + ), ), ); }); From e02e1be174deea3910b8dab61c6e1b8b51515fd8 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Mon, 20 Apr 2020 12:21:42 +0200 Subject: [PATCH 09/17] add image on tap to channel preview --- lib/src/channel_list_view.dart | 29 ++++++++++++++++++----------- lib/src/channel_preview.dart | 8 +++++++- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/lib/src/channel_list_view.dart b/lib/src/channel_list_view.dart index e968e6c0..1d5992c7 100644 --- a/lib/src/channel_list_view.dart +++ b/lib/src/channel_list_view.dart @@ -56,6 +56,7 @@ class ChannelListView extends StatefulWidget { this.channelWidget, this.channelPreviewBuilder, this.errorBuilder, + this.onImageTap, }) : super(key: key); final Widget Function(Error error) errorBuilder; @@ -94,6 +95,9 @@ class ChannelListView extends StatefulWidget { /// Builder used to create a custom channel preview final ChannelPreviewBuilder channelPreviewBuilder; + /// The function called when the image is tapped + final Function(Channel) onImageTap; + @override _ChannelListViewState createState() => _ChannelListViewState(); } @@ -215,8 +219,6 @@ class _ChannelListViewState extends State { if (i < channels.length) { final channel = channels[i]; - final channelClient = streamChat.client.channels[channel.cid]; - ChannelTapCallback onTap; if (widget.onChannelTap != null) { onTap = widget.onChannelTap; @@ -237,11 +239,11 @@ class _ChannelListViewState extends State { } return StreamChannel( - key: ValueKey('CHANNEL-${channelClient.id}'), - channel: channelClient, + key: ValueKey('CHANNEL-${channel.id}'), + channel: channel, child: StreamBuilder( - initialData: channelClient.updatedAt, - stream: channelClient.updatedAtStream, + initialData: channel.updatedAt, + stream: channel.updatedAtStream, builder: (context, snapshot) { Widget child; if (widget.channelPreviewBuilder != null) { @@ -249,14 +251,14 @@ class _ChannelListViewState extends State { children: [ widget.channelPreviewBuilder( context, - channelClient, + channel, ), Positioned.fill( child: Material( color: Colors.transparent, child: InkWell( onTap: () { - onTap(channelClient, widget.channelWidget); + onTap(channel, widget.channelWidget); }, ), ), @@ -265,9 +267,14 @@ class _ChannelListViewState extends State { ); } else { child = ChannelPreview( - channel: channelClient, - onTap: (channelClient) { - onTap(channelClient, widget.channelWidget); + channel: channel, + onImageTap: widget.onImageTap != null + ? () { + widget.onImageTap(channel); + } + : null, + onTap: (channel) { + onTap(channel, widget.channelWidget); }, ); } diff --git a/lib/src/channel_preview.dart b/lib/src/channel_preview.dart index b6e3beba..9b949a68 100644 --- a/lib/src/channel_preview.dart +++ b/lib/src/channel_preview.dart @@ -25,10 +25,14 @@ class ChannelPreview extends StatelessWidget { /// Channel displayed final Channel channel; + /// The function called when the image is tapped + final VoidCallback onImageTap; + ChannelPreview({ @required this.channel, Key key, this.onTap, + this.onImageTap, }) : super(key: key); @override @@ -37,7 +41,9 @@ class ChannelPreview extends StatelessWidget { onTap: () { onTap(channel); }, - leading: ChannelImage(), + leading: ChannelImage( + onTap: onImageTap, + ), title: ChannelName( textStyle: StreamChatTheme.of(context).channelPreviewTheme.title, ), From 0b039bf2f2931dfc55f5f73db4e9c114703a22d5 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Mon, 20 Apr 2020 12:33:53 +0200 Subject: [PATCH 10/17] version bump --- CHANGELOG.md | 10 +++++++++- pubspec.yaml | 6 +++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 13377276..32eaeb30 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,18 @@ +## 0.1.28 + +- Add `onTap` to `ChannelImage` + +- Add `onImageTap` and `onTitleTap` to `ChannelHeader` + +- Add `onImageTap` to `ChannelListView` + ## 0.1.27 - Show other member user's name and image in one to one channels ## 0.1.25 -- Fx overflow in mentions overlay +- Fix overflow in mentions overlay ## 0.1.23 diff --git a/pubspec.yaml b/pubspec.yaml index e1f09feb..9a3de2bc 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: stream_chat_flutter homepage: https://github.com/GetStream/stream-chat-flutter description: Stream Chat official Flutter SDK. Build your own chat experience using Dart and Flutter. -version: 0.1.27 +version: 0.1.28 environment: sdk: ">=2.3.0 <3.0.0" @@ -16,10 +16,10 @@ dependencies: url_launcher: ^5.4.2 video_player: ^0.10.8+1 chewie: ^0.9.10 - file_picker: ^1.6.3+1 + file_picker: ^1.6.3+2 image_picker: ^0.6.5 flutter_keyboard_visibility: ^2.0.0 - stream_chat: ^0.1.21 + stream_chat: ^0.1.27 mime: ^0.9.6+3 visibility_detector: ^0.1.4 http_parser: ^3.1.4 From 4957619707cee2b326d4f4a7d7fa8b8a68f83bd8 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 21 Apr 2020 10:24:15 +0200 Subject: [PATCH 11/17] fix message divider for week and years --- lib/src/message_list_view.dart | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/src/message_list_view.dart b/lib/src/message_list_view.dart index 2476c69e..468bf054 100644 --- a/lib/src/message_list_view.dart +++ b/lib/src/message_list_view.dart @@ -241,8 +241,18 @@ class _MessageListViewState extends State { } else if (Jiffy(createdAt) .isSame(now.subtract(Duration(days: 1)), Units.DAY)) { dayInfo = 'YESTERDAY'; - } else { + } 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 Column( From a156f7bdc2b9d609fcb3fdd1e22bf277ee6137c4 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 21 Apr 2020 15:35:19 +0200 Subject: [PATCH 12/17] refs #27: add upload image/file function parameters to MessageInput --- lib/src/message_input.dart | 90 ++++++++++++++++++++++++++----------- lib/src/message_widget.dart | 3 +- 2 files changed, 67 insertions(+), 26 deletions(-) diff --git a/lib/src/message_input.dart b/lib/src/message_input.dart index 5c725e8b..5788d293 100644 --- a/lib/src/message_input.dart +++ b/lib/src/message_input.dart @@ -16,6 +16,8 @@ import 'package:stream_chat_flutter/src/user_avatar.dart'; import '../stream_chat_flutter.dart'; import 'stream_channel.dart'; +typedef FileUploader = Future Function(File, Channel); + /// Inactive state /// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/screenshots/message_input.png) /// ![screenshot](https://raw.githubusercontent.com/GetStream/stream-chat-flutter/master/screenshots/message_input_paint.png) @@ -67,6 +69,8 @@ class MessageInput extends StatefulWidget { this.maxHeight = 150, this.keyboardType = TextInputType.multiline, this.disableAttachments = false, + this.doImageUploadRequest, + this.doFileUploadRequest, }) : super(key: key); /// Message to edit @@ -87,14 +91,25 @@ class MessageInput extends StatefulWidget { /// If true the attachments button will not be displayed final bool disableAttachments; + /// Override image upload request + final FileUploader doImageUploadRequest; + + /// Override file upload request + final FileUploader doFileUploadRequest; + @override - _MessageInputState createState() => _MessageInputState(); + _MessageInputState createState() => _MessageInputState( + doFileUploadRequest: doFileUploadRequest, + doImageUploadRequest: doImageUploadRequest, + ); } class _MessageInputState extends State { final List<_SendingAttachment> _attachments = []; final _focusNode = FocusNode(); final List _mentionedUsers = []; + FileUploader doImageUploadRequest; + FileUploader doFileUploadRequest; TextEditingController _textController; bool _inputEnabled = true; @@ -102,6 +117,14 @@ class _MessageInputState extends State { bool _typingStarted = false; OverlayEntry _commandsOverlay, _mentionsOverlay; + _MessageInputState({ + this.doImageUploadRequest, + this.doFileUploadRequest, + }) { + doImageUploadRequest ??= _uploadImage; + doFileUploadRequest ??= _uploadFile; + } + @override Widget build(BuildContext context) { return SafeArea( @@ -616,8 +639,6 @@ class _MessageInputState extends State { final channel = StreamChannel.of(context).channel; - final bytes = await file.readAsBytes(); - final attachment = _SendingAttachment( file: file, type: type, @@ -627,28 +648,7 @@ class _MessageInputState extends State { _attachments.add(attachment); }); - String url; - final filename = file.path.split('/').last; - - if (type == FileType.image) { - final res = await channel.sendImage( - MultipartFile.fromBytes( - bytes, - filename: filename, - contentType: MediaType.parse(lookupMimeType(filename)), - ), - ); - url = res.file; - } else { - final res = await channel.sendFile( - MultipartFile.fromBytes( - bytes, - filename: filename, - contentType: MediaType.parse(lookupMimeType(filename)), - ), - ); - url = res.file; - } + final url = await _uploadAttachment(file, type, channel); attachment.url = url; @@ -657,6 +657,46 @@ class _MessageInputState extends State { }); } + Future _uploadAttachment( + File file, + FileType type, + Channel channel, + ) async { + String url; + if (type == FileType.image) { + url = await doImageUploadRequest(file, channel); + } else { + url = await doFileUploadRequest(file, channel); + } + return url; + } + + Future _uploadImage(File file, Channel channel) async { + final filename = file.path.split('/').last; + final bytes = await file.readAsBytes(); + final res = await channel.sendImage( + MultipartFile.fromBytes( + bytes, + filename: filename, + contentType: MediaType.parse(lookupMimeType(filename)), + ), + ); + return res.file; + } + + Future _uploadFile(File file, Channel channel) async { + final filename = file.path.split('/').last; + final bytes = await file.readAsBytes(); + final res = await channel.sendFile( + MultipartFile.fromBytes( + bytes, + filename: filename, + contentType: MediaType.parse(lookupMimeType(filename)), + ), + ); + return res.file; + } + Widget _buildSendButton(BuildContext context) { return IconTheme( data: diff --git a/lib/src/message_widget.dart b/lib/src/message_widget.dart index acd1ff58..d0802488 100644 --- a/lib/src/message_widget.dart +++ b/lib/src/message_widget.dart @@ -154,7 +154,8 @@ class _MessageWidgetState extends State UserAvatar(user: widget.message.user), if (_isMyMessage && widget.nextMessage == null && - widget.message.status == MessageSendingStatus.SENT) + (widget.message.status == MessageSendingStatus.SENT || + widget.message.status == null)) Padding( padding: const EdgeInsets.symmetric( horizontal: 1.0, From 95b0c991a190fad06eb90ee405c6499b5ea11715 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 21 Apr 2020 15:50:44 +0200 Subject: [PATCH 13/17] version bump --- CHANGELOG.md | 4 ++++ pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 32eaeb30..2cc31ca3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.29 + +- Add `doImageUploadRequest` and `doFileUploadRequest` to `MessageInput` to let users customize file uploading (eg: custom cdn) + ## 0.1.28 - Add `onTap` to `ChannelImage` diff --git a/pubspec.yaml b/pubspec.yaml index 9a3de2bc..4dbe6911 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: stream_chat_flutter homepage: https://github.com/GetStream/stream-chat-flutter description: Stream Chat official Flutter SDK. Build your own chat experience using Dart and Flutter. -version: 0.1.28 +version: 0.1.29 environment: sdk: ">=2.3.0 <3.0.0" From fee0eff11f718ddc20764759c200b7b2562472b9 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 21 Apr 2020 16:36:53 +0200 Subject: [PATCH 14/17] add simple rendering of files --- lib/src/message_widget.dart | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/lib/src/message_widget.dart b/lib/src/message_widget.dart index d0802488..18a8cfdd 100644 --- a/lib/src/message_widget.dart +++ b/lib/src/message_widget.dart @@ -301,6 +301,21 @@ class _MessageWidgetState extends State attachmentWidget = _buildVideo(attachment); } else if (attachment.type == 'image' || attachment.type == 'giphy') { attachmentWidget = _buildImage(attachment); + } else if (attachment.type == 'file') { + attachmentWidget = Material( + child: InkWell( + onTap: () { + _launchURL(attachment.assetUrl); + }, + child: Container( + width: 100, + height: 100, + child: Center( + child: Icon(Icons.attach_file), + ), + ), + ), + ); } if (attachmentWidget != null) { From 50f26007bd1159c0d42ca7dd8c8f7b713409c86e Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 21 Apr 2020 16:38:23 +0200 Subject: [PATCH 15/17] version bump --- CHANGELOG.md | 4 ++++ pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2cc31ca3..9c530887 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.30 + +- Add simple rendering of file attachments + ## 0.1.29 - Add `doImageUploadRequest` and `doFileUploadRequest` to `MessageInput` to let users customize file uploading (eg: custom cdn) diff --git a/pubspec.yaml b/pubspec.yaml index 4dbe6911..45ae9eda 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: stream_chat_flutter homepage: https://github.com/GetStream/stream-chat-flutter description: Stream Chat official Flutter SDK. Build your own chat experience using Dart and Flutter. -version: 0.1.29 +version: 0.1.30 environment: sdk: ">=2.3.0 <3.0.0" From 48ac6da7b2b83e3df54b90773c10aad36799c022 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 21 Apr 2020 17:16:15 +0200 Subject: [PATCH 16/17] add initialMessage property to MessageInput --- lib/src/message_input.dart | 70 ++++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 30 deletions(-) diff --git a/lib/src/message_input.dart b/lib/src/message_input.dart index 5788d293..6338732b 100644 --- a/lib/src/message_input.dart +++ b/lib/src/message_input.dart @@ -71,11 +71,15 @@ class MessageInput extends StatefulWidget { this.disableAttachments = false, this.doImageUploadRequest, this.doFileUploadRequest, + this.initialMessage, }) : super(key: key); /// Message to edit final Message editMessage; + /// Message to start with + final Message initialMessage; + /// Function called after sending the message final void Function(Message) onMessageSent; @@ -763,7 +767,7 @@ class _MessageInputState extends State { sendingFuture = StreamChat.of(context).client.updateMessage(message); } else { - message = Message( + message = (widget.initialMessage ?? Message()).copyWith( parentId: widget.parentMessage?.id, text: text, attachments: _getAttachments(attachments).toList(), @@ -839,40 +843,46 @@ class _MessageInputState extends State { }); if (widget.editMessage != null) { - _textController = TextEditingController(text: widget.editMessage.text); - - _typingStarted = true; - _messageIsPresent = true; - - widget.editMessage.attachments.forEach((attachment) { - if (attachment.type == 'image') { - _attachments.add(_SendingAttachment( - type: FileType.image, - url: attachment.imageUrl ?? - attachment.assetUrl ?? - attachment.thumbUrl ?? - attachment.ogScrapeUrl, - uploaded: true, - )); - } else if (attachment.type == 'video') { - _attachments.add(_SendingAttachment( - type: FileType.video, - url: attachment.assetUrl, - uploaded: true, - )); - } else if (attachment.type != 'giphy') { - _attachments.add(_SendingAttachment( - type: FileType.any, - url: attachment.assetUrl, - uploaded: true, - )); - } - }); + _parseExistingMessage(widget.editMessage); + } else if (widget.initialMessage != null) { + _parseExistingMessage(widget.initialMessage); } else { _textController = TextEditingController(); } } + void _parseExistingMessage(Message message) { + _textController = TextEditingController(text: message.text); + + _typingStarted = true; + _messageIsPresent = true; + + message.attachments?.forEach((attachment) { + if (attachment.type == 'image') { + _attachments.add(_SendingAttachment( + type: FileType.image, + url: attachment.imageUrl ?? + attachment.assetUrl ?? + attachment.thumbUrl ?? + attachment.ogScrapeUrl, + uploaded: true, + )); + } else if (attachment.type == 'video') { + _attachments.add(_SendingAttachment( + type: FileType.video, + url: attachment.assetUrl, + uploaded: true, + )); + } else if (attachment.type != 'giphy') { + _attachments.add(_SendingAttachment( + type: FileType.any, + url: attachment.assetUrl, + uploaded: true, + )); + } + }); + } + @override void dispose() { _commandsOverlay?.remove(); From 6356decd186a74d70586da964d27703fe736e59f Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 21 Apr 2020 18:05:22 +0200 Subject: [PATCH 17/17] version bump --- CHANGELOG.md | 4 ++++ pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c530887..a79a2b66 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.31 + +- Add `initialMessage` property to `MessageInput` + ## 0.1.30 - Add simple rendering of file attachments diff --git a/pubspec.yaml b/pubspec.yaml index 45ae9eda..148745a0 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: stream_chat_flutter homepage: https://github.com/GetStream/stream-chat-flutter description: Stream Chat official Flutter SDK. Build your own chat experience using Dart and Flutter. -version: 0.1.30 +version: 0.1.31 environment: sdk: ">=2.3.0 <3.0.0"