feat: add ChatScope inherited widget for accessing the options, service and userId everywhere through the context

This commit is contained in:
Freek van de Ven 2025-02-10 08:25:50 +01:00
parent da3b78f63b
commit 45b5d4eeea
6 changed files with 105 additions and 22 deletions

View file

@ -2,6 +2,7 @@
- Added messageType to the ChatMessageModel to allow for different type of messages, it is nullable to remain backwards compatible - 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 - Get the color for the imagepicker from the Theme's primaryColor
- Added chatMessageBuilder to the userstory configuration to customize the chat messages - 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 ## 4.0.0
- Move to the new user story architecture - Move to the new user story architecture

View file

@ -1,7 +1,5 @@
// ignore_for_file: prefer_double_quotes
// Core // Core
export 'package:chat_repository_interface/chat_repository_interface.dart'; export "package:chat_repository_interface/chat_repository_interface.dart";
// User story // User story
export "package:flutter_chat/src/flutter_chat_entry_widget.dart"; 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_builders.dart";
export "src/config/chat_options.dart"; export "src/config/chat_options.dart";
export "src/config/chat_translations.dart"; export "src/config/chat_translations.dart";
export 'src/config/screen_types.dart'; export "src/config/screen_types.dart";
// Screens // Screens
export "src/screens/chat_detail_screen.dart"; 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_overview.dart";
export "src/screens/creation/new_group_chat_screen.dart"; export "src/screens/creation/new_group_chat_screen.dart";
export "src/services/date_formatter.dart"; export "src/services/date_formatter.dart";
// Utils
export "src/util/scope.dart";
export "src/util/utils.dart";

View file

@ -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_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_overview.dart";
import "package:flutter_chat/src/screens/creation/new_group_chat_screen.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 /// The flutter chat navigator userstory
/// [userId] is the id of the user /// [userId] is the id of the user
@ -44,29 +46,45 @@ class FlutterChatNavigatorUserstory extends StatefulWidget {
class _FlutterChatNavigatorUserstoryState class _FlutterChatNavigatorUserstoryState
extends State<FlutterChatNavigatorUserstory> { extends State<FlutterChatNavigatorUserstory> {
late ChatService chatService; late ChatService _service = widget.chatService ?? ChatService();
late ChatOptions chatOptions;
late final PopHandler _popHandler = PopHandler();
@override @override
void initState() { Widget build(BuildContext context) => ChatScope(
chatService = widget.chatService ?? ChatService(); userId: widget.userId,
chatOptions = widget.chatOptions ?? const ChatOptions(); options: widget.chatOptions ?? const ChatOptions(),
super.initState(); service: _service,
} popHandler: _popHandler,
child: NavigatorPopHandler(
@override // ignore: deprecated_member_use
Widget build(BuildContext context) => Navigator( onPop: _popHandler.handlePop,
key: const ValueKey( child: Navigator(
"chat_navigator", key: const ValueKey(
), "chat_navigator",
onGenerateRoute: (settings) => MaterialPageRoute( ),
builder: (context) => _NavigatorWrapper( onGenerateRoute: (settings) => MaterialPageRoute(
userId: widget.userId, builder: (context) => _NavigatorWrapper(
chatService: chatService, userId: widget.userId,
chatOptions: chatOptions, 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 { class _NavigatorWrapper extends StatelessWidget {

View file

@ -0,0 +1,24 @@
import "package:flutter/material.dart";
///
class PopHandler {
/// Constructor
PopHandler();
final List<VoidCallback> _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();
}
}

View file

@ -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<ChatScope>()!;
}

View file

@ -0,0 +1 @@
// add generic utils that are used in the package