diff --git a/packages/stream_chat_v1/lib/advanced_options_page.dart b/packages/stream_chat_v1/lib/advanced_options_page.dart index a654f3d..b4a4326 100644 --- a/packages/stream_chat_v1/lib/advanced_options_page.dart +++ b/packages/stream_chat_v1/lib/advanced_options_page.dart @@ -17,13 +17,13 @@ class _AdvancedOptionsPageState extends State { final _formKey = GlobalKey(); final TextEditingController _apiKeyController = TextEditingController(); - String _apiKeyError; + String? _apiKeyError; final TextEditingController _userIdController = TextEditingController(); - String _userIdError; + String? _userIdError; final TextEditingController _userTokenController = TextEditingController(); - String _userTokenError; + String? _userTokenError; final TextEditingController _usernameController = TextEditingController(); @@ -73,7 +73,7 @@ class _AdvancedOptionsPageState extends State { } }, validator: (value) { - if (value.isEmpty) { + if (value!.isEmpty) { setState(() { _apiKeyError = 'Please enter the Chat API Key'.toUpperCase(); @@ -119,7 +119,7 @@ class _AdvancedOptionsPageState extends State { } }, validator: (value) { - if (value.isEmpty) { + if (value!.isEmpty) { setState(() { _userIdError = 'Please enter the User ID'.toUpperCase(); @@ -165,7 +165,7 @@ class _AdvancedOptionsPageState extends State { }, controller: _userTokenController, validator: (value) { - if (value.isEmpty) { + if (value!.isEmpty) { setState(() { _userTokenError = 'Please enter the user token'.toUpperCase(); @@ -243,7 +243,7 @@ class _AdvancedOptionsPageState extends State { if (loading) { return; } - if (_formKey.currentState.validate()) { + if (_formKey.currentState!.validate()) { final apiKey = _apiKeyController.text; final userId = _userIdController.text; final userToken = _userTokenController.text; diff --git a/packages/stream_chat_v1/lib/channel_file_display_screen.dart b/packages/stream_chat_v1/lib/channel_file_display_screen.dart index cbd5264..806f184 100644 --- a/packages/stream_chat_v1/lib/channel_file_display_screen.dart +++ b/packages/stream_chat_v1/lib/channel_file_display_screen.dart @@ -6,16 +6,16 @@ class ChannelFileDisplayScreen extends StatefulWidget { /// Sorting is based on field and direction, multiple sorting options can be provided. /// You can sort based on last_updated, last_message_at, updated_at, created_at or member_count. /// Direction can be ascending or descending. - final List sortOptions; + final List? sortOptions; /// Pagination parameters /// limit: the number of users to return (max is 30) /// offset: the offset (max is 1000) /// message_limit: how many messages should be included to each channel - final PaginationParams paginationParams; + final PaginationParams? paginationParams; /// The builder used when the file list is empty. - final WidgetBuilder emptyBuilder; + final WidgetBuilder? emptyBuilder; const ChannelFileDisplayScreen({ this.sortOptions, @@ -36,7 +36,7 @@ class _ChannelFileDisplayScreenState extends State { messageSearchBloc.search( filter: Filter.in_( 'cid', - [StreamChannel.of(context).channel.cid], + [StreamChannel.of(context).channel.cid!], ), messageFilter: Filter.in_( 'attachments.type', @@ -93,9 +93,9 @@ class _ChannelFileDisplayScreenState extends State { ); } - if (snapshot.data.isEmpty) { + if (snapshot.data!.isEmpty) { if (widget.emptyBuilder != null) { - return widget.emptyBuilder(context); + return widget.emptyBuilder!(context); } return Center( child: Column( @@ -132,7 +132,7 @@ class _ChannelFileDisplayScreenState extends State { final media = {}; - for (var item in snapshot.data) { + for (var item in snapshot.data!) { item.message.attachments.where((e) => e.type == 'file').forEach((e) { media[e] = item.message; }); @@ -142,14 +142,14 @@ class _ChannelFileDisplayScreenState extends State { onEndOfPage: () => messageSearchBloc.search( filter: Filter.in_( 'cid', - [StreamChannel.of(context).channel.cid], + [StreamChannel.of(context).channel.cid!], ), messageFilter: Filter.in_( 'attachments.type', ['file'], ), sort: widget.sortOptions, - pagination: widget.paginationParams.copyWith( + pagination: widget.paginationParams!.copyWith( offset: messageSearchBloc.messageResponses?.length ?? 0, ), ), diff --git a/packages/stream_chat_v1/lib/channel_media_display_screen.dart b/packages/stream_chat_v1/lib/channel_media_display_screen.dart index 2bf0fb1..5c33622 100644 --- a/packages/stream_chat_v1/lib/channel_media_display_screen.dart +++ b/packages/stream_chat_v1/lib/channel_media_display_screen.dart @@ -7,23 +7,23 @@ class ChannelMediaDisplayScreen extends StatefulWidget { /// Sorting is based on field and direction, multiple sorting options can be provided. /// You can sort based on last_updated, last_message_at, updated_at, created_at or member_count. /// Direction can be ascending or descending. - final List sortOptions; + final List? sortOptions; /// Pagination parameters /// limit: the number of users to return (max is 30) /// offset: the offset (max is 1000) /// message_limit: how many messages should be included to each channel - final PaginationParams paginationParams; + final PaginationParams? paginationParams; /// The builder used when the file list is empty. - final WidgetBuilder emptyBuilder; + final WidgetBuilder? emptyBuilder; - final ShowMessageCallback onShowMessage; + final ShowMessageCallback? onShowMessage; final MessageTheme messageTheme; const ChannelMediaDisplayScreen({ - @required this.messageTheme, + required this.messageTheme, this.sortOptions, this.paginationParams, this.emptyBuilder, @@ -36,7 +36,7 @@ class ChannelMediaDisplayScreen extends StatefulWidget { } class _ChannelMediaDisplayScreenState extends State { - Map controllerCache = {}; + Map controllerCache = {}; @override void initState() { @@ -45,7 +45,7 @@ class _ChannelMediaDisplayScreenState extends State { messageSearchBloc.search( filter: Filter.in_( 'cid', - [StreamChannel.of(context).channel.cid], + [StreamChannel.of(context).channel.cid!], ), messageFilter: Filter.in_( 'attachments.type', @@ -103,9 +103,9 @@ class _ChannelMediaDisplayScreenState extends State { ); } - if (snapshot.data.isEmpty) { + if (snapshot.data!.isEmpty) { if (widget.emptyBuilder != null) { - return widget.emptyBuilder(context); + return widget.emptyBuilder!(context); } return Center( child: Column( @@ -142,18 +142,18 @@ class _ChannelMediaDisplayScreenState extends State { final media = <_AssetPackage>[]; - for (var item in snapshot.data) { + for (var item in snapshot.data!) { item.message.attachments .where((e) => (e.type == 'image' || e.type == 'video') && e.ogScrapeUrl == null) .forEach((e) { - VideoPlayerController controller; + VideoPlayerController? controller; if (e.type == 'video') { var cachedController = controllerCache[e.assetUrl]; if (cachedController == null) { - controller = VideoPlayerController.network(e.assetUrl); + controller = VideoPlayerController.network(e.assetUrl!); controller.initialize(); controllerCache[e.assetUrl] = controller; } else { @@ -168,14 +168,14 @@ class _ChannelMediaDisplayScreenState extends State { onEndOfPage: () => messageSearchBloc.search( filter: Filter.in_( 'cid', - [StreamChannel.of(context).channel.cid], + [StreamChannel.of(context).channel.cid!], ), messageFilter: Filter.in_( 'attachments.type', ['image', 'video'], ), sort: widget.sortOptions, - pagination: widget.paginationParams.copyWith( + pagination: widget.paginationParams!.copyWith( offset: messageSearchBloc.messageResponses?.length ?? 0, ), ), @@ -198,7 +198,7 @@ class _ChannelMediaDisplayScreenState extends State { media.map((e) => e.attachment).toList(), startIndex: position, message: media[position].message, - userName: media[position].message.user.name, + userName: media[position].message.user!.name, onShowMessage: widget.onShowMessage, ), ), @@ -218,7 +218,7 @@ class _ChannelMediaDisplayScreenState extends State { messageTheme: widget.messageTheme, ), ) - : VideoPlayer(media[position].videoPlayer), + : VideoPlayer(media[position].videoPlayer!), ), ); }, @@ -234,7 +234,7 @@ class _ChannelMediaDisplayScreenState extends State { void dispose() { super.dispose(); for (var c in controllerCache.values) { - c.dispose(); + c!.dispose(); } } } @@ -242,7 +242,7 @@ class _ChannelMediaDisplayScreenState extends State { class _AssetPackage { Attachment attachment; Message message; - VideoPlayerController videoPlayer; + VideoPlayerController? videoPlayer; _AssetPackage(this.attachment, this.message, this.videoPlayer); } diff --git a/packages/stream_chat_v1/lib/chat_info_screen.dart b/packages/stream_chat_v1/lib/chat_info_screen.dart index 99611c8..8a09f43 100644 --- a/packages/stream_chat_v1/lib/chat_info_screen.dart +++ b/packages/stream_chat_v1/lib/chat_info_screen.dart @@ -1,3 +1,4 @@ +import 'package:collection/collection.dart' show IterableExtension; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:jiffy/jiffy.dart'; @@ -11,13 +12,13 @@ import 'routes/routes.dart'; /// Detail screen for a 1:1 chat correspondence class ChatInfoScreen extends StatefulWidget { /// User in consideration - final User user; + final User? user; final MessageTheme messageTheme; const ChatInfoScreen({ - Key key, - @required this.messageTheme, + Key? key, + required this.messageTheme, this.user, }) : super(key: key); @@ -26,7 +27,7 @@ class ChatInfoScreen extends StatefulWidget { } class _ChatInfoScreenState extends State { - ValueNotifier mutedBool = ValueNotifier(false); + ValueNotifier mutedBool = ValueNotifier(false); @override void initState() { @@ -54,9 +55,8 @@ class _ChatInfoScreenState extends State { if ([ 'admin', 'owner', - ].contains(channel.state.members - .firstWhere((m) => m.userId == channel.client.state.user.id, - orElse: () => null) + ].contains(channel.state!.members + .firstWhereOrNull((m) => m.userId == channel.client.state.user!.id) ?.role)) _buildDeleteListTile(), ], @@ -76,7 +76,7 @@ class _ChatInfoScreenState extends State { Padding( padding: const EdgeInsets.all(16.0), child: UserAvatar( - user: widget.user, + user: widget.user!, constraints: BoxConstraints( maxWidth: 72.0, maxHeight: 72.0, @@ -86,19 +86,19 @@ class _ChatInfoScreenState extends State { ), ), Text( - widget.user.name, + widget.user!.name, style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold), ), SizedBox(height: 7.0), _buildConnectedTitleState(), SizedBox(height: 15.0), OptionListTile( - title: '@${widget.user.id}', + title: '@${widget.user!.id}', tileColor: StreamChatTheme.of(context).colorTheme.whiteSnow, trailing: Padding( padding: const EdgeInsets.symmetric(horizontal: 8.0), child: Text( - widget.user.name, + widget.user!.name, style: TextStyle( color: StreamChatTheme.of(context) .colorTheme @@ -161,15 +161,15 @@ class _ChatInfoScreenState extends State { ), trailing: snapshot.data == null ? CircularProgressIndicator() - : ValueListenableBuilder( + : ValueListenableBuilder( valueListenable: mutedBool, builder: (context, value, _) { return CupertinoSwitch( - value: value, + value: value!, onChanged: (val) { mutedBool.value = val; - if (snapshot.data) { + if (snapshot.data!) { channel.channel.unmute(); } else { channel.channel.mute(); @@ -394,7 +394,7 @@ class _ChatInfoScreenState extends State { return Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - if (widget.user.online) + if (widget.user!.online) Material( type: MaterialType.circle, child: Container( @@ -411,7 +411,7 @@ class _ChatInfoScreenState extends State { color: StreamChatTheme.of(context).colorTheme.white, ), alternativeWidget, - if (widget.user.online) + if (widget.user!.online) SizedBox( width: 24.0, ), @@ -421,8 +421,8 @@ class _ChatInfoScreenState extends State { } class _SharedGroupsScreen extends StatefulWidget { - final User mainUser; - final User otherUser; + final User? mainUser; + final User? otherUser; _SharedGroupsScreen(this.mainUser, this.otherUser); @@ -453,8 +453,8 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { body: StreamBuilder>( stream: chat.client.queryChannels( filter: Filter.and([ - Filter.in_('members', [widget.otherUser.id]), - Filter.in_('members', [widget.mainUser.id]), + Filter.in_('members', [widget.otherUser!.id]), + Filter.in_('members', [widget.mainUser!.id]), ]), ), builder: (context, snapshot) { @@ -464,7 +464,7 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { ); } - if (snapshot.data.isEmpty) { + if (snapshot.data!.isEmpty) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, @@ -498,11 +498,11 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { ); } - final channels = snapshot.data + final channels = snapshot.data! .where((c) => - c.state.members.any((m) => - m.userId != widget.mainUser.id && - m.userId != widget.otherUser.id) || + c.state!.members.any((m) => + m.userId != widget.mainUser!.id && + m.userId != widget.otherUser!.id) || !c.isDistinct) .toList(); @@ -522,24 +522,24 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { Widget _buildListTile(Channel channel) { var extraData = channel.extraData; - var members = channel.state.members; + var members = channel.state!.members; var textStyle = TextStyle(fontSize: 14.0, fontWeight: FontWeight.bold); return Container( height: 64.0, child: LayoutBuilder(builder: (context, constraints) { - String title; + String? title; if (extraData['name'] == null) { final otherMembers = members.where( - (member) => member.userId != StreamChat.of(context).user.id); + (member) => member.userId != StreamChat.of(context).user!.id); if (otherMembers.isNotEmpty) { final maxWidth = constraints.maxWidth; - final maxChars = maxWidth / textStyle.fontSize; + final maxChars = maxWidth / textStyle.fontSize!; var currentChars = 0; final currentMembers = []; otherMembers.forEach((element) { - final newLength = currentChars + element.user.name.length; + final newLength = currentChars + element.user!.name.length; if (newLength < maxChars) { currentChars = newLength; currentMembers.add(element); @@ -549,7 +549,7 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { final exceedingMembers = otherMembers.length - currentMembers.length; title = - '${currentMembers.map((e) => e.user.name).join(', ')} ${exceedingMembers > 0 ? '+ $exceedingMembers' : ''}'; + '${currentMembers.map((e) => e.user!.name).join(', ')} ${exceedingMembers > 0 ? '+ $exceedingMembers' : ''}'; } else { title = 'No title'; } @@ -572,7 +572,7 @@ class __SharedGroupsScreenState extends State<_SharedGroupsScreen> { ), Expanded( child: Text( - title, + title!, style: textStyle, )), Padding( diff --git a/packages/stream_chat_v1/lib/chips_input_text_field.dart b/packages/stream_chat_v1/lib/chips_input_text_field.dart index 0fc0791..c36e4ae 100644 --- a/packages/stream_chat_v1/lib/chips_input_text_field.dart +++ b/packages/stream_chat_v1/lib/chips_input_text_field.dart @@ -6,18 +6,18 @@ typedef OnChipAdded = void Function(T chip); typedef OnChipRemoved = void Function(T chip); class ChipsInputTextField extends StatefulWidget { - final TextEditingController controller; - final FocusNode focusNode; - final ValueChanged onInputChanged; + final TextEditingController? controller; + final FocusNode? focusNode; + final ValueChanged? onInputChanged; final ChipBuilder chipBuilder; - final OnChipAdded onChipAdded; - final OnChipRemoved onChipRemoved; + final OnChipAdded? onChipAdded; + final OnChipRemoved? onChipRemoved; final String hint; const ChipsInputTextField({ - Key key, - @required this.chipBuilder, - @required this.controller, + Key? key, + required this.chipBuilder, + required this.controller, this.onInputChanged, this.focusNode, this.onChipAdded, @@ -35,7 +35,7 @@ class ChipInputTextFieldState extends State> { void addItem(T item) { setState(() => _chips.add(item)); - if (widget.onChipAdded != null) widget.onChipAdded(item); + if (widget.onChipAdded != null) widget.onChipAdded!(item); } void removeItem(T item) { @@ -43,7 +43,7 @@ class ChipInputTextFieldState extends State> { _chips.remove(item); if (_chips.isEmpty) resumeItemAddition(); }); - if (widget.onChipRemoved != null) widget.onChipRemoved(item); + if (widget.onChipRemoved != null) widget.onChipRemoved!(item); } void pauseItemAddition() { diff --git a/packages/stream_chat_v1/lib/group_chat_details_screen.dart b/packages/stream_chat_v1/lib/group_chat_details_screen.dart index afc9d12..1819fe8 100644 --- a/packages/stream_chat_v1/lib/group_chat_details_screen.dart +++ b/packages/stream_chat_v1/lib/group_chat_details_screen.dart @@ -6,11 +6,11 @@ import 'main.dart'; import 'routes/routes.dart'; class GroupChatDetailsScreen extends StatefulWidget { - final List selectedUsers; + final List? selectedUsers; const GroupChatDetailsScreen({ - Key key, - @required this.selectedUsers, + Key? key, + required this.selectedUsers, }) : super(key: key); @override @@ -20,14 +20,14 @@ class GroupChatDetailsScreen extends StatefulWidget { class _GroupChatDetailsScreenState extends State { final _selectedUsers = []; - TextEditingController _groupNameController; + TextEditingController? _groupNameController; bool _isGroupNameEmpty = true; int get _totalUsers => _selectedUsers.length; void _groupNameListener() { - final name = _groupNameController.text; + final name = _groupNameController!.text; if (mounted) { setState(() { _isGroupNameEmpty = name.isEmpty; @@ -38,7 +38,7 @@ class _GroupChatDetailsScreenState extends State { @override void initState() { super.initState(); - _selectedUsers.addAll(widget.selectedUsers); + _selectedUsers.addAll(widget.selectedUsers!); _groupNameController = TextEditingController() ..addListener(_groupNameListener); } @@ -124,13 +124,13 @@ class _GroupChatDetailsScreenState extends State { ? null : () async { try { - final groupName = _groupNameController.text; + final groupName = _groupNameController!.text; final client = StreamChat.of(context).client; final channel = client.channel('messaging', id: Uuid().v4(), extraData: { 'members': [ - client.state.user.id, + client.state.user!.id, ..._selectedUsers.map((e) => e.id), ], 'name': groupName, diff --git a/packages/stream_chat_v1/lib/group_info_screen.dart b/packages/stream_chat_v1/lib/group_info_screen.dart index d84826c..00e3966 100644 --- a/packages/stream_chat_v1/lib/group_info_screen.dart +++ b/packages/stream_chat_v1/lib/group_info_screen.dart @@ -1,5 +1,6 @@ import 'dart:async'; +import 'package:collection/collection.dart' show IterableExtension; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:jiffy/jiffy.dart'; @@ -17,8 +18,8 @@ class GroupInfoScreen extends StatefulWidget { final MessageTheme messageTheme; const GroupInfoScreen({ - Key key, - @required this.messageTheme, + Key? key, + required this.messageTheme, }) : super(key: key); @override @@ -26,29 +27,29 @@ class GroupInfoScreen extends StatefulWidget { } class _GroupInfoScreenState extends State { - TextEditingController _nameController; + TextEditingController? _nameController; - TextEditingController _searchController; + TextEditingController? _searchController; String _userNameQuery = ''; - Timer _debounce; - Function modalSetStateCallback; + Timer? _debounce; + Function? modalSetStateCallback; final FocusNode _focusNode = FocusNode(); bool listExpanded = false; - ValueNotifier mutedBool = ValueNotifier(false); + ValueNotifier mutedBool = ValueNotifier(false); void _userNameListener() { - if (_searchController.text == _userNameQuery) { + if (_searchController!.text == _userNameQuery) { return; } - if (_debounce?.isActive ?? false) _debounce.cancel(); + if (_debounce?.isActive ?? false) _debounce!.cancel(); _debounce = Timer(const Duration(milliseconds: 350), () { if (mounted && modalSetStateCallback != null) { - modalSetStateCallback(() { - _userNameQuery = _searchController.text; + modalSetStateCallback!(() { + _userNameQuery = _searchController!.text; }); } }); @@ -62,7 +63,7 @@ class _GroupInfoScreenState extends State { TextEditingValue(text: channel.channel.extraData['name'] ?? '')); _searchController = TextEditingController()..addListener(_userNameListener); - _nameController.addListener(() { + _nameController!.addListener(() { setState(() {}); }); mutedBool = ValueNotifier(StreamChannel.of(context).channel.isMuted); @@ -73,7 +74,7 @@ class _GroupInfoScreenState extends State { var channel = StreamChannel.of(context); return StreamBuilder>( - stream: channel.channel.state.membersStream, + stream: channel.channel.state!.membersStream, builder: (context, snapshot) { if (!snapshot.hasData) { return Container( @@ -82,9 +83,8 @@ class _GroupInfoScreenState extends State { ); } - var userMember = snapshot.data.firstWhere( - (e) => e.user.id == StreamChat.of(context).user.id, - orElse: () => null, + var userMember = snapshot.data!.firstWhereOrNull( + (e) => e.user!.id == StreamChat.of(context).user!.id, ); var isOwner = userMember?.role == 'owner'; @@ -118,9 +118,9 @@ class _GroupInfoScreenState extends State { _getChannelName( 2 * MediaQuery.of(context).size.width / 3, members: snapshot.data, - extraData: state.data.channel.extraData, + extraData: state.data!.channel!.extraData, maxFontSize: 16.0, - ), + )!, style: TextStyle( color: StreamChatTheme.of(context).colorTheme.black, fontSize: 16, @@ -133,7 +133,7 @@ class _GroupInfoScreenState extends State { height: 3.0, ), Text( - '${channel.channel.memberCount} Members, ${snapshot?.data?.where((e) => e.user.online)?.length ?? 0} Online', + '${channel.channel.memberCount} Members, ${snapshot.data?.where((e) => e.user!.online).length ?? 0} Online', style: TextStyle( color: StreamChatTheme.of(context) .colorTheme @@ -165,7 +165,7 @@ class _GroupInfoScreenState extends State { ), body: ListView( children: [ - _buildMembers(snapshot.data), + _buildMembers(snapshot.data!), Container( height: 8.0, color: StreamChatTheme.of(context).colorTheme.greyGainsboro, @@ -204,9 +204,8 @@ class _GroupInfoScreenState extends State { return Material( child: InkWell( onTap: () { - final userMember = groupMembers.firstWhere( - (e) => e.user.id == StreamChat.of(context).user.id, - orElse: () => null, + final userMember = groupMembers.firstWhereOrNull( + (e) => e.user!.id == StreamChat.of(context).user!.id, ); _showUserInfoModal(member.user, userMember?.role == 'owner'); }, @@ -220,7 +219,7 @@ class _GroupInfoScreenState extends State { padding: const EdgeInsets.symmetric( horizontal: 8.0, vertical: 12.0), child: UserAvatar( - user: member.user, + user: member.user!, constraints: BoxConstraints( maxHeight: 40.0, maxWidth: 40.0), ), @@ -231,14 +230,14 @@ class _GroupInfoScreenState extends State { mainAxisAlignment: MainAxisAlignment.center, children: [ Text( - member.user.name, + member.user!.name, style: TextStyle(fontWeight: FontWeight.bold), ), SizedBox( height: 1.0, ), Text( - _getLastSeen(member.user), + _getLastSeen(member.user!), style: TextStyle( color: StreamChatTheme.of(context) .colorTheme @@ -378,7 +377,7 @@ class _GroupInfoScreenState extends State { ), ), if ((channelName == null) || - (channelName != _nameController.text.trim())) + (channelName != _nameController!.text.trim())) Row( mainAxisSize: MainAxisSize.min, children: [ @@ -386,12 +385,12 @@ class _GroupInfoScreenState extends State { child: StreamSvgIcon.closeSmall(), onTap: () { setState(() { - _nameController.text = _getChannelName( + _nameController!.text = _getChannelName( 2 * MediaQuery.of(context).size.width / 3, - members: channel.state.members, + members: channel.state!.members, extraData: channel.extraData, maxFontSize: 16.0, - ); + )!; _focusNode.unfocus(); }); }, @@ -406,10 +405,10 @@ class _GroupInfoScreenState extends State { ), onTap: () { StreamChannel.of(context).channel.update({ - 'name': _nameController.text.trim(), + 'name': _nameController!.text.trim(), }).catchError((err) { setState(() { - _nameController.text = channelName; + _nameController!.text = channelName; _focusNode.unfocus(); }); }); @@ -464,15 +463,15 @@ class _GroupInfoScreenState extends State { ), trailing: snapshot.data == null ? CircularProgressIndicator() - : ValueListenableBuilder( + : ValueListenableBuilder( valueListenable: mutedBool, builder: (context, value, _) { return CupertinoSwitch( - value: value, + value: value!, onChanged: (val) { mutedBool.value = val; - if (snapshot.data) { + if (snapshot.data!) { channel.channel.unmute(); } else { channel.channel.mute(); @@ -617,7 +616,7 @@ class _GroupInfoScreenState extends State { ); if (res == true) { final channel = StreamChannel.of(context).channel; - await channel.removeMembers([StreamChat.of(context).user.id]); + await channel.removeMembers([StreamChat.of(context).user!.id]); Navigator.pop(context); } }, @@ -655,7 +654,7 @@ class _GroupInfoScreenState extends State { child: UserListView( selectedUsers: {}, onUserTap: (user, _) async { - _searchController.clear(); + _searchController!.clear(); await channel.addMembers([user.id]); Navigator.pop(context); @@ -667,11 +666,12 @@ class _GroupInfoScreenState extends State { ), filter: Filter.and( [ - if (_searchController.text.isNotEmpty) + if (_searchController!.text.isNotEmpty) Filter.autoComplete('name', _userNameQuery), Filter.notIn('id', [ - StreamChat.of(context).user.id, - ...channel.state.members.map((e) => e.userId), + StreamChat.of(context).user!.id, + ...channel.state!.members.map(((e) => e.userId!) + as Object Function(Member)), ]), ], ), @@ -784,7 +784,7 @@ class _GroupInfoScreenState extends State { ); } - void _showUserInfoModal(User user, bool isUserAdmin) { + void _showUserInfoModal(User? user, bool isUserAdmin) { var channel = StreamChannel.of(context).channel; showModalBottomSheet( @@ -804,7 +804,7 @@ class _GroupInfoScreenState extends State { ), Center( child: Text( - user.name, + user!.name, style: TextStyle( fontSize: 16.0, fontWeight: FontWeight.bold, @@ -814,7 +814,7 @@ class _GroupInfoScreenState extends State { SizedBox( height: 5.0, ), - _buildConnectedTitleState(user), + _buildConnectedTitleState(user)!, Center( child: Padding( padding: const EdgeInsets.all(16.0), @@ -828,7 +828,7 @@ class _GroupInfoScreenState extends State { ), ), ), - if (StreamChat.of(context).user.id != user.id) + if (StreamChat.of(context).user!.id != user.id) _buildModalListTile( context, StreamSvgIcon.user( @@ -842,7 +842,7 @@ class _GroupInfoScreenState extends State { var c = client.channel('messaging', extraData: { 'members': [ user.id, - StreamChat.of(context).user.id, + StreamChat.of(context).user!.id, ], }); @@ -862,7 +862,7 @@ class _GroupInfoScreenState extends State { ); }, ), - if (StreamChat.of(context).user.id != user.id) + if (StreamChat.of(context).user!.id != user.id) _buildModalListTile( context, StreamSvgIcon.message( @@ -876,7 +876,7 @@ class _GroupInfoScreenState extends State { var c = client.channel('messaging', extraData: { 'members': [ user.id, - StreamChat.of(context).user.id, + StreamChat.of(context).user!.id, ], }); @@ -894,7 +894,7 @@ class _GroupInfoScreenState extends State { }, ), if (!channel.isDistinct && - StreamChat.of(context).user.id != user.id && + StreamChat.of(context).user!.id != user.id && isUserAdmin) _buildModalListTile( context, @@ -906,7 +906,7 @@ class _GroupInfoScreenState extends State { // TODO: Add make owner implementation (Remaining from backend) }), if (!channel.isDistinct && - StreamChat.of(context).user.id != user.id && + StreamChat.of(context).user!.id != user.id && isUserAdmin) _buildModalListTile( context, @@ -941,7 +941,7 @@ class _GroupInfoScreenState extends State { ); } - Widget _buildConnectedTitleState(User user) { + Widget? _buildConnectedTitleState(User? user) { var alternativeWidget; final otherMember = user; @@ -973,7 +973,7 @@ class _GroupInfoScreenState extends State { Widget _buildModalListTile( BuildContext context, Widget leading, String title, VoidCallback onTap, - {Color color}) { + {Color? color}) { color ??= StreamChatTheme.of(context).colorTheme.black; return Material( @@ -1010,24 +1010,24 @@ class _GroupInfoScreenState extends State { ); } - String _getChannelName( + String? _getChannelName( double width, { - List members, - Map extraData, - double maxFontSize, + List? members, + required Map extraData, + double? maxFontSize, }) { - String title; + String? title; var client = StreamChat.of(context); if (extraData['name'] == null) { final otherMembers = - members.where((member) => member.user.id != client.user.id); + members!.where((member) => member.user!.id != client.user!.id); if (otherMembers.isNotEmpty) { final maxWidth = width; - final maxChars = maxWidth / maxFontSize; + final maxChars = maxWidth / maxFontSize!; var currentChars = 0; final currentMembers = []; otherMembers.forEach((element) { - final newLength = currentChars + element.user.name.length; + final newLength = currentChars + element.user!.name.length; if (newLength < maxChars) { currentChars = newLength; currentMembers.add(element); @@ -1036,7 +1036,7 @@ class _GroupInfoScreenState extends State { final exceedingMembers = otherMembers.length - currentMembers.length; title = - '${currentMembers.map((e) => e.user.name).join(', ')} ${exceedingMembers > 0 ? '+ $exceedingMembers' : ''}'; + '${currentMembers.map((e) => e.user!.name).join(', ')} ${exceedingMembers > 0 ? '+ $exceedingMembers' : ''}'; } else { title = 'No title'; } diff --git a/packages/stream_chat_v1/lib/main.dart b/packages/stream_chat_v1/lib/main.dart index 4610d55..8b982e4 100644 --- a/packages/stream_chat_v1/lib/main.dart +++ b/packages/stream_chat_v1/lib/main.dart @@ -1,5 +1,6 @@ import 'dart:async'; +import 'package:collection/collection.dart' show IterableExtension; import 'package:example/chat_info_screen.dart'; import 'package:example/choose_user_page.dart'; import 'package:example/group_info_screen.dart'; @@ -38,15 +39,15 @@ class MyApp extends StatefulWidget { } class _MyAppState extends State with TickerProviderStateMixin { - InitData _initData; + InitData? _initData; bool _animCompleted = false; - Animation _animation, _scaleAnimation; - AnimationController _animationController, _scaleAnimationController; - Animation _colorAnimation; - int timeOfStartMs; + Animation? _animation, _scaleAnimation; + AnimationController? _animationController, _scaleAnimationController; + Animation? _colorAnimation; + late int timeOfStartMs; Future _initConnection() async { - String apiKey, userId, token; + String? apiKey, userId, token; if (!kIsWeb) { final secureStorage = FlutterSecureStorage(); @@ -84,7 +85,7 @@ class _MyAppState extends State with TickerProviderStateMixin { begin: 1.0, end: 1.5, ).animate(CurvedAnimation( - parent: _scaleAnimationController, + parent: _scaleAnimationController!, curve: Curves.easeInOutBack, )); @@ -98,21 +99,21 @@ class _MyAppState extends State with TickerProviderStateMixin { begin: 0.0, end: 1000.0, ).animate(CurvedAnimation( - parent: _animationController, + parent: _animationController!, curve: Curves.easeInOut, )); _colorAnimation = ColorTween( begin: Color(0xff005FFF), end: Color(0xff005FFF), ).animate(CurvedAnimation( - parent: _animationController, + parent: _animationController!, curve: Curves.easeInOut, )); _colorAnimation = ColorTween( begin: Color(0xff005FFF), end: Colors.transparent, ).animate(CurvedAnimation( - parent: _animationController, + parent: _animationController!, curve: Curves.easeInOut, )); } @@ -132,22 +133,22 @@ class _MyAppState extends State with TickerProviderStateMixin { var now = DateTime.now().millisecondsSinceEpoch; if (now - timeOfStartMs > 1500) { - SchedulerBinding.instance.addPostFrameCallback((timeStamp) { - _scaleAnimationController.forward().whenComplete(() { - _animationController.forward(); + SchedulerBinding.instance!.addPostFrameCallback((timeStamp) { + _scaleAnimationController?.forward().whenComplete(() { + _animationController?.forward(); }); }); } else { Future.delayed(Duration(milliseconds: 1500)).then((value) { - _scaleAnimationController.forward().whenComplete(() { - _animationController.forward(); + _scaleAnimationController?.forward().whenComplete(() { + _animationController?.forward(); }); }); } if (!kIsWeb) { - _initData.client.state?.totalUnreadCountStream?.listen((count) { - if (count > 0) { + _initData!.client.state.totalUnreadCountStream.listen((count) { + if (count! > 0) { FlutterAppBadger.updateBadgeCount(count); } else { FlutterAppBadger.removeBadge(); @@ -156,7 +157,7 @@ class _MyAppState extends State with TickerProviderStateMixin { } }, ); - _animationController.addStatusListener((status) { + _animationController?.addStatusListener((status) { if (status == AnimationStatus.completed) { setState(() { _animCompleted = true; @@ -174,20 +175,20 @@ class _MyAppState extends State with TickerProviderStateMixin { alignment: Alignment.center, children: [ AnimatedBuilder( - animation: _scaleAnimation, + animation: _scaleAnimation!, builder: (context, _) { return Transform.scale( - scale: _scaleAnimation.value, + scale: _scaleAnimation!.value, child: AnimatedBuilder( - animation: _colorAnimation, + animation: _colorAnimation!, builder: (context, snapshot) { return Container( alignment: Alignment.center, constraints: BoxConstraints.expand(), color: _colorAnimation == null ? Color(0xff005FFF) - : _colorAnimation.value, - child: !_animationController.isAnimating + : _colorAnimation!.value, + child: !_animationController!.isAnimating ? Lottie.asset( 'assets/floating_boat.json', alignment: Alignment.center, @@ -199,16 +200,16 @@ class _MyAppState extends State with TickerProviderStateMixin { }, ), AnimatedBuilder( - animation: _animation, + animation: _animation!, builder: (context, snapshot) { return Transform.scale( - scale: _animation.value, + scale: _animation!.value, child: Container( width: 1.0, height: 1.0, decoration: BoxDecoration( color: Colors.white - .withOpacity(1 - _animationController.value), + .withOpacity(1 - _animationController!.value), shape: BoxShape.circle, ), ), @@ -227,19 +228,19 @@ class _MyAppState extends State with TickerProviderStateMixin { children: [ if (_initData != null) PreferenceBuilder( - preference: _initData.preferences.getInt( + preference: _initData!.preferences.getInt( 'theme', defaultValue: 0, ), builder: (context, snapshot) => MaterialApp( builder: (context, child) { return StreamChat( - client: _initData.client, - onBackgroundEventReceived: (e) => - showLocalNotification(e, _initData.client.state.user.id), + client: _initData!.client, + onBackgroundEventReceived: (e) => showLocalNotification( + e, _initData!.client.state.user!.id), child: Builder( builder: (context) => AnnotatedRegion( - child: child, + child: child!, value: SystemUiOverlayStyle( systemNavigationBarColor: StreamChatTheme.of(context).colorTheme.white, @@ -260,7 +261,7 @@ class _MyAppState extends State with TickerProviderStateMixin { 1: ThemeMode.light, }[snapshot], onGenerateRoute: AppRoutes.generateRoute, - initialRoute: _initData.client.state.user == null + initialRoute: _initData!.client.state.user == null ? Routes.CHOOSE_USER : Routes.HOME, ), @@ -319,7 +320,7 @@ class _HomePageState extends State { @override Widget build(BuildContext context) { - final user = StreamChat.of(context).user; + final user = StreamChat.of(context).user!; return Scaffold( backgroundColor: StreamChatTheme.of(context).colorTheme.whiteSnow, appBar: ChannelListHeader( @@ -495,7 +496,7 @@ class _HomePageState extends State { class UserMentionPage extends StatelessWidget { @override Widget build(BuildContext context) { - final user = StreamChat.of(context).user; + final user = StreamChat.of(context).user!; return MessageSearchBloc( child: MessageSearchListView( filters: Filter.in_('members', [user.id]), @@ -555,8 +556,8 @@ class UserMentionPage extends StatelessWidget { final client = StreamChat.of(context).client; final message = messageResponse.message; final channel = client.channel( - messageResponse.channel.type, - id: messageResponse.channel.id, + messageResponse.channel!.type, + id: messageResponse.channel!.id, ); if (channel.state == null) { await channel.watch(); @@ -581,20 +582,20 @@ class ChannelListPage extends StatefulWidget { } class _ChannelListPageState extends State { - TextEditingController _controller; + TextEditingController? _controller; String _channelQuery = ''; bool _isSearchActive = false; - Timer _debounce; + Timer? _debounce; void _channelQueryListener() { - if (_debounce?.isActive ?? false) _debounce.cancel(); + if (_debounce?.isActive ?? false) _debounce!.cancel(); _debounce = Timer(const Duration(milliseconds: 350), () { if (mounted) { setState(() { - _channelQuery = _controller.text; + _channelQuery = _controller!.text; _isSearchActive = _channelQuery.isNotEmpty; }); } @@ -620,7 +621,7 @@ class _ChannelListPageState extends State { return WillPopScope( onWillPop: () async { if (_isSearchActive) { - _controller.clear(); + _controller!.clear(); setState(() => _isSearchActive = false); return false; } @@ -647,7 +648,7 @@ class _ChannelListPageState extends State { ? MessageSearchListView( showErrorTile: true, messageQuery: _channelQuery, - filters: Filter.in_('members', [user.id]), + filters: Filter.in_('members', [user!.id]), sortOptions: [ SortOption( 'created_at', @@ -691,8 +692,8 @@ class _ChannelListPageState extends State { final client = StreamChat.of(context).client; final message = messageResponse.message; final channel = client.channel( - messageResponse.channel.type, - id: messageResponse.channel.id, + messageResponse.channel!.type, + id: messageResponse.channel!.id, ); if (channel.state == null) { await channel.watch(); @@ -712,7 +713,7 @@ class _ChannelListPageState extends State { Navigator.pushNamed(context, Routes.NEW_CHAT); }, swipeToAction: true, - filter: Filter.in_('members', [user.id]), + filter: Filter.in_('members', [user!.id]), options: { 'presence': true, }, @@ -731,10 +732,10 @@ class _ChannelListPageState extends State { child: ChatInfoScreen( messageTheme: StreamChatTheme.of(context) .ownMessageTheme, - user: channel.state.members + user: channel.state!.members .where((m) => m.userId != - channel.client.state.user.id) + channel.client.state.user!.id) .first .user, ), @@ -767,8 +768,8 @@ class _ChannelListPageState extends State { } class ChannelPageArgs { - final Channel channel; - final Message initialMessage; + final Channel? channel; + final Message? initialMessage; const ChannelPageArgs({ this.channel, @@ -777,12 +778,12 @@ class ChannelPageArgs { } class ChannelPage extends StatefulWidget { - final int initialScrollIndex; - final double initialAlignment; + final int? initialScrollIndex; + final double? initialAlignment; final bool highlightInitialMessage; const ChannelPage({ - Key key, + Key? key, this.initialScrollIndex, this.initialAlignment, this.highlightInitialMessage = false, @@ -793,8 +794,8 @@ class ChannelPage extends StatefulWidget { } class _ChannelPageState extends State { - Message _quotedMessage; - FocusNode _focusNode; + Message? _quotedMessage; + FocusNode? _focusNode; @override void initState() { @@ -804,14 +805,14 @@ class _ChannelPageState extends State { @override void dispose() { - _focusNode.dispose(); + _focusNode!.dispose(); super.dispose(); } void _reply(Message message) { setState(() => _quotedMessage = message); - WidgetsBinding.instance.addPostFrameCallback((timeStamp) { - _focusNode.requestFocus(); + WidgetsBinding.instance!.addPostFrameCallback((timeStamp) { + _focusNode!.requestFocus(); }); } @@ -826,9 +827,8 @@ class _ChannelPageState extends State { if (channel.memberCount == 2 && channel.isDistinct) { final currentUser = StreamChat.of(context).user; - final otherUser = channel.state.members.firstWhere( - (element) => element.user.id != currentUser.id, - orElse: () => null, + final otherUser = channel.state!.members.firstWhereOrNull( + (element) => element.user!.id != currentUser!.id, ); if (otherUser != null) { final pop = await Navigator.push( @@ -932,7 +932,7 @@ class _ChannelPageState extends State { quotedMessage: _quotedMessage, onQuotedMessageCleared: () { setState(() => _quotedMessage = null); - _focusNode.unfocus(); + _focusNode!.unfocus(); }, ), ], @@ -942,12 +942,12 @@ class _ChannelPageState extends State { } class ThreadPage extends StatefulWidget { - final Message parent; - final int initialScrollIndex; - final double initialAlignment; + final Message? parent; + final int? initialScrollIndex; + final double? initialAlignment; ThreadPage({ - Key key, + Key? key, this.parent, this.initialScrollIndex, this.initialAlignment, @@ -958,7 +958,7 @@ class ThreadPage extends StatefulWidget { } class _ThreadPageState extends State { - Message _quotedMessage; + Message? _quotedMessage; FocusNode _focusNode = FocusNode(); @override @@ -969,7 +969,7 @@ class _ThreadPageState extends State { void _reply(Message message) { setState(() => _quotedMessage = message); - WidgetsBinding.instance.addPostFrameCallback((timeStamp) { + WidgetsBinding.instance!.addPostFrameCallback((timeStamp) { _focusNode.requestFocus(); }); } @@ -979,7 +979,7 @@ class _ThreadPageState extends State { return Scaffold( backgroundColor: StreamChatTheme.of(context).colorTheme.whiteSnow, appBar: ThreadHeader( - parent: widget.parent, + parent: widget.parent!, ), body: Column( children: [ @@ -992,7 +992,7 @@ class _ThreadPageState extends State { onReplyTap: _reply, ), ), - if (widget.parent.type != 'deleted') + if (widget.parent!.type != 'deleted') MessageInput( parentMessage: widget.parent, focusNode: _focusNode, @@ -1017,8 +1017,8 @@ class InitData { class HolePainter extends CustomPainter { HolePainter({ - @required this.color, - @required this.holeSize, + required this.color, + required this.holeSize, }); Color color; diff --git a/packages/stream_chat_v1/lib/new_chat_screen.dart b/packages/stream_chat_v1/lib/new_chat_screen.dart index fac0ed0..2213db4 100644 --- a/packages/stream_chat_v1/lib/new_chat_screen.dart +++ b/packages/stream_chat_v1/lib/new_chat_screen.dart @@ -16,9 +16,9 @@ class _NewChatScreenState extends State { final _chipInputTextFieldStateKey = GlobalKey>(); - TextEditingController _controller; + late TextEditingController _controller; - ChipInputTextFieldState get _chipInputTextFieldState => + ChipInputTextFieldState? get _chipInputTextFieldState => _chipInputTextFieldStateKey.currentState; String _userNameQuery = ''; @@ -30,14 +30,14 @@ class _NewChatScreenState extends State { bool _isSearchActive = false; - Channel channel; + Channel? channel; - Timer _debounce; + Timer? _debounce; bool _showUserList = true; void _userNameListener() { - if (_debounce?.isActive ?? false) _debounce.cancel(); + if (_debounce?.isActive ?? false) _debounce!.cancel(); _debounce = Timer(const Duration(milliseconds: 350), () { if (mounted) setState(() { @@ -73,7 +73,7 @@ class _NewChatScreenState extends State { filter: Filter.and([ Filter.equal('members', [ ..._selectedUsers.map((e) => e.id), - chatState.user.id, + chatState.user!.id, ]), Filter.equal('distinct', true), ]), @@ -86,14 +86,14 @@ class _NewChatScreenState extends State { final _channelExisted = res.length == 1; if (_channelExisted) { channel = res.first; - await channel.watch(); + await channel!.watch(); } else { channel = chatState.client.channel( 'messaging', extraData: { 'members': [ ..._selectedUsers.map((e) => e.id), - chatState.user.id, + chatState.user!.id, ], }, ); @@ -110,9 +110,9 @@ class _NewChatScreenState extends State { void dispose() { _searchFocusNode.dispose(); _messageInputFocusNode.dispose(); - _controller?.clear(); - _controller?.removeListener(_userNameListener); - _controller?.dispose(); + _controller.clear(); + _controller.removeListener(_userNameListener); + _controller.dispose(); super.dispose(); } @@ -158,7 +158,7 @@ class _NewChatScreenState extends State { message: statusString, child: StreamChannel( showLoading: false, - channel: channel, + channel: channel!, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -169,7 +169,7 @@ class _NewChatScreenState extends State { chipBuilder: (context, user) { return GestureDetector( onTap: () { - _chipInputTextFieldState.removeItem(user); + _chipInputTextFieldState?.removeItem(user); _searchFocusNode.requestFocus(); }, child: Stack( @@ -299,10 +299,10 @@ class _NewChatScreenState extends State { _controller.clear(); if (!_selectedUsers.contains(user)) { _chipInputTextFieldState - ..addItem(user) + ?..addItem(user) ..pauseItemAddition(); } else { - _chipInputTextFieldState.removeItem(user); + _chipInputTextFieldState!.removeItem(user); } }, pagination: PaginationParams( @@ -312,7 +312,7 @@ class _NewChatScreenState extends State { if (_userNameQuery.isNotEmpty) Filter.autoComplete('name', _userNameQuery), Filter.notEqual( - 'id', StreamChat.of(context).user.id), + 'id', StreamChat.of(context).user!.id), ]), sort: [ SortOption( @@ -367,7 +367,7 @@ class _NewChatScreenState extends State { ), ) : FutureBuilder( - future: channel.initialized, + future: channel!.initialized, builder: (context, snapshot) { if (snapshot.data == true) { return MessageListView(); @@ -391,7 +391,7 @@ class _NewChatScreenState extends State { MessageInput( focusNode: _messageInputFocusNode, preMessageSending: (message) async { - await channel.watch(); + await channel!.watch(); return message; }, onMessageSent: (m) { diff --git a/packages/stream_chat_v1/lib/new_group_chat_screen.dart b/packages/stream_chat_v1/lib/new_group_chat_screen.dart index 9944572..0db780e 100644 --- a/packages/stream_chat_v1/lib/new_group_chat_screen.dart +++ b/packages/stream_chat_v1/lib/new_group_chat_screen.dart @@ -12,7 +12,7 @@ class NewGroupChatScreen extends StatefulWidget { } class _NewGroupChatScreenState extends State { - TextEditingController _controller; + TextEditingController? _controller; String _userNameQuery = ''; @@ -20,14 +20,14 @@ class _NewGroupChatScreenState extends State { bool _isSearchActive = false; - Timer _debounce; + Timer? _debounce; void _userNameListener() { - if (_debounce?.isActive ?? false) _debounce.cancel(); + if (_debounce?.isActive ?? false) _debounce!.cancel(); _debounce = Timer(const Duration(milliseconds: 350), () { if (mounted) { setState(() { - _userNameQuery = _controller.text; + _userNameQuery = _controller!.text; _isSearchActive = _userNameQuery.isNotEmpty; }); } @@ -80,7 +80,7 @@ class _NewGroupChatScreenState extends State { setState(() { _selectedUsers ..clear() - ..addAll(updatedList); + ..addAll(updatedList as Iterable); }); } }, @@ -247,7 +247,7 @@ class _NewGroupChatScreenState extends State { filter: Filter.and([ if (_userNameQuery.isNotEmpty) Filter.autoComplete('name', _userNameQuery), - Filter.notEqual('id', StreamChat.of(context).user.id), + Filter.notEqual('id', StreamChat.of(context).user!.id), ]), sort: [ SortOption( @@ -311,8 +311,8 @@ class _HeaderDelegate extends SliverPersistentHeaderDelegate { final double height; const _HeaderDelegate({ - @required this.child, - @required this.height, + required this.child, + required this.height, }); @override diff --git a/packages/stream_chat_v1/lib/notifications_service.dart b/packages/stream_chat_v1/lib/notifications_service.dart index c72ac19..56f6ad7 100644 --- a/packages/stream_chat_v1/lib/notifications_service.dart +++ b/packages/stream_chat_v1/lib/notifications_service.dart @@ -7,7 +7,7 @@ void showLocalNotification(Event event, String currentUserId) async { EventType.messageNew, EventType.notificationMessageNew, ].contains(event.type) || - event.user.id == currentUserId) { + event.user!.id == currentUserId) { return; } if (event.message == null) return; @@ -21,9 +21,9 @@ void showLocalNotification(Event event, String currentUserId) async { ); await flutterLocalNotificationsPlugin.initialize(initializationSettings); await flutterLocalNotificationsPlugin.show( - event.message.id.hashCode, - event.message.user.name, - event.message.text, + event.message!.id.hashCode, + event.message!.user!.name, + event.message!.text, NotificationDetails( android: AndroidNotificationDetails( 'message channel', diff --git a/packages/stream_chat_v1/lib/routes/app_routes.dart b/packages/stream_chat_v1/lib/routes/app_routes.dart index 1be8bf7..a8ce583 100644 --- a/packages/stream_chat_v1/lib/routes/app_routes.dart +++ b/packages/stream_chat_v1/lib/routes/app_routes.dart @@ -12,7 +12,7 @@ import '../group_info_screen.dart'; class AppRoutes { /// Add entry for new route here - static Route generateRoute(RouteSettings settings) { + static Route? generateRoute(RouteSettings settings) { final args = settings.arguments; switch (settings.name) { case Routes.APP: @@ -44,7 +44,7 @@ class AppRoutes { builder: (_) { final arg = args as ChannelPageArgs; return StreamChannel( - channel: arg.channel, + channel: arg.channel!, initialMessageId: arg.initialMessage?.id, child: ChannelPage( highlightInitialMessage: arg.initialMessage != null, @@ -68,7 +68,7 @@ class AppRoutes { settings: const RouteSettings(name: Routes.NEW_GROUP_CHAT_DETAILS), builder: (_) { return GroupChatDetailsScreen( - selectedUsers: args, + selectedUsers: args as List?, ); }); case Routes.CHAT_INFO_SCREEN: @@ -76,7 +76,7 @@ class AppRoutes { settings: const RouteSettings(name: Routes.CHAT_INFO_SCREEN), builder: (context) { return ChatInfoScreen( - user: args, + user: args as User?, messageTheme: StreamChatTheme.of(context).ownMessageTheme, ); }); diff --git a/packages/stream_chat_v1/lib/search_text_field.dart b/packages/stream_chat_v1/lib/search_text_field.dart index 9628ddb..c3850c2 100644 --- a/packages/stream_chat_v1/lib/search_text_field.dart +++ b/packages/stream_chat_v1/lib/search_text_field.dart @@ -2,15 +2,15 @@ import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; class SearchTextField extends StatelessWidget { - final TextEditingController controller; - final ValueChanged onChanged; + final TextEditingController? controller; + final ValueChanged? onChanged; final String hintText; - final VoidCallback onTap; + final VoidCallback? onTap; final bool showCloseButton; const SearchTextField({ - Key key, - @required this.controller, + Key? key, + required this.controller, this.onChanged, this.onTap, this.hintText = 'Search', @@ -76,11 +76,11 @@ class SearchTextField extends StatelessWidget { ), splashRadius: 24, onPressed: () { - if (controller.text.isNotEmpty) { + if (controller!.text.isNotEmpty) { Future.microtask( () => [ - controller.clear(), - if (onChanged != null) onChanged(''), + controller!.clear(), + if (onChanged != null) onChanged!(''), ], ); } diff --git a/packages/stream_chat_v1/lib/stream_version.dart b/packages/stream_chat_v1/lib/stream_version.dart index b3f926b..0458d75 100644 --- a/packages/stream_chat_v1/lib/stream_version.dart +++ b/packages/stream_chat_v1/lib/stream_version.dart @@ -5,7 +5,7 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart'; class StreamVersion extends StatelessWidget { const StreamVersion({ - Key key, + Key? key, }) : super(key: key); @override @@ -20,7 +20,7 @@ class StreamVersion extends StatelessWidget { return SizedBox(); } - final pubspec = snapshot.data; + final pubspec = snapshot.data!; final yaml = loadYaml(pubspec); final streamChatDep = yaml['packages']['stream_chat_flutter']['version']; diff --git a/packages/stream_chat_v1/pubspec.yaml b/packages/stream_chat_v1/pubspec.yaml index 464d235..9f1f30d 100644 --- a/packages/stream_chat_v1/pubspec.yaml +++ b/packages/stream_chat_v1/pubspec.yaml @@ -4,7 +4,7 @@ publish_to: 'none' version: 1.5.4+1 environment: - sdk: ">=2.2.2 <3.0.0" + sdk: '>=2.12.0 <3.0.0' dependencies: flutter_app_badger: ^1.2.0 @@ -27,6 +27,7 @@ dependencies: uuid: ^3.0.4 streaming_shared_preferences: ^2.0.0 lottie: ^1.0.1 + collection: ^1.15.0-nullsafety.4 dependency_overrides: stream_chat: