import 'package:flutter/material.dart'; import 'package:stream_chat_flutter/src/indicators/loading_indicator.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; /// {@template streamChatConfiguration} /// Inherited widget providing the [StreamChatConfigurationData] /// to the widget tree /// {@endtemplate} class StreamChatConfiguration extends InheritedWidget { /// {@macro streamChatConfiguration} const StreamChatConfiguration({ super.key, required this.data, required super.child, }); /// {@macro streamChatConfigurationData} final StreamChatConfigurationData data; @override bool updateShouldNotify(StreamChatConfiguration oldWidget) => data != oldWidget.data; /// Use this method to get the current [StreamChatThemeData] instance static StreamChatConfigurationData of(BuildContext context) { final streamChatConfiguration = context.dependOnInheritedWidgetOfExactType(); assert( streamChatConfiguration != null, ''' You must have a StreamChatConfigurationProvider widget at the top of your widget tree''', ); return streamChatConfiguration!.data; } } /// {@template streamChatConfigurationData} /// Provides global, user-configurable, non-theme related configuration /// options to Flutter applications that use Stream Chat. /// /// In order to set these configuration options, you must pass an instance of /// this class to the [StreamChat] widget, or wrap a subtree using /// the [StreamChatConfiguration] inherited widget. /// /// If you need to access the configuration directly at a later point in your /// application, you can use the [StreamChatConfiguration.of] method /// to retrieve it. /// /// If no [StreamChatConfigurationData] is provided, the /// [StreamChatConfiguration.defaults] factory constructor is used to provide a /// default configuration. /// /// If you want to keep some of the default values, but not others, you can use /// the [StreamChatConfigurationData.copyWith] method to override the values in /// question. /// /// Example 1: /// ```dart /// class MyApp extends StatelessWidget { /// const MyApp({ /// required this.client, /// }); /// /// final StreamChatClient client; /// /// @override /// Widget build(BuildContext context) { /// return MaterialApp( /// home: Container( /// child: StreamChat( /// client: client, /// // No configuration provided, so the defaults are used. /// child: ChannelListPage(), /// ), /// ), /// ); /// } /// } /// ``` /// /// Example 2: /// ```dart /// class MyApp extends StatelessWidget { /// const MyApp({ /// required this.client, /// }); /// /// final StreamChatClient client; /// /// @override /// Widget build(BuildContext context) { /// return MaterialApp( /// home: Container( /// child: StreamChat( /// client: client, /// config: StreamChatConfiguration.defaults().copyWith( /// // Override a specific default value here /// ), /// child: ChannelListPage(), /// ), /// ), /// ); /// } /// } /// ``` /// {@endtemplate} class StreamChatConfigurationData { /// {@macro streamChatConfigurationData} factory StreamChatConfigurationData({ Widget loadingIndicator = const StreamLoadingIndicator(), Widget Function(BuildContext, User)? defaultUserImage, Widget Function(BuildContext, User)? placeholderUserImage, List? reactionIcons, bool? enforceUniqueReactions, }) { return StreamChatConfigurationData._( loadingIndicator: loadingIndicator, defaultUserImage: defaultUserImage ?? _defaultUserImage, placeholderUserImage: placeholderUserImage, reactionIcons: reactionIcons ?? _defaultReactionIcons, enforceUniqueReactions: enforceUniqueReactions ?? true, ); } StreamChatConfigurationData._({ required this.loadingIndicator, required this.defaultUserImage, required this.placeholderUserImage, required this.reactionIcons, required this.enforceUniqueReactions, }); /// Copies the configuration options from one [StreamChatConfigurationData] to /// another. StreamChatConfigurationData copyWith({ Widget? loadingIndicator, Widget Function(BuildContext, User)? defaultUserImage, Widget Function(BuildContext, User)? placeholderUserImage, List? reactionIcons, bool? enforceUniqueReactions, }) { return StreamChatConfigurationData( reactionIcons: reactionIcons ?? this.reactionIcons, defaultUserImage: defaultUserImage ?? this.defaultUserImage, placeholderUserImage: placeholderUserImage ?? this.placeholderUserImage, loadingIndicator: loadingIndicator ?? this.loadingIndicator, enforceUniqueReactions: enforceUniqueReactions ?? this.enforceUniqueReactions, ); } /// The widget that will be shown to indicate loading. final Widget loadingIndicator; /// The widget that will be built when the user image is unavailable. final Widget Function(BuildContext, User) defaultUserImage; /// The widget that will be built when the user image is loading. final Widget Function(BuildContext, User)? placeholderUserImage; /// Assets used for rendering reactions. final List reactionIcons; /// Whether a new reaction should replace the existing one. final bool enforceUniqueReactions; static final _defaultReactionIcons = [ StreamReactionIcon( type: 'love', builder: (context, highlighted, size) { final theme = StreamChatTheme.of(context); return StreamSvgIcon.loveReaction( color: highlighted ? theme.colorTheme.accentPrimary : theme.primaryIconTheme.color, size: size, ); }, ), StreamReactionIcon( type: 'like', builder: (context, highlighted, size) { final theme = StreamChatTheme.of(context); return StreamSvgIcon.thumbsUpReaction( color: highlighted ? theme.colorTheme.accentPrimary : theme.primaryIconTheme.color, size: size, ); }, ), StreamReactionIcon( type: 'sad', builder: (context, highlighted, size) { final theme = StreamChatTheme.of(context); return StreamSvgIcon.thumbsDownReaction( color: highlighted ? theme.colorTheme.accentPrimary : theme.primaryIconTheme.color, size: size, ); }, ), StreamReactionIcon( type: 'haha', builder: (context, highlighted, size) { final theme = StreamChatTheme.of(context); return StreamSvgIcon.lolReaction( color: highlighted ? theme.colorTheme.accentPrimary : theme.primaryIconTheme.color, size: size, ); }, ), StreamReactionIcon( type: 'wow', builder: (context, highlighted, size) { final theme = StreamChatTheme.of(context); return StreamSvgIcon.wutReaction( color: highlighted ? theme.colorTheme.accentPrimary : theme.primaryIconTheme.color, size: size, ); }, ), ]; static Widget _defaultUserImage(BuildContext context, User user) => Center( child: StreamGradientAvatar( name: user.name, userId: user.id, ), ); }