chore: upgrade AvatarTheme

* `AvatarTheme` is now an `InheritedTheme` and has a corresponding `AvatarThemeData` class
This commit is contained in:
groovinchip
2021-07-27 10:32:49 -04:00
parent bcabbf12db
commit f90fd713c2
8 changed files with 127 additions and 31 deletions
@@ -59,7 +59,7 @@ class MyApp extends StatelessWidget {
final colorTheme = defaultTheme.colorTheme; final colorTheme = defaultTheme.colorTheme;
final customTheme = defaultTheme.merge(StreamChatThemeData( final customTheme = defaultTheme.merge(StreamChatThemeData(
channelPreviewTheme: ChannelPreviewTheme( channelPreviewTheme: ChannelPreviewTheme(
avatarTheme: AvatarTheme( avatarTheme: AvatarThemeData(
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
), ),
), ),
@@ -68,7 +68,7 @@ class MyApp extends StatelessWidget {
messageText: TextStyle( messageText: TextStyle(
color: colorTheme.barsBg, color: colorTheme.barsBg,
), ),
avatarTheme: AvatarTheme( avatarTheme: AvatarThemeData(
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
), ),
), ),
@@ -62,6 +62,7 @@ class StreamChatThemeData {
ChannelListViewThemeData? channelListViewTheme, ChannelListViewThemeData? channelListViewTheme,
UserListViewThemeData? userListViewTheme, UserListViewThemeData? userListViewTheme,
MessageSearchListViewThemeData? messageSearchListViewTheme, MessageSearchListViewThemeData? messageSearchListViewTheme,
AvatarThemeData? avatarTheme,
}) { }) {
brightness ??= colorTheme?.brightness ?? Brightness.light; brightness ??= colorTheme?.brightness ?? Brightness.light;
final isDark = brightness == Brightness.dark; final isDark = brightness == Brightness.dark;
@@ -89,6 +90,7 @@ class StreamChatThemeData {
channelListViewTheme: channelListViewTheme, channelListViewTheme: channelListViewTheme,
userListViewTheme: userListViewTheme, userListViewTheme: userListViewTheme,
messageSearchListViewTheme: messageSearchListViewTheme, messageSearchListViewTheme: messageSearchListViewTheme,
avatarTheme: avatarTheme,
); );
return defaultData.merge(customizedData); return defaultData.merge(customizedData);
@@ -121,6 +123,7 @@ class StreamChatThemeData {
required this.channelListViewTheme, required this.channelListViewTheme,
required this.userListViewTheme, required this.userListViewTheme,
required this.messageSearchListViewTheme, required this.messageSearchListViewTheme,
required this.avatarTheme,
}); });
/// Create a theme from a Material [Theme] /// Create a theme from a Material [Theme]
@@ -188,6 +191,9 @@ class StreamChatThemeData {
/// Theme configuration for the [] widget. /// Theme configuration for the [] widget.
final MessageSearchListViewThemeData messageSearchListViewTheme; final MessageSearchListViewThemeData messageSearchListViewTheme;
/// Theme configuration for the [] widget.
final AvatarThemeData avatarTheme;
/// Creates a copy of [StreamChatThemeData] with specified attributes /// Creates a copy of [StreamChatThemeData] with specified attributes
/// overridden. /// overridden.
StreamChatThemeData copyWith({ StreamChatThemeData copyWith({
@@ -208,6 +214,7 @@ class StreamChatThemeData {
ChannelListViewThemeData? channelListViewTheme, ChannelListViewThemeData? channelListViewTheme,
UserListViewThemeData? userListViewTheme, UserListViewThemeData? userListViewTheme,
MessageSearchListViewThemeData? messageSearchListViewTheme, MessageSearchListViewThemeData? messageSearchListViewTheme,
AvatarThemeData? avatarTheme,
}) => }) =>
StreamChatThemeData.raw( StreamChatThemeData.raw(
channelListHeaderTheme: channelListHeaderTheme:
@@ -230,6 +237,7 @@ class StreamChatThemeData {
userListViewTheme: userListViewTheme ?? this.userListViewTheme, userListViewTheme: userListViewTheme ?? this.userListViewTheme,
messageSearchListViewTheme: messageSearchListViewTheme:
messageSearchListViewTheme ?? this.messageSearchListViewTheme, messageSearchListViewTheme ?? this.messageSearchListViewTheme,
avatarTheme: avatarTheme ?? this.avatarTheme,
); );
/// Merge themes /// Merge themes
@@ -257,6 +265,7 @@ class StreamChatThemeData {
userListViewTheme: userListViewTheme.merge(other.userListViewTheme), userListViewTheme: userListViewTheme.merge(other.userListViewTheme),
messageSearchListViewTheme: messageSearchListViewTheme:
messageSearchListViewTheme.merge(other.messageSearchListViewTheme), messageSearchListViewTheme.merge(other.messageSearchListViewTheme),
avatarTheme: avatarTheme.merge(other.avatarTheme),
); );
} }
@@ -271,7 +280,7 @@ class StreamChatThemeData {
IconThemeData(color: colorTheme.textHighEmphasis.withOpacity(.5)); IconThemeData(color: colorTheme.textHighEmphasis.withOpacity(.5));
final channelTheme = ChannelTheme( final channelTheme = ChannelTheme(
channelHeaderTheme: ChannelHeaderTheme( channelHeaderTheme: ChannelHeaderTheme(
avatarTheme: AvatarTheme( avatarTheme: AvatarThemeData(
borderRadius: BorderRadius.circular(20), borderRadius: BorderRadius.circular(20),
constraints: const BoxConstraints.tightFor( constraints: const BoxConstraints.tightFor(
height: 40, height: 40,
@@ -287,7 +296,7 @@ class StreamChatThemeData {
); );
final channelPreviewTheme = ChannelPreviewTheme( final channelPreviewTheme = ChannelPreviewTheme(
unreadCounterColor: colorTheme.accentError, unreadCounterColor: colorTheme.accentError,
avatarTheme: AvatarTheme( avatarTheme: AvatarThemeData(
borderRadius: BorderRadius.circular(20), borderRadius: BorderRadius.circular(20),
constraints: const BoxConstraints.tightFor( constraints: const BoxConstraints.tightFor(
height: 40, height: 40,
@@ -315,7 +324,7 @@ class StreamChatThemeData {
), ),
channelPreviewTheme: channelPreviewTheme, channelPreviewTheme: channelPreviewTheme,
channelListHeaderTheme: ChannelListHeaderTheme( channelListHeaderTheme: ChannelListHeaderTheme(
avatarTheme: AvatarTheme( avatarTheme: AvatarThemeData(
borderRadius: BorderRadius.circular(20), borderRadius: BorderRadius.circular(20),
constraints: const BoxConstraints.tightFor( constraints: const BoxConstraints.tightFor(
height: 40, height: 40,
@@ -338,7 +347,7 @@ class StreamChatThemeData {
reactionsBorderColor: colorTheme.borders, reactionsBorderColor: colorTheme.borders,
reactionsMaskColor: colorTheme.appBg, reactionsMaskColor: colorTheme.appBg,
messageBorderColor: colorTheme.disabled, messageBorderColor: colorTheme.disabled,
avatarTheme: AvatarTheme( avatarTheme: AvatarThemeData(
borderRadius: BorderRadius.circular(20), borderRadius: BorderRadius.circular(20),
constraints: const BoxConstraints.tightFor( constraints: const BoxConstraints.tightFor(
height: 32, height: 32,
@@ -364,7 +373,7 @@ class StreamChatThemeData {
), ),
messageBackgroundColor: colorTheme.barsBg, messageBackgroundColor: colorTheme.barsBg,
messageBorderColor: colorTheme.borders, messageBorderColor: colorTheme.borders,
avatarTheme: AvatarTheme( avatarTheme: AvatarThemeData(
borderRadius: BorderRadius.circular(20), borderRadius: BorderRadius.circular(20),
constraints: const BoxConstraints.tightFor( constraints: const BoxConstraints.tightFor(
height: 32, height: 32,
@@ -487,7 +496,9 @@ class StreamChatThemeData {
messageSearchListViewTheme: MessageSearchListViewThemeData( messageSearchListViewTheme: MessageSearchListViewThemeData(
backgroundColor: colorTheme.appBg, backgroundColor: colorTheme.appBg,
), ),
avatarTheme: AvatarThemeData(
borderRadius: BorderRadius.circular(8),
),
); );
} }
} }
@@ -1,9 +1,62 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:stream_chat_flutter/src/stream_chat_theme.dart';
import 'package:stream_chat_flutter/src/theme/themes.dart';
/// Theme for avatar /// Overrides the default style of [UserAvatar] descendants.
class AvatarTheme { ///
/// Constructor for creating [AvatarTheme] /// See also:
AvatarTheme({ ///
/// * [AvatarThemeData], which is used to configure this theme.
class AvatarTheme extends InheritedTheme {
/// Creates an [AvatarTheme].
///
/// The [data] parameter must not be null.
const AvatarTheme({
Key? key,
required this.data,
required Widget child,
}) : super(key: key, child: child);
/// The configuration of this theme.
final AvatarThemeData data;
/// The closest instance of this class that encloses the given context.
///
/// If there is no enclosing [GalleryHeaderTheme] widget, then
/// [StreamChatThemeData.avatarTheme] is used.
///
/// Typical usage is as follows:
///
/// ```dart
/// final theme = AvatarTheme.of(context);
/// ```
static AvatarThemeData of(BuildContext context) {
final avatarTheme =
context.dependOnInheritedWidgetOfExactType<AvatarTheme>();
return avatarTheme?.data ?? StreamChatTheme.of(context).avatarTheme;
}
@override
Widget wrap(BuildContext context, Widget child) =>
AvatarTheme(data: data, child: child);
@override
bool updateShouldNotify(AvatarTheme oldWidget) => data != oldWidget.data;
}
/// A style that overrides the default appearance of [UserAvatar]s when used
/// with [AvatarTheme] or with the overall [StreamChatTheme]'s
/// [StreamChatThemeData.avatarTheme].
///
/// See also:
///
/// * [AvatarTheme], the theme which is configured with this class.
/// * [StreamChatThemeData.avatarTheme], which can be used to override
/// the default style for [UserAvatar]s below the overall [StreamChatTheme].
class AvatarThemeData with Diagnosticable {
/// Creates an [AvatarThemeData].
AvatarThemeData({
BoxConstraints? constraints, BoxConstraints? constraints,
BorderRadius? borderRadius, BorderRadius? borderRadius,
}) : _constraints = constraints, }) : _constraints = constraints,
@@ -15,30 +68,62 @@ class AvatarTheme {
/// Get constraints for avatar /// Get constraints for avatar
BoxConstraints get constraints => BoxConstraints get constraints =>
_constraints ?? _constraints ??
const BoxConstraints.tightFor( const BoxConstraints.tightFor(
height: 32, height: 32,
width: 32, width: 32,
); );
/// Get border radius /// Get border radius
BorderRadius get borderRadius => _borderRadius ?? BorderRadius.circular(20); BorderRadius get borderRadius => _borderRadius ?? BorderRadius.circular(20);
/// Copy with another theme /// Copy this [AvatarThemeData] to another.
AvatarTheme copyWith({ AvatarThemeData copyWith({
BoxConstraints? constraints, BoxConstraints? constraints,
BorderRadius? borderRadius, BorderRadius? borderRadius,
}) => }) =>
AvatarTheme( AvatarThemeData(
constraints: constraints ?? _constraints, constraints: constraints ?? _constraints,
borderRadius: borderRadius ?? _borderRadius, borderRadius: borderRadius ?? _borderRadius,
); );
/// Merge with another AvatarTheme /// Linearly interpolate between two [UserAvatar] themes.
AvatarTheme merge(AvatarTheme? other) { ///
/// All the properties must be non-null.
AvatarThemeData lerp(
AvatarThemeData a,
AvatarThemeData b,
double t,
) =>
AvatarThemeData(
borderRadius: BorderRadius.lerp(a.borderRadius, b.borderRadius, t),
constraints: BoxConstraints.lerp(a.constraints, b.constraints, t),
);
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is AvatarThemeData &&
runtimeType == other.runtimeType &&
_constraints == other._constraints &&
_borderRadius == other._borderRadius;
@override
int get hashCode => _constraints.hashCode ^ _borderRadius.hashCode;
/// Merges one [AvatarThemeData] with the another
AvatarThemeData merge(AvatarThemeData? other) {
if (other == null) return this; if (other == null) return this;
return copyWith( return copyWith(
constraints: other._constraints, constraints: other._constraints,
borderRadius: other._borderRadius, borderRadius: other._borderRadius,
); );
} }
}
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties
..add(DiagnosticsProperty('borderRadius', borderRadius))
..add(DiagnosticsProperty('constraints', constraints));
}
}
@@ -18,7 +18,7 @@ class ChannelHeaderTheme {
final TextStyle? subtitle; final TextStyle? subtitle;
/// Theme for avatar /// Theme for avatar
final AvatarTheme? avatarTheme; final AvatarThemeData? avatarTheme;
/// Color for [ChannelHeaderTheme] /// Color for [ChannelHeaderTheme]
final Color? color; final Color? color;
@@ -27,7 +27,7 @@ class ChannelHeaderTheme {
ChannelHeaderTheme copyWith({ ChannelHeaderTheme copyWith({
TextStyle? title, TextStyle? title,
TextStyle? subtitle, TextStyle? subtitle,
AvatarTheme? avatarTheme, AvatarThemeData? avatarTheme,
Color? color, Color? color,
}) => }) =>
ChannelHeaderTheme( ChannelHeaderTheme(
@@ -14,7 +14,7 @@ class ChannelListHeaderTheme {
final TextStyle? title; final TextStyle? title;
/// Theme dedicated to the userAvatar /// Theme dedicated to the userAvatar
final AvatarTheme? avatarTheme; final AvatarThemeData? avatarTheme;
/// Background color of the appbar /// Background color of the appbar
final Color? color; final Color? color;
@@ -22,7 +22,7 @@ class ChannelListHeaderTheme {
/// Returns a new [ChannelListHeaderTheme] replacing some of its properties /// Returns a new [ChannelListHeaderTheme] replacing some of its properties
ChannelListHeaderTheme copyWith({ ChannelListHeaderTheme copyWith({
TextStyle? title, TextStyle? title,
AvatarTheme? avatarTheme, AvatarThemeData? avatarTheme,
Color? color, Color? color,
}) => }) =>
ChannelListHeaderTheme( ChannelListHeaderTheme(
@@ -23,7 +23,7 @@ class ChannelPreviewTheme {
final TextStyle? lastMessageAt; final TextStyle? lastMessageAt;
/// Avatar theme /// Avatar theme
final AvatarTheme? avatarTheme; final AvatarThemeData? avatarTheme;
/// Unread counter color /// Unread counter color
final Color? unreadCounterColor; final Color? unreadCounterColor;
@@ -36,7 +36,7 @@ class ChannelPreviewTheme {
TextStyle? title, TextStyle? title,
TextStyle? subtitle, TextStyle? subtitle,
TextStyle? lastMessageAt, TextStyle? lastMessageAt,
AvatarTheme? avatarTheme, AvatarThemeData? avatarTheme,
Color? unreadCounterColor, Color? unreadCounterColor,
double? indicatorIconSize, double? indicatorIconSize,
}) => }) =>
@@ -8,7 +8,7 @@ import 'package:stream_chat_flutter/src/stream_chat_theme.dart';
/// ///
/// * [GalleryHeaderThemeData], which is used to configure this theme. /// * [GalleryHeaderThemeData], which is used to configure this theme.
class GalleryHeaderTheme extends InheritedTheme { class GalleryHeaderTheme extends InheritedTheme {
/// Creates an [GalleryHeaderTheme]. /// Creates a [GalleryHeaderTheme].
/// ///
/// The [data] parameter must not be null. /// The [data] parameter must not be null.
const GalleryHeaderTheme({ const GalleryHeaderTheme({
@@ -49,7 +49,7 @@ class MessageTheme {
final Color? reactionsMaskColor; final Color? reactionsMaskColor;
/// Theme of the avatar /// Theme of the avatar
final AvatarTheme? avatarTheme; final AvatarThemeData? avatarTheme;
/// Copy with a theme /// Copy with a theme
MessageTheme copyWith({ MessageTheme copyWith({
@@ -60,7 +60,7 @@ class MessageTheme {
TextStyle? replies, TextStyle? replies,
Color? messageBackgroundColor, Color? messageBackgroundColor,
Color? messageBorderColor, Color? messageBorderColor,
AvatarTheme? avatarTheme, AvatarThemeData? avatarTheme,
Color? reactionsBackgroundColor, Color? reactionsBackgroundColor,
Color? reactionsBorderColor, Color? reactionsBorderColor,
Color? reactionsMaskColor, Color? reactionsMaskColor,