diff --git a/.github/workflows/component-documentation.yml b/.github/workflows/component-documentation.yml new file mode 100644 index 0000000..c12e46a --- /dev/null +++ b/.github/workflows/component-documentation.yml @@ -0,0 +1,14 @@ +name: Iconica Standard Component Documentation Workflow +# Workflow Caller version: 1.0.0 + +on: + release: + types: [published] + + workflow_dispatch: + +jobs: + call-iconica-component-documentation-workflow: + uses: Iconica-Development/.github/.github/workflows/component-documentation.yml@master + secrets: inherit + permissions: write-all diff --git a/CHANGELOG.md b/CHANGELOG.md index a683ca2..9b3348a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.2.0 + +- Added linter and workflow + ## 1.1.0 - Added LocalChatService for example app diff --git a/packages/flutter_chat/analysis_options.yaml b/packages/flutter_chat/analysis_options.yaml index a5744c1..31b4b51 100644 --- a/packages/flutter_chat/analysis_options.yaml +++ b/packages/flutter_chat/analysis_options.yaml @@ -1,4 +1,9 @@ -include: package:flutter_lints/flutter.yaml +include: package:flutter_iconica_analysis/analysis_options.yaml -# Additional information about this file can be found at -# https://dart.dev/guides/language/analysis-options +# Possible to overwrite the rules from the package + +analyzer: + exclude: + +linter: + rules: diff --git a/packages/flutter_chat/example/pubspec.yaml b/packages/flutter_chat/example/pubspec.yaml index c0292a6..61bf253 100644 --- a/packages/flutter_chat/example/pubspec.yaml +++ b/packages/flutter_chat/example/pubspec.yaml @@ -16,8 +16,6 @@ dependencies: path: ../ flutter_chat_firebase: path: ../../flutter_chat_firebase - flutter_chat_local: - path: ../../flutter_chat_local dev_dependencies: flutter_test: diff --git a/packages/flutter_chat/lib/flutter_chat.dart b/packages/flutter_chat/lib/flutter_chat.dart index b35027e..5ec247f 100644 --- a/packages/flutter_chat/lib/flutter_chat.dart +++ b/packages/flutter_chat/lib/flutter_chat.dart @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: 2022 Iconica // // SPDX-License-Identifier: BSD-3-Clause - +/// library flutter_chat; export 'package:flutter_chat/src/chat_entry_widget.dart'; @@ -10,4 +10,5 @@ export 'package:flutter_chat/src/flutter_chat_userstory.dart'; export 'package:flutter_chat/src/models/chat_configuration.dart'; export 'package:flutter_chat/src/routes.dart'; export 'package:flutter_chat_interface/flutter_chat_interface.dart'; +export 'package:flutter_chat_local/local_chat_service.dart'; export 'package:flutter_chat_view/flutter_chat_view.dart'; diff --git a/packages/flutter_chat/lib/src/chat_entry_widget.dart b/packages/flutter_chat/lib/src/chat_entry_widget.dart index 702201d..037cecb 100644 --- a/packages/flutter_chat/lib/src/chat_entry_widget.dart +++ b/packages/flutter_chat/lib/src/chat_entry_widget.dart @@ -2,7 +2,6 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_chat/flutter_chat.dart'; -import 'package:flutter_chat_local/local_chat_service.dart'; class ChatEntryWidget extends StatefulWidget { const ChatEntryWidget({ @@ -40,25 +39,23 @@ class _ChatEntryWidgetState extends State { } @override - Widget build(BuildContext context) { - return GestureDetector( - onTap: () => - widget.onTap?.call() ?? - Navigator.of(context).pushReplacement( - MaterialPageRoute( - builder: (context) => chatNavigatorUserStory( - context, - configuration: ChatUserStoryConfiguration( - chatService: chatService!, - chatOptionsBuilder: (ctx) => const ChatOptions(), + Widget build(BuildContext context) => GestureDetector( + onTap: () async => + widget.onTap?.call() ?? + Navigator.of(context).pushReplacement( + MaterialPageRoute( + builder: (context) => chatNavigatorUserStory( + context, + configuration: ChatUserStoryConfiguration( + chatService: chatService!, + chatOptionsBuilder: (ctx) => const ChatOptions(), + ), ), ), ), - ), - child: StreamBuilder( - stream: chatService!.chatOverviewService.getUnreadChatsCountStream(), - builder: (BuildContext context, snapshot) { - return Stack( + child: StreamBuilder( + stream: chatService!.chatOverviewService.getUnreadChatsCountStream(), + builder: (BuildContext context, snapshot) => Stack( alignment: Alignment.center, children: [ Container( @@ -96,11 +93,9 @@ class _ChatEntryWidgetState extends State { ), ), ], - ); - }, - ), - ); - } + ), + ), + ); } class _AnimatedNotificationIcon extends StatefulWidget { @@ -145,7 +140,7 @@ class _AnimatedNotificationIconState extends State<_AnimatedNotificationIcon> super.didUpdateWidget(oldWidget); if (oldWidget.notifications != widget.notifications) { - _runAnimation(); + unawaited(_runAnimation()); } } @@ -155,12 +150,10 @@ class _AnimatedNotificationIconState extends State<_AnimatedNotificationIcon> } @override - Widget build(BuildContext context) { - return RotationTransition( - turns: Tween(begin: 0.0, end: -.1) - .chain(CurveTween(curve: Curves.elasticIn)) - .animate(_animationController), - child: widget.icon, - ); - } + Widget build(BuildContext context) => RotationTransition( + turns: Tween(begin: 0.0, end: -.1) + .chain(CurveTween(curve: Curves.elasticIn)) + .animate(_animationController), + child: widget.icon, + ); } diff --git a/packages/flutter_chat/lib/src/flutter_chat_navigator_userstory.dart b/packages/flutter_chat/lib/src/flutter_chat_navigator_userstory.dart index 663d988..0685fce 100644 --- a/packages/flutter_chat/lib/src/flutter_chat_navigator_userstory.dart +++ b/packages/flutter_chat/lib/src/flutter_chat_navigator_userstory.dart @@ -4,167 +4,180 @@ import 'package:flutter/material.dart'; import 'package:flutter_chat/flutter_chat.dart'; -import 'package:flutter_chat_local/service/local_chat_service.dart'; Widget chatNavigatorUserStory( BuildContext context, { ChatUserStoryConfiguration? configuration, -}) { - return _chatScreenRoute( - configuration ?? - ChatUserStoryConfiguration( - chatService: LocalChatService(), - chatOptionsBuilder: (ctx) => const ChatOptions(), - ), - context, - ); -} +}) => + _chatScreenRoute( + configuration ?? + ChatUserStoryConfiguration( + chatService: LocalChatService(), + chatOptionsBuilder: (ctx) => const ChatOptions(), + ), + context, + ); Widget _chatScreenRoute( - ChatUserStoryConfiguration configuration, BuildContext context) { - return ChatScreen( - service: configuration.chatService, - options: configuration.chatOptionsBuilder(context), - onNoChats: () async => await Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => _newChatScreenRoute( - configuration, - context, - ), - ), - ), - onPressStartChat: () async { - if (configuration.onPressStartChat != null) { - return await configuration.onPressStartChat?.call(); - } - - return await Navigator.of(context).push( + ChatUserStoryConfiguration configuration, + BuildContext context, +) => + ChatScreen( + service: configuration.chatService, + options: configuration.chatOptionsBuilder(context), + onNoChats: () async => Navigator.of(context).push( MaterialPageRoute( builder: (context) => _newChatScreenRoute( configuration, context, ), ), - ); - }, - onPressChat: (chat) async => - configuration.onPressChat?.call(context, chat) ?? - await Navigator.of(context).push( + ), + onPressStartChat: () async { + if (configuration.onPressStartChat != null) { + return await configuration.onPressStartChat?.call(); + } + + return Navigator.of(context).push( MaterialPageRoute( - builder: (context) => _chatDetailScreenRoute( + builder: (context) => _newChatScreenRoute( configuration, context, - chat.id!, ), ), - ), - onDeleteChat: (chat) => - configuration.onDeleteChat?.call(context, chat) ?? - configuration.chatService.chatOverviewService.deleteChat(chat), - deleteChatDialog: configuration.deleteChatDialog, - translations: configuration.translations, - ); -} + ); + }, + onPressChat: (chat) async => + configuration.onPressChat?.call(context, chat) ?? + await Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => _chatDetailScreenRoute( + configuration, + context, + chat.id!, + ), + ), + ), + onDeleteChat: (chat) async => + configuration.onDeleteChat?.call(context, chat) ?? + configuration.chatService.chatOverviewService.deleteChat(chat), + deleteChatDialog: configuration.deleteChatDialog, + translations: configuration.translations, + ); -Widget _chatDetailScreenRoute(ChatUserStoryConfiguration configuration, - BuildContext context, String chatId) { - return ChatDetailScreen( - pageSize: configuration.messagePageSize, - options: configuration.chatOptionsBuilder(context), - translations: configuration.translations, - service: configuration.chatService, - chatId: chatId, - onMessageSubmit: (message) async { - configuration.onMessageSubmit?.call(message) ?? - configuration.chatService.chatDetailService +Widget _chatDetailScreenRoute( + ChatUserStoryConfiguration configuration, + BuildContext context, + String chatId, +) => + ChatDetailScreen( + pageSize: configuration.messagePageSize, + options: configuration.chatOptionsBuilder(context), + translations: configuration.translations, + service: configuration.chatService, + chatId: chatId, + onMessageSubmit: (message) async { + if (configuration.onMessageSubmit != null) { + await configuration.onMessageSubmit?.call(message); + } else { + await configuration.chatService.chatDetailService .sendTextMessage(chatId: chatId, text: message); - configuration.afterMessageSent?.call(chatId); - }, - onUploadImage: (image) async { - configuration.onUploadImage?.call(image) ?? - configuration.chatService.chatDetailService + } + + configuration.afterMessageSent?.call(chatId); + }, + onUploadImage: (image) async { + if (configuration.onUploadImage != null) { + await configuration.onUploadImage?.call(image); + } else { + await configuration.chatService.chatDetailService .sendImageMessage(chatId: chatId, image: image); - configuration.afterMessageSent?.call(chatId); - }, - onReadChat: (chat) => - configuration.onReadChat?.call(chat) ?? - configuration.chatService.chatOverviewService.readChat(chat), - onPressChatTitle: (context, chat) async { - if (configuration.onPressChatTitle?.call(context, chat) != null) { - return configuration.onPressChatTitle?.call(context, chat); - } + } - return await Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => _chatProfileScreenRoute( - configuration, - context, - chatId, - null, + configuration.afterMessageSent?.call(chatId); + }, + onReadChat: (chat) async => + configuration.onReadChat?.call(chat) ?? + configuration.chatService.chatOverviewService.readChat(chat), + onPressChatTitle: (context, chat) async { + if (configuration.onPressChatTitle?.call(context, chat) != null) { + return configuration.onPressChatTitle?.call(context, chat); + } + + return Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => _chatProfileScreenRoute( + configuration, + context, + chatId, + null, + ), ), - ), - ); - }, - iconColor: configuration.iconColor, - ); -} + ); + }, + iconColor: configuration.iconColor, + ); -Widget _chatProfileScreenRoute(ChatUserStoryConfiguration configuration, - BuildContext context, String chatId, String? userId) { - return ChatProfileScreen( - translations: configuration.translations, - chatService: configuration.chatService, - chatId: chatId, - userId: userId, - onTapUser: (user) async { - if (configuration.onPressUserProfile != null) { - return configuration.onPressUserProfile!.call(); - } +Widget _chatProfileScreenRoute( + ChatUserStoryConfiguration configuration, + BuildContext context, + String chatId, + String? userId, +) => + ChatProfileScreen( + translations: configuration.translations, + chatService: configuration.chatService, + chatId: chatId, + userId: userId, + onTapUser: (user) async { + if (configuration.onPressUserProfile != null) { + return configuration.onPressUserProfile!.call(); + } - return Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => _chatProfileScreenRoute( - configuration, - context, - chatId, - userId, + return Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => _chatProfileScreenRoute( + configuration, + context, + chatId, + userId, + ), ), - ), - ); - }, - ); -} + ); + }, + ); Widget _newChatScreenRoute( - ChatUserStoryConfiguration configuration, BuildContext context) { - return NewChatScreen( - options: configuration.chatOptionsBuilder(context), - translations: configuration.translations, - service: configuration.chatService, - onPressCreateChat: (user) async { - configuration.onPressCreateChat?.call(user); - if (configuration.onPressCreateChat != null) return; - var chat = await configuration.chatService.chatOverviewService - .getChatByUser(user); - if (chat.id == null) { - chat = - await configuration.chatService.chatOverviewService.storeChatIfNot( - PersonalChatModel( - user: user, - ), - ); - } - if (context.mounted) { - await Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => _chatDetailScreenRoute( - configuration, - context, - chat.id!, + ChatUserStoryConfiguration configuration, + BuildContext context, +) => + NewChatScreen( + options: configuration.chatOptionsBuilder(context), + translations: configuration.translations, + service: configuration.chatService, + onPressCreateChat: (user) async { + configuration.onPressCreateChat?.call(user); + if (configuration.onPressCreateChat != null) return; + var chat = await configuration.chatService.chatOverviewService + .getChatByUser(user); + if (chat.id == null) { + chat = await configuration.chatService.chatOverviewService + .storeChatIfNot( + PersonalChatModel( + user: user, ), - ), - ); - } - }, - ); -} + ); + } + if (context.mounted) { + await Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => _chatDetailScreenRoute( + configuration, + context, + chat.id!, + ), + ), + ); + } + }, + ); diff --git a/packages/flutter_chat/lib/src/flutter_chat_userstory.dart b/packages/flutter_chat/lib/src/flutter_chat_userstory.dart index e3fc275..ffcf1f4 100644 --- a/packages/flutter_chat/lib/src/flutter_chat_userstory.dart +++ b/packages/flutter_chat/lib/src/flutter_chat_userstory.dart @@ -18,18 +18,18 @@ List getChatStoryRoutes( service: configuration.chatService, options: configuration.chatOptionsBuilder(context), onNoChats: () async => - await context.push(ChatUserStoryRoutes.newChatScreen), + context.push(ChatUserStoryRoutes.newChatScreen), onPressStartChat: () async { if (configuration.onPressStartChat != null) { return await configuration.onPressStartChat?.call(); } - return await context.push(ChatUserStoryRoutes.newChatScreen); + return context.push(ChatUserStoryRoutes.newChatScreen); }, - onPressChat: (chat) => + onPressChat: (chat) async => configuration.onPressChat?.call(context, chat) ?? context.push(ChatUserStoryRoutes.chatDetailViewPath(chat.id!)), - onDeleteChat: (chat) => + onDeleteChat: (chat) async => configuration.onDeleteChat?.call(context, chat) ?? configuration.chatService.chatOverviewService.deleteChat(chat), deleteChatDialog: configuration.deleteChatDialog, @@ -59,27 +59,34 @@ List getChatStoryRoutes( service: configuration.chatService, chatId: chatId!, onMessageSubmit: (message) async { - configuration.onMessageSubmit?.call(message) ?? - configuration.chatService.chatDetailService - .sendTextMessage(chatId: chatId, text: message); + if (configuration.onMessageSubmit != null) { + await configuration.onMessageSubmit?.call(message); + } else { + await configuration.chatService.chatDetailService + .sendTextMessage(chatId: chatId, text: message); + } configuration.afterMessageSent?.call(chatId); }, onUploadImage: (image) async { - configuration.onUploadImage?.call(image) ?? - configuration.chatService.chatDetailService - .sendImageMessage(chatId: chatId, image: image); + if (configuration.onUploadImage?.call(image) != null) { + await configuration.onUploadImage?.call(image); + } else { + await configuration.chatService.chatDetailService + .sendImageMessage(chatId: chatId, image: image); + } configuration.afterMessageSent?.call(chatId); }, - onReadChat: (chat) => + onReadChat: (chat) async => configuration.onReadChat?.call(chat) ?? configuration.chatService.chatOverviewService.readChat(chat), - onPressChatTitle: (context, chat) { + onPressChatTitle: (context, chat) async { if (configuration.onPressChatTitle?.call(context, chat) != null) { return configuration.onPressChatTitle?.call(context, chat); } return context.push( - ChatUserStoryRoutes.chatProfileScreenPath(chat.id!, null)); + ChatUserStoryRoutes.chatProfileScreenPath(chat.id!, null), + ); }, iconColor: configuration.iconColor, ); @@ -100,27 +107,29 @@ List getChatStoryRoutes( path: ChatUserStoryRoutes.newChatScreen, pageBuilder: (context, state) { var newChatScreen = NewChatScreen( - options: configuration.chatOptionsBuilder(context), - translations: configuration.translations, - service: configuration.chatService, - onPressCreateChat: (user) async { - configuration.onPressCreateChat?.call(user); - if (configuration.onPressCreateChat != null) return; - var chat = await configuration.chatService.chatOverviewService - .getChatByUser(user); - if (chat.id == null) { - chat = await configuration.chatService.chatOverviewService - .storeChatIfNot( - PersonalChatModel( - user: user, - ), - ); - } - if (context.mounted) { - await context.push( - ChatUserStoryRoutes.chatDetailViewPath(chat.id ?? '')); - } - }); + options: configuration.chatOptionsBuilder(context), + translations: configuration.translations, + service: configuration.chatService, + onPressCreateChat: (user) async { + configuration.onPressCreateChat?.call(user); + if (configuration.onPressCreateChat != null) return; + var chat = await configuration.chatService.chatOverviewService + .getChatByUser(user); + if (chat.id == null) { + chat = await configuration.chatService.chatOverviewService + .storeChatIfNot( + PersonalChatModel( + user: user, + ), + ); + } + if (context.mounted) { + await context.push( + ChatUserStoryRoutes.chatDetailViewPath(chat.id ?? ''), + ); + } + }, + ); return buildScreenWithoutTransition( context: context, state: state, @@ -150,7 +159,7 @@ List getChatStoryRoutes( return configuration.onPressUserProfile!.call(); } - return await context.push( + return context.push( ChatUserStoryRoutes.chatProfileScreenPath(chatId, user), ); }, diff --git a/packages/flutter_chat/lib/src/models/chat_configuration.dart b/packages/flutter_chat/lib/src/models/chat_configuration.dart index 60e7078..8288eeb 100644 --- a/packages/flutter_chat/lib/src/models/chat_configuration.dart +++ b/packages/flutter_chat/lib/src/models/chat_configuration.dart @@ -38,13 +38,15 @@ class ChatUserStoryConfiguration { final Future Function(Uint8List image)? onUploadImage; final Future Function(String text)? onMessageSubmit; - /// Called after a new message is sent. This can be used to do something extra like sending a push notification. + /// Called after a new message is sent. This can be used to do something + /// extra like sending a push notification. final Function(String chatId)? afterMessageSent; final Future Function(ChatModel chat)? onReadChat; final Function(ChatUserModel)? onPressCreateChat; final ChatOptions Function(BuildContext context) chatOptionsBuilder; - /// If true, the user will be routed to the new chat screen if there are no chats. + /// If true, the user will be routed to the new chat screen if there are + /// no chats. final bool routeToNewChatIfEmpty; final int messagePageSize; diff --git a/packages/flutter_chat/pubspec.yaml b/packages/flutter_chat/pubspec.yaml index 4be42a3..f5d813c 100644 --- a/packages/flutter_chat/pubspec.yaml +++ b/packages/flutter_chat/pubspec.yaml @@ -4,7 +4,7 @@ name: flutter_chat description: A new Flutter package project. -version: 1.1.0 +version: 1.2.0 publish_to: none @@ -20,19 +20,22 @@ dependencies: git: url: https://github.com/Iconica-Development/flutter_chat path: packages/flutter_chat_view - ref: 1.1.0 + ref: 1.2.0 flutter_chat_interface: git: url: https://github.com/Iconica-Development/flutter_chat path: packages/flutter_chat_interface - ref: 1.1.0 + ref: 1.2.0 flutter_chat_local: git: url: https://github.com/Iconica-Development/flutter_chat path: packages/flutter_chat_local - ref: 1.1.0 + ref: 1.2.0 dev_dependencies: - flutter_lints: ^2.0.0 + flutter_iconica_analysis: + git: + url: https://github.com/Iconica-Development/flutter_iconica_analysis + ref: 6.0.0 flutter: diff --git a/packages/flutter_chat_firebase/analysis_options.yaml b/packages/flutter_chat_firebase/analysis_options.yaml index a5744c1..31b4b51 100644 --- a/packages/flutter_chat_firebase/analysis_options.yaml +++ b/packages/flutter_chat_firebase/analysis_options.yaml @@ -1,4 +1,9 @@ -include: package:flutter_lints/flutter.yaml +include: package:flutter_iconica_analysis/analysis_options.yaml -# Additional information about this file can be found at -# https://dart.dev/guides/language/analysis-options +# Possible to overwrite the rules from the package + +analyzer: + exclude: + +linter: + rules: diff --git a/packages/flutter_chat_firebase/lib/config/firebase_chat_options.dart b/packages/flutter_chat_firebase/lib/config/firebase_chat_options.dart index 73c6319..938cd76 100644 --- a/packages/flutter_chat_firebase/lib/config/firebase_chat_options.dart +++ b/packages/flutter_chat_firebase/lib/config/firebase_chat_options.dart @@ -31,18 +31,17 @@ class FirebaseChatOptions { String? usersCollectionName, String? chatsMetaDataCollectionName, String? userChatsCollectionName, - }) { - return FirebaseChatOptions( - groupChatsCollectionName: - groupChatsCollectionName ?? this.groupChatsCollectionName, - chatsCollectionName: chatsCollectionName ?? this.chatsCollectionName, - messagesCollectionName: - messagesCollectionName ?? this.messagesCollectionName, - usersCollectionName: usersCollectionName ?? this.usersCollectionName, - chatsMetaDataCollectionName: - chatsMetaDataCollectionName ?? this.chatsMetaDataCollectionName, - userChatsCollectionName: - userChatsCollectionName ?? this.userChatsCollectionName, - ); - } + }) => + FirebaseChatOptions( + groupChatsCollectionName: + groupChatsCollectionName ?? this.groupChatsCollectionName, + chatsCollectionName: chatsCollectionName ?? this.chatsCollectionName, + messagesCollectionName: + messagesCollectionName ?? this.messagesCollectionName, + usersCollectionName: usersCollectionName ?? this.usersCollectionName, + chatsMetaDataCollectionName: + chatsMetaDataCollectionName ?? this.chatsMetaDataCollectionName, + userChatsCollectionName: + userChatsCollectionName ?? this.userChatsCollectionName, + ); } diff --git a/packages/flutter_chat_firebase/lib/dto/firebase_chat_document.dart b/packages/flutter_chat_firebase/lib/dto/firebase_chat_document.dart index 12c5002..02fd8a1 100644 --- a/packages/flutter_chat_firebase/lib/dto/firebase_chat_document.dart +++ b/packages/flutter_chat_firebase/lib/dto/firebase_chat_document.dart @@ -19,15 +19,6 @@ class FirebaseChatDocument { this.lastMessage, }); - final String? id; - final String? title; - final String? imageUrl; - final bool personal; - final bool canBeDeleted; - final Timestamp? lastUsed; - final List users; - final FirebaseMessageDocument? lastMessage; - FirebaseChatDocument.fromJson(Map json, this.id) : title = json['title'], imageUrl = json['image_url'], @@ -42,6 +33,15 @@ class FirebaseChatDocument { null, ); + final String? id; + final String? title; + final String? imageUrl; + final bool personal; + final bool canBeDeleted; + final Timestamp? lastUsed; + final List users; + final FirebaseMessageDocument? lastMessage; + Map toJson() => { 'title': title, 'image_url': imageUrl, diff --git a/packages/flutter_chat_firebase/lib/dto/firebase_message_document.dart b/packages/flutter_chat_firebase/lib/dto/firebase_message_document.dart index ae67215..b396fd3 100644 --- a/packages/flutter_chat_firebase/lib/dto/firebase_message_document.dart +++ b/packages/flutter_chat_firebase/lib/dto/firebase_message_document.dart @@ -15,18 +15,18 @@ class FirebaseMessageDocument { this.imageUrl, }); - final String? id; - final String sender; - final String? text; - final String? imageUrl; - final Timestamp timestamp; - FirebaseMessageDocument.fromJson(Map json, this.id) : sender = json['sender'], text = json['text'], imageUrl = json['image_url'], timestamp = json['timestamp']; + final String? id; + final String sender; + final String? text; + final String? imageUrl; + final Timestamp timestamp; + Map toJson() => { 'sender': sender, 'text': text, diff --git a/packages/flutter_chat_firebase/lib/dto/firebase_user_document.dart b/packages/flutter_chat_firebase/lib/dto/firebase_user_document.dart index aa834ee..b3db5ca 100644 --- a/packages/flutter_chat_firebase/lib/dto/firebase_user_document.dart +++ b/packages/flutter_chat_firebase/lib/dto/firebase_user_document.dart @@ -13,28 +13,27 @@ class FirebaseUserDocument { this.id, }); + FirebaseUserDocument.fromJson( + Map json, + String id, + ) : this( + id: id, + firstName: + json['first_name'] == null ? '' : json['first_name']! as String, + lastName: + json['last_name'] == null ? '' : json['last_name']! as String, + imageUrl: + json['image_url'] == null ? null : json['image_url']! as String, + ); + final String? firstName; final String? lastName; final String? imageUrl; final String? id; - FirebaseUserDocument.fromJson( - Map json, - String id, - ) : this( - id: id, - firstName: - json['first_name'] == null ? '' : json['first_name'] as String, - lastName: - json['last_name'] == null ? '' : json['last_name'] as String, - imageUrl: - json['image_url'] == null ? null : json['image_url'] as String); - - Map toJson() { - return { - 'first_name': firstName, - 'last_name': lastName, - 'image_url': imageUrl, - }; - } + Map toJson() => { + 'first_name': firstName, + 'last_name': lastName, + 'image_url': imageUrl, + }; } diff --git a/packages/flutter_chat_firebase/lib/flutter_chat_firebase.dart b/packages/flutter_chat_firebase/lib/flutter_chat_firebase.dart index 7ad2e3a..86d053b 100644 --- a/packages/flutter_chat_firebase/lib/flutter_chat_firebase.dart +++ b/packages/flutter_chat_firebase/lib/flutter_chat_firebase.dart @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: 2022 Iconica // // SPDX-License-Identifier: BSD-3-Clause - +/// library flutter_chat_firebase; export 'package:flutter_chat_firebase/service/service.dart'; diff --git a/packages/flutter_chat_firebase/lib/service/firebase_chat_detail_service.dart b/packages/flutter_chat_firebase/lib/service/firebase_chat_detail_service.dart index b5a23ed..6c2de13 100644 --- a/packages/flutter_chat_firebase/lib/service/firebase_chat_detail_service.dart +++ b/packages/flutter_chat_firebase/lib/service/firebase_chat_detail_service.dart @@ -16,6 +16,18 @@ import 'package:uuid/uuid.dart'; class FirebaseChatDetailService with ChangeNotifier implements ChatDetailService { + FirebaseChatDetailService({ + required ChatUserService userService, + FirebaseApp? app, + FirebaseChatOptions? options, + }) { + var appInstance = app ?? Firebase.app(); + + _db = FirebaseFirestore.instanceFor(app: appInstance); + _storage = FirebaseStorage.instanceFor(app: appInstance); + _userService = userService; + _options = options ?? const FirebaseChatOptions(); + } late final FirebaseFirestore _db; late final FirebaseStorage _storage; late final ChatUserService _userService; @@ -29,19 +41,6 @@ class FirebaseChatDetailService int? chatPageSize; DateTime timestampToFilter = DateTime.now(); - FirebaseChatDetailService({ - required ChatUserService userService, - FirebaseApp? app, - FirebaseChatOptions? options, - }) { - var appInstance = app ?? Firebase.app(); - - _db = FirebaseFirestore.instanceFor(app: appInstance); - _storage = FirebaseStorage.instanceFor(app: appInstance); - _userService = userService; - _options = options ?? const FirebaseChatOptions(); - } - Future _sendMessage(String chatId, Map data) async { var currentUser = await _userService.getCurrentUser(); @@ -52,7 +51,7 @@ class FirebaseChatDetailService var message = { 'sender': currentUser.id, 'timestamp': DateTime.now(), - ...data + ...data, }; var chatReference = _db @@ -89,7 +88,8 @@ class FirebaseChatDetailService // update the chat counter for the other users // get all users from the chat - // there is a field in the chat document called users that has a list of user ids + // there is a field in the chat document called users that has a + // list of user ids var fetchedChat = await metadataReference.get(); var chatUsers = fetchedChat.data()?['users'] as List; // for all users except the message sender update the unread counter @@ -112,9 +112,12 @@ class FirebaseChatDetailService 'amount_unread_messages': FieldValue.increment(1), }); } else { - await userReference.set({ - 'amount_unread_messages': 1, - }, SetOptions(merge: true)); + await userReference.set( + { + 'amount_unread_messages': 1, + }, + SetOptions(merge: true), + ); } } } @@ -124,14 +127,13 @@ class FirebaseChatDetailService Future sendTextMessage({ required String text, required String chatId, - }) { - return _sendMessage( - chatId, - { - 'text': text, - }, - ); - } + }) => + _sendMessage( + chatId, + { + 'text': text, + }, + ); @override Future sendImageMessage({ @@ -171,7 +173,9 @@ class FirebaseChatDetailService ) .withConverter( fromFirestore: (snapshot, _) => FirebaseMessageDocument.fromJson( - snapshot.data()!, snapshot.id), + snapshot.data()!, + snapshot.id, + ), toFirestore: (user, _) => user.toJson(), ) .snapshots(); @@ -181,7 +185,7 @@ class FirebaseChatDetailService var data = message.doc.data(); var sender = await _userService.getUser(data!.sender); var timestamp = DateTime.fromMillisecondsSinceEpoch( - (data.timestamp).millisecondsSinceEpoch, + data.timestamp.millisecondsSinceEpoch, ); if (timestamp.isBefore(timestampToFilter)) { @@ -206,16 +210,15 @@ class FirebaseChatDetailService ..._cumulativeMessages, ...messages, ]; - List uniqueObjects = - _cumulativeMessages.toSet().toList(); + var uniqueObjects = _cumulativeMessages.toSet().toList(); _cumulativeMessages = uniqueObjects; _cumulativeMessages .sort((a, b) => a.timestamp.compareTo(b.timestamp)); notifyListeners(); }); }, - onCancel: () { - _subscription?.cancel(); + onCancel: () async { + await _subscription?.cancel(); _subscription = null; debugPrint('Canceling messages stream'); }, @@ -225,10 +228,10 @@ class FirebaseChatDetailService } @override - void stopListeningForMessages() { - _subscription?.cancel(); + Future stopListeningForMessages() async { + await _subscription?.cancel(); _subscription = null; - _controller?.close(); + await _controller?.close(); _controller = null; } @@ -241,8 +244,9 @@ class FirebaseChatDetailService lastChat = chatId; lastMessage = null; } - // get the x amount of last messages from the oldest message that is in cumulative messages and add that to the list - List messages = []; + // get the x amount of last messages from the oldest message that is in + // cumulative messages and add that to the list + var messages = []; QuerySnapshot? messagesQuerySnapshot; var query = _db .collection(_options.chatsCollectionName) @@ -275,14 +279,14 @@ class FirebaseChatDetailService } } - List messageDocuments = messagesQuerySnapshot.docs + var messageDocuments = messagesQuerySnapshot.docs .map((QueryDocumentSnapshot doc) => doc.data()) .toList(); for (var message in messageDocuments) { var sender = await _userService.getUser(message.sender); if (sender != null) { var timestamp = DateTime.fromMillisecondsSinceEpoch( - (message.timestamp).millisecondsSinceEpoch, + message.timestamp.millisecondsSinceEpoch, ); messages.add( @@ -310,7 +314,5 @@ class FirebaseChatDetailService } @override - List getMessages() { - return _cumulativeMessages; - } + List getMessages() => _cumulativeMessages; } diff --git a/packages/flutter_chat_firebase/lib/service/firebase_chat_overview_service.dart b/packages/flutter_chat_firebase/lib/service/firebase_chat_overview_service.dart index 30e63f2..93a31ca 100644 --- a/packages/flutter_chat_firebase/lib/service/firebase_chat_overview_service.dart +++ b/packages/flutter_chat_firebase/lib/service/firebase_chat_overview_service.dart @@ -48,6 +48,7 @@ class FirebaseChatOverviewService implements ChatOverviewService { @override Stream> getChatsStream() { StreamSubscription? chatSubscription; + // ignore: close_sinks late StreamController> controller; controller = StreamController( onListen: () async { @@ -68,11 +69,13 @@ class FirebaseChatOverviewService implements ChatOverviewService { ) .withConverter( fromFirestore: (snapshot, _) => FirebaseChatDocument.fromJson( - snapshot.data()!, snapshot.id), + snapshot.data()!, + snapshot.id, + ), toFirestore: (chat, _) => chat.toJson(), ) .snapshots(); - List chats = []; + var chats = []; ChatModel? chatModel; chatSubscription = chatSnapshot.listen((event) async { @@ -84,7 +87,7 @@ class FirebaseChatOverviewService implements ChatOverviewService { (element) => element != currentUser?.id, ), ); - int? unread = + var unread = await _addUnreadChatSubscription(chat.id!, currentUser!.id!); if (chat.personal) { @@ -157,10 +160,10 @@ class FirebaseChatOverviewService implements ChatOverviewService { } chats.add(chatModel!); } - Set uniqueIds = {}; - List uniqueChatModels = []; + var uniqueIds = {}; + var uniqueChatModels = []; - for (ChatModel chatModel in chats) { + for (var chatModel in chats) { if (uniqueIds.add(chatModel.id!)) { uniqueChatModels.add(chatModel); } else { @@ -189,8 +192,8 @@ class FirebaseChatOverviewService implements ChatOverviewService { }); }); }, - onCancel: () { - chatSubscription?.cancel(); + onCancel: () async { + await chatSubscription?.cancel(); }, ); return controller.stream; @@ -225,6 +228,7 @@ class FirebaseChatOverviewService implements ChatOverviewService { .get(); if (chatCollection.exists && chatCollection.data()?['users'] != null) { + // ignore: avoid_dynamic_calls var otherUser = chatCollection.data()?['users'].firstWhere( (element) => element != currentUser?.id, ); @@ -278,7 +282,7 @@ class FirebaseChatOverviewService implements ChatOverviewService { if (chatData != null) { for (var userId in chatData.users) { - _db + await _db .collection(_options.usersCollectionName) .doc(userId) .collection(_options.userChatsCollectionName) @@ -349,7 +353,7 @@ class FirebaseChatOverviewService implements ChatOverviewService { return chat; } - List userIds = [ + var userIds = [ currentUser!.id!, ...chat.users.map((e) => e.id!), ]; @@ -390,8 +394,10 @@ class FirebaseChatOverviewService implements ChatOverviewService { @override Stream getUnreadChatsCountStream() { - // open a stream to the user's chats collection and listen to changes in this collection we will also add the amount of read chats + // open a stream to the user's chats collection and listen to changes in + // this collection we will also add the amount of read chats StreamSubscription? unreadChatSubscription; + // ignore: close_sinks late StreamController controller; controller = StreamController( onListen: () async { @@ -403,17 +409,20 @@ class FirebaseChatOverviewService implements ChatOverviewService { .snapshots(); unreadChatSubscription = userSnapshot.listen((event) { - // every chat has a field called amount_unread_messages, combine all of these fields to get the total amount of unread messages + // every chat has a field called amount_unread_messages, combine all + // of these fields to get the total amount of unread messages var unreadChats = event.docs .map((chat) => chat.data()['amount_unread_messages'] ?? 0) .toList(); var totalUnreadChats = unreadChats.fold( - 0, (previousValue, element) => previousValue + (element as int)); + 0, + (previousValue, element) => previousValue + (element as int), + ); controller.add(totalUnreadChats); }); }, - onCancel: () { - unreadChatSubscription?.cancel(); + onCancel: () async { + await unreadChatSubscription?.cancel(); }, ); return controller.stream; @@ -429,7 +438,7 @@ class FirebaseChatOverviewService implements ChatOverviewService { // set the amount of unread messages to 0 await _db .collection(_options.usersCollectionName) - .doc(currentUser!.id!) + .doc(currentUser!.id) .collection(_options.userChatsCollectionName) .doc(chat.id) .set({'amount_unread_messages': 0}, SetOptions(merge: true)); diff --git a/packages/flutter_chat_firebase/lib/service/service.dart b/packages/flutter_chat_firebase/lib/service/service.dart index 4ea8aac..0aa9d95 100644 --- a/packages/flutter_chat_firebase/lib/service/service.dart +++ b/packages/flutter_chat_firebase/lib/service/service.dart @@ -1,4 +1,4 @@ -export 'package:flutter_chat_firebase/service/firebase_chat_user_service.dart'; export 'package:flutter_chat_firebase/service/firebase_chat_detail_service.dart'; export 'package:flutter_chat_firebase/service/firebase_chat_overview_service.dart'; export 'package:flutter_chat_firebase/service/firebase_chat_service.dart'; +export 'package:flutter_chat_firebase/service/firebase_chat_user_service.dart'; diff --git a/packages/flutter_chat_firebase/pubspec.yaml b/packages/flutter_chat_firebase/pubspec.yaml index 35708cb..b36512d 100644 --- a/packages/flutter_chat_firebase/pubspec.yaml +++ b/packages/flutter_chat_firebase/pubspec.yaml @@ -4,7 +4,7 @@ name: flutter_chat_firebase description: A new Flutter package project. -version: 1.1.0 +version: 1.2.0 publish_to: none environment: @@ -23,9 +23,12 @@ dependencies: git: url: https://github.com/Iconica-Development/flutter_chat path: packages/flutter_chat_interface - ref: 1.1.0 + ref: 1.2.0 dev_dependencies: - flutter_lints: ^2.0.0 + flutter_iconica_analysis: + git: + url: https://github.com/Iconica-Development/flutter_iconica_analysis + ref: 6.0.0 flutter: diff --git a/packages/flutter_chat_interface/analysis_options.yaml b/packages/flutter_chat_interface/analysis_options.yaml index a5744c1..31b4b51 100644 --- a/packages/flutter_chat_interface/analysis_options.yaml +++ b/packages/flutter_chat_interface/analysis_options.yaml @@ -1,4 +1,9 @@ -include: package:flutter_lints/flutter.yaml +include: package:flutter_iconica_analysis/analysis_options.yaml -# Additional information about this file can be found at -# https://dart.dev/guides/language/analysis-options +# Possible to overwrite the rules from the package + +analyzer: + exclude: + +linter: + rules: diff --git a/packages/flutter_chat_interface/lib/flutter_chat_interface.dart b/packages/flutter_chat_interface/lib/flutter_chat_interface.dart index 986f170..9cdb2fe 100644 --- a/packages/flutter_chat_interface/lib/flutter_chat_interface.dart +++ b/packages/flutter_chat_interface/lib/flutter_chat_interface.dart @@ -1,9 +1,9 @@ // SPDX-FileCopyrightText: 2022 Iconica // // SPDX-License-Identifier: BSD-3-Clause - +/// library flutter_chat_interface; +export 'package:flutter_chat_interface/src/chat_data_provider.dart'; export 'package:flutter_chat_interface/src/model/model.dart'; export 'package:flutter_chat_interface/src/service/service.dart'; -export 'package:flutter_chat_interface/src/chat_data_provider.dart'; diff --git a/packages/flutter_chat_interface/lib/src/model/group_chat.dart b/packages/flutter_chat_interface/lib/src/model/group_chat.dart index 80b0ddf..742c102 100644 --- a/packages/flutter_chat_interface/lib/src/model/group_chat.dart +++ b/packages/flutter_chat_interface/lib/src/model/group_chat.dart @@ -34,15 +34,15 @@ abstract class GroupChatModelInterface extends ChatModel { class GroupChatModel implements GroupChatModelInterface { GroupChatModel({ + required this.canBeDeleted, + required this.title, + required this.imageUrl, + required this.users, this.id, this.messages, this.unreadMessages, this.lastUsed, this.lastMessage, - required this.canBeDeleted, - required this.title, - required this.imageUrl, - required this.users, }); @override @@ -75,17 +75,16 @@ class GroupChatModel implements GroupChatModelInterface { String? title, String? imageUrl, List? users, - }) { - return GroupChatModel( - id: id ?? this.id, - messages: messages ?? this.messages, - unreadMessages: unreadMessages ?? this.unreadMessages, - lastUsed: lastUsed ?? this.lastUsed, - lastMessage: lastMessage ?? this.lastMessage, - canBeDeleted: canBeDeleted ?? this.canBeDeleted, - title: title ?? this.title, - imageUrl: imageUrl ?? this.imageUrl, - users: users ?? this.users, - ); - } + }) => + GroupChatModel( + id: id ?? this.id, + messages: messages ?? this.messages, + unreadMessages: unreadMessages ?? this.unreadMessages, + lastUsed: lastUsed ?? this.lastUsed, + lastMessage: lastMessage ?? this.lastMessage, + canBeDeleted: canBeDeleted ?? this.canBeDeleted, + title: title ?? this.title, + imageUrl: imageUrl ?? this.imageUrl, + users: users ?? this.users, + ); } diff --git a/packages/flutter_chat_interface/lib/src/model/model.dart b/packages/flutter_chat_interface/lib/src/model/model.dart index 907dd83..2e23e5c 100644 --- a/packages/flutter_chat_interface/lib/src/model/model.dart +++ b/packages/flutter_chat_interface/lib/src/model/model.dart @@ -1,7 +1,7 @@ export 'chat.dart'; export 'chat_image_message.dart'; +export 'chat_message.dart'; export 'chat_text_message.dart'; export 'chat_user.dart'; export 'group_chat.dart'; export 'personal_chat.dart'; -export 'chat_message.dart'; diff --git a/packages/flutter_chat_interface/lib/src/model/personal_chat.dart b/packages/flutter_chat_interface/lib/src/model/personal_chat.dart index a264ab4..1fd82f5 100644 --- a/packages/flutter_chat_interface/lib/src/model/personal_chat.dart +++ b/packages/flutter_chat_interface/lib/src/model/personal_chat.dart @@ -30,13 +30,13 @@ abstract class PersonalChatModelInterface extends ChatModel { class PersonalChatModel implements PersonalChatModelInterface { PersonalChatModel({ + required this.user, this.id, this.messages = const [], this.unreadMessages, this.lastUsed, this.lastMessage, this.canBeDeleted = true, - required this.user, }); @override @@ -64,15 +64,14 @@ class PersonalChatModel implements PersonalChatModelInterface { ChatMessageModel? lastMessage, bool? canBeDeleted, ChatUserModel? user, - }) { - return PersonalChatModel( - id: id ?? this.id, - messages: messages ?? this.messages, - unreadMessages: unreadMessages ?? this.unreadMessages, - lastUsed: lastUsed ?? this.lastUsed, - lastMessage: lastMessage ?? this.lastMessage, - user: user ?? this.user, - canBeDeleted: canBeDeleted ?? this.canBeDeleted, - ); - } + }) => + PersonalChatModel( + id: id ?? this.id, + messages: messages ?? this.messages, + unreadMessages: unreadMessages ?? this.unreadMessages, + lastUsed: lastUsed ?? this.lastUsed, + lastMessage: lastMessage ?? this.lastMessage, + user: user ?? this.user, + canBeDeleted: canBeDeleted ?? this.canBeDeleted, + ); } diff --git a/packages/flutter_chat_interface/lib/src/service/service.dart b/packages/flutter_chat_interface/lib/src/service/service.dart index a65b80e..7eddcf4 100644 --- a/packages/flutter_chat_interface/lib/src/service/service.dart +++ b/packages/flutter_chat_interface/lib/src/service/service.dart @@ -1,4 +1,4 @@ -export 'chat_overview_service.dart'; -export 'user_service.dart'; export 'chat_detail_service.dart'; +export 'chat_overview_service.dart'; export 'chat_service.dart'; +export 'user_service.dart'; diff --git a/packages/flutter_chat_interface/pubspec.yaml b/packages/flutter_chat_interface/pubspec.yaml index ebb38dc..8f316e1 100644 --- a/packages/flutter_chat_interface/pubspec.yaml +++ b/packages/flutter_chat_interface/pubspec.yaml @@ -4,7 +4,7 @@ name: flutter_chat_interface description: A new Flutter package project. -version: 1.1.0 +version: 1.2.0 publish_to: none environment: @@ -20,6 +20,9 @@ dependencies: ref: 1.0.0 dev_dependencies: - flutter_lints: ^2.0.0 + flutter_iconica_analysis: + git: + url: https://github.com/Iconica-Development/flutter_iconica_analysis + ref: 6.0.0 flutter: diff --git a/packages/flutter_chat_local/analysis_options.yaml b/packages/flutter_chat_local/analysis_options.yaml index a5744c1..31b4b51 100644 --- a/packages/flutter_chat_local/analysis_options.yaml +++ b/packages/flutter_chat_local/analysis_options.yaml @@ -1,4 +1,9 @@ -include: package:flutter_lints/flutter.yaml +include: package:flutter_iconica_analysis/analysis_options.yaml -# Additional information about this file can be found at -# https://dart.dev/guides/language/analysis-options +# Possible to overwrite the rules from the package + +analyzer: + exclude: + +linter: + rules: diff --git a/packages/flutter_chat_local/lib/local_chat_service.dart b/packages/flutter_chat_local/lib/local_chat_service.dart index 4db41b2..ca4162a 100644 --- a/packages/flutter_chat_local/lib/local_chat_service.dart +++ b/packages/flutter_chat_local/lib/local_chat_service.dart @@ -1,6 +1,7 @@ +/// library local_chat_service; -export 'service/local_chat_service.dart'; export 'service/local_chat_detail_service.dart'; export 'service/local_chat_overview_service.dart'; +export 'service/local_chat_service.dart'; export 'service/local_chat_user_service.dart'; diff --git a/packages/flutter_chat_local/lib/service/local_chat_detail_service.dart b/packages/flutter_chat_local/lib/service/local_chat_detail_service.dart index 8210169..abc7458 100644 --- a/packages/flutter_chat_local/lib/service/local_chat_detail_service.dart +++ b/packages/flutter_chat_local/lib/service/local_chat_detail_service.dart @@ -5,9 +5,8 @@ import 'package:flutter_chat_interface/flutter_chat_interface.dart'; import 'package:flutter_chat_local/local_chat_service.dart'; class LocalChatDetailService with ChangeNotifier implements ChatDetailService { - final ChatOverviewService chatOverviewService; - LocalChatDetailService({required this.chatOverviewService}); + final ChatOverviewService chatOverviewService; final List _cumulativeMessages = []; final StreamController> _controller = StreamController>.broadcast(); @@ -25,13 +24,11 @@ class LocalChatDetailService with ChangeNotifier implements ChatDetailService { } @override - List getMessages() { - return _cumulativeMessages; - } + List getMessages() => _cumulativeMessages; @override Stream> getMessagesStream(String chatId) { - _controller.onListen = () { + _controller.onListen = () async { _subscription = chatOverviewService.getChatById(chatId).asStream().listen((event) { _cumulativeMessages.clear(); @@ -44,20 +41,22 @@ class LocalChatDetailService with ChangeNotifier implements ChatDetailService { } @override - Future sendImageMessage( - {required String chatId, required Uint8List image}) async { + Future sendImageMessage({ + required String chatId, + required Uint8List image, + }) async { var chat = (chatOverviewService as LocalChatOverviewService) .chats .firstWhere((element) => element.id == chatId); var message = ChatImageMessageModel( sender: ChatUserModel( - id: "3", - firstName: "ico", - lastName: "nica", - imageUrl: "https://picsum.photos/100/200", + id: '3', + firstName: 'ico', + lastName: 'nica', + imageUrl: 'https://picsum.photos/100/200', ), timestamp: DateTime.now(), - imageUrl: "https://picsum.photos/200/300", + imageUrl: 'https://picsum.photos/200/300', ); await (chatOverviewService as LocalChatOverviewService).updateChat( @@ -75,17 +74,19 @@ class LocalChatDetailService with ChangeNotifier implements ChatDetailService { } @override - Future sendTextMessage( - {required String chatId, required String text}) async { + Future sendTextMessage({ + required String chatId, + required String text, + }) async { var chat = (chatOverviewService as LocalChatOverviewService) .chats .firstWhere((element) => element.id == chatId); var message = ChatTextMessageModel( sender: ChatUserModel( - id: "3", - firstName: "ico", - lastName: "nica", - imageUrl: "https://picsum.photos/100/200", + id: '3', + firstName: 'ico', + lastName: 'nica', + imageUrl: 'https://picsum.photos/100/200', ), timestamp: DateTime.now(), text: text, @@ -106,8 +107,8 @@ class LocalChatDetailService with ChangeNotifier implements ChatDetailService { } @override - void stopListeningForMessages() { - _subscription?.cancel(); + Future stopListeningForMessages() async { + await _subscription?.cancel(); _subscription = null; } } diff --git a/packages/flutter_chat_local/lib/service/local_chat_overview_service.dart b/packages/flutter_chat_local/lib/service/local_chat_overview_service.dart index 8c0a0d7..cf0e4f6 100644 --- a/packages/flutter_chat_local/lib/service/local_chat_overview_service.dart +++ b/packages/flutter_chat_local/lib/service/local_chat_overview_service.dart @@ -29,16 +29,15 @@ class LocalChatOverviewService } @override - Future getChatById(String id) { - return Future.value(_chats.firstWhere((element) => element.id == id)); - } + Future getChatById(String id) => + Future.value(_chats.firstWhere((element) => element.id == id)); @override Future getChatByUser(ChatUserModel user) { PersonalChatModel? chat; try { chat = _chats.firstWhere((element) => element.user.id == user.id); - } catch (e) { + } on Exception catch (_) { chat = PersonalChatModel( user: user, messages: [], @@ -54,22 +53,14 @@ class LocalChatOverviewService } @override - Stream> getChatsStream() { - return _chatsController.stream; - } + Stream> getChatsStream() => _chatsController.stream; @override - Stream getUnreadChatsCountStream() { - return Stream.value(0); - } + Stream getUnreadChatsCountStream() => Stream.value(0); @override - Future readChat(ChatModel chat) async { - return Future.value(); - } + Future readChat(ChatModel chat) async => Future.value(); @override - Future storeChatIfNot(ChatModel chat) { - return Future.value(chat); - } + Future storeChatIfNot(ChatModel chat) => Future.value(chat); } diff --git a/packages/flutter_chat_local/lib/service/local_chat_user_service.dart b/packages/flutter_chat_local/lib/service/local_chat_user_service.dart index 6ba8b3e..b5a69d6 100644 --- a/packages/flutter_chat_local/lib/service/local_chat_user_service.dart +++ b/packages/flutter_chat_local/lib/service/local_chat_user_service.dart @@ -5,25 +5,21 @@ class LocalChatUserService implements ChatUserService { ChatUserModel( id: '1', firstName: 'John', - lastName: "Doe", + lastName: 'Doe', imageUrl: 'https://picsum.photos/200/300', ), ChatUserModel( id: '2', firstName: 'Jane', - lastName: "Doe", + lastName: 'Doe', imageUrl: 'https://picsum.photos/200/300', ), ]; @override - Future> getAllUsers() { - return Future.value(users); - } + Future> getAllUsers() => Future.value(users); @override - Future getCurrentUser() { - return Future.value(ChatUserModel()); - } + Future getCurrentUser() => Future.value(ChatUserModel()); @override Future getUser(String id) { diff --git a/packages/flutter_chat_local/pubspec.yaml b/packages/flutter_chat_local/pubspec.yaml index 7c1dfb3..f858d71 100644 --- a/packages/flutter_chat_local/pubspec.yaml +++ b/packages/flutter_chat_local/pubspec.yaml @@ -1,6 +1,6 @@ name: flutter_chat_local description: "A new Flutter package project." -version: 1.1.0 +version: 1.2.0 publish_to: none homepage: @@ -15,10 +15,13 @@ dependencies: git: url: https://github.com/Iconica-Development/flutter_chat path: packages/flutter_chat_interface - ref: 1.1.0 + ref: 1.2.0 dev_dependencies: flutter_test: sdk: flutter - flutter_lints: ^2.0.0 + flutter_iconica_analysis: + git: + url: https://github.com/Iconica-Development/flutter_iconica_analysis + ref: 6.0.0 flutter: diff --git a/packages/flutter_chat_view/analysis_options.yaml b/packages/flutter_chat_view/analysis_options.yaml index 7f14ad5..31b4b51 100644 --- a/packages/flutter_chat_view/analysis_options.yaml +++ b/packages/flutter_chat_view/analysis_options.yaml @@ -1,214 +1,9 @@ -# SPDX-FileCopyrightText: 2022 Iconica -# -# SPDX-License-Identifier: GPL-3.0-or-later +include: package:flutter_iconica_analysis/analysis_options.yaml + +# Possible to overwrite the rules from the package -include: package:flutter_lints/flutter.yaml analyzer: - errors: - todo: ignore - exclude: [lib/generated_plugin_registrant.dart] -linter: - # https://dart.dev/tools/linter-rules#lints - rules: - # error rules - always_use_package_imports: false - avoid_dynamic_calls: true - avoid_empty_else: true - avoid_print: true - avoid_relative_lib_imports: true - avoid_returning_null_for_future: true - avoid_slow_async_io: true - avoid_type_to_string: true - avoid_types_as_parameter_names: true - avoid_web_libraries_in_flutter: true - cancel_subscriptions: true - close_sinks: true - comment_references: false - control_flow_in_finally: true - diagnostic_describe_all_properties: false - empty_statements: true - hash_and_equals: true - literal_only_boolean_expressions: true - no_adjacent_strings_in_list: true - no_duplicate_case_values: true - no_logic_in_create_state: true - prefer_relative_imports: false - prefer_void_to_null: true - test_types_in_equals: true - throw_in_finally: true - unnecessary_statements: true - unrelated_type_equality_checks: true - unsafe_html: true - use_build_context_synchronously: true - use_key_in_widget_constructors: true - valid_regexps: true - # style rules - always_declare_return_types: true - always_put_control_body_on_new_line: true - always_put_required_named_parameters_first: true - always_require_non_null_named_parameters: true - always_specify_types: false - annotate_overrides: true - avoid_annotating_with_dynamic: false - avoid_bool_literals_in_conditional_expressions: true - avoid_catches_without_on_clauses: false - avoid_catching_errors: false - avoid_classes_with_only_static_members: true - avoid_double_and_int_checks: true - avoid_equals_and_hash_code_on_mutable_classes: false - avoid_escaping_inner_quotes: false - avoid_field_initializers_in_const_classes: true - avoid_final_parameters: true - avoid_function_literals_in_foreach_calls: true - avoid_implementing_value_types: true - avoid_init_to_null: true - avoid_js_rounded_ints: true - avoid_multiple_declarations_per_line: true - avoid_null_checks_in_equality_operators: true - avoid_positional_boolean_parameters: true - avoid_private_typedef_functions: true - avoid_redundant_argument_values: false - avoid_renaming_method_parameters: true - avoid_return_types_on_setters: true - avoid_returning_null: true - avoid_returning_null_for_void: true - avoid_returning_this: true - avoid_setters_without_getters: true - avoid_shadowing_type_parameters: true - avoid_single_cascade_in_expression_statements: true - avoid_types_on_closure_parameters: false - avoid_unnecessary_containers: false - avoid_unused_constructor_parameters: true - avoid_void_async: true - await_only_futures: true - camel_case_extensions: true - camel_case_types: true - cascade_invocations: true - cast_nullable_to_non_nullable: true - conditional_uri_does_not_exist: true - constant_identifier_names: true - curly_braces_in_flow_control_structures: true - deprecated_consistency: true - directives_ordering: true - do_not_use_environment: true - empty_catches: true - empty_constructor_bodies: true - eol_at_end_of_file: true - exhaustive_cases: true - file_names: true - flutter_style_todos: true - implementation_imports: true - join_return_with_assignment: true - leading_newlines_in_multiline_strings: true - library_names: true - library_prefixes: true - library_private_types_in_public_api: true - lines_longer_than_80_chars: true - missing_whitespace_between_adjacent_strings: true - no_default_cases: true - no_leading_underscores_for_library_prefixes: true - no_leading_underscores_for_local_identifiers: true - no_runtimeType_toString: true - non_constant_identifier_names: true - noop_primitive_operations: true - null_check_on_nullable_type_parameter: true - null_closures: true - omit_local_variable_types: true - one_member_abstracts: true - only_throw_errors: true - overridden_fields: true - package_api_docs: true - package_prefixed_library_names: true - parameter_assignments: true - prefer_adjacent_string_concatenation: true - prefer_asserts_in_initializer_lists: true - prefer_asserts_with_message: true - prefer_collection_literals: true - prefer_conditional_assignment: true - prefer_const_constructors: true - prefer_const_constructors_in_immutables: true - prefer_const_declarations: false - prefer_const_literals_to_create_immutables: false - prefer_constructors_over_static_methods: true - prefer_contains: true - prefer_double_quotes: false - prefer_equal_for_default_values: true - prefer_expression_function_bodies: false - prefer_final_fields: true - prefer_final_in_for_each: false - prefer_final_locals: false - prefer_final_parameters: false - prefer_for_elements_to_map_fromIterable: true - prefer_foreach: true - prefer_function_declarations_over_variables: true - prefer_generic_function_type_aliases: true - prefer_if_elements_to_conditional_expressions: true - prefer_if_null_operators: true - prefer_initializing_formals: true - prefer_inlined_adds: true - prefer_int_literals: false - prefer_interpolation_to_compose_strings: true - prefer_is_empty: true - prefer_is_not_empty: true - prefer_is_not_operator: true - prefer_iterable_whereType: true - prefer_mixin: true - prefer_null_aware_method_calls: true - prefer_null_aware_operators: true - prefer_single_quotes: true - prefer_spread_collections: true - prefer_typing_uninitialized_variables: true - provide_deprecation_message: true - public_member_api_docs: false - recursive_getters: true - require_trailing_commas: true - sized_box_for_whitespace: true - sized_box_shrink_expand: true - slash_for_doc_comments: true - sort_child_properties_last: true - sort_constructors_first: true - sort_unnamed_constructors_first: true - tighten_type_of_initializing_formals: true - type_annotate_public_apis: true - type_init_formals: true - unawaited_futures: true - unnecessary_await_in_return: true - unnecessary_brace_in_string_interps: true - unnecessary_const: false - unnecessary_constructor_name: true - unnecessary_final: true - unnecessary_getters_setters: true - unnecessary_lambdas: true - unnecessary_late: true - unnecessary_new: true - unnecessary_null_aware_assignments: true - unnecessary_null_checks: true - unnecessary_null_in_if_null_operators: true - unnecessary_nullable_for_final_variable_declarations: true - unnecessary_overrides: true - unnecessary_parenthesis: true - unnecessary_raw_strings: true - unnecessary_string_escapes: true - unnecessary_string_interpolations: true - unnecessary_this: true - use_decorated_box: true - use_full_hex_values_for_flutter_colors: true - use_function_type_syntax_for_parameters: true - use_if_null_to_convert_nulls_to_bools: true - use_is_even_rather_than_modulo: true - use_late_for_private_fields_and_variables: true - use_named_constants: true - use_raw_strings: false - use_rethrow_when_possible: true - use_setters_to_change_properties: true - use_string_buffers: true - use_test_throws_matchers: true - use_to_and_as_if_applicable: true - void_checks: true - # pub rules - depend_on_referenced_packages: true - secure_pubspec_urls: false - sort_pub_dependencies: false + exclude: -# Additional information about this file can be found at -# https://dart.dev/guides/language/analysis-options +linter: + rules: diff --git a/packages/flutter_chat_view/lib/flutter_chat_view.dart b/packages/flutter_chat_view/lib/flutter_chat_view.dart index 962fc99..4a5e7c4 100644 --- a/packages/flutter_chat_view/lib/flutter_chat_view.dart +++ b/packages/flutter_chat_view/lib/flutter_chat_view.dart @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: 2022 Iconica // // SPDX-License-Identifier: BSD-3-Clause - +/// library flutter_chat_view; export 'package:flutter_chat_interface/flutter_chat_interface.dart'; diff --git a/packages/flutter_chat_view/lib/src/components/chat_bottom.dart b/packages/flutter_chat_view/lib/src/components/chat_bottom.dart index df56ea4..b1bc242 100644 --- a/packages/flutter_chat_view/lib/src/components/chat_bottom.dart +++ b/packages/flutter_chat_view/lib/src/components/chat_bottom.dart @@ -53,11 +53,11 @@ class _ChatBottomState extends State { ), ), IconButton( - onPressed: () { + onPressed: () async { var value = _textEditingController.text; if (value.isNotEmpty) { - widget.onMessageSubmit(value); + await widget.onMessageSubmit(value); _textEditingController.clear(); } }, diff --git a/packages/flutter_chat_view/lib/src/components/chat_detail_row.dart b/packages/flutter_chat_view/lib/src/components/chat_detail_row.dart index d296920..ca7d370 100644 --- a/packages/flutter_chat_view/lib/src/components/chat_detail_row.dart +++ b/packages/flutter_chat_view/lib/src/components/chat_detail_row.dart @@ -64,85 +64,80 @@ class _ChatDetailRowState extends State { ), ], Expanded( - child: Container( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 22.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - if (isNewDate || isSameSender) - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - widget.message.sender.fullName?.toUpperCase() ?? - widget.translations.anonymousUser, - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w500, - color: Theme.of(context) - .textTheme - .labelMedium - ?.color, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 22.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + if (isNewDate || isSameSender) + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + widget.message.sender.fullName?.toUpperCase() ?? + widget.translations.anonymousUser, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + color: + Theme.of(context).textTheme.labelMedium?.color, + ), + ), + Padding( + padding: const EdgeInsets.only(top: 5.0), + child: Text( + _dateFormatter.format( + date: widget.message.timestamp, + showFullDate: true, + ), + style: const TextStyle( + fontSize: 12, + color: Color(0xFFBBBBBB), ), ), - Padding( - padding: const EdgeInsets.only(top: 5.0), - child: Text( - _dateFormatter.format( - date: widget.message.timestamp, - showFullDate: true, - ), - style: const TextStyle( - fontSize: 12, - color: Color(0xFFBBBBBB), - ), - ), - ), - ], - ), - Padding( - padding: const EdgeInsets.only(top: 3.0), - child: widget.message is ChatTextMessageModel - ? RichText( - text: TextSpan( - text: (widget.message as ChatTextMessageModel) - .text, - style: TextStyle( - fontSize: 16, - color: Theme.of(context) - .textTheme - .labelMedium - ?.color, - ), - children: [ - if (widget.showTime) - TextSpan( - text: " ${_dateFormatter.format( - date: widget.message.timestamp, - showFullDate: true, - ).split(' ').last}", - style: const TextStyle( - fontSize: 12, - color: Color(0xFFBBBBBB), - ), - ) - else - const TextSpan(), - ], - ), - overflow: TextOverflow.ellipsis, - maxLines: 999, - ) - : CachedNetworkImage( - imageUrl: - (widget.message as ChatImageMessageModel) - .imageUrl, - ), + ), + ], ), - ], - ), + Padding( + padding: const EdgeInsets.only(top: 3.0), + child: widget.message is ChatTextMessageModel + ? RichText( + text: TextSpan( + text: + (widget.message as ChatTextMessageModel).text, + style: TextStyle( + fontSize: 16, + color: Theme.of(context) + .textTheme + .labelMedium + ?.color, + ), + children: [ + if (widget.showTime) + TextSpan( + text: " ${_dateFormatter.format( + date: widget.message.timestamp, + showFullDate: true, + ).split(' ').last}", + style: const TextStyle( + fontSize: 12, + color: Color(0xFFBBBBBB), + ), + ) + else + const TextSpan(), + ], + ), + overflow: TextOverflow.ellipsis, + maxLines: 999, + ) + : CachedNetworkImage( + imageUrl: (widget.message as ChatImageMessageModel) + .imageUrl, + ), + ), + ], ), ), ), diff --git a/packages/flutter_chat_view/lib/src/screens/chat_detail_screen.dart b/packages/flutter_chat_view/lib/src/screens/chat_detail_screen.dart index 288f7ab..dcbaa6a 100644 --- a/packages/flutter_chat_view/lib/src/screens/chat_detail_screen.dart +++ b/packages/flutter_chat_view/lib/src/screens/chat_detail_screen.dart @@ -123,7 +123,7 @@ class _ChatDetailScreenState extends State { @override Widget build(BuildContext context) { - Future onPressSelectImage() => showModalBottomSheet( + Future onPressSelectImage() async => showModalBottomSheet( context: context, builder: (BuildContext context) => widget.options.imagePickerContainerBuilder( @@ -147,6 +147,7 @@ class _ChatDetailScreenState extends State { ); return FutureBuilder( + // ignore: discarded_futures future: widget.service.chatOverviewService.getChatById(widget.chatId), builder: (context, AsyncSnapshot snapshot) { var chatModel = snapshot.data; @@ -199,7 +200,7 @@ class _ChatDetailScreenState extends State { var isTop = controller.position.pixels == controller.position.maxScrollExtent; - if (showIndicator == false && + if (!showIndicator && !isTop && controller.position.userScrollDirection == ScrollDirection.reverse) { diff --git a/packages/flutter_chat_view/lib/src/screens/chat_profile_screen.dart b/packages/flutter_chat_view/lib/src/screens/chat_profile_screen.dart index cdbb478..4a1c2fd 100644 --- a/packages/flutter_chat_view/lib/src/screens/chat_profile_screen.dart +++ b/packages/flutter_chat_view/lib/src/screens/chat_profile_screen.dart @@ -30,7 +30,9 @@ class _ProfileScreenState extends State { var hasUser = widget.userId == null; return FutureBuilder( future: hasUser + // ignore: discarded_futures ? widget.chatService.chatOverviewService.getChatById(widget.chatId) + // ignore: discarded_futures : widget.chatService.chatUserService.getUser(widget.userId!), builder: (context, snapshot) { var data = snapshot.data; diff --git a/packages/flutter_chat_view/lib/src/screens/chat_screen.dart b/packages/flutter_chat_view/lib/src/screens/chat_screen.dart index 192a2da..afae69a 100644 --- a/packages/flutter_chat_view/lib/src/screens/chat_screen.dart +++ b/packages/flutter_chat_view/lib/src/screens/chat_screen.dart @@ -258,55 +258,53 @@ class ChatListItem extends StatelessWidget { final DateFormatter _dateFormatter; @override - Widget build(BuildContext context) { - return GestureDetector( - onTap: () => widget.onPressChat(chat), - child: Container( - color: Colors.transparent, - child: widget.options.chatRowContainerBuilder( - (chat is PersonalChatModel) - ? ChatRow( - unreadMessages: chat.unreadMessages ?? 0, - avatar: widget.options.userAvatarBuilder( - (chat as PersonalChatModel).user, - 40.0, + Widget build(BuildContext context) => GestureDetector( + onTap: () => widget.onPressChat(chat), + child: Container( + color: Colors.transparent, + child: widget.options.chatRowContainerBuilder( + (chat is PersonalChatModel) + ? ChatRow( + unreadMessages: chat.unreadMessages ?? 0, + avatar: widget.options.userAvatarBuilder( + (chat as PersonalChatModel).user, + 40.0, + ), + title: (chat as PersonalChatModel).user.fullName ?? + translations.anonymousUser, + subTitle: chat.lastMessage != null + ? chat.lastMessage is ChatTextMessageModel + ? (chat.lastMessage! as ChatTextMessageModel).text + : '📷 ' + '${translations.image}' + : '', + lastUsed: chat.lastUsed != null + ? _dateFormatter.format( + date: chat.lastUsed!, + ) + : null, + ) + : ChatRow( + title: (chat as GroupChatModel).title, + unreadMessages: chat.unreadMessages ?? 0, + subTitle: chat.lastMessage != null + ? chat.lastMessage is ChatTextMessageModel + ? (chat.lastMessage! as ChatTextMessageModel).text + : '📷 ' + '${translations.image}' + : '', + avatar: widget.options.groupAvatarBuilder( + (chat as GroupChatModel).title, + (chat as GroupChatModel).imageUrl, + 40.0, + ), + lastUsed: chat.lastUsed != null + ? _dateFormatter.format( + date: chat.lastUsed!, + ) + : null, ), - title: (chat as PersonalChatModel).user.fullName ?? - translations.anonymousUser, - subTitle: chat.lastMessage != null - ? chat.lastMessage is ChatTextMessageModel - ? (chat.lastMessage! as ChatTextMessageModel).text - : '📷 ' - '${translations.image}' - : '', - lastUsed: chat.lastUsed != null - ? _dateFormatter.format( - date: chat.lastUsed!, - ) - : null, - ) - : ChatRow( - title: (chat as GroupChatModel).title, - unreadMessages: chat.unreadMessages ?? 0, - subTitle: chat.lastMessage != null - ? chat.lastMessage is ChatTextMessageModel - ? (chat.lastMessage! as ChatTextMessageModel).text - : '📷 ' - '${translations.image}' - : '', - avatar: widget.options.groupAvatarBuilder( - (chat as GroupChatModel).title, - (chat as GroupChatModel).imageUrl, - 40.0, - ), - lastUsed: chat.lastUsed != null - ? _dateFormatter.format( - date: chat.lastUsed!, - ) - : null, - ), + ), ), - ), - ); - } + ); } diff --git a/packages/flutter_chat_view/lib/src/screens/new_chat_screen.dart b/packages/flutter_chat_view/lib/src/screens/new_chat_screen.dart index b18395a..c4eef9b 100644 --- a/packages/flutter_chat_view/lib/src/screens/new_chat_screen.dart +++ b/packages/flutter_chat_view/lib/src/screens/new_chat_screen.dart @@ -29,67 +29,62 @@ class _NewChatScreenState extends State { String query = ''; @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: _buildSearchField(), - actions: [ - _buildSearchIcon(), - ], - ), - body: FutureBuilder>( - future: widget.service.chatUserService.getAllUsers(), - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - return const Center(child: CircularProgressIndicator()); - } else if (snapshot.hasError) { - return Text('Error: ${snapshot.error}'); - } else if (snapshot.hasData) { - return _buildUserList(snapshot.data!); - } else { - return widget.options - .noChatsPlaceholderBuilder(widget.translations); + Widget build(BuildContext context) => Scaffold( + appBar: AppBar( + title: _buildSearchField(), + actions: [ + _buildSearchIcon(), + ], + ), + body: FutureBuilder>( + // ignore: discarded_futures + future: widget.service.chatUserService.getAllUsers(), + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return const Center(child: CircularProgressIndicator()); + } else if (snapshot.hasError) { + return Text('Error: ${snapshot.error}'); + } else if (snapshot.hasData) { + return _buildUserList(snapshot.data!); + } else { + return widget.options + .noChatsPlaceholderBuilder(widget.translations); + } + }, + ), + ); + + Widget _buildSearchField() => _isSearching + ? Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0), + child: TextField( + focusNode: _textFieldFocusNode, + onChanged: (value) { + setState(() { + query = value; + }); + }, + decoration: InputDecoration( + hintText: widget.translations.searchPlaceholder, + ), + ), + ) + : Text(widget.translations.newChatButton); + + Widget _buildSearchIcon() => IconButton( + onPressed: () { + setState(() { + _isSearching = !_isSearching; + }); + + if (_isSearching) { + _textFieldFocusNode.requestFocus(); } }, - ), - ); - } - - Widget _buildSearchField() { - return _isSearching - ? Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: TextField( - focusNode: _textFieldFocusNode, - onChanged: (value) { - setState(() { - query = value; - }); - }, - decoration: InputDecoration( - hintText: widget.translations.searchPlaceholder, - ), - ), - ) - : Text(widget.translations.newChatButton); - } - - Widget _buildSearchIcon() { - return IconButton( - onPressed: () { - setState(() { - _isSearching = !_isSearching; - }); - - if (_isSearching) { - _textFieldFocusNode.requestFocus(); - } - }, - icon: Icon( - _isSearching ? Icons.close : Icons.search, - ), - ); - } + icon: Icon( + _isSearching ? Icons.close : Icons.search, + ), + ); Widget _buildUserList(List users) { var filteredUsers = users diff --git a/packages/flutter_chat_view/pubspec.yaml b/packages/flutter_chat_view/pubspec.yaml index 7f6b3ef..24a77fc 100644 --- a/packages/flutter_chat_view/pubspec.yaml +++ b/packages/flutter_chat_view/pubspec.yaml @@ -4,7 +4,7 @@ name: flutter_chat_view description: A standard flutter package. -version: 1.1.0 +version: 1.2.0 publish_to: none @@ -20,7 +20,7 @@ dependencies: git: url: https://github.com/Iconica-Development/flutter_chat path: packages/flutter_chat_interface - ref: 1.1.0 + ref: 1.2.0 cached_network_image: ^3.2.2 flutter_image_picker: git: @@ -34,6 +34,9 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - flutter_lints: ^2.0.0 + flutter_iconica_analysis: + git: + url: https://github.com/Iconica-Development/flutter_iconica_analysis + ref: 6.0.0 flutter: