From e27b45e4f88eb6cfbc01f5ae609e71b2f6127c15 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Thu, 5 Nov 2020 09:50:08 +0100 Subject: [PATCH 01/11] use scrollable_positioned_list --- lib/src/message_list_view.dart | 400 ++++++++++++++++----------------- pubspec.yaml | 2 +- 2 files changed, 194 insertions(+), 208 deletions(-) diff --git a/lib/src/message_list_view.dart b/lib/src/message_list_view.dart index bb0f98c0..d2e1d972 100644 --- a/lib/src/message_list_view.dart +++ b/lib/src/message_list_view.dart @@ -1,12 +1,13 @@ import 'dart:async'; +import 'dart:math'; import 'package:flutter/material.dart'; import 'package:jiffy/jiffy.dart'; +import 'package:scrollable_positioned_list/scrollable_positioned_list.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 'package:widgets_visibility_provider/widgets_visibility_provider.dart'; import '../stream_chat_flutter.dart'; import 'date_divider.dart'; @@ -106,7 +107,10 @@ class MessageListView extends StatefulWidget { this.onThreadTap, this.dateDividerBuilder, this.scrollPhysics = const AlwaysScrollableScrollPhysics(), - this.keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual, + this.initialScrollIndex, + this.initialAlignment, + this.scrollController, + this.itemPositionListener, }) : super(key: key); /// Function used to build a custom message widget @@ -131,95 +135,101 @@ class MessageListView extends StatefulWidget { /// Builder used to render date dividers final Widget Function(DateTime) dateDividerBuilder; + /// Index of an item to initially align within the viewport. + final int initialScrollIndex; + + /// Determines where the leading edge of the item at [initialScrollIndex] + /// should be placed. + final double initialAlignment; + + /// Controller for jumping or scrolling to an item. + final ItemScrollController scrollController; + + /// Provides a listenable iterable of [itemPositions] of items that are on + /// screen and their locations. + final ItemPositionsListener itemPositionListener; + /// The ScrollPhysics used by the ListView final ScrollPhysics scrollPhysics; - /// The [ScrollViewKeyboardDismissBehavior] used by the ListView - final ScrollViewKeyboardDismissBehavior keyboardDismissBehavior; - @override _MessageListViewState createState() => _MessageListViewState(); } class _MessageListViewState extends State { - static const _newMessageLoadingOffset = 100; - final ScrollController _scrollController = ScrollController(); - bool _bottomWasVisible = true; + ItemScrollController _scrollController; + bool _bottomWasVisible = false; bool _topWasVisible = false; - List _messages = []; - List _newMessageList = []; Function _onThreadTap; bool _showScrollToBottom = false; + ItemPositionsListener _itemPositionListener; @override Widget build(BuildContext context) { final streamChannel = StreamChannel.of(context); - /// TODO: find a better solution when (https://github.com/flutter/flutter/issues/21023) is fixed - return WidgetsVisibilityProvider( - condition: (positionData) => - positionData.endPosition >= 20 && - positionData.startPosition <= positionData.viewportSize, - child: Stack( - alignment: Alignment.center, - children: [ - NotificationListener( - onNotification: (_) { - if (_scrollController.offset < 150 && - _newMessageList.isNotEmpty) { - setState(() { - _messages.insertAll(0, _newMessageList); - _newMessageList.clear(); - }); - } - return true; - }, - child: ListView.custom( - key: Key('messageListView'), - physics: widget.scrollPhysics, - keyboardDismissBehavior: widget.keyboardDismissBehavior, - controller: _scrollController, - reverse: true, - childrenDelegate: SliverChildBuilderDelegate( - (context, i) { - if (i == _messages.length + 1) { - if (widget.parentMessage != null) { - if (widget.parentMessageBuilder != null) { - return widget.parentMessageBuilder( - context, - widget.parentMessage, - ); - } else { - return Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - buildParentMessage(widget.parentMessage), - Padding( - padding: - const EdgeInsets.symmetric(horizontal: 32), - child: Container( - padding: const EdgeInsets.all(8), - child: Text( - 'Start of thread', - textAlign: TextAlign.center, - ), - color: - Theme.of(context).accentColor.withAlpha(50), - ), - ), - ], - ); - } + final messagesStream = widget.parentMessage != null + ? streamChannel.channel.state.threadsStream + .where((threads) => threads.containsKey(widget.parentMessage.id)) + .map((threads) => threads[widget.parentMessage.id]) + : streamChannel.channel.state.messagesStream; + + return StreamBuilder>( + stream: messagesStream, + initialData: widget.parentMessage != null + ? streamChannel.channel.state.threads[widget.parentMessage.id] + : streamChannel.channel.state.messages, + builder: (context, snapshot) { + final messages = snapshot.data?.reversed?.toList() ?? []; + return Stack( + alignment: Alignment.center, + children: [ + ScrollablePositionedList.builder( + itemPositionsListener: _itemPositionListener, + addAutomaticKeepAlives: true, + key: Key('messageListView'), + initialScrollIndex: widget.initialScrollIndex, + initialAlignment: widget.initialAlignment, + physics: widget.scrollPhysics, + itemScrollController: _scrollController, + reverse: true, + itemCount: messages.length + + 1 + + (widget.parentMessage != null ? 1 : 0), + itemBuilder: (context, i) { + if (i == messages.length + 1) { + if (widget.parentMessageBuilder != null) { + return widget.parentMessageBuilder( + context, + widget.parentMessage, + ); } else { - return SizedBox(); + return Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + buildParentMessage(widget.parentMessage), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 32), + child: Container( + padding: const EdgeInsets.all(8), + child: Text( + 'Start of thread', + textAlign: TextAlign.center, + ), + color: + Theme.of(context).accentColor.withAlpha(50), + ), + ), + ], + ); } } - if (i == _messages.length) { + if (i == messages.length) { return _buildLoadingIndicator(streamChannel); } - final message = _messages[i]; - final nextMessage = i > 0 ? _messages[i - 1] : null; + final message = messages[i]; + final nextMessage = i > 0 ? messages[i - 1] : null; Widget messageWidget; @@ -227,14 +237,14 @@ class _MessageListViewState extends State { messageWidget = _buildBottomMessage( context, message, - _messages, + messages, streamChannel, ); - } else if (i == _messages.length - 1) { + } else if (i == messages.length - 1) { messageWidget = _buildTopMessage( context, message, - _messages, + messages, streamChannel, ); } else { @@ -246,13 +256,13 @@ class _MessageListViewState extends State { MessageDetails( context, message, - _messages, + messages, i, ), - _messages), + messages), ); } else { - messageWidget = buildMessage(message, _messages, i); + messageWidget = buildMessage(message, messages, i); } } @@ -265,84 +275,74 @@ class _MessageListViewState extends State { messageWidget, Padding( padding: const EdgeInsets.symmetric(vertical: 12.0), - child: VisibleNotifierWidget( - condition: ( - ScrollNotification previousNotification, - PositionData previousPositionData, - ScrollNotification currentNotification, - PositionData currentPositionData, - ) { - print( - 'currentPositionData.endPosition: ${currentPositionData.endPosition}'); - return true; - }, - data: i, - child: widget.dateDividerBuilder != null - ? widget.dateDividerBuilder( - nextMessage.createdAt.toLocal()) - : DateDivider( - dateTime: nextMessage.createdAt.toLocal(), - ), - ), + child: widget.dateDividerBuilder != null + ? widget.dateDividerBuilder( + nextMessage.createdAt.toLocal()) + : DateDivider( + dateTime: nextMessage.createdAt.toLocal(), + ), ), ], ); } - return VisibleNotifierWidget( - child: messageWidget, - data: i, - ); - }, - childCount: _messages.length + 2, - findChildIndexCallback: (key) { - final ValueKey valueKey = key; - final index = _messages - .indexWhere((m) => 'MESSAGE-${m.id}' == valueKey.value); - return index != -1 ? index : null; + return messageWidget; }, ), - ), - ), - if (widget.showScrollToBottom) - StreamBuilder( - stream: streamChannel.channel.on( - EventType.messageNew, - ), - builder: (context, _) { - if (!_showScrollToBottom || - streamChannel.channel.state.unreadCount == 0) { - return SizedBox(); - } - return _buildScrollToBottom(streamChannel); - }), - Positioned( - top: 20.0, - child: WidgetsVisibilityConsumer( - listener: ( - context, - event, - ) {}, - builder: (context, event) { - if (event.positionDataList == null || - event.positionDataList.isEmpty) { - return Container(); - } + if (widget.showScrollToBottom) + StreamBuilder( + stream: streamChannel.channel.state.unreadCountStream, + builder: (context, snapshot) { + if (!_showScrollToBottom || + !snapshot.hasData || + snapshot.data == 0) { + return SizedBox(); + } + return _buildScrollToBottom(snapshot.data); + }), + Positioned( + top: 20.0, + child: ValueListenableBuilder>( + valueListenable: _itemPositionListener.itemPositions, + builder: (context, values, _) { + final items = _itemPositionListener.itemPositions?.value; + if (items.isEmpty) { + return SizedBox(); + } - return DateDivider( - dateTime: _messages[event.positionDataList.last.data] - .createdAt - .toLocal(), - ); - }, - ), - ), - ], - ), - ); + var index = _getTopElement(values).index; + + if (index > messages.length) { + return SizedBox(); + } + + if (index == messages.length) { + index = max(index - 1, 0); + } + + return widget.dateDividerBuilder != null + ? widget.dateDividerBuilder( + messages[index].createdAt.toLocal(), + ) + : DateDivider( + dateTime: messages[index].createdAt.toLocal(), + ); + }, + ), + ), + ], + ); + }); } - Widget _buildScrollToBottom(StreamChannelState streamChannel) { + ItemPosition _getTopElement(Iterable values) { + return values + .where((ItemPosition position) => position.itemLeadingEdge < 0.9) + .reduce((ItemPosition max, ItemPosition position) => + position.itemLeadingEdge > max.itemLeadingEdge ? position : max); + } + + Widget _buildScrollToBottom(int unreadCount) { return Positioned( bottom: 8, right: 8, @@ -358,13 +358,11 @@ class _MessageListViewState extends State { color: Colors.black, ), onPressed: () { - Future.delayed(Duration(milliseconds: 500), () { - setState(() { - _showScrollToBottom = false; - }); + setState(() { + _showScrollToBottom = false; }); - _scrollController.animateTo( - 0, + _scrollController.scrollTo( + index: 0, duration: Duration(seconds: 1), curve: Curves.easeInOut, ); @@ -377,7 +375,7 @@ class _MessageListViewState extends State { top: -10, child: CircleAvatar( radius: 20, - child: Text(streamChannel.channel.state.unreadCount.toString()), + child: Text(unreadCount.toString()), ), ), ], @@ -387,7 +385,9 @@ class _MessageListViewState extends State { Container _buildLoadingIndicator(StreamChannelState streamChannel) { return Container( + key: Key('LOADING-INDICATOR'), height: 50, + width: double.infinity, child: StreamBuilder( stream: streamChannel.queryMessage, initialData: false, @@ -401,7 +401,7 @@ class _MessageListViewState extends State { ); } if (!snapshot.data) { - return Container(); + return SizedBox(); } return Center( child: Padding( @@ -428,14 +428,14 @@ class _MessageListViewState extends State { MessageDetails( context, message, - _messages, - _messages.length - 1, + messages, + messages.length - 1, ), - _messages, + messages, ), ); } else { - messageWidget = buildMessage(message, messages, _messages.length - 1); + messageWidget = buildMessage(message, messages, messages.length - 1); } return VisibilityDetector( @@ -470,10 +470,10 @@ class _MessageListViewState extends State { MessageDetails( context, message, - _messages, + messages, 0, ), - _messages, + messages, ), ); } else { @@ -492,9 +492,11 @@ class _MessageListViewState extends State { } } _bottomWasVisible = isVisible; - setState(() { - _showScrollToBottom = !isVisible; - }); + if (mounted) { + setState(() { + _showScrollToBottom = !isVisible; + }); + } }, child: messageWidget, ); @@ -541,6 +543,7 @@ class _MessageListViewState extends State { ) { if (message.type == 'system' && message.text?.isNotEmpty == true) { return SystemMessage( + key: ValueKey('MESSAGE-${message.id}'), message: message, ); } @@ -563,6 +566,7 @@ class _MessageListViewState extends State { final allRead = readList.length >= (channel.memberCount ?? 0) - 1; return MessageWidget( + key: ValueKey('MESSAGE-${message.id}'), message: message, reverse: isMyMessage, showReactions: !message.isDeleted, @@ -600,63 +604,45 @@ class _MessageListViewState extends State { ); } - StreamSubscription _streamListener; + StreamSubscription _messageNewListener; @override void initState() { super.initState(); + _scrollController = widget.scrollController ?? ItemScrollController(); + _itemPositionListener = + widget.itemPositionListener ?? ItemPositionsListener.create(); + final streamChannel = StreamChannel.of(context); - Stream> stream; - - if (widget.parentMessage == null) { - stream = streamChannel.channel.state.messagesStream; - } else { - streamChannel.getReplies(widget.parentMessage.id); - stream = streamChannel.channel.state.threadsStream - .where((threads) => threads.containsKey(widget.parentMessage.id)) - .map((threads) => threads[widget.parentMessage.id]); - } - - _streamListener = stream - .map((messages) => - messages - ?.where((m) => - !(m.status == MessageSendingStatus.FAILED && m.isDeleted)) - ?.toList() ?? - []) - .listen((newMessages) { - newMessages = newMessages.reversed.toList(); - if (_messages.isEmpty || - newMessages.isEmpty || - newMessages.first.id != _messages.first.id) { - if (!_scrollController.hasClients || - _scrollController.offset < _newMessageLoadingOffset) { - if (streamChannel.channel.state.unreadCount > 0) { - streamChannel.channel.markRead(); - } - setState(() { - _messages = newMessages; - }); - } else if (newMessages.first.user.id == - streamChannel.channel.client.state.user.id) { - _scrollController.jumpTo(0); - WidgetsBinding.instance.addPostFrameCallback((_) { - setState(() { - _messages = newMessages; - }); - }); - } else { - _newMessageList = newMessages; - } - } else { - setState(() { - _messages = newMessages; + _messageNewListener = + streamChannel.channel.on(EventType.messageNew).listen((event) { + final firstElementInViewport = + _itemPositionListener.itemPositions.value.first; + if (event.message.user.id == streamChannel.channel.client.state.user.id) { + WidgetsBinding.instance.addPostFrameCallback((_) { + _scrollController.jumpTo( + index: 0, + ); }); + } else { + if (firstElementInViewport.index != 0) { + _scrollController.jumpTo( + index: firstElementInViewport.index + 1, + alignment: firstElementInViewport.itemLeadingEdge, + ); + } + } + if (firstElementInViewport.index == 0) { + streamChannel.channel.markRead(); } }); + if (widget.parentMessage != null) { + streamChannel.getReplies(widget.parentMessage.id); + } + _getOnThreadTap(); } @@ -696,7 +682,7 @@ class _MessageListViewState extends State { @override void dispose() { - _streamListener.cancel(); + _messageNewListener?.cancel(); super.dispose(); } } diff --git a/pubspec.yaml b/pubspec.yaml index 452eb69a..e6f6bf38 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -14,6 +14,7 @@ dependencies: flutter_app_badger: ^1.1.2 photo_view: ^0.10.1 rxdart: ^0.24.1 + scrollable_positioned_list: ^0.1.8 jiffy: ^3.0.1 flutter_portal: ^0.3.0 cached_network_image: ^2.2.0+1 @@ -31,7 +32,6 @@ dependencies: flutter_slidable: ^0.5.4 carousel_slider: ^2.2.1 clipboard: ^0.1.2+8 - widgets_visibility_provider: ^2.0.2 flutter: assets: From da2ca558743e5e9ce603ae317210503e19e72184 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Thu, 5 Nov 2020 11:37:12 +0100 Subject: [PATCH 02/11] fix giphy corner tag --- lib/src/giphy_attachment.dart | 136 +++++++++++++++++----------------- 1 file changed, 70 insertions(+), 66 deletions(-) diff --git a/lib/src/giphy_attachment.dart b/lib/src/giphy_attachment.dart index f913b557..89beb4b1 100644 --- a/lib/src/giphy_attachment.dart +++ b/lib/src/giphy_attachment.dart @@ -55,76 +55,80 @@ class GiphyAttachment extends StatelessWidget { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - Padding( - padding: const EdgeInsets.all(8.0), - 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, + Stack( + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: GestureDetector( + onTap: () { + Navigator.push(context, MaterialPageRoute(builder: (_) { + return FullScreenImage( + url: attachment.imageUrl ?? + attachment.assetUrl ?? + attachment.thumbUrl, + ); + })); + }, + child: CachedNetworkImage( height: size?.height, - child: Center( - child: CircularProgressIndicator(), + 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, ), - ); - }, - imageUrl: attachment.thumbUrl ?? - attachment.imageUrl ?? - attachment.assetUrl, - errorWidget: (context, url, error) => AttachmentError( - attachment: attachment, - size: size, - ), - fit: BoxFit.cover, - ), - ), - ), - Positioned( - left: 0, - top: 0, - child: Container( - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.only( - bottomRight: Radius.circular(16.0), - )), - child: Padding( - padding: const EdgeInsets.only( - left: 8.0, - right: 8.0, - top: 8.0, - bottom: 4.0, - ), - child: Row( - children: [ - Icon( - StreamIcons.lightning, - color: StreamChatTheme.of(context).accentColor, - size: 16.0, - ), - Text( - 'GIPHY', - style: TextStyle( - color: StreamChatTheme.of(context).accentColor, - fontWeight: FontWeight.bold, - fontSize: 11.0, - ), - ), - ], + fit: BoxFit.cover, + ), ), ), - ), + Positioned( + left: 0, + top: 0, + child: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.only( + bottomRight: Radius.circular(16.0), + )), + child: Padding( + padding: const EdgeInsets.only( + left: 8.0, + right: 8.0, + top: 8.0, + bottom: 4.0, + ), + child: Row( + children: [ + Icon( + StreamIcons.lightning, + color: StreamChatTheme.of(context).accentColor, + size: 16.0, + ), + Text( + 'GIPHY', + style: TextStyle( + color: StreamChatTheme.of(context).accentColor, + fontWeight: FontWeight.bold, + fontSize: 11.0, + ), + ), + ], + ), + ), + ), + ), + ], ), if (attachment.title != null) Container( From 5b93afcb5a2e1989d48645f3395459ff2871310b Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Thu, 5 Nov 2020 13:47:53 +0100 Subject: [PATCH 03/11] fix listview default params --- example/ios/Flutter/.last_build_id | 2 +- example/pubspec.yaml | 2 +- lib/src/message_list_view.dart | 7 +++---- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/example/ios/Flutter/.last_build_id b/example/ios/Flutter/.last_build_id index 5d3809be..8aba7787 100644 --- a/example/ios/Flutter/.last_build_id +++ b/example/ios/Flutter/.last_build_id @@ -1 +1 @@ -bdf1751976c4ee1e2ef7638eabcfd1ea \ No newline at end of file +bb5f9103d9045cd6244bcae1f5f343e5 \ No newline at end of file diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 842f471c..97971445 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -1,6 +1,6 @@ name: example description: A new Flutter project. -version: 1.0.39+41 +version: 1.0.40+42 environment: sdk: ">=2.2.2 <3.0.0" diff --git a/lib/src/message_list_view.dart b/lib/src/message_list_view.dart index d2e1d972..6c23ea4b 100644 --- a/lib/src/message_list_view.dart +++ b/lib/src/message_list_view.dart @@ -107,8 +107,8 @@ class MessageListView extends StatefulWidget { this.onThreadTap, this.dateDividerBuilder, this.scrollPhysics = const AlwaysScrollableScrollPhysics(), - this.initialScrollIndex, - this.initialAlignment, + this.initialScrollIndex = 0, + this.initialAlignment = 0, this.scrollController, this.itemPositionListener, }) : super(key: key); @@ -608,8 +608,6 @@ class _MessageListViewState extends State { @override void initState() { - super.initState(); - _scrollController = widget.scrollController ?? ItemScrollController(); _itemPositionListener = widget.itemPositionListener ?? ItemPositionsListener.create(); @@ -644,6 +642,7 @@ class _MessageListViewState extends State { } _getOnThreadTap(); + super.initState(); } void _getOnThreadTap() { From 4dd68d3de903be1d5e46281921ca5f0433509df1 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Thu, 5 Nov 2020 13:57:09 +0100 Subject: [PATCH 04/11] fix giphy padding --- lib/src/giphy_attachment.dart | 84 +++++++++++++++++------------------ 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/lib/src/giphy_attachment.dart b/lib/src/giphy_attachment.dart index 89beb4b1..7a1d0ad1 100644 --- a/lib/src/giphy_attachment.dart +++ b/lib/src/giphy_attachment.dart @@ -97,7 +97,7 @@ class GiphyAttachment extends StatelessWidget { top: 0, child: Container( decoration: BoxDecoration( - color: Colors.white, + color: Colors.transparent, borderRadius: BorderRadius.only( bottomRight: Radius.circular(16.0), )), @@ -133,53 +133,50 @@ class GiphyAttachment extends StatelessWidget { if (attachment.title != null) Container( alignment: Alignment.bottomCenter, - child: Material( - color: Colors.white, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Card( - child: IconButton( - icon: Icon( - StreamIcons.left, - size: 24.0, - ), - splashRadius: 24, - onPressed: () { - streamChannel.channel.sendAction(message, { - 'image_action': 'shuffle', - }); - }, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Card( + child: IconButton( + icon: Icon( + StreamIcons.left, + size: 24.0, ), - shape: CircleBorder(), + splashRadius: 24, + onPressed: () { + streamChannel.channel.sendAction(message, { + 'image_action': 'shuffle', + }); + }, ), - Expanded( - child: Center( - child: Text( - '"${attachment.title}"', - style: TextStyle( - fontStyle: FontStyle.italic, - ), + shape: CircleBorder(), + ), + Expanded( + child: Center( + child: Text( + '"${attachment.title}"', + style: TextStyle( + fontStyle: FontStyle.italic, ), ), ), - Card( - child: IconButton( - icon: Icon( - StreamIcons.right, - size: 24.0, - ), - splashRadius: 24, - onPressed: () { - streamChannel.channel.sendAction(message, { - 'image_action': 'shuffle', - }); - }, + ), + Card( + child: IconButton( + icon: Icon( + StreamIcons.right, + size: 24.0, ), - shape: CircleBorder(), + splashRadius: 24, + onPressed: () { + streamChannel.channel.sendAction(message, { + 'image_action': 'shuffle', + }); + }, ), - ], - ), + shape: CircleBorder(), + ), + ], ), ), SizedBox( @@ -317,7 +314,10 @@ class GiphyAttachment extends StatelessWidget { ), ), Padding( - padding: const EdgeInsets.only(top: 8.0), + padding: const EdgeInsets.only( + top: 8.0, + bottom: 8, + ), child: Row( children: [ Row( From be4805116fb27ab715ce70d9210d797c8afdadec Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Thu, 5 Nov 2020 14:15:22 +0100 Subject: [PATCH 05/11] fix giphy color --- lib/src/giphy_attachment.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/giphy_attachment.dart b/lib/src/giphy_attachment.dart index 7a1d0ad1..766f7720 100644 --- a/lib/src/giphy_attachment.dart +++ b/lib/src/giphy_attachment.dart @@ -97,7 +97,7 @@ class GiphyAttachment extends StatelessWidget { top: 0, child: Container( decoration: BoxDecoration( - color: Colors.transparent, + color: Colors.white, borderRadius: BorderRadius.only( bottomRight: Radius.circular(16.0), )), From 119c6660e9ab736ad1500350256309b92271e830 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Thu, 5 Nov 2020 14:35:50 +0100 Subject: [PATCH 06/11] fix qa problems --- example/ios/Flutter/.last_build_id | 2 +- example/pubspec.yaml | 2 +- lib/src/giphy_attachment.dart | 359 +++++++++++++++-------------- lib/src/message_input.dart | 20 +- 4 files changed, 195 insertions(+), 188 deletions(-) diff --git a/example/ios/Flutter/.last_build_id b/example/ios/Flutter/.last_build_id index 5d3809be..8aba7787 100644 --- a/example/ios/Flutter/.last_build_id +++ b/example/ios/Flutter/.last_build_id @@ -1 +1 @@ -bdf1751976c4ee1e2ef7638eabcfd1ea \ No newline at end of file +bb5f9103d9045cd6244bcae1f5f343e5 \ No newline at end of file diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 842f471c..97971445 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -1,6 +1,6 @@ name: example description: A new Flutter project. -version: 1.0.39+41 +version: 1.0.40+42 environment: sdk: ">=2.2.2 <3.0.0" diff --git a/lib/src/giphy_attachment.dart b/lib/src/giphy_attachment.dart index 766f7720..bfa21239 100644 --- a/lib/src/giphy_attachment.dart +++ b/lib/src/giphy_attachment.dart @@ -41,196 +41,211 @@ class GiphyAttachment extends StatelessWidget { return Column( mainAxisSize: MainAxisSize.min, children: [ - Card( - clipBehavior: Clip.antiAlias, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.only( - topRight: Radius.circular(16.0), - bottomRight: Radius.circular(0.0), - topLeft: Radius.circular(16.0), - bottomLeft: Radius.circular(16.0), + DecoratedBox( + decoration: BoxDecoration(), + child: Card( + elevation: 2, + clipBehavior: Clip.antiAlias, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topRight: Radius.circular(16.0), + bottomRight: Radius.circular(0.0), + topLeft: Radius.circular(16.0), + bottomLeft: Radius.circular(16.0), + ), ), - ), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Stack( - children: [ - Padding( - padding: const EdgeInsets.all(8.0), - 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: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Stack( + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: GestureDetector( + onTap: () { + Navigator.push(context, + MaterialPageRoute(builder: (_) { + return FullScreenImage( + url: attachment.imageUrl ?? + attachment.assetUrl ?? + attachment.thumbUrl, + ); + })); }, - imageUrl: attachment.thumbUrl ?? - attachment.imageUrl ?? - attachment.assetUrl, - errorWidget: (context, url, error) => AttachmentError( - attachment: attachment, - size: size, + 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, ), - fit: BoxFit.cover, ), ), - ), - Positioned( - left: 0, - top: 0, - child: Container( - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.only( - bottomRight: Radius.circular(16.0), - )), - child: Padding( - padding: const EdgeInsets.only( - left: 8.0, - right: 8.0, - top: 8.0, - bottom: 4.0, - ), - child: Row( - children: [ - Icon( - StreamIcons.lightning, - color: StreamChatTheme.of(context).accentColor, - size: 16.0, - ), - Text( - 'GIPHY', - style: TextStyle( + Positioned( + left: 0, + top: 0, + child: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.only( + bottomRight: Radius.circular(16.0), + )), + child: Padding( + padding: const EdgeInsets.only( + left: 8.0, + right: 8.0, + top: 8.0, + bottom: 4.0, + ), + child: Row( + children: [ + Icon( + StreamIcons.lightning, color: StreamChatTheme.of(context).accentColor, - fontWeight: FontWeight.bold, - fontSize: 11.0, + size: 16.0, + ), + Text( + 'GIPHY', + style: TextStyle( + color: + StreamChatTheme.of(context).accentColor, + fontWeight: FontWeight.bold, + fontSize: 11.0, + ), + ), + ], + ), + ), + ), + ), + ], + ), + if (attachment.title != null) + Container( + alignment: Alignment.bottomCenter, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 8.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Card( + elevation: 2, + child: IconButton( + padding: const EdgeInsets.all(0), + constraints: BoxConstraints.tight(Size(32, 32)), + icon: Icon( + StreamIcons.left, + size: 24.0, + ), + splashRadius: 16, + onPressed: () { + streamChannel.channel.sendAction(message, { + 'image_action': 'shuffle', + }); + }, + ), + shape: CircleBorder(), + ), + Expanded( + child: Center( + child: Text( + '"${attachment.title}"', + style: TextStyle( + fontStyle: FontStyle.italic, + ), ), ), - ], - ), - ), - ), - ), - ], - ), - if (attachment.title != null) - Container( - alignment: Alignment.bottomCenter, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Card( - child: IconButton( - icon: Icon( - StreamIcons.left, - size: 24.0, ), - splashRadius: 24, - onPressed: () { - streamChannel.channel.sendAction(message, { - 'image_action': 'shuffle', - }); - }, - ), - shape: CircleBorder(), - ), - Expanded( - child: Center( - child: Text( - '"${attachment.title}"', - style: TextStyle( - fontStyle: FontStyle.italic, + Card( + elevation: 2, + child: IconButton( + padding: const EdgeInsets.all(0), + constraints: BoxConstraints.tight(Size(32, 32)), + icon: Icon( + StreamIcons.right, + size: 24.0, + ), + splashRadius: 16, + onPressed: () { + streamChannel.channel.sendAction(message, { + 'image_action': 'shuffle', + }); + }, ), + shape: CircleBorder(), ), - ), + ], ), - Card( - child: IconButton( - icon: Icon( - StreamIcons.right, - size: 24.0, - ), - splashRadius: 24, - onPressed: () { - streamChannel.channel.sendAction(message, { - 'image_action': 'shuffle', - }); - }, - ), - shape: CircleBorder(), - ), - ], + ), ), + SizedBox( + height: 4.0, ), - SizedBox( - height: 4.0, - ), - Container( - color: Colors.black.withOpacity(0.2), - width: double.infinity, - height: 0.5, - ), - Row( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Expanded( - child: FlatButton( - height: 50, - onPressed: () { - streamChannel.channel.sendAction(message, { - 'image_action': 'cancel', - }); - }, - child: Text( - 'Cancel', - style: TextStyle( - fontWeight: FontWeight.bold, - color: Colors.black.withOpacity(0.5)), + Container( + color: Colors.black.withOpacity(0.2), + width: double.infinity, + height: 0.5, + ), + Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Expanded( + child: FlatButton( + height: 50, + onPressed: () { + streamChannel.channel.sendAction(message, { + 'image_action': 'cancel', + }); + }, + child: Text( + 'Cancel', + style: TextStyle( + fontWeight: FontWeight.bold, + color: Colors.black.withOpacity(0.5)), + ), ), ), - ), - Container( - width: 0.5, - color: Colors.black.withOpacity(0.2), - height: 50.0, - ), - Expanded( - child: FlatButton( - height: 50, - onPressed: () { - streamChannel.channel.sendAction(message, { - 'image_action': 'send', - }); - }, - child: Text( - 'Send', - style: TextStyle( - color: StreamChatTheme.of(context).accentColor, - fontWeight: FontWeight.bold), + Container( + width: 0.5, + color: Colors.black.withOpacity(0.2), + height: 50.0, + ), + Expanded( + child: FlatButton( + height: 50, + onPressed: () { + streamChannel.channel.sendAction(message, { + 'image_action': 'send', + }); + }, + child: Text( + 'Send', + style: TextStyle( + color: StreamChatTheme.of(context).accentColor, + fontWeight: FontWeight.bold), + ), ), ), - ), - ], - ), - ], + ], + ), + ], + ), ), ), SizedBox( diff --git a/lib/src/message_input.dart b/lib/src/message_input.dart index 9c9cf67f..7959901a 100644 --- a/lib/src/message_input.dart +++ b/lib/src/message_input.dart @@ -483,13 +483,6 @@ class MessageInputState extends State { child: Container( constraints: BoxConstraints.loose(Size.fromHeight(400)), decoration: BoxDecoration( - // boxShadow: [ - // BoxShadow( - // spreadRadius: -8, - // blurRadius: 5.0, - // offset: Offset(0, -4), - // ), - // ], color: StreamChatTheme.of(context).primaryColor, borderRadius: BorderRadius.circular(8.0)), child: ListView( @@ -606,13 +599,6 @@ class MessageInputState extends State { child: Container( constraints: BoxConstraints.loose(Size.fromHeight(400)), decoration: BoxDecoration( - boxShadow: [ - BoxShadow( - spreadRadius: -8, - blurRadius: 5.0, - offset: Offset(0, -4), - ), - ], color: StreamChatTheme.of(context).primaryColor, ), child: FutureBuilder>( @@ -625,6 +611,12 @@ class MessageInputState extends State { children: snapshot.data .map((m) => ListTile( leading: UserAvatar( + constraints: BoxConstraints.tight( + Size( + 40, + 40, + ), + ), user: m.user, ), title: Text( From d485c96f81bd856910ac5603358c5d1a44cae144 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Thu, 5 Nov 2020 15:16:16 +0100 Subject: [PATCH 07/11] use svg icon --- lib/src/message_input.dart | 116 ++++++++++++++++++++++++++++++------- pubspec.yaml | 4 +- svgs/giphy_icon.svg | 8 +++ 3 files changed, 107 insertions(+), 21 deletions(-) create mode 100644 svgs/giphy_icon.svg diff --git a/lib/src/message_input.dart b/lib/src/message_input.dart index 7959901a..aff98b41 100644 --- a/lib/src/message_input.dart +++ b/lib/src/message_input.dart @@ -6,6 +6,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart'; +import 'package:flutter_svg/flutter_svg.dart'; import 'package:http_parser/http_parser.dart'; import 'package:image_picker/image_picker.dart'; import 'package:mime/mime.dart'; @@ -220,16 +221,72 @@ class MessageInputState extends State { } Widget _buildDmCheckbox() { + return Container( + height: 36, + padding: const EdgeInsets.only( + left: 12, + bottom: 12, + top: 8, + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Center( + child: Container( + height: 16, + width: 16, + child: Material( + borderRadius: BorderRadius.circular(3), + color: _sendAsDm + ? StreamChatTheme.of(context).accentColor + : Colors.white, + child: InkWell( + onTap: () { + setState(() { + _sendAsDm = !_sendAsDm; + }); + }, + child: AnimatedCrossFade( + duration: Duration(milliseconds: 300), + reverseDuration: Duration(milliseconds: 300), + crossFadeState: _sendAsDm + ? CrossFadeState.showFirst + : CrossFadeState.showSecond, + firstChild: Icon( + Icons.check, + size: 16.0, + color: Colors.white, + ), + secondChild: SizedBox( + height: 16, + width: 16, + ), + ), + ), + ), + ), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 8.0), + child: Text('Send also as direct message'), + ), + ], + ), + ); return Row( children: [ - Checkbox( - value: _sendAsDm, - onChanged: (val) => setState( - () { - _sendAsDm = val; - }, + ClipRRect( + clipBehavior: Clip.hardEdge, + borderRadius: BorderRadius.circular(1), + child: Checkbox( + value: _sendAsDm, + onChanged: (val) => setState( + () { + _sendAsDm = val; + }, + ), + activeColor: StreamChatTheme.of(context).accentColor, ), - activeColor: StreamChatTheme.of(context).accentColor, ), Padding( padding: const EdgeInsets.symmetric(horizontal: 8.0), @@ -500,25 +557,19 @@ class MessageInputState extends State { child: Icon(StreamIcons.lightning, color: StreamChatTheme.of(context).accentColor), ), - Text('Instant Commands') + Text( + 'Instant Commands', + style: TextStyle( + color: Colors.black.withOpacity(.5), + ), + ) ], ), ), ...commands .map( (c) => ListTile( - leading: c.name == 'giphy' - ? CircleAvatar( - backgroundColor: Colors.black, - child: Image.asset( - 'images/giphy_icon.png', - package: 'stream_chat_flutter', - width: 16.0, - height: 16.0, - ), - maxRadius: 12.0, - ) - : null, + leading: c.name == 'giphy' ? _buildGiphyIcon() : null, title: Text.rich( TextSpan( text: '${c.name.capitalize()}', @@ -559,6 +610,31 @@ class MessageInputState extends State { }); } + CircleAvatar _buildGiphyIcon() { + if (kIsWeb) { + return CircleAvatar( + backgroundColor: Colors.black, + child: Image.asset( + 'images/giphy_icon.png', + package: 'stream_chat_flutter', + width: 24.0, + height: 24.0, + ), + radius: 12, + ); + } else { + return CircleAvatar( + child: SvgPicture.asset( + 'svgs/giphy_icon.svg', + package: 'stream_chat_flutter', + width: 24.0, + height: 24.0, + ), + radius: 12, + ); + } + } + OverlayEntry _buildMentionsOverlayEntry() { final splits = textEditingController.text .substring(0, textEditingController.value.selection.start) diff --git a/pubspec.yaml b/pubspec.yaml index 452eb69a..a2d92d69 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -15,6 +15,7 @@ dependencies: photo_view: ^0.10.1 rxdart: ^0.24.1 jiffy: ^3.0.1 + flutter_svg: ^0.19.1 flutter_portal: ^0.3.0 cached_network_image: ^2.2.0+1 flutter_markdown: ^0.5.0 @@ -35,7 +36,8 @@ dependencies: flutter: assets: - - images/giphy_icon.png + - images/ + - svgs/ fonts: - family: stream-icons fonts: diff --git a/svgs/giphy_icon.svg b/svgs/giphy_icon.svg new file mode 100644 index 00000000..e1a1d4bb --- /dev/null +++ b/svgs/giphy_icon.svg @@ -0,0 +1,8 @@ + + + + + + + + From 38fb9460711e8bdafad0c2a191889f273e2ed1bd Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Thu, 5 Nov 2020 15:26:48 +0100 Subject: [PATCH 08/11] modify checkbox to have 3 radius --- lib/src/message_input.dart | 59 ++++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 24 deletions(-) diff --git a/lib/src/message_input.dart b/lib/src/message_input.dart index aff98b41..f2b3ccd0 100644 --- a/lib/src/message_input.dart +++ b/lib/src/message_input.dart @@ -235,31 +235,42 @@ class MessageInputState extends State { child: Container( height: 16, width: 16, - child: Material( + foregroundDecoration: BoxDecoration( + border: _sendAsDm + ? null + : Border.all( + color: Colors.black.withOpacity(.5), + width: 2, + ), borderRadius: BorderRadius.circular(3), - color: _sendAsDm - ? StreamChatTheme.of(context).accentColor - : Colors.white, - child: InkWell( - onTap: () { - setState(() { - _sendAsDm = !_sendAsDm; - }); - }, - child: AnimatedCrossFade( - duration: Duration(milliseconds: 300), - reverseDuration: Duration(milliseconds: 300), - crossFadeState: _sendAsDm - ? CrossFadeState.showFirst - : CrossFadeState.showSecond, - firstChild: Icon( - Icons.check, - size: 16.0, - color: Colors.white, - ), - secondChild: SizedBox( - height: 16, - width: 16, + ), + child: Center( + child: Material( + borderRadius: BorderRadius.circular(3), + color: _sendAsDm + ? StreamChatTheme.of(context).accentColor + : Colors.white, + child: InkWell( + onTap: () { + setState(() { + _sendAsDm = !_sendAsDm; + }); + }, + child: AnimatedCrossFade( + duration: Duration(milliseconds: 300), + reverseDuration: Duration(milliseconds: 300), + crossFadeState: _sendAsDm + ? CrossFadeState.showFirst + : CrossFadeState.showSecond, + firstChild: Icon( + StreamIcons.check, + size: 16.0, + color: Colors.white, + ), + secondChild: SizedBox( + height: 16, + width: 16, + ), ), ), ), From d51584e3ca205ba6d4ff98fce3bf72939690f4ef Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Thu, 5 Nov 2020 15:27:32 +0100 Subject: [PATCH 09/11] cleanup --- lib/src/message_input.dart | 99 +++++++++++++++----------------------- 1 file changed, 38 insertions(+), 61 deletions(-) diff --git a/lib/src/message_input.dart b/lib/src/message_input.dart index f2b3ccd0..32e812e7 100644 --- a/lib/src/message_input.dart +++ b/lib/src/message_input.dart @@ -231,46 +231,44 @@ class MessageInputState extends State { child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ - Center( - child: Container( - height: 16, - width: 16, - foregroundDecoration: BoxDecoration( - border: _sendAsDm - ? null - : Border.all( - color: Colors.black.withOpacity(.5), - width: 2, - ), + Container( + height: 16, + width: 16, + foregroundDecoration: BoxDecoration( + border: _sendAsDm + ? null + : Border.all( + color: Colors.black.withOpacity(.5), + width: 2, + ), + borderRadius: BorderRadius.circular(3), + ), + child: Center( + child: Material( borderRadius: BorderRadius.circular(3), - ), - child: Center( - child: Material( - borderRadius: BorderRadius.circular(3), - color: _sendAsDm - ? StreamChatTheme.of(context).accentColor - : Colors.white, - child: InkWell( - onTap: () { - setState(() { - _sendAsDm = !_sendAsDm; - }); - }, - child: AnimatedCrossFade( - duration: Duration(milliseconds: 300), - reverseDuration: Duration(milliseconds: 300), - crossFadeState: _sendAsDm - ? CrossFadeState.showFirst - : CrossFadeState.showSecond, - firstChild: Icon( - StreamIcons.check, - size: 16.0, - color: Colors.white, - ), - secondChild: SizedBox( - height: 16, - width: 16, - ), + color: _sendAsDm + ? StreamChatTheme.of(context).accentColor + : Colors.white, + child: InkWell( + onTap: () { + setState(() { + _sendAsDm = !_sendAsDm; + }); + }, + child: AnimatedCrossFade( + duration: Duration(milliseconds: 300), + reverseDuration: Duration(milliseconds: 300), + crossFadeState: _sendAsDm + ? CrossFadeState.showFirst + : CrossFadeState.showSecond, + firstChild: Icon( + StreamIcons.check, + size: 16.0, + color: Colors.white, + ), + secondChild: SizedBox( + height: 16, + width: 16, ), ), ), @@ -278,33 +276,12 @@ class MessageInputState extends State { ), ), Padding( - padding: const EdgeInsets.symmetric(horizontal: 8.0), + padding: const EdgeInsets.symmetric(horizontal: 16.0), child: Text('Send also as direct message'), ), ], ), ); - return Row( - children: [ - ClipRRect( - clipBehavior: Clip.hardEdge, - borderRadius: BorderRadius.circular(1), - child: Checkbox( - value: _sendAsDm, - onChanged: (val) => setState( - () { - _sendAsDm = val; - }, - ), - activeColor: StreamChatTheme.of(context).accentColor, - ), - ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 8.0), - child: Text('Send also as direct message'), - ), - ], - ); } AnimatedCrossFade _animateSendButton(BuildContext context) { From 4865f93ce34f48b154efab1747d976f18da1a727 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Fri, 6 Nov 2020 09:42:41 +0100 Subject: [PATCH 10/11] fix empty list error --- lib/src/message_list_view.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/message_list_view.dart b/lib/src/message_list_view.dart index 6c23ea4b..946ad66f 100644 --- a/lib/src/message_list_view.dart +++ b/lib/src/message_list_view.dart @@ -306,7 +306,7 @@ class _MessageListViewState extends State { valueListenable: _itemPositionListener.itemPositions, builder: (context, values, _) { final items = _itemPositionListener.itemPositions?.value; - if (items.isEmpty) { + if (items.isEmpty || messages.isEmpty) { return SizedBox(); } From 7d45feafbb7c145c09088f2f974c3affd97af3a9 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Fri, 6 Nov 2020 12:12:35 +0100 Subject: [PATCH 11/11] remove dark theme for now --- example/lib/main.dart | 4 +++- example/pubspec.yaml | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index 667b1e0f..ca727cf7 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -98,7 +98,9 @@ class MyApp extends StatelessWidget { return MaterialApp( theme: ThemeData.light(), darkTheme: ThemeData.dark(), - themeMode: ThemeMode.system, + themeMode: ThemeMode.light, + + ///TODO change to system once dark theme is implemented builder: (context, widget) { return StreamChat( child: widget, diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 97971445..d87454dc 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -1,6 +1,6 @@ name: example description: A new Flutter project. -version: 1.0.40+42 +version: 1.0.41+43 environment: sdk: ">=2.2.2 <3.0.0"