11import 'package:flutter/material.dart' ;
2+ import 'package:stream_chat_flutter/src/components/stream_chat_component_builders.dart' ;
23import 'package:stream_chat_flutter/src/misc/empty_widget.dart' ;
3- import 'package:stream_chat_flutter/src/theme/stream_chat_theme.dart' ;
44import 'package:stream_chat_flutter/src/utils/extensions.dart' ;
55import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart' ;
66import 'package:stream_core_flutter/stream_core_flutter.dart' ;
@@ -24,6 +24,32 @@ typedef UnreadIndicatorBuilder =
2424 OnUnreadIndicatorDismissTap onDismissTap,
2525 );
2626
27+ /// Properties for configuring an [UnreadIndicatorButton] .
28+ ///
29+ /// This class holds all the configuration options for an unread indicator,
30+ /// allowing them to be passed through the [StreamComponentFactory] .
31+ ///
32+ /// See also:
33+ ///
34+ /// * [UnreadIndicatorButton] , which uses these properties.
35+ class UnreadIndicatorProps {
36+ /// Creates properties for an unread indicator.
37+ const UnreadIndicatorProps ({
38+ required this .unreadCount,
39+ required this .onTap,
40+ required this .onDismissTap,
41+ });
42+
43+ /// The number of unread messages.
44+ final int unreadCount;
45+
46+ /// Callback triggered when the indicator is tapped.
47+ final OnUnreadIndicatorTap onTap;
48+
49+ /// Callback triggered when the dismiss button is tapped.
50+ final OnUnreadIndicatorDismissTap onDismissTap;
51+ }
52+
2753/// {@template unreadIndicatorButton}
2854/// A button that displays the number of unread messages in a channel.
2955///
@@ -52,7 +78,8 @@ class UnreadIndicatorButton extends StatelessWidget {
5278
5379 /// Optional builder for customizing the appearance of the unread indicator.
5480 ///
55- /// If not provided, a default indicator will be built.
81+ /// If not provided, falls back to [StreamComponentFactory] , then to the
82+ /// default indicator.
5683 final UnreadIndicatorBuilder ? unreadIndicatorBuilder;
5784
5885 @override
@@ -67,46 +94,68 @@ class UnreadIndicatorButton extends StatelessWidget {
6794 final unreadCount = currentUserRead.unreadMessages;
6895 if (unreadCount <= 0 ) return const Empty ();
6996
97+ final props = UnreadIndicatorProps (
98+ unreadCount: unreadCount,
99+ onTap: onTap,
100+ onDismissTap: onDismissTap,
101+ );
102+
70103 if (unreadIndicatorBuilder case final builder? ) {
71104 return builder (unreadCount, onTap, onDismissTap);
72105 }
73106
74- final theme = StreamChatTheme .of (context);
75- final textTheme = theme.textTheme;
76- final colorTheme = theme.colorTheme;
107+ final factoryBuilder = context.chatComponentBuilder <UnreadIndicatorProps >();
108+ if (factoryBuilder != null ) return factoryBuilder (context, props);
109+
110+ final colorTheme = context.streamColorScheme;
111+ final textTheme = context.streamTextTheme;
77112
78113 return Material (
79- elevation: 4 ,
114+ elevation: 3 ,
80115 clipBehavior: Clip .antiAlias,
81- color: colorTheme.textLowEmphasis ,
116+ color: colorTheme.backgroundElevation1 ,
82117 shape: RoundedRectangleBorder (
83- borderRadius: BorderRadius . circular ( 18 ),
118+ borderRadius: BorderRadiusDirectional . all (context.streamRadius.max ),
84119 ),
85- child: InkWell (
86- onTap: () => onTap (currentUserRead.lastReadMessageId),
87- child: Padding (
88- padding: const EdgeInsets .fromLTRB (16 , 2 , 8 , 2 ),
89- child: Row (
90- children: [
91- Text (
92- context.translations.unreadCountIndicatorLabel (
93- unreadCount: unreadCount,
94- ),
95- style: textTheme.body.copyWith (color: colorTheme.barsBg),
96- ),
97- const SizedBox (width: 12 ),
98- IconButton (
99- iconSize: 24 ,
100- icon: Icon (context.streamIcons.crossMedium),
101- padding: const EdgeInsets .all (4 ),
102- style: IconButton .styleFrom (
103- foregroundColor: colorTheme.barsBg,
104- minimumSize: const Size .square (24 ),
105- tapTargetSize: MaterialTapTargetSize .shrinkWrap,
106- ),
107- onPressed: onDismissTap,
120+ child: SizedBox (
121+ height: 40 ,
122+ child: InkWell (
123+ onTap: () => onTap (currentUserRead.lastReadMessageId),
124+ child: Padding (
125+ padding: const EdgeInsets .fromLTRB (16 , 2 , 8 , 2 ),
126+ child: IntrinsicHeight (
127+ child: Row (
128+ children: [
129+ Icon (
130+ context.streamIcons.arrowUp,
131+ size: 20 ,
132+ ),
133+ SizedBox (width: context.streamSpacing.xs),
134+ Text (
135+ context.translations.unreadCountIndicatorLabel (
136+ unreadCount: unreadCount,
137+ ),
138+ style: textTheme.bodyEmphasis.copyWith (color: colorTheme.textSecondary),
139+ ),
140+ SizedBox (width: context.streamSpacing.md),
141+ VerticalDivider (
142+ color: colorTheme.borderDefault,
143+ thickness: 1 ,
144+ ),
145+ IconButton (
146+ iconSize: 20 ,
147+ icon: Icon (context.streamIcons.crossMedium),
148+ padding: const EdgeInsets .all (5 ),
149+ style: IconButton .styleFrom (
150+ foregroundColor: colorTheme.textSecondary,
151+ minimumSize: const Size .square (20 ),
152+ tapTargetSize: MaterialTapTargetSize .shrinkWrap,
153+ ),
154+ onPressed: onDismissTap,
155+ ),
156+ ],
108157 ),
109- ] ,
158+ ) ,
110159 ),
111160 ),
112161 ),
0 commit comments