diff --git a/CHANGELOG.md b/CHANGELOG.md index b30294c..5de7258 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ - Added messageType to the ChatMessageModel to allow for different type of messages, it is nullable to remain backwards compatible - Get the color for the imagepicker from the Theme's primaryColor - Added chatMessageBuilder to the userstory configuration to customize the chat messages +- Added ChatScope that can be used to get the ChatService and ChatTranslations from the context. If you use individual components instead of the userstory you need to wrap them with the ChatScope. The options and service will be removed from all the component constructors. ## 4.0.0 - Move to the new user story architecture diff --git a/packages/flutter_chat/lib/flutter_chat.dart b/packages/flutter_chat/lib/flutter_chat.dart index 6f8053e..59d24b6 100644 --- a/packages/flutter_chat/lib/flutter_chat.dart +++ b/packages/flutter_chat/lib/flutter_chat.dart @@ -1,7 +1,5 @@ -// ignore_for_file: prefer_double_quotes - // Core -export 'package:chat_repository_interface/chat_repository_interface.dart'; +export "package:chat_repository_interface/chat_repository_interface.dart"; // User story export "package:flutter_chat/src/flutter_chat_entry_widget.dart"; @@ -11,7 +9,7 @@ export "package:flutter_chat/src/flutter_chat_navigator_userstory.dart"; export "src/config/chat_builders.dart"; export "src/config/chat_options.dart"; export "src/config/chat_translations.dart"; -export 'src/config/screen_types.dart'; +export "src/config/screen_types.dart"; // Screens export "src/screens/chat_detail_screen.dart"; @@ -21,3 +19,7 @@ export "src/screens/creation/new_chat_screen.dart"; export "src/screens/creation/new_group_chat_overview.dart"; export "src/screens/creation/new_group_chat_screen.dart"; export "src/services/date_formatter.dart"; + +// Utils +export "src/util/scope.dart"; +export "src/util/utils.dart"; 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 256a63a..2a3b02a 100644 --- a/packages/flutter_chat/lib/src/flutter_chat_navigator_userstory.dart +++ b/packages/flutter_chat/lib/src/flutter_chat_navigator_userstory.dart @@ -13,6 +13,8 @@ import "package:flutter_chat/src/screens/chat_screen.dart"; import "package:flutter_chat/src/screens/creation/new_chat_screen.dart"; import "package:flutter_chat/src/screens/creation/new_group_chat_overview.dart"; import "package:flutter_chat/src/screens/creation/new_group_chat_screen.dart"; +import "package:flutter_chat/src/services/pop_handler.dart"; +import "package:flutter_chat/src/util/scope.dart"; /// The flutter chat navigator userstory /// [userId] is the id of the user @@ -44,29 +46,45 @@ class FlutterChatNavigatorUserstory extends StatefulWidget { class _FlutterChatNavigatorUserstoryState extends State { - late ChatService chatService; - late ChatOptions chatOptions; + late ChatService _service = widget.chatService ?? ChatService(); + + late final PopHandler _popHandler = PopHandler(); @override - void initState() { - chatService = widget.chatService ?? ChatService(); - chatOptions = widget.chatOptions ?? const ChatOptions(); - super.initState(); - } - - @override - Widget build(BuildContext context) => Navigator( - key: const ValueKey( - "chat_navigator", - ), - onGenerateRoute: (settings) => MaterialPageRoute( - builder: (context) => _NavigatorWrapper( - userId: widget.userId, - chatService: chatService, - chatOptions: chatOptions, + Widget build(BuildContext context) => ChatScope( + userId: widget.userId, + options: widget.chatOptions ?? const ChatOptions(), + service: _service, + popHandler: _popHandler, + child: NavigatorPopHandler( + // ignore: deprecated_member_use + onPop: _popHandler.handlePop, + child: Navigator( + key: const ValueKey( + "chat_navigator", + ), + onGenerateRoute: (settings) => MaterialPageRoute( + builder: (context) => _NavigatorWrapper( + userId: widget.userId, + chatService: _service, + chatOptions: widget.chatOptions ?? const ChatOptions(), + ), + ), ), ), ); + + @override + void didUpdateWidget(covariant FlutterChatNavigatorUserstory oldWidget) { + super.didUpdateWidget(oldWidget); + + if (oldWidget.userId != widget.userId || + oldWidget.chatOptions != widget.chatOptions) { + setState(() { + _service = widget.chatService ?? ChatService(); + }); + } + } } class _NavigatorWrapper extends StatelessWidget { diff --git a/packages/flutter_chat/lib/src/services/pop_handler.dart b/packages/flutter_chat/lib/src/services/pop_handler.dart new file mode 100644 index 0000000..348a28d --- /dev/null +++ b/packages/flutter_chat/lib/src/services/pop_handler.dart @@ -0,0 +1,24 @@ +import "package:flutter/material.dart"; + +/// +class PopHandler { + /// Constructor + PopHandler(); + + final List _handlers = []; + + /// Registers a new handler + void add(VoidCallback handler) { + _handlers.add(handler); + } + + /// Removes a handler + void remove(VoidCallback handler) { + _handlers.remove(handler); + } + + /// Handles the pop + void handlePop() { + _handlers.lastOrNull?.call(); + } +} diff --git a/packages/flutter_chat/lib/src/util/scope.dart b/packages/flutter_chat/lib/src/util/scope.dart new file mode 100644 index 0000000..e82dae4 --- /dev/null +++ b/packages/flutter_chat/lib/src/util/scope.dart @@ -0,0 +1,37 @@ +import "package:chat_repository_interface/chat_repository_interface.dart"; +import "package:flutter/widgets.dart"; +import "package:flutter_chat/src/config/chat_options.dart"; +import "package:flutter_chat/src/services/pop_handler.dart"; + +/// +class ChatScope extends InheritedWidget { + /// + const ChatScope({ + required this.userId, + required this.options, + required this.service, + required this.popHandler, + required super.child, + super.key, + }); + + /// + final String userId; + + /// + final ChatOptions options; + + /// + final ChatService service; + + /// + final PopHandler popHandler; + + @override + bool updateShouldNotify(ChatScope oldWidget) => + oldWidget.userId != userId || oldWidget.options != options; + + /// + static ChatScope of(BuildContext context) => + context.dependOnInheritedWidgetOfExactType()!; +} diff --git a/packages/flutter_chat/lib/src/util/utils.dart b/packages/flutter_chat/lib/src/util/utils.dart new file mode 100644 index 0000000..5312e4f --- /dev/null +++ b/packages/flutter_chat/lib/src/util/utils.dart @@ -0,0 +1 @@ +// add generic utils that are used in the package