diff --git a/packages/stream_chat_flutter/lib/src/channel_header.dart b/packages/stream_chat_flutter/lib/src/channel_header.dart index 8b0eb8fb..d06c128c 100644 --- a/packages/stream_chat_flutter/lib/src/channel_header.dart +++ b/packages/stream_chat_flutter/lib/src/channel_header.dart @@ -104,6 +104,7 @@ class ChannelHeader extends StatelessWidget implements PreferredSizeWidget { @override Widget build(BuildContext context) { final channel = StreamChannel.of(context).channel; + final chatThemeData = StreamChatTheme.of(context); final leadingWidget = leading ?? (showBackButton @@ -139,26 +140,18 @@ class ChannelHeader extends StatelessWidget implements PreferredSizeWidget { brightness: Theme.of(context).brightness, elevation: 1, leading: leadingWidget, - backgroundColor: StreamChatTheme.of(context) - .channelTheme - .channelHeaderTheme - .color, + backgroundColor: + chatThemeData.channelTheme.channelHeaderTheme.color, actions: actions ?? [ Padding( padding: const EdgeInsets.only(right: 10), child: Center( child: ChannelImage( - borderRadius: StreamChatTheme.of(context) - .channelTheme - .channelHeaderTheme - .avatarTheme - ?.borderRadius, - constraints: StreamChatTheme.of(context) - .channelTheme - .channelHeaderTheme - .avatarTheme - ?.constraints, + borderRadius: chatThemeData.channelTheme + .channelHeaderTheme.avatarTheme?.borderRadius, + constraints: chatThemeData.channelTheme + .channelHeaderTheme.avatarTheme?.constraints, onTap: onImageTap, ), ), @@ -175,20 +168,16 @@ class ChannelHeader extends StatelessWidget implements PreferredSizeWidget { children: [ title ?? ChannelName( - textStyle: StreamChatTheme.of(context) - .channelTheme - .channelHeaderTheme - .title, + textStyle: chatThemeData + .channelTheme.channelHeaderTheme.title, ), const SizedBox(height: 2), subtitle ?? ChannelInfo( showTypingIndicator: showTypingIndicator, channel: channel, - textStyle: StreamChatTheme.of(context) - .channelTheme - .channelHeaderTheme - .subtitle, + textStyle: chatThemeData + .channelTheme.channelHeaderTheme.subtitle, ), ], ), diff --git a/packages/stream_chat_flutter/lib/src/channel_image.dart b/packages/stream_chat_flutter/lib/src/channel_image.dart index 80e32f07..19495809 100644 --- a/packages/stream_chat_flutter/lib/src/channel_image.dart +++ b/packages/stream_chat_flutter/lib/src/channel_image.dart @@ -88,6 +88,7 @@ class ChannelImage extends StatelessWidget { initialData: channel.extraData, builder: (context, snapshot) { String? image; + final chatThemeData = StreamChatTheme.of(context); if (snapshot.data!.containsKey('image') == true) { image = snapshot.data!['image']; } else if (channel.state?.members.length == 2) { @@ -99,20 +100,16 @@ class ChannelImage extends StatelessWidget { initialData: otherMember!.user, builder: (context, snapshot) => UserAvatar( borderRadius: borderRadius ?? - StreamChatTheme.of(context) - .channelPreviewTheme - .avatarTheme - ?.borderRadius, + chatThemeData + .channelPreviewTheme.avatarTheme?.borderRadius, user: snapshot.data ?? otherMember.user!, constraints: constraints ?? - StreamChatTheme.of(context) - .channelPreviewTheme - .avatarTheme - ?.constraints, + chatThemeData + .channelPreviewTheme.avatarTheme?.constraints, onTap: onTap != null ? (_) => onTap!() : null, selected: selected, - selectionColor: selectionColor ?? - StreamChatTheme.of(context).colorTheme.accentBlue, + selectionColor: + selectionColor ?? chatThemeData.colorTheme.accentBlue, selectionThickness: selectionThickness, )); } else { @@ -127,37 +124,25 @@ class ChannelImage extends StatelessWidget { return GroupImage( images: images ?? [], borderRadius: borderRadius ?? - StreamChatTheme.of(context) - .channelPreviewTheme - .avatarTheme - ?.borderRadius, + chatThemeData.channelPreviewTheme.avatarTheme?.borderRadius, constraints: constraints ?? - StreamChatTheme.of(context) - .channelPreviewTheme - .avatarTheme - ?.constraints, + chatThemeData.channelPreviewTheme.avatarTheme?.constraints, onTap: onTap, selected: selected, - selectionColor: selectionColor ?? - StreamChatTheme.of(context).colorTheme.accentBlue, + selectionColor: + selectionColor ?? chatThemeData.colorTheme.accentBlue, selectionThickness: selectionThickness, ); } Widget child = ClipRRect( borderRadius: borderRadius ?? - StreamChatTheme.of(context) - .channelPreviewTheme - .avatarTheme - ?.borderRadius, + chatThemeData.channelPreviewTheme.avatarTheme?.borderRadius, child: Container( constraints: constraints ?? - StreamChatTheme.of(context) - .channelPreviewTheme - .avatarTheme - ?.constraints, + chatThemeData.channelPreviewTheme.avatarTheme?.constraints, decoration: BoxDecoration( - color: StreamChatTheme.of(context).colorTheme.accentBlue, + color: chatThemeData.colorTheme.accentBlue, ), child: Stack( alignment: Alignment.center, @@ -172,7 +157,7 @@ class ChannelImage extends StatelessWidget { ? snapshot.data!['name'][0] : '', style: TextStyle( - color: StreamChatTheme.of(context).colorTheme.white, + color: chatThemeData.colorTheme.white, fontWeight: FontWeight.bold, ), ), @@ -180,7 +165,7 @@ class ChannelImage extends StatelessWidget { fit: BoxFit.cover, ) else - StreamChatTheme.of(context).defaultChannelImage( + chatThemeData.defaultChannelImage( context, channel, ), @@ -198,20 +183,13 @@ class ChannelImage extends StatelessWidget { child = ClipRRect( key: const Key('selectedImage'), borderRadius: (borderRadius ?? - StreamChatTheme.of(context) - .ownMessageTheme - .avatarTheme - ?.borderRadius ?? + chatThemeData.ownMessageTheme.avatarTheme?.borderRadius ?? BorderRadius.zero) + BorderRadius.circular(selectionThickness), child: Container( constraints: constraints ?? - StreamChatTheme.of(context) - .ownMessageTheme - .avatarTheme - ?.constraints, - color: selectionColor ?? - StreamChatTheme.of(context).colorTheme.accentBlue, + chatThemeData.ownMessageTheme.avatarTheme?.constraints, + color: selectionColor ?? chatThemeData.colorTheme.accentBlue, child: Padding( padding: EdgeInsets.all(selectionThickness), child: child, diff --git a/packages/stream_chat_flutter/lib/src/channel_info.dart b/packages/stream_chat_flutter/lib/src/channel_info.dart index 5fa6f704..f59ac2e0 100644 --- a/packages/stream_chat_flutter/lib/src/channel_info.dart +++ b/packages/stream_chat_flutter/lib/src/channel_info.dart @@ -46,7 +46,9 @@ class ChannelInfo extends StatelessWidget { } Widget _buildConnectedTitleState( - BuildContext context, List? members) { + BuildContext context, + List? members, + ) { Widget? alternativeWidget; if (channel.memberCount != null && channel.memberCount! > 2) { @@ -61,8 +63,9 @@ class ChannelInfo extends StatelessWidget { .subtitle, ); } else { + final userId = StreamChat.of(context).user?.id; final otherMember = members?.firstWhereOrNull( - (element) => element.userId != StreamChat.of(context).user?.id, + (element) => element.userId != userId, ); if (otherMember != null) { diff --git a/packages/stream_chat_flutter/lib/src/channel_list_header.dart b/packages/stream_chat_flutter/lib/src/channel_list_header.dart index afc1884c..325736f1 100644 --- a/packages/stream_chat_flutter/lib/src/channel_list_header.dart +++ b/packages/stream_chat_flutter/lib/src/channel_list_header.dart @@ -114,6 +114,7 @@ class ChannelListHeader extends StatelessWidget implements PreferredSizeWidget { break; } + final chatThemeData = StreamChatTheme.of(context); return InfoTile( // ignore: avoid_bool_literals_in_conditional_expressions showMessage: showConnectionStateTile ? showStatus : false, @@ -121,8 +122,7 @@ class ChannelListHeader extends StatelessWidget implements PreferredSizeWidget { child: AppBar( brightness: Theme.of(context).brightness, elevation: 1, - backgroundColor: - StreamChatTheme.of(context).channelListHeaderTheme.color, + backgroundColor: chatThemeData.channelListHeaderTheme.color, centerTitle: true, leading: leading ?? Center( @@ -137,14 +137,10 @@ class ChannelListHeader extends StatelessWidget implements PreferredSizeWidget { } Scaffold.of(context).openDrawer(); }, - borderRadius: StreamChatTheme.of(context) - .channelListHeaderTheme - .avatarTheme - ?.borderRadius, - constraints: StreamChatTheme.of(context) - .channelListHeaderTheme - .avatarTheme - ?.constraints, + borderRadius: chatThemeData + .channelListHeaderTheme.avatarTheme?.borderRadius, + constraints: chatThemeData + .channelListHeaderTheme.avatarTheme?.constraints, ) : const Offstage(), ), @@ -157,9 +153,7 @@ class ChannelListHeader extends StatelessWidget implements PreferredSizeWidget { Color? color; switch (status) { case ConnectionStatus.connected: - color = StreamChatTheme.of(context) - .colorTheme - .accentBlue; + color = chatThemeData.colorTheme.accentBlue; break; case ConnectionStatus.connecting: color = Colors.grey; @@ -209,12 +203,15 @@ class ChannelListHeader extends StatelessWidget implements PreferredSizeWidget { ); } - Widget _buildConnectedTitleState(BuildContext context) => Text( - 'Stream Chat', - style: StreamChatTheme.of(context).textTheme.headlineBold.copyWith( - color: StreamChatTheme.of(context).colorTheme.black, - ), - ); + Widget _buildConnectedTitleState(BuildContext context) { + final chatThemeData = StreamChatTheme.of(context); + return Text( + 'Stream Chat', + style: chatThemeData.textTheme.headlineBold.copyWith( + color: chatThemeData.colorTheme.black, + ), + ); + } Widget _buildConnectingTitleState(BuildContext context) => Row( mainAxisAlignment: MainAxisAlignment.center, @@ -243,39 +240,35 @@ class ChannelListHeader extends StatelessWidget implements PreferredSizeWidget { Widget _buildDisconnectedTitleState( BuildContext context, StreamChatClient client, - ) => - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - 'Offline...', - style: StreamChatTheme.of(context) - .channelListHeaderTheme - .title - ?.copyWith( - fontSize: 16, - fontWeight: FontWeight.bold, - ), + ) { + final chatThemeData = StreamChatTheme.of(context); + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'Offline...', + style: chatThemeData.channelListHeaderTheme.title?.copyWith( + fontSize: 16, + fontWeight: FontWeight.bold, ), - TextButton( - onPressed: () async { - await client.disconnect(); - await client.connect(); - }, - child: Text( - 'Try Again', - style: StreamChatTheme.of(context) - .channelListHeaderTheme - .title - ?.copyWith( - fontSize: 16, - fontWeight: FontWeight.bold, - color: StreamChatTheme.of(context).colorTheme.accentBlue, - ), + ), + TextButton( + onPressed: () async { + await client.disconnect(); + await client.connect(); + }, + child: Text( + 'Try Again', + style: chatThemeData.channelListHeaderTheme.title?.copyWith( + fontSize: 16, + fontWeight: FontWeight.bold, + color: chatThemeData.colorTheme.accentBlue, ), ), - ], - ); + ), + ], + ); + } @override Size get preferredSize => const Size.fromHeight(kToolbarHeight); diff --git a/packages/stream_chat_flutter/lib/src/channel_list_view.dart b/packages/stream_chat_flutter/lib/src/channel_list_view.dart index fb713ea8..766fe4ba 100644 --- a/packages/stream_chat_flutter/lib/src/channel_list_view.dart +++ b/packages/stream_chat_flutter/lib/src/channel_list_view.dart @@ -237,78 +237,70 @@ class _ChannelListViewState extends State { } Widget _buildEmptyWidget(BuildContext context) => LayoutBuilder( - builder: (context, viewportConstraints) => SingleChildScrollView( - physics: const AlwaysScrollableScrollPhysics(), - child: Stack( - children: [ - ConstrainedBox( - constraints: BoxConstraints( - minHeight: viewportConstraints.maxHeight, + builder: (context, viewportConstraints) { + final chatThemeData = StreamChatTheme.of(context); + return SingleChildScrollView( + physics: const AlwaysScrollableScrollPhysics(), + child: Stack( + children: [ + ConstrainedBox( + constraints: BoxConstraints( + minHeight: viewportConstraints.maxHeight, + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.all(8), + child: StreamSvgIcon.message( + size: 136, + color: chatThemeData.colorTheme.greyGainsboro, + ), + ), + Padding( + padding: const EdgeInsets.all(8), + child: Text( + 'Let’s start chatting!', + style: chatThemeData.textTheme.headline, + ), + ), + Padding( + padding: const EdgeInsets.symmetric( + vertical: 8, + horizontal: 52, + ), + child: Text( + 'How about sending your first message to a friend?', + textAlign: TextAlign.center, + style: chatThemeData.textTheme.body.copyWith( + color: chatThemeData.colorTheme.grey, + ), + ), + ), + ], + ), ), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Padding( - padding: const EdgeInsets.all(8), - child: StreamSvgIcon.message( - size: 136, - color: StreamChatTheme.of(context) - .colorTheme - .greyGainsboro, - ), - ), - Padding( - padding: const EdgeInsets.all(8), - child: Text( - 'Let’s start chatting!', - style: StreamChatTheme.of(context).textTheme.headline, - ), - ), - Padding( - padding: const EdgeInsets.symmetric( - vertical: 8, - horizontal: 52, - ), - child: Text( - 'How about sending your first message to a friend?', - textAlign: TextAlign.center, - style: StreamChatTheme.of(context) - .textTheme - .body - .copyWith( - color: - StreamChatTheme.of(context).colorTheme.grey, - ), - ), - ), - ], - ), - ), - if (widget.onStartChatPressed != null) - Positioned( - right: 0, - left: 0, - bottom: 32, - child: Center( - child: TextButton( - onPressed: widget.onStartChatPressed, - child: Text( - 'Start a chat', - style: StreamChatTheme.of(context) - .textTheme - .bodyBold - .copyWith( - color: StreamChatTheme.of(context) - .colorTheme - .accentBlue, - ), + if (widget.onStartChatPressed != null) + Positioned( + right: 0, + left: 0, + bottom: 32, + child: Center( + child: TextButton( + onPressed: widget.onStartChatPressed, + child: Text( + 'Start a chat', + style: chatThemeData.textTheme.bodyBold.copyWith( + color: chatThemeData.colorTheme.accentBlue, + ), + ), ), ), ), - ), - ], - ), - ), + ], + ), + ); + }, ); Widget _buildLoadingWidget(BuildContext context) => ListView( @@ -331,10 +323,11 @@ class _ChannelListViewState extends State { ); Shimmer _buildLoadingItem(BuildContext context) { + final chatThemeData = StreamChatTheme.of(context); if (widget.crossAxisCount > 1) { return Shimmer.fromColors( - baseColor: StreamChatTheme.of(context).colorTheme.greyGainsboro, - highlightColor: StreamChatTheme.of(context).colorTheme.whiteSmoke, + baseColor: chatThemeData.colorTheme.greyGainsboro, + highlightColor: chatThemeData.colorTheme.whiteSmoke, child: Column( children: [ const SizedBox(height: 4), @@ -362,12 +355,12 @@ class _ChannelListViewState extends State { ); } else { return Shimmer.fromColors( - baseColor: StreamChatTheme.of(context).colorTheme.greyGainsboro, - highlightColor: StreamChatTheme.of(context).colorTheme.whiteSmoke, + baseColor: chatThemeData.colorTheme.greyGainsboro, + highlightColor: chatThemeData.colorTheme.whiteSmoke, child: ListTile( leading: Container( decoration: BoxDecoration( - color: StreamChatTheme.of(context).colorTheme.white, + color: chatThemeData.colorTheme.white, shape: BoxShape.circle, ), constraints: const BoxConstraints.tightFor( @@ -383,7 +376,7 @@ class _ChannelListViewState extends State { alignment: Alignment.centerLeft, child: Container( decoration: BoxDecoration( - color: StreamChatTheme.of(context).colorTheme.white, + color: chatThemeData.colorTheme.white, borderRadius: BorderRadius.circular(11), ), constraints: const BoxConstraints.tightFor( @@ -400,7 +393,7 @@ class _ChannelListViewState extends State { alignment: Alignment.centerLeft, child: Container( decoration: BoxDecoration( - color: StreamChatTheme.of(context).colorTheme.white, + color: chatThemeData.colorTheme.white, borderRadius: BorderRadius.circular(11), ), constraints: const BoxConstraints.expand( @@ -412,7 +405,7 @@ class _ChannelListViewState extends State { Container( margin: const EdgeInsets.only(left: 16), decoration: BoxDecoration( - color: StreamChatTheme.of(context).colorTheme.white, + color: chatThemeData.colorTheme.white, borderRadius: BorderRadius.circular(11), ), constraints: const BoxConstraints.tightFor( @@ -456,12 +449,13 @@ class _ChannelListViewState extends State { ); Widget _listItemBuilder(BuildContext context, int i, List channels) { - final channelsProvider = ChannelsBloc.of(context); + final channelsBloc = ChannelsBloc.of(context); if (i < channels.length) { final channel = channels[i]; final onTap = _getChannelTap(context); - final backgroundColor = StreamChatTheme.of(context).colorTheme.whiteSmoke; + final chatThemeData = StreamChatTheme.of(context); + final backgroundColor = chatThemeData.colorTheme.whiteSmoke; return StreamChannel( key: ValueKey('CHANNEL-${channel.id}'), channel: channel, @@ -506,7 +500,7 @@ class _ChannelListViewState extends State { IconSlideAction( color: backgroundColor, iconWidget: StreamSvgIcon.delete( - color: StreamChatTheme.of(context).colorTheme.accentRed, + color: chatThemeData.colorTheme.accentRed, ), onTap: () async { final res = await showConfirmationDialog( @@ -517,7 +511,7 @@ class _ChannelListViewState extends State { 'Are you sure you want to delete this conversation?', cancelText: 'CANCEL', icon: StreamSvgIcon.delete( - color: StreamChatTheme.of(context).colorTheme.accentRed, + color: chatThemeData.colorTheme.accentRed, ), ); if (res == true) { @@ -527,7 +521,7 @@ class _ChannelListViewState extends State { ), ], child: Container( - color: StreamChatTheme.of(context).colorTheme.whiteSnow, + color: chatThemeData.colorTheme.whiteSnow, child: widget.channelPreviewBuilder?.call(context, channel) ?? ChannelPreview( onLongPress: widget.onChannelLongPress, @@ -540,7 +534,7 @@ class _ChannelListViewState extends State { ), ); } else { - return _buildQueryProgressIndicator(context, channelsProvider); + return _buildQueryProgressIndicator(context, channelsBloc); } } diff --git a/packages/stream_chat_flutter/lib/src/channel_preview.dart b/packages/stream_chat_flutter/lib/src/channel_preview.dart index 70ad0e3f..3189b0cb 100644 --- a/packages/stream_chat_flutter/lib/src/channel_preview.dart +++ b/packages/stream_chat_flutter/lib/src/channel_preview.dart @@ -68,6 +68,8 @@ class ChannelPreview extends StatelessWidget { @override Widget build(BuildContext context) { final channelPreviewTheme = StreamChatTheme.of(context).channelPreviewTheme; + final streamChatState = StreamChat.of(context); + return StreamBuilder( stream: channel.isMutedStream, initialData: channel.isMuted, @@ -130,7 +132,7 @@ class ChannelPreview extends StatelessWidget { (m) => !m.isDeleted && m.shadowed != true, ); if (lastMessage?.user?.id == - StreamChat.of(context).user?.id) { + streamChatState.user?.id) { return Padding( padding: const EdgeInsets.only(right: 4), child: SendingIndicator( @@ -194,6 +196,7 @@ class ChannelPreview extends StatelessWidget { ); Widget _buildSubtitle(BuildContext context) { + final chatThemeData = StreamChatTheme.of(context); if (channel.isMuted) { return Row( crossAxisAlignment: CrossAxisAlignment.end, @@ -203,7 +206,7 @@ class ChannelPreview extends StatelessWidget { ), Text( ' Channel is muted', - style: StreamChatTheme.of(context).channelPreviewTheme.subtitle, + style: chatThemeData.channelPreviewTheme.subtitle, ), ], ); @@ -211,7 +214,7 @@ class ChannelPreview extends StatelessWidget { return TypingIndicator( channel: channel, alternativeWidget: _buildLastMessage(context), - style: StreamChatTheme.of(context).channelPreviewTheme.subtitle, + style: chatThemeData.channelPreviewTheme.subtitle, ); } @@ -245,35 +248,24 @@ class ChannelPreview extends StatelessWidget { text = parts.join(' '); + final chatThemeData = StreamChatTheme.of(context); return Text.rich( _getDisplayText( text, lastMessage.mentionedUsers, lastMessage.attachments, - StreamChatTheme.of(context) - .channelPreviewTheme - .subtitle - ?.copyWith( - color: StreamChatTheme.of(context) - .channelPreviewTheme - .subtitle - ?.color, - fontStyle: (lastMessage.isSystem || lastMessage.isDeleted) - ? FontStyle.italic - : FontStyle.normal), - StreamChatTheme.of(context) - .channelPreviewTheme - .subtitle - ?.copyWith( - color: StreamChatTheme.of(context) - .channelPreviewTheme - .subtitle - ?.color, - fontStyle: (lastMessage.isSystem || lastMessage.isDeleted) - ? FontStyle.italic - : FontStyle.normal, - fontWeight: FontWeight.bold, - ), + chatThemeData.channelPreviewTheme.subtitle?.copyWith( + color: chatThemeData.channelPreviewTheme.subtitle?.color, + fontStyle: (lastMessage.isSystem || lastMessage.isDeleted) + ? FontStyle.italic + : FontStyle.normal), + chatThemeData.channelPreviewTheme.subtitle?.copyWith( + color: chatThemeData.channelPreviewTheme.subtitle?.color, + fontStyle: (lastMessage.isSystem || lastMessage.isDeleted) + ? FontStyle.italic + : FontStyle.normal, + fontWeight: FontWeight.bold, + ), ), maxLines: 1, overflow: TextOverflow.ellipsis,