Merge branch 'feature/new-ui' of https://github.com/GetStream/stream-chat-flutter into fix/channel-list

 Conflicts:
	lib/src/stream_chat_theme.dart
	lib/src/stream_svg_icon.dart
This commit is contained in:
Deven Joshi
2021-01-06 20:56:01 +05:30
21 changed files with 735 additions and 885 deletions
+13 -75
View File
@@ -29,27 +29,8 @@ class ImageActionsModal extends StatelessWidget {
Widget build(BuildContext context) {
return GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () {
Navigator.pop(context);
},
child: Stack(
children: [
Positioned.fill(
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Colors.black.withOpacity(0.8),
Colors.transparent,
],
stops: [0.0, 0.4],
)),
)),
_buildPage(context),
],
),
onTap: () => Navigator.maybePop(context),
child: _buildPage(context),
);
}
@@ -57,53 +38,14 @@ class ImageActionsModal extends StatelessWidget {
return Material(
color: Colors.transparent,
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
width: 40.0,
),
),
Column(
children: [
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Text(
userName,
style: StreamChatTheme.of(context)
.textTheme
.headlineBold
.copyWith(
color:
StreamChatTheme.of(context).colorTheme.white),
),
),
Text(
sentAt,
style: StreamChatTheme.of(context)
.channelPreviewTheme
.subtitle
.copyWith(
color: StreamChatTheme.of(context)
.colorTheme
.white
.withOpacity(0.5)),
),
],
),
IconButton(
icon: StreamSvgIcon.close(
size: 24.0,
color: StreamChatTheme.of(context).colorTheme.white,
),
onPressed: () {
Navigator.pop(context);
},
),
],
SizedBox(
height: kToolbarHeight,
child: IconButton(
icon: StreamSvgIcon.close(),
onPressed: () => Navigator.maybePop(context),
),
),
Align(
alignment: Alignment.centerRight,
@@ -127,10 +69,8 @@ class ImageActionsModal extends StatelessWidget {
'Reply',
StreamSvgIcon.Icon_curve_line_left_up(
size: 24.0,
color: StreamChatTheme.of(context)
.colorTheme
.black
.withOpacity(0.5),
color:
StreamChatTheme.of(context).colorTheme.grey,
),
() {}),
_buildButton(
@@ -147,10 +87,8 @@ class ImageActionsModal extends StatelessWidget {
'Save ${urls[currentIndex].type == 'video' ? 'Video' : 'Image'}',
StreamSvgIcon.Icon_save(
size: 24.0,
color: StreamChatTheme.of(context)
.colorTheme
.black
.withOpacity(0.5),
color:
StreamChatTheme.of(context).colorTheme.grey,
), () async {
var url = urls[currentIndex].imageUrl ??
urls[currentIndex].assetUrl ??
+4 -7
View File
@@ -157,9 +157,7 @@ class _ImageFooterState extends State<ImageFooter> {
icon: StreamSvgIcon.Icon_grid(
color: StreamChatTheme.of(context).colorTheme.black,
),
onPressed: () {
_buildPhotosModal(context);
},
onPressed: () => _showPhotosModal(context),
),
],
),
@@ -168,13 +166,14 @@ class _ImageFooterState extends State<ImageFooter> {
);
}
Widget _buildPhotosModal(context) {
void _showPhotosModal(context) {
var videoAttachments = widget.mediaAttachments
.where((element) => element.type == 'video')
.toList();
showModalBottomSheet(
context: context,
barrierColor: StreamChatTheme.of(context).colorTheme.overlay,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16.0),
),
@@ -207,9 +206,7 @@ class _ImageFooterState extends State<ImageFooter> {
icon: StreamSvgIcon.close(
color: StreamChatTheme.of(context).colorTheme.black,
),
onPressed: () {
Navigator.pop(context);
},
onPressed: () => Navigator.maybePop(context),
),
),
],
+1
View File
@@ -106,6 +106,7 @@ class ImageHeader extends StatelessWidget implements PreferredSizeWidget {
showDialog(
context: context,
barrierColor: StreamChatTheme.of(context).colorTheme.overlay,
builder: (context) {
return StreamChannel(
channel: channel,
+4 -4
View File
@@ -73,17 +73,17 @@ class MessageActionsModal extends StatelessWidget {
return GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () => Navigator.pop(context),
onTap: () => Navigator.maybePop(context),
child: Stack(
children: [
Positioned.fill(
child: BackdropFilter(
filter: ImageFilter.blur(
sigmaX: 10.8731,
sigmaY: 10.8731,
sigmaX: 10,
sigmaY: 10,
),
child: Container(
color: Colors.black.withOpacity(.2),
color: StreamChatTheme.of(context).colorTheme.overlay,
),
),
),
+14 -19
View File
@@ -122,6 +122,7 @@ class MessageListView extends StatefulWidget {
this.itemPositionListener,
this.onMessageSwiped,
this.highlightInitialMessage = false,
this.messageHighlightColor,
this.onShowMessage,
}) : super(key: key);
@@ -175,6 +176,9 @@ class MessageListView extends StatefulWidget {
/// Also See [StreamChannel]
final bool highlightInitialMessage;
/// Color used while highlighting initial message
final Color messageHighlightColor;
final ShowMessageCallback onShowMessage;
@override
@@ -346,18 +350,9 @@ class _MessageListViewState extends State<MessageListView> {
buildParentMessage(widget.parentMessage),
Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
StreamChatTheme.of(context)
.colorTheme
.whiteSmoke,
StreamChatTheme.of(context)
.colorTheme
.whiteSnow,
],
),
gradient: StreamChatTheme.of(context)
.colorTheme
.bgGradient,
),
child: Padding(
padding: const EdgeInsets.all(8.0),
@@ -845,17 +840,17 @@ class _MessageListViewState extends State<MessageListView> {
if (!initialMessageHighlightComplete &&
widget.highlightInitialMessage &&
_isInitialMessage(message.id)) {
final accentColor = Theme.of(context).accentColor;
final colorTheme = StreamChatTheme.of(context).colorTheme;
final highlightColor =
widget.messageHighlightColor ?? colorTheme.highlight;
child = TweenAnimationBuilder<Color>(
tween: ColorTween(
begin: accentColor.withOpacity(0.7),
end: Colors.transparent,
begin: highlightColor,
end: colorTheme.white.withOpacity(0),
),
duration: const Duration(seconds: 2),
duration: const Duration(seconds: 3),
child: child,
onEnd: () {
initialMessageHighlightComplete = true;
},
onEnd: () => initialMessageHighlightComplete = true,
builder: (_, color, child) {
return Container(
color: color,
+15 -7
View File
@@ -40,27 +40,35 @@ class MessageReactionsModal extends StatelessWidget {
final user = StreamChat.of(context).user;
final roughMaxSize = 2 * size.width / 3;
var messageTextLength = message.text.length;
if (message.quotedMessage != null) {
var quotedMessageLength = message.quotedMessage.text.length + 40;
if (message.quotedMessage.attachments?.isNotEmpty == true) {
quotedMessageLength += 40;
}
if (quotedMessageLength > messageTextLength) {
messageTextLength = quotedMessageLength;
}
}
final roughSentenceSize =
message.text.length * messageTheme.messageText.fontSize * 1.2;
messageTextLength * messageTheme.messageText.fontSize * 1.2;
final divFactor = message.attachments?.isNotEmpty == true
? 1
: (roughSentenceSize == 0 ? 1 : (roughSentenceSize / roughMaxSize));
return GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () {
Navigator.pop(context);
},
onTap: () => Navigator.maybePop(context),
child: Stack(
children: [
Positioned.fill(
child: BackdropFilter(
filter: ImageFilter.blur(
sigmaX: 10.8731,
sigmaY: 10.8731,
sigmaX: 10,
sigmaY: 10,
),
child: Container(
color: Colors.black.withOpacity(0.2),
color: StreamChatTheme.of(context).colorTheme.overlay,
),
),
),
+2 -19
View File
@@ -313,21 +313,7 @@ class _MessageSearchListViewState extends State<MessageSearchListView> {
Container(
width: double.maxFinite,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: [
StreamChatTheme.of(context)
.colorTheme
.black
.withOpacity(0.02),
StreamChatTheme.of(context)
.colorTheme
.white
.withOpacity(0.05),
],
stops: [0, 1],
),
gradient: StreamChatTheme.of(context).colorTheme.bgGradient,
),
child: Padding(
padding: const EdgeInsets.symmetric(
@@ -337,10 +323,7 @@ class _MessageSearchListViewState extends State<MessageSearchListView> {
child: Text(
'${items.length} results',
style: TextStyle(
color: StreamChatTheme.of(context)
.colorTheme
.black
.withOpacity(0.5),
color: StreamChatTheme.of(context).colorTheme.grey,
),
),
),
+5 -1
View File
@@ -374,7 +374,9 @@ class _MessageWidgetState extends State<MessageWidget> {
elevation: 0.0,
shape: widget.shape ??
RoundedRectangleBorder(
side: isOnlyEmoji
side: isOnlyEmoji &&
!(showThreadReplyIndicator ||
showInChannel)
? BorderSide.none
: widget.borderSide ??
BorderSide(
@@ -676,6 +678,7 @@ class _MessageWidgetState extends State<MessageWidget> {
final channel = StreamChannel.of(context).channel;
showDialog(
context: context,
barrierColor: StreamChatTheme.of(context).colorTheme.overlay,
builder: (context) {
return StreamChannel(
channel: channel,
@@ -716,6 +719,7 @@ class _MessageWidgetState extends State<MessageWidget> {
final channel = StreamChannel.of(context).channel;
showDialog(
context: context,
barrierColor: StreamChatTheme.of(context).colorTheme.overlay,
builder: (context) {
return StreamChannel(
channel: channel,
+2 -70
View File
@@ -78,6 +78,7 @@ class StreamChatState extends State<StreamChat> with WidgetsBindingObserver {
primaryIconTheme: streamTheme.primaryIconTheme,
accentColor: streamTheme.colorTheme.accentBlue,
scaffoldBackgroundColor: streamTheme.colorTheme.white,
buttonTheme: streamTheme.buttonTheme,
),
child: widget.child,
);
@@ -91,76 +92,7 @@ class StreamChatState extends State<StreamChat> with WidgetsBindingObserver {
StreamChatThemeData themeData,
) {
final defaultTheme = StreamChatThemeData.getDefaultTheme(Theme.of(context));
final theme = defaultTheme.copyWith(
defaultChannelImage: themeData?.defaultChannelImage,
primaryIconTheme: themeData?.primaryIconTheme,
defaultUserImage: themeData?.defaultUserImage,
channelTheme: defaultTheme.channelTheme.copyWith(
channelHeaderTheme:
defaultTheme.channelTheme.channelHeaderTheme.copyWith(
color: themeData?.channelTheme?.channelHeaderTheme?.color,
lastMessageAt:
themeData?.channelTheme?.channelHeaderTheme?.lastMessageAt,
title: themeData?.channelTheme?.channelHeaderTheme?.title,
avatarTheme: defaultTheme.channelPreviewTheme.avatarTheme.copyWith(
constraints: themeData
?.channelTheme?.channelHeaderTheme?.avatarTheme?.constraints,
borderRadius: themeData
?.channelTheme?.channelHeaderTheme?.avatarTheme?.borderRadius,
),
),
inputBackground: themeData?.channelTheme?.inputBackground,
messageInputButtonIconTheme:
themeData?.channelTheme?.messageInputButtonIconTheme,
messageInputButtonTheme:
themeData?.channelTheme?.messageInputButtonTheme,
),
ownMessageTheme: defaultTheme.ownMessageTheme.copyWith(
replies: themeData?.ownMessageTheme?.replies,
createdAt: themeData?.ownMessageTheme?.createdAt,
messageText: themeData?.ownMessageTheme?.messageText,
messageBackgroundColor:
themeData?.ownMessageTheme?.messageBackgroundColor,
messageAuthor: themeData?.ownMessageTheme?.messageAuthor,
messageLinks: themeData?.ownMessageTheme?.messageLinks,
avatarTheme: defaultTheme.ownMessageTheme.avatarTheme.copyWith(
constraints: themeData?.ownMessageTheme?.avatarTheme?.constraints,
borderRadius: themeData?.ownMessageTheme?.avatarTheme?.borderRadius,
),
reactionsBorderColor: themeData?.ownMessageTheme?.reactionsBorderColor,
reactionsBackgroundColor:
themeData?.ownMessageTheme?.reactionsBackgroundColor,
),
otherMessageTheme: defaultTheme.otherMessageTheme.copyWith(
replies: themeData?.otherMessageTheme?.replies,
createdAt: themeData?.otherMessageTheme?.createdAt,
messageText: themeData?.otherMessageTheme?.messageText,
messageBackgroundColor:
themeData?.otherMessageTheme?.messageBackgroundColor,
messageAuthor: themeData?.otherMessageTheme?.messageAuthor,
messageLinks: themeData?.otherMessageTheme?.messageLinks,
avatarTheme: defaultTheme.otherMessageTheme.avatarTheme.copyWith(
constraints: themeData?.otherMessageTheme?.avatarTheme?.constraints,
borderRadius: themeData?.otherMessageTheme?.avatarTheme?.borderRadius,
),
reactionsBorderColor:
themeData?.otherMessageTheme?.reactionsBorderColor,
reactionsBackgroundColor:
themeData?.otherMessageTheme?.reactionsBackgroundColor,
),
channelPreviewTheme: defaultTheme.channelPreviewTheme.copyWith(
avatarTheme: defaultTheme.channelPreviewTheme.avatarTheme.copyWith(
constraints: themeData?.channelPreviewTheme?.avatarTheme?.constraints,
borderRadius:
themeData?.channelPreviewTheme?.avatarTheme?.borderRadius,
),
title: themeData?.channelPreviewTheme?.title,
lastMessageAt: themeData?.channelPreviewTheme?.lastMessageAt,
subtitle: themeData?.channelPreviewTheme?.subtitle,
unreadCounterColor: themeData?.channelPreviewTheme?.unreadCounterColor,
),
);
return theme;
return defaultTheme.merge(themeData) ?? themeData;
}
/// The current user
+190 -104
View File
@@ -45,6 +45,9 @@ class StreamChatThemeData {
/// The text themes used in the widgets
final TextTheme textTheme;
/// The button themes used in the widgets
final ButtonThemeData buttonTheme;
/// The text themes used in the widgets
final ColorTheme colorTheme;
@@ -73,8 +76,9 @@ class StreamChatThemeData {
final List<ReactionIcon> reactionIcons;
/// Create a theme from scratch
StreamChatThemeData({
const StreamChatThemeData({
this.textTheme,
this.buttonTheme,
this.colorTheme,
this.channelPreviewTheme,
this.channelTheme,
@@ -89,32 +93,24 @@ class StreamChatThemeData {
/// Create a theme from a Material [Theme]
factory StreamChatThemeData.fromTheme(ThemeData theme) {
final defaultTheme = getDefaultTheme(theme);
return defaultTheme.copyWith(
final customizedTheme = StreamChatThemeData(
primaryIconTheme: theme.primaryIconTheme,
channelTheme: defaultTheme.channelTheme,
ownMessageTheme: defaultTheme.ownMessageTheme.copyWith(
replies: defaultTheme.ownMessageTheme.replies.copyWith(
color: theme.accentColor,
),
messageLinks: TextStyle(
color: theme.accentColor,
),
ownMessageTheme: MessageTheme(
replies: TextStyle(color: theme.accentColor),
messageLinks: TextStyle(color: theme.accentColor),
),
otherMessageTheme: defaultTheme.otherMessageTheme.copyWith(
replies: defaultTheme.otherMessageTheme.replies.copyWith(
color: theme.accentColor,
),
messageLinks: TextStyle(
color: theme.accentColor,
),
otherMessageTheme: MessageTheme(
replies: TextStyle(color: theme.accentColor),
messageLinks: TextStyle(color: theme.accentColor),
),
);
return defaultTheme.merge(customizedTheme) ?? customizedTheme;
}
/// Creates a copy of [StreamChatThemeData] with specified attributes overridden.
StreamChatThemeData copyWith({
TextTheme textTheme,
ButtonThemeData buttonTheme,
ColorTheme colorTheme,
ChannelPreviewTheme channelPreviewTheme,
ChannelTheme channelTheme,
@@ -126,88 +122,41 @@ class StreamChatThemeData {
List<ReactionIcon> reactionIcons,
}) =>
StreamChatThemeData(
textTheme: this.textTheme?.copyWith(
title: textTheme?.title,
body: textTheme?.body,
bodyBold: textTheme?.bodyBold,
captionBold: textTheme?.captionBold,
footnote: textTheme?.footnote,
footnoteBold: textTheme?.footnoteBold,
headline: textTheme?.headline,
headlineBold: textTheme?.headlineBold,
),
colorTheme: this.colorTheme?.copyWith(
black: colorTheme?.black,
grey: colorTheme?.grey,
greyGainsboro: colorTheme?.greyGainsboro,
greyWhisper: colorTheme?.greyWhisper,
whiteSmoke: colorTheme?.whiteSmoke,
whiteSnow: colorTheme?.whiteSnow,
white: colorTheme?.white,
blueAlice: colorTheme?.blueAlice,
),
textTheme: textTheme ?? this.textTheme,
buttonTheme: buttonTheme ?? this.buttonTheme,
colorTheme: colorTheme ?? this.colorTheme,
primaryIconTheme: primaryIconTheme ?? this.primaryIconTheme,
defaultChannelImage: defaultChannelImage ?? this.defaultChannelImage,
defaultUserImage: defaultUserImage ?? this.defaultUserImage,
channelPreviewTheme: this.channelPreviewTheme?.copyWith(
title: channelPreviewTheme.title,
subtitle: channelPreviewTheme.subtitle,
lastMessageAt: channelPreviewTheme.lastMessageAt,
avatarTheme: channelPreviewTheme.avatarTheme,
),
channelTheme: channelTheme?.copyWith(
channelHeaderTheme: channelTheme.channelHeaderTheme ??
this.channelTheme.channelHeaderTheme,
messageInputButtonIconTheme:
channelTheme.messageInputButtonIconTheme ??
this.channelTheme.messageInputButtonIconTheme,
messageInputButtonTheme: channelTheme.messageInputButtonTheme ??
this.channelTheme.messageInputButtonTheme,
inputBackground: channelTheme.inputBackground ??
this.channelTheme.inputBackground,
) ??
this.channelTheme,
ownMessageTheme: ownMessageTheme?.copyWith(
messageText: ownMessageTheme?.messageText ??
this.ownMessageTheme.messageText,
messageAuthor: ownMessageTheme?.messageAuthor ??
this.ownMessageTheme.messageAuthor,
messageLinks: ownMessageTheme?.messageLinks ??
this.ownMessageTheme.messageLinks,
createdAt:
ownMessageTheme?.createdAt ?? this.ownMessageTheme.createdAt,
replies: ownMessageTheme?.replies ?? this.ownMessageTheme.replies,
messageBackgroundColor: ownMessageTheme?.messageBackgroundColor ??
this.ownMessageTheme.messageBackgroundColor,
avatarTheme: ownMessageTheme?.avatarTheme ??
this.ownMessageTheme.avatarTheme,
messageBorderColor: ownMessageTheme?.messageBorderColor ??
this.ownMessageTheme.messageBorderColor,
) ??
this.ownMessageTheme,
otherMessageTheme: otherMessageTheme?.copyWith(
messageText: otherMessageTheme?.messageText ??
this.otherMessageTheme.messageText,
messageAuthor: otherMessageTheme?.messageAuthor ??
this.otherMessageTheme.messageAuthor,
messageLinks: otherMessageTheme?.messageLinks ??
this.otherMessageTheme.messageLinks,
createdAt: otherMessageTheme?.createdAt ??
this.otherMessageTheme.createdAt,
replies:
otherMessageTheme?.replies ?? this.otherMessageTheme.replies,
messageBackgroundColor:
otherMessageTheme?.messageBackgroundColor ??
this.otherMessageTheme.messageBackgroundColor,
messageBorderColor: otherMessageTheme?.messageBorderColor ??
this.otherMessageTheme.messageBorderColor,
avatarTheme: otherMessageTheme?.avatarTheme ??
this.otherMessageTheme.avatarTheme,
) ??
this.otherMessageTheme,
channelPreviewTheme: channelPreviewTheme ?? this.channelPreviewTheme,
channelTheme: channelTheme ?? this.channelTheme,
ownMessageTheme: ownMessageTheme ?? this.ownMessageTheme,
otherMessageTheme: otherMessageTheme ?? this.otherMessageTheme,
reactionIcons: reactionIcons ?? this.reactionIcons,
);
StreamChatThemeData merge(StreamChatThemeData other) {
if (other == null) return this;
return copyWith(
textTheme: textTheme?.merge(other.textTheme) ?? other.textTheme,
buttonTheme: other.buttonTheme,
colorTheme: colorTheme?.merge(other.colorTheme) ?? other.colorTheme,
primaryIconTheme: other.primaryIconTheme,
defaultChannelImage: other.defaultChannelImage,
defaultUserImage: other.defaultUserImage,
channelPreviewTheme:
channelPreviewTheme?.merge(other.channelPreviewTheme) ??
other.channelPreviewTheme,
channelTheme:
channelTheme?.merge(other.channelTheme) ?? other.channelTheme,
ownMessageTheme: ownMessageTheme?.merge(other.ownMessageTheme) ??
other.ownMessageTheme,
otherMessageTheme: otherMessageTheme?.merge(other.otherMessageTheme) ??
other.otherMessageTheme,
reactionIcons: other.reactionIcons,
);
}
/// Get the default Stream Chat theme
static StreamChatThemeData getDefaultTheme(ThemeData theme) {
final accentColor = Color(0xff006cff);
@@ -217,6 +166,17 @@ class StreamChatThemeData {
return StreamChatThemeData(
textTheme: textTheme,
colorTheme: colorTheme,
buttonTheme: ButtonThemeData(
height: 48.0,
buttonColor: isDark ? Color(0xffffffff) : Color(0xff006aff),
textTheme: ButtonTextTheme.accent,
colorScheme: theme.colorScheme.copyWith(
secondary: isDark ? Color(0xff005eff) : Color(0xffffffff),
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(26),
),
),
primaryIconTheme: IconThemeData(color: colorTheme.black.withOpacity(.5)),
defaultChannelImage: (context, channel) => SizedBox(),
defaultUserImage: (context, user) => Center(
@@ -483,6 +443,22 @@ class TextTheme {
captionBold: captionBold ?? this.captionBold,
);
}
TextTheme merge(TextTheme other) {
if (other == null) return this;
return copyWith(
body: body?.merge(other.body) ?? other.body,
title: title?.merge(other.title) ?? other.title,
headlineBold:
headlineBold?.merge(other.headlineBold) ?? other.headlineBold,
headline: headline?.merge(other.headline) ?? other.headline,
bodyBold: bodyBold?.merge(other.bodyBold) ?? other.bodyBold,
footnoteBold:
footnoteBold?.merge(other.footnoteBold) ?? other.footnoteBold,
footnote: footnote?.merge(other.footnote) ?? other.footnote,
captionBold: captionBold?.merge(other.captionBold) ?? other.captionBold,
);
}
}
enum ColorThemeType {
@@ -506,6 +482,10 @@ class ColorTheme {
final Effect borderBottom;
final Effect shadowIconButton;
final Effect modalShadow;
final Color highlight;
final Color overlay;
final Color overlayDark;
final Gradient bgGradient;
ColorTheme.light({
this.black = const Color(0xff000000),
@@ -517,8 +497,17 @@ class ColorTheme {
this.white = const Color(0xffffffff),
this.blueAlice = const Color(0xffe9f2ff),
this.accentBlue = const Color(0xff005FFF),
this.accentRed = const Color(0xffFF3742),
this.accentRed = const Color(0xffFF3842),
this.accentGreen = const Color(0xff20E070),
this.highlight = const Color(0xfffbf4dd),
this.overlay = const Color.fromRGBO(0, 0, 0, 0.2),
this.overlayDark = const Color.fromRGBO(0, 0, 0, 0.6),
this.bgGradient = const LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [const Color(0xfff7f7f7), const Color(0xfffcfcfc)],
stops: [0, 1],
),
this.borderTop = const Effect(
sigmaX: 0, sigmaY: -1, color: Color(0xff141924), blur: 0.0),
this.borderBottom = const Effect(
@@ -549,6 +538,15 @@ class ColorTheme {
sigmaX: 0, sigmaY: 2, color: Color(0xff000000), alpha: 0.5, blur: 4.0),
this.modalShadow = const Effect(
sigmaX: 0, sigmaY: 0, color: Color(0xff000000), alpha: 1, blur: 8.0),
this.highlight = const Color(0xff302d22),
this.overlay = const Color.fromRGBO(0, 0, 0, 0.4),
this.overlayDark = const Color.fromRGBO(255, 255, 255, 0.6),
this.bgGradient = const LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [const Color(0xff101214), const Color(0xff070a0d)],
stops: [0, 1],
),
});
ColorTheme copyWith({
@@ -568,6 +566,10 @@ class ColorTheme {
Effect borderBottom,
Effect shadowIconButton,
Effect modalShadow,
Color highlight,
Color overlay,
Color overlayDark,
Gradient bgGradient,
}) {
return type == ColorThemeType.light
? ColorTheme.light(
@@ -586,6 +588,10 @@ class ColorTheme {
borderBottom: borderBottom ?? this.borderBottom,
shadowIconButton: shadowIconButton ?? this.shadowIconButton,
modalShadow: modalShadow ?? this.modalShadow,
highlight: highlight ?? this.highlight,
overlay: overlay ?? this.overlay,
overlayDark: overlayDark ?? this.overlayDark,
bgGradient: bgGradient ?? this.bgGradient,
)
: ColorTheme.dark(
black: black ?? this.black,
@@ -603,8 +609,33 @@ class ColorTheme {
borderBottom: borderBottom ?? this.borderBottom,
shadowIconButton: shadowIconButton ?? this.shadowIconButton,
modalShadow: modalShadow ?? this.modalShadow,
highlight: highlight ?? this.highlight,
overlay: overlay ?? this.overlay,
overlayDark: overlayDark ?? this.overlayDark,
bgGradient: bgGradient ?? this.bgGradient,
);
}
ColorTheme merge(ColorTheme other) {
if (other == null) return this;
return copyWith(
black: other.black,
grey: other.grey,
greyGainsboro: other.greyGainsboro,
greyWhisper: other.greyWhisper,
whiteSmoke: other.whiteSmoke,
whiteSnow: other.whiteSnow,
white: other.white,
blueAlice: other.blueAlice,
accentBlue: other.accentBlue,
accentRed: other.accentRed,
accentGreen: other.accentGreen,
highlight: other.highlight,
overlay: other.overlay,
overlayDark: other.overlayDark,
bgGradient: other.bgGradient,
);
}
}
/// Channel theme data
@@ -636,20 +667,26 @@ class ChannelTheme {
Color inputBackground,
}) =>
ChannelTheme(
channelHeaderTheme: channelHeaderTheme?.copyWith(
title: channelHeaderTheme?.title ?? this.channelHeaderTheme.title,
lastMessageAt: channelHeaderTheme?.lastMessageAt ??
this.channelHeaderTheme.lastMessageAt,
avatarTheme: channelHeaderTheme?.avatarTheme ??
this.channelHeaderTheme.avatarTheme,
color: channelHeaderTheme?.color ?? this.channelHeaderTheme.color,
) ??
this.channelHeaderTheme,
channelHeaderTheme: channelHeaderTheme ?? this.channelHeaderTheme,
messageInputButtonIconTheme:
messageInputButtonIconTheme ?? this.messageInputButtonIconTheme,
messageInputButtonTheme:
messageInputButtonTheme ?? this.messageInputButtonTheme,
inputBackground: inputBackground ?? this.inputBackground,
);
ChannelTheme merge(ChannelTheme other) {
if (other == null) return this;
return copyWith(
channelHeaderTheme: channelHeaderTheme?.merge(other.channelHeaderTheme) ??
other.channelHeaderTheme,
messageInputButtonIconTheme: messageInputButtonIconTheme
?.merge(other.messageInputButtonIconTheme) ??
other.messageInputButtonIconTheme,
messageInputButtonTheme: other.messageInputButtonTheme,
inputBackground: other.inputBackground,
);
}
}
class AvatarTheme {
@@ -669,6 +706,14 @@ class AvatarTheme {
constraints: constraints ?? this.constraints,
borderRadius: borderRadius ?? this.borderRadius,
);
AvatarTheme merge(AvatarTheme other) {
if (other == null) return this;
return copyWith(
constraints: other.constraints,
borderRadius: other.borderRadius,
);
}
}
class MessageTheme {
@@ -722,6 +767,24 @@ class MessageTheme {
reactionsBackgroundColor ?? this.reactionsBackgroundColor,
reactionsBorderColor: reactionsBorderColor ?? this.reactionsBorderColor,
);
MessageTheme merge(MessageTheme other) {
if (other == null) return this;
return copyWith(
messageText: messageText?.merge(other.messageText) ?? other.messageText,
messageAuthor:
messageAuthor?.merge(other.messageAuthor) ?? other.messageAuthor,
messageLinks:
messageLinks?.merge(other.messageLinks) ?? other.messageLinks,
createdAt: createdAt?.merge(other.createdAt) ?? other.createdAt,
replies: replies?.merge(other.replies) ?? other.replies,
messageBackgroundColor: other.messageBackgroundColor,
messageBorderColor: other.messageBorderColor,
avatarTheme: avatarTheme?.merge(other.avatarTheme) ?? other.avatarTheme,
reactionsBackgroundColor: other.reactionsBackgroundColor,
reactionsBorderColor: other.reactionsBorderColor,
);
}
}
class ChannelPreviewTheme {
@@ -757,6 +820,18 @@ class ChannelPreviewTheme {
unreadCounterColor: unreadCounterColor ?? this.unreadCounterColor,
indicatorIconSize: indicatorIconSize ?? this.indicatorIconSize,
);
ChannelPreviewTheme merge(ChannelPreviewTheme other) {
if (other == null) return this;
return copyWith(
title: title?.merge(other.title) ?? other.title,
subtitle: subtitle?.merge(other.subtitle) ?? other.subtitle,
lastMessageAt:
lastMessageAt?.merge(other.lastMessageAt) ?? other.lastMessageAt,
avatarTheme: avatarTheme?.merge(other.avatarTheme) ?? other.avatarTheme,
unreadCounterColor: other.unreadCounterColor,
);
}
}
class ChannelHeaderTheme {
@@ -784,6 +859,17 @@ class ChannelHeaderTheme {
avatarTheme: avatarTheme ?? this.avatarTheme,
color: color ?? this.color,
);
ChannelHeaderTheme merge(ChannelHeaderTheme other) {
if (other == null) return this;
return copyWith(
title: title?.merge(other.title) ?? other.title,
lastMessageAt:
lastMessageAt?.merge(other.lastMessageAt) ?? other.lastMessageAt,
avatarTheme: avatarTheme?.merge(other.avatarTheme) ?? other.avatarTheme,
color: other.color,
);
}
}
class Effect {
+12
View File
@@ -206,6 +206,18 @@ class StreamSvgIcon extends StatelessWidget {
);
}
factory StreamSvgIcon.checkSend({
double size,
Color color,
}) {
return StreamSvgIcon(
assetName: 'Icon_check_send.svg',
color: color,
width: size,
height: size,
);
}
factory StreamSvgIcon.penWrite({
double size,
Color color,
+2 -8
View File
@@ -73,14 +73,8 @@ class UserItem extends StatelessWidget {
),
),
trailing: selected
? CircleAvatar(
backgroundColor:
StreamChatTheme.of(context).colorTheme.accentBlue,
child: StreamSvgIcon.check(
size: 20,
color: StreamChatTheme.of(context).colorTheme.white,
),
radius: 10,
? StreamSvgIcon.checkSend(
color: StreamChatTheme.of(context).colorTheme.accentBlue,
)
: null,
title: Text(
+5 -9
View File
@@ -363,12 +363,10 @@ class _UserListViewState extends State<UserListView>
child: Text(
header,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 14.5,
color: StreamChatTheme.of(context)
.colorTheme
.black
.withOpacity(0.3)),
fontWeight: FontWeight.bold,
fontSize: 14.5,
color: StreamChatTheme.of(context).colorTheme.grey,
),
),
),
);
@@ -478,9 +476,7 @@ class _UserListViewState extends State<UserListView>
Widget _separatorBuilder(context, i) {
return Container(
height: 1,
color: Theme.of(context).brightness == Brightness.dark
? StreamChatTheme.of(context).colorTheme.white.withOpacity(0.1)
: StreamChatTheme.of(context).colorTheme.black.withOpacity(0.1),
color: StreamChatTheme.of(context).colorTheme.greyWhisper,
);
}