diff --git a/packages/imessage/lib/channel_image.dart b/packages/imessage/lib/channel_image.dart index 65b23ff..d7b6343 100644 --- a/packages/imessage/lib/channel_image.dart +++ b/packages/imessage/lib/channel_image.dart @@ -4,7 +4,7 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart' show Channel; import 'package:imessage/utils.dart'; class ChannelImage extends StatelessWidget { - const ChannelImage({Key key, @required this.channel, @required this.size}) + const ChannelImage({Key? key, required this.channel, required this.size}) : super(key: key); final Channel channel; @@ -14,7 +14,7 @@ class ChannelImage extends StatelessWidget { Widget build(BuildContext context) { final avatarUrl = channel.extraData.containsKey('image') && (channel.extraData['image'] as String).isNotEmpty - ? channel.extraData['image'] as String + ? channel.extraData['image'] as String? : 'https://4.bp.blogspot.com/-Jx21kNqFSTU/UXemtqPhZCI/AAAAAAAAh74/BMGSzpU6F48/s1600/funny-cat-pictures-047-001.jpg'; return CupertinoCircleAvatar( diff --git a/packages/imessage/lib/channel_list_view.dart b/packages/imessage/lib/channel_list_view.dart index 89c03b5..9421b6d 100644 --- a/packages/imessage/lib/channel_list_view.dart +++ b/packages/imessage/lib/channel_list_view.dart @@ -6,7 +6,7 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart' show Channel, StreamChannel; class ChannelListView extends StatelessWidget { - const ChannelListView({Key key, @required this.channels}) : super(key: key); + const ChannelListView({Key? key, required this.channels}) : super(key: key); final List channels; @override Widget build(BuildContext context) { @@ -36,10 +36,10 @@ class ChannelListView extends StatelessWidget { child, ) => SharedAxisTransition( - child: child, animation: animation, secondaryAnimation: secondaryAnimation, transitionType: SharedAxisTransitionType.horizontal, + child: child, ), ), ); diff --git a/packages/imessage/lib/channel_name_text.dart b/packages/imessage/lib/channel_name_text.dart index e2e8d2b..169bb9d 100644 --- a/packages/imessage/lib/channel_name_text.dart +++ b/packages/imessage/lib/channel_name_text.dart @@ -3,8 +3,8 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart' show Channel; class ChannelNameText extends StatelessWidget { const ChannelNameText({ - Key key, - @required this.channel, + Key? key, + required this.channel, this.size = 17, }) : super(key: key); @@ -14,7 +14,7 @@ class ChannelNameText extends StatelessWidget { @override Widget build(BuildContext context) { return Text( - channel.extraData['name'] as String ?? 'No name', + channel.extraData['name'] as String? ?? 'No name', style: TextStyle( fontSize: size, fontWeight: FontWeight.bold, diff --git a/packages/imessage/lib/channel_page_appbar.dart b/packages/imessage/lib/channel_page_appbar.dart index f991829..5f44995 100644 --- a/packages/imessage/lib/channel_page_appbar.dart +++ b/packages/imessage/lib/channel_page_appbar.dart @@ -2,7 +2,7 @@ import 'package:flutter/cupertino.dart'; class ChannelPageAppBar extends StatelessWidget { const ChannelPageAppBar({ - Key key, + Key? key, }) : super(key: key); @override diff --git a/packages/imessage/lib/channel_preview.dart b/packages/imessage/lib/channel_preview.dart index 8b8c039..98a16c4 100644 --- a/packages/imessage/lib/channel_preview.dart +++ b/packages/imessage/lib/channel_preview.dart @@ -11,19 +11,20 @@ class ChannelPreview extends StatelessWidget { final Channel channel; const ChannelPreview({ - Key key, - @required this.onTap, - @required this.channel, + Key? key, + required this.onTap, + required this.channel, }) : super(key: key); @override Widget build(BuildContext context) { - final lastMessage = - channel.state.messages.isNotEmpty ? channel.state.messages.last : null; + final lastMessage = channel.state!.messages.isNotEmpty + ? channel.state!.messages.last + : null; final prefix = lastMessage?.attachments != null ? lastMessage?.attachments //TODO: ugly - ?.map((e) { + .map((e) { if (e.type == 'image') { return '📷 '; } else if (e.type == 'video') { @@ -31,8 +32,8 @@ class ChannelPreview extends StatelessWidget { } return null; }) - ?.where((e) => e != null) - ?.join(' ') + .where((e) => e != null) + .join(' ') : ''; return GestureDetector( onTap: onTap, @@ -76,9 +77,9 @@ class ChannelPreview extends StatelessWidget { child: Row( children: [ Text( - isSameWeek(channel.lastMessageAt) - ? formatDateSameWeek(channel.lastMessageAt) - : formatDate(channel.lastMessageAt), + isSameWeek(channel.lastMessageAt!) + ? formatDateSameWeek(channel.lastMessageAt!) + : formatDate(channel.lastMessageAt!), style: TextStyle( fontSize: 15, color: CupertinoColors.systemGrey, diff --git a/packages/imessage/lib/cutom_painter.dart b/packages/imessage/lib/cutom_painter.dart index 4437fc3..0ed6213 100644 --- a/packages/imessage/lib/cutom_painter.dart +++ b/packages/imessage/lib/cutom_painter.dart @@ -2,10 +2,10 @@ import 'package:flutter/cupertino.dart'; class ChatBubble extends CustomPainter { final Color color; - final Alignment alignment; + final Alignment? alignment; ChatBubble({ - @required this.color, + required this.color, this.alignment, }); diff --git a/packages/imessage/lib/main.dart b/packages/imessage/lib/main.dart index f235f41..fc7283d 100644 --- a/packages/imessage/lib/main.dart +++ b/packages/imessage/lib/main.dart @@ -1,18 +1,7 @@ import 'package:flutter/cupertino.dart'; import 'package:intl/date_symbol_data_local.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart' - show - Channel, - ChannelListController, - ChannelListCore, - ChannelsBloc, - LazyLoadScrollView, - Level, - PaginationParams, - SortOption, - StreamChatClient, - StreamChatCore, - User; + hide ChannelListView; import 'package:imessage/channel_list_view.dart'; @@ -37,7 +26,7 @@ Future main() async { class IMessage extends StatelessWidget { final StreamChatClient client; - IMessage({@required this.client}); + IMessage({required this.client}); @override Widget build(BuildContext context) { initializeDateFormatting('en_US', null); @@ -52,70 +41,69 @@ class IMessage extends StatelessWidget { class ChatLoader extends StatelessWidget { ChatLoader({ - Key key, + Key? key, }) : super(key: key); final channelListController = ChannelListController(); @override Widget build(BuildContext context) { - final user = StreamChatCore.of(context).user; + final user = StreamChatCore.of(context).user!; return CupertinoPageScaffold( - child: ChannelsBloc( - child: ChannelListCore( - channelListController: channelListController, - filter: { - 'members': { - r'$in': [user.id], - }, - 'type': { - r'$eq': 'messaging', - }, - }, - sort: [SortOption('last_message_at')], - pagination: PaginationParams( - limit: 20, - ), - emptyBuilder: (BuildContext context) { - return Center( - child: Text('Looks like you are not in any channels'), - ); - }, - loadingBuilder: (BuildContext context) { - return Center( - child: SizedBox( - height: 100.0, - width: 100.0, - child: CupertinoActivityIndicator(), - ), - ); - }, - errorBuilder: (BuildContext context, dynamic error) { - return Center( - child: Text( - 'Oh no, something went wrong. Please check your config.'), - ); - }, - listBuilder: ( - BuildContext context, - List channels, - ) => - LazyLoadScrollView( - onEndOfPage: () async { - channelListController.paginateData(); - }, - child: CustomScrollView( - slivers: [ - CupertinoSliverRefreshControl(onRefresh: () async { - channelListController.loadData(); - }), - ChannelPageAppBar(), - SliverPadding( - sliver: ChannelListView(channels: channels), - padding: const EdgeInsets.only(top: 16), - ) - ], - ), - )))); + child: ChannelsBloc( + child: ChannelListCore( + channelListController: channelListController, + filter: Filter.and([ + Filter.in_('members', [user.id]), + Filter.equal('type', 'messaging'), + ]), + sort: [SortOption('last_message_at')], + pagination: PaginationParams( + limit: 20, + ), + emptyBuilder: (BuildContext context) { + return Center( + child: Text('Looks like you are not in any channels'), + ); + }, + loadingBuilder: (BuildContext context) { + return Center( + child: SizedBox( + height: 100.0, + width: 100.0, + child: CupertinoActivityIndicator(), + ), + ); + }, + errorBuilder: (BuildContext context, dynamic error) { + return Center( + child: Text( + 'Oh no, something went wrong. Please check your config.'), + ); + }, + listBuilder: ( + BuildContext context, + List channels, + ) => + LazyLoadScrollView( + onEndOfPage: () async { + return channelListController.paginateData!(); + }, + child: CustomScrollView( + slivers: [ + CupertinoSliverRefreshControl(onRefresh: () async { + return channelListController.loadData!(); + }), + ChannelPageAppBar(), + SliverPadding( + sliver: ChannelListView(channels: channels), + padding: const EdgeInsets.only(top: 16), + ) + ], + ), + ), + ), + ), + ); } } diff --git a/packages/imessage/lib/message_header.dart b/packages/imessage/lib/message_header.dart index 31ae34b..e8ee94b 100644 --- a/packages/imessage/lib/message_header.dart +++ b/packages/imessage/lib/message_header.dart @@ -4,7 +4,7 @@ import 'package:imessage/utils.dart'; class MessageHeader extends StatelessWidget { final String rawTimeStamp; - const MessageHeader({Key key, @required this.rawTimeStamp}) : super(key: key); + const MessageHeader({Key? key, required this.rawTimeStamp}) : super(key: key); @override Widget build(BuildContext context) { diff --git a/packages/imessage/lib/message_input.dart b/packages/imessage/lib/message_input.dart index 9d9d831..7836498 100644 --- a/packages/imessage/lib/message_input.dart +++ b/packages/imessage/lib/message_input.dart @@ -3,11 +3,11 @@ import 'dart:io'; import 'package:flutter/cupertino.dart'; import 'package:image_picker/image_picker.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart' - show Attachment, AttachmentFile, Message, MultipartFile, StreamChannel; + show Attachment, AttachmentFile, Message, StreamChannel; class MessageInput extends StatefulWidget { const MessageInput({ - Key key, + Key? key, }) : super(key: key); @override @@ -16,7 +16,6 @@ class MessageInput extends StatefulWidget { class _MessageInputState extends State { final textController = TextEditingController(); - File _image; final picker = ImagePicker(); @override @@ -39,16 +38,25 @@ class _MessageInputState extends State { GestureDetector( onTap: () async { final pickedFile = - await picker.getImage(source: ImageSource.gallery); + await (picker.getImage(source: ImageSource.gallery)); + if (pickedFile == null) { + return; + } final bytes = await File(pickedFile.path).readAsBytes(); final channel = StreamChannel.of(context).channel; - final message = - Message(text: textController.value.text, attachments: [ - Attachment( - type: 'image', - file: AttachmentFile(bytes: bytes, path: pickedFile.path), - ), - ]); + final message = Message( + text: textController.value.text, + attachments: [ + Attachment( + type: 'image', + file: AttachmentFile( + bytes: bytes, + path: pickedFile.path, + size: bytes.length, + ), + ), + ], + ); await channel.sendMessage(message); }, child: Padding( @@ -68,10 +76,11 @@ class _MessageInputState extends State { }, placeholder: 'Text Message', prefix: Padding( - padding: const EdgeInsets.all(8.0), - child: Text( - "") //trick to add padding around placeholder iMessage text - ), + padding: const EdgeInsets.all(8.0), + child: Text( + '', + ), //trick to add padding around placeholder iMessage text + ), suffix: GestureDetector( onTap: () async { if (textController.value.text.isNotEmpty) { diff --git a/packages/imessage/lib/message_list_view.dart b/packages/imessage/lib/message_list_view.dart index e12572c..b76f506 100644 --- a/packages/imessage/lib/message_list_view.dart +++ b/packages/imessage/lib/message_list_view.dart @@ -7,12 +7,12 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart' show Message, StreamChatCore; class MessageListView extends StatelessWidget { - const MessageListView({Key key, this.messages}) : super(key: key); - final List messages; + const MessageListView({Key? key, this.messages}) : super(key: key); + final List? messages; @override Widget build(BuildContext context) { - final entries = groupBy(messages, + final entries = groupBy(messages!, (Message message) => message.createdAt.toString().substring(0, 10)) .entries .toList(); @@ -64,8 +64,8 @@ class MessageListView extends StatelessWidget { } bool isReceived(Message message, BuildContext context) { - final currentUserId = StreamChatCore.of(context).user.id; - return message.user.id == currentUserId; + final currentUserId = StreamChatCore.of(context).user!.id; + return message.user!.id == currentUserId; } bool isSameDay(Message message) => diff --git a/packages/imessage/lib/message_page.dart b/packages/imessage/lib/message_page.dart index 01b555e..f64eb66 100644 --- a/packages/imessage/lib/message_page.dart +++ b/packages/imessage/lib/message_page.dart @@ -53,7 +53,7 @@ class MessagePage extends StatelessWidget { }, messageListBuilder: (context, messages) => LazyLoadScrollView( onStartOfPage: () async { - messageListController.paginateData(); + await messageListController.paginateData!(); }, child: MessageListView( messages: messages, diff --git a/packages/imessage/lib/message_widget.dart b/packages/imessage/lib/message_widget.dart index 494e9d2..8fa6638 100644 --- a/packages/imessage/lib/message_widget.dart +++ b/packages/imessage/lib/message_widget.dart @@ -1,8 +1,7 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/cupertino.dart'; import 'package:imessage/cutom_painter.dart'; -import 'package:stream_chat_flutter/stream_chat_flutter.dart' - show Message, AttachmentUploadStateBuilder; +import 'package:stream_chat_flutter/stream_chat_flutter.dart' show Message; class MessageWidget extends StatelessWidget { final Alignment alignment; @@ -11,16 +10,16 @@ class MessageWidget extends StatelessWidget { final Color messageColor; const MessageWidget( - {Key key, - @required this.alignment, - @required this.message, - @required this.color, - @required this.messageColor}) + {Key? key, + required this.alignment, + required this.message, + required this.color, + required this.messageColor}) : super(key: key); @override Widget build(BuildContext context) { - if (message.attachments?.isNotEmpty == true && + if (message.attachments.isNotEmpty == true && message.attachments.first.type == 'image') { return MessageImage( color: color, message: message, messageColor: messageColor); @@ -36,10 +35,10 @@ class MessageWidget extends StatelessWidget { class MessageImage extends StatelessWidget { const MessageImage({ - Key key, - @required this.color, - @required this.message, - @required this.messageColor, + Key? key, + required this.color, + required this.message, + required this.messageColor, }) : super(key: key); final Color color; @@ -61,23 +60,23 @@ class MessageImage extends StatelessWidget { children: [ if (message.attachments.first.file != null) Image.memory( - message.attachments.first.file.bytes, + message.attachments.first.file!.bytes!, fit: BoxFit.cover, ) else CachedNetworkImage( imageUrl: message.attachments.first.thumbUrl ?? message.attachments.first.imageUrl ?? - message.attachments.first.assetUrl, + message.attachments.first.assetUrl!, ), - if (message.attachments.first?.title != null) + if (message.attachments.first.title != null) Padding( padding: const EdgeInsets.all(8.0), - child: Text(message.attachments.first.title, + child: Text(message.attachments.first.title!, style: TextStyle(color: messageColor)), ), message.attachments.first.pretext != null - ? Text(message.attachments.first.pretext) + ? Text(message.attachments.first.pretext!) : Container() ], ), @@ -92,7 +91,7 @@ class MessageImage extends StatelessWidget { child: Container( color: color, child: CachedNetworkImage( - imageUrl: message.attachments.first.thumbUrl, + imageUrl: message.attachments.first.thumbUrl!, )), ); } @@ -101,11 +100,11 @@ class MessageImage extends StatelessWidget { class MessageText extends StatelessWidget { const MessageText({ - Key key, - @required this.alignment, - @required this.color, - @required this.message, - @required this.messageColor, + Key? key, + required this.alignment, + required this.color, + required this.message, + required this.messageColor, }) : super(key: key); final Alignment alignment; @@ -133,7 +132,7 @@ class MessageText extends StatelessWidget { child: Padding( padding: const EdgeInsets.all(4.0), child: Text( - message.text, + message.text!, style: TextStyle(color: messageColor), ), ), diff --git a/packages/imessage/lib/utils.dart b/packages/imessage/lib/utils.dart index 4600512..6487b35 100644 --- a/packages/imessage/lib/utils.dart +++ b/packages/imessage/lib/utils.dart @@ -26,24 +26,26 @@ bool isSameWeek(DateTime timestamp) => DateTime.now().difference(timestamp).inDays < 7; class CupertinoCircleAvatar extends StatelessWidget { - final String url; - final double size; - const CupertinoCircleAvatar({Key key, this.url, this.size}) : super(key: key); + final String? url; + final double? size; + const CupertinoCircleAvatar({Key? key, this.url, this.size}) + : super(key: key); @override Widget build(BuildContext context) { return ClipRRect( - borderRadius: BorderRadius.circular(size / 2), + borderRadius: BorderRadius.circular(size! / 2), child: CachedNetworkImage( - imageUrl: url, + imageUrl: url!, height: size, width: size, fit: BoxFit.cover, errorWidget: (context, url, error) { //TODO: this crash the app when getting 404 and in debug mode, see :https://github.com/Baseflow/flutter_cached_network_image/issues/504 return CachedNetworkImage( - imageUrl: - "https://4.bp.blogspot.com/-Jx21kNqFSTU/UXemtqPhZCI/AAAAAAAAh74/BMGSzpU6F48/s1600/funny-cat-pictures-047-001.jpg"); + imageUrl: + 'https://4.bp.blogspot.com/-Jx21kNqFSTU/UXemtqPhZCI/AAAAAAAAh74/BMGSzpU6F48/s1600/funny-cat-pictures-047-001.jp', + ); }), ); } @@ -51,18 +53,18 @@ class CupertinoCircleAvatar extends StatelessWidget { class Divider extends StatelessWidget { const Divider({ - Key key, + Key? key, }) : super(key: key); @override Widget build(BuildContext context) { return Expanded( child: Align( + alignment: Alignment.bottomCenter, child: Container( height: 1, color: CupertinoColors.systemGrey5, ), - alignment: Alignment.bottomCenter, ), ); } diff --git a/packages/imessage/pubspec.yaml b/packages/imessage/pubspec.yaml index 62e7507..9d05f4c 100644 --- a/packages/imessage/pubspec.yaml +++ b/packages/imessage/pubspec.yaml @@ -18,16 +18,16 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev version: 1.0.0+1 environment: - sdk: ">=2.7.0 <3.0.0" + sdk: '>=2.12.0 <3.0.0' dependencies: flutter: sdk: flutter - intl: ^0.16.1 - stream_chat_flutter: ^1.3.0-beta - animations: ^1.0.0+5 - collection: ^1.14.13 - cached_network_image: ^2.0.0-rc + intl: ^0.17.0 + stream_chat_flutter: ^2.0.0-nullsafety.3 + animations: ^2.0.0 + collection: ^1.15.0 + cached_network_image: ^3.0.0 # The following adds the Cupertino Icons font to your application.