From 7dc7261a06a98a285e2225553c6cdb6903583f4f Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Fri, 28 Feb 2020 11:43:48 +0100 Subject: [PATCH] add initial example --- example/lib/custom_theme.dart | 129 +++++++++++++++++++++++++++++++++ lib/src/message_widget.dart | 43 +++++------ lib/src/stream_chat.dart | 40 ++++++---- lib/src/stream_chat_theme.dart | 117 ++++++++++++++++++++---------- lib/src/user_avatar.dart | 8 +- 5 files changed, 260 insertions(+), 77 deletions(-) create mode 100644 example/lib/custom_theme.dart diff --git a/example/lib/custom_theme.dart b/example/lib/custom_theme.dart new file mode 100644 index 00000000..cc65d81f --- /dev/null +++ b/example/lib/custom_theme.dart @@ -0,0 +1,129 @@ +import 'package:flutter/material.dart'; +import 'package:stream_chat_flutter/stream_chat_flutter.dart'; + +void main() async { + final client = Client('qk4nn7rpcn75', logLevel: Level.INFO); + + await client.setUser( + User(id: 'wild-breeze-7'), + 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoid2lsZC1icmVlemUtNyJ9.VM2EX1EXOfgqa-bTH_3JzeY0T99ngWzWahSauP3dBMo', + ); + + runApp(MyApp(client)); +} + +class MyApp extends StatelessWidget { + final Client client; + + MyApp(this.client); + + @override + Widget build(BuildContext context) { + final theme = ThemeData( + primarySwatch: Colors.green, + ); + + final streamTheme = StreamChatThemeData.fromTheme(theme); + + return MaterialApp( + theme: theme, + home: Container( + child: StreamChat( + streamChatThemeData: streamTheme.copyWith( + channelPreviewTheme: ChannelPreviewTheme( + avatarTheme: AvatarTheme( + borderRadius: BorderRadius.circular(16), + ), + ), + ownMessageTheme: MessageTheme( + replies: streamTheme.ownMessageTheme.replies + .copyWith(fontStyle: FontStyle.italic), + avatarTheme: AvatarTheme( + borderRadius: BorderRadius.circular(12), + ), + ), + otherMessageTheme: MessageTheme( + messageBackgroundColor: Colors.red, + ), + ), + client: client, + child: ChannelListPage(), + ), + ), + ); + } +} + +class ChannelListPage extends StatelessWidget { + @override + Widget build(BuildContext context) { + return Scaffold( + body: ChannelListView( + filter: { + 'members': { + '\$in': [StreamChat.of(context).user.id], + } + }, + sort: [SortOption('last_message_at')], + pagination: PaginationParams( + limit: 20, + ), + channelWidget: ChannelPage(), + ), + ); + } +} + +class ChannelPage extends StatelessWidget { + const ChannelPage({ + Key key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: ChannelHeader(), + body: Column( + children: [ + Expanded( + child: MessageListView( + threadBuilder: (_, parentMessage) { + return ThreadPage( + parent: parentMessage, + ); + }, + ), + ), + MessageInput(), + ], + ), + ); + } +} + +class ThreadPage extends StatelessWidget { + final Message parent; + + ThreadPage({ + Key key, + this.parent, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Column( + children: [ + Expanded( + child: MessageListView( + parentMessage: parent, + ), + ), + MessageInput( + parentMessage: parent, + ), + ], + ), + ); + } +} diff --git a/lib/src/message_widget.dart b/lib/src/message_widget.dart index 9c3aa322..5d499f6a 100644 --- a/lib/src/message_widget.dart +++ b/lib/src/message_widget.dart @@ -41,6 +41,8 @@ class _MessageWidgetState extends State final Map _videoControllers = {}; final Map _chuwieControllers = {}; + MessageTheme messageTheme; + @override Widget build(BuildContext context) { super.build(context); @@ -56,6 +58,10 @@ class _MessageWidgetState extends State final alignment = isMyMessage ? Alignment.centerRight : Alignment.centerLeft; + messageTheme = isMyMessage + ? StreamChatTheme.of(context).ownMessageTheme + : StreamChatTheme.of(context).otherMessageTheme; + Widget child; if (widget.message.type == 'deleted') { @@ -121,9 +127,10 @@ class _MessageWidgetState extends State ), child: Text( 'This message was deleted...', - style: StreamChatTheme.of(context).messageTheme.messageText.copyWith( - fontStyle: FontStyle.italic, - ), + style: messageTheme.messageText.copyWith( + fontStyle: FontStyle.italic, + color: Colors.black, + ), ), ), ); @@ -133,7 +140,7 @@ class _MessageWidgetState extends State var row = [ Text( 'Replies: ${widget.message.replyCount}', - style: StreamChatTheme.of(context).messageTheme.replies, + style: messageTheme.replies, ), Transform( transform: Matrix4.rotationY(isMyMessage ? 0 : pi), @@ -220,13 +227,11 @@ class _MessageWidgetState extends State Text( attachment.title, overflow: TextOverflow.ellipsis, - style: StreamChatTheme.of(context) - .messageTheme - .messageText - .copyWith( - color: Colors.blue, - fontWeight: FontWeight.bold, - ), + style: + messageTheme.messageText.copyWith( + color: Colors.blue, + fontWeight: FontWeight.bold, + ), ), Text( Uri.parse(attachment.thumbUrl) @@ -238,9 +243,7 @@ class _MessageWidgetState extends State .reversed .join('.'), overflow: TextOverflow.ellipsis, - style: StreamChatTheme.of(context) - .messageTheme - .createdAt, + style: messageTheme.createdAt, ), ], ), @@ -321,9 +324,7 @@ class _MessageWidgetState extends State styleSheet: MarkdownStyleSheet.fromTheme(Theme.of(context)) .copyWith( - p: StreamChatTheme.of(context) - .messageTheme - .messageText, + p: messageTheme.messageText, ), ), ), @@ -602,7 +603,7 @@ class _MessageWidgetState extends State padding: const EdgeInsets.only(top: 5.0), child: Text( formatDate(widget.message.createdAt.toLocal(), [HH, ':', nn]), - style: StreamChatTheme.of(context).messageTheme.createdAt, + style: messageTheme.createdAt, ), ); } @@ -616,11 +617,7 @@ class _MessageWidgetState extends State topRight: Radius.circular((isMyMessage && isLastUser) ? 2 : 16), bottomRight: Radius.circular(isMyMessage ? 2 : 16), ), - color: isMyMessage - ? StreamChatTheme.of(context).messageTheme.ownMessageBackgroundColor - : StreamChatTheme.of(context) - .messageTheme - .otherMessageBackgroundColor, + color: messageTheme.messageBackgroundColor, ); } diff --git a/lib/src/stream_chat.dart b/lib/src/stream_chat.dart index 2ce338a5..c9b03f92 100644 --- a/lib/src/stream_chat.dart +++ b/lib/src/stream_chat.dart @@ -107,20 +107,32 @@ class StreamChatState extends State { messageInputButtonTheme: themeData?.channelTheme?.messageInputButtonTheme, ), - messageTheme: defaultTheme.messageTheme.copyWith( - replies: themeData?.messageTheme?.replies, - createdAt: themeData?.messageTheme?.createdAt, - messageText: themeData?.messageTheme?.messageText, - otherMessageBackgroundColor: - themeData?.messageTheme?.otherMessageBackgroundColor, - ownMessageBackgroundColor: - themeData?.messageTheme?.ownMessageBackgroundColor, - fontFamily: themeData?.messageTheme?.fontFamily, - messageAuthor: themeData?.messageTheme?.messageAuthor, - messageMention: themeData?.messageTheme?.messageMention, - avatarTheme: defaultTheme.messageTheme.avatarTheme.copyWith( - constraints: themeData?.messageTheme?.avatarTheme?.constraints, - borderRadius: themeData?.messageTheme?.avatarTheme?.borderRadius, + ownMessageTheme: defaultTheme.ownMessageTheme.copyWith( + replies: themeData?.ownMessageTheme?.replies, + createdAt: themeData?.ownMessageTheme?.createdAt, + messageText: themeData?.ownMessageTheme?.messageText, + messageBackgroundColor: + themeData?.ownMessageTheme?.messageBackgroundColor, + fontFamily: themeData?.ownMessageTheme?.fontFamily, + messageAuthor: themeData?.ownMessageTheme?.messageAuthor, + messageMention: themeData?.ownMessageTheme?.messageMention, + avatarTheme: defaultTheme.ownMessageTheme.avatarTheme.copyWith( + constraints: themeData?.ownMessageTheme?.avatarTheme?.constraints, + borderRadius: themeData?.ownMessageTheme?.avatarTheme?.borderRadius, + ), + ), + otherMessageTheme: defaultTheme.otherMessageTheme.copyWith( + replies: themeData?.otherMessageTheme?.replies, + createdAt: themeData?.otherMessageTheme?.createdAt, + messageText: themeData?.otherMessageTheme?.messageText, + messageBackgroundColor: + themeData?.otherMessageTheme?.messageBackgroundColor, + fontFamily: themeData?.otherMessageTheme?.fontFamily, + messageAuthor: themeData?.otherMessageTheme?.messageAuthor, + messageMention: themeData?.otherMessageTheme?.messageMention, + avatarTheme: defaultTheme.otherMessageTheme.avatarTheme.copyWith( + constraints: themeData?.otherMessageTheme?.avatarTheme?.constraints, + borderRadius: themeData?.otherMessageTheme?.avatarTheme?.borderRadius, ), ), accentColor: themeData?.accentColor, diff --git a/lib/src/stream_chat_theme.dart b/lib/src/stream_chat_theme.dart index c3db901f..bcd098c3 100644 --- a/lib/src/stream_chat_theme.dart +++ b/lib/src/stream_chat_theme.dart @@ -28,7 +28,8 @@ class StreamChatThemeData { final Color accentColor; final ChannelPreviewTheme channelPreviewTheme; final ChannelTheme channelTheme; - final MessageTheme messageTheme; + final MessageTheme ownMessageTheme; + final MessageTheme otherMessageTheme; StreamChatThemeData({ this.primaryColor, @@ -36,7 +37,8 @@ class StreamChatThemeData { this.accentColor, this.channelPreviewTheme, this.channelTheme, - this.messageTheme, + this.otherMessageTheme, + this.ownMessageTheme, }); factory StreamChatThemeData.fromTheme(ThemeData theme) { @@ -52,8 +54,13 @@ class StreamChatThemeData { theme.accentColor, ]), ), - messageTheme: MessageTheme( - replies: defaultTheme.messageTheme.replies.copyWith( + ownMessageTheme: MessageTheme( + replies: defaultTheme.ownMessageTheme.replies.copyWith( + color: theme.accentColor, + ), + ), + otherMessageTheme: MessageTheme( + replies: defaultTheme.ownMessageTheme.replies.copyWith( color: theme.accentColor, ), ), @@ -66,7 +73,8 @@ class StreamChatThemeData { Color accentColor, ChannelPreviewTheme channelPreviewTheme, ChannelTheme channelTheme, - MessageTheme messageTheme, + MessageTheme ownMessageTheme, + MessageTheme otherMessageTheme, }) => StreamChatThemeData( primaryColor: primaryColor ?? this.primaryColor, @@ -97,27 +105,44 @@ class StreamChatThemeData { this.channelTheme.inputBackground, ) ?? this.channelTheme, - messageTheme: messageTheme?.copyWith( - messageText: - messageTheme?.messageText ?? this.messageTheme.messageText, - messageAuthor: messageTheme?.messageAuthor ?? - this.messageTheme.messageAuthor, - messageMention: messageTheme?.messageMention ?? - this.messageTheme.messageMention, - createdAt: messageTheme?.createdAt ?? this.messageTheme.createdAt, - replies: messageTheme?.replies ?? this.messageTheme.replies, - fontFamily: - messageTheme?.fontFamily ?? this.messageTheme.fontFamily, - ownMessageBackgroundColor: - messageTheme?.ownMessageBackgroundColor ?? - this.messageTheme.ownMessageBackgroundColor, - otherMessageBackgroundColor: - messageTheme?.otherMessageBackgroundColor ?? - this.messageTheme.otherMessageBackgroundColor, - avatarTheme: - messageTheme?.avatarTheme ?? this.messageTheme.avatarTheme, + ownMessageTheme: ownMessageTheme?.copyWith( + messageText: ownMessageTheme?.messageText ?? + this.ownMessageTheme.messageText, + messageAuthor: ownMessageTheme?.messageAuthor ?? + this.ownMessageTheme.messageAuthor, + messageMention: ownMessageTheme?.messageMention ?? + this.ownMessageTheme.messageMention, + createdAt: + ownMessageTheme?.createdAt ?? this.ownMessageTheme.createdAt, + replies: ownMessageTheme?.replies ?? this.ownMessageTheme.replies, + fontFamily: ownMessageTheme?.fontFamily ?? + this.ownMessageTheme.fontFamily, + messageBackgroundColor: ownMessageTheme?.messageBackgroundColor ?? + this.ownMessageTheme.messageBackgroundColor, + avatarTheme: ownMessageTheme?.avatarTheme ?? + this.ownMessageTheme.avatarTheme, ) ?? - this.messageTheme, + this.ownMessageTheme, + otherMessageTheme: otherMessageTheme?.copyWith( + messageText: otherMessageTheme?.messageText ?? + this.otherMessageTheme.messageText, + messageAuthor: otherMessageTheme?.messageAuthor ?? + this.otherMessageTheme.messageAuthor, + messageMention: otherMessageTheme?.messageMention ?? + this.otherMessageTheme.messageMention, + createdAt: otherMessageTheme?.createdAt ?? + this.otherMessageTheme.createdAt, + replies: + otherMessageTheme?.replies ?? this.otherMessageTheme.replies, + fontFamily: otherMessageTheme?.fontFamily ?? + this.otherMessageTheme.fontFamily, + messageBackgroundColor: + otherMessageTheme?.messageBackgroundColor ?? + this.otherMessageTheme.messageBackgroundColor, + avatarTheme: otherMessageTheme?.avatarTheme ?? + this.otherMessageTheme.avatarTheme, + ) ?? + this.otherMessageTheme, ); static StreamChatThemeData getDefaultTheme(ThemeData theme) { @@ -174,7 +199,7 @@ class StreamChatThemeData { Color(0xFF0076FF), ]), ), - messageTheme: MessageTheme( + ownMessageTheme: MessageTheme( messageText: TextStyle( fontSize: 15, color: Colors.black, @@ -188,8 +213,30 @@ class StreamChatThemeData { fontWeight: FontWeight.bold, fontSize: 12, ), - ownMessageBackgroundColor: Color(0xffebebeb), - otherMessageBackgroundColor: Colors.white, + messageBackgroundColor: Color(0xffebebeb), + avatarTheme: AvatarTheme( + borderRadius: BorderRadius.circular(20), + constraints: BoxConstraints.tightFor( + height: 32, + width: 32, + ), + ), + ), + otherMessageTheme: MessageTheme( + messageText: TextStyle( + fontSize: 15, + color: Colors.black, + ), + createdAt: TextStyle( + color: Colors.black.withOpacity(.5), + fontSize: 11, + ), + replies: TextStyle( + color: accentColor, + fontWeight: FontWeight.bold, + fontSize: 12, + ), + messageBackgroundColor: Colors.white, avatarTheme: AvatarTheme( borderRadius: BorderRadius.circular(20), constraints: BoxConstraints.tightFor( @@ -269,8 +316,7 @@ class MessageTheme { final TextStyle createdAt; final TextStyle replies; final String fontFamily; - final Color ownMessageBackgroundColor; - final Color otherMessageBackgroundColor; + final Color messageBackgroundColor; final AvatarTheme avatarTheme; const MessageTheme({ @@ -279,8 +325,7 @@ class MessageTheme { this.messageAuthor, this.messageMention, this.fontFamily, - this.ownMessageBackgroundColor, - this.otherMessageBackgroundColor, + this.messageBackgroundColor, this.avatarTheme, this.createdAt, }); @@ -292,7 +337,7 @@ class MessageTheme { TextStyle createdAt, TextStyle replies, String fontFamily, - Color ownMessageBackgroundColor, + Color messageBackgroundColor, Color otherMessageBackgroundColor, AvatarTheme avatarTheme, }) => @@ -302,10 +347,8 @@ class MessageTheme { messageMention: messageMention ?? this.messageMention, createdAt: createdAt ?? this.createdAt, fontFamily: fontFamily ?? this.fontFamily, - ownMessageBackgroundColor: - ownMessageBackgroundColor ?? this.ownMessageBackgroundColor, - otherMessageBackgroundColor: - otherMessageBackgroundColor ?? this.otherMessageBackgroundColor, + messageBackgroundColor: + messageBackgroundColor ?? this.messageBackgroundColor, avatarTheme: avatarTheme ?? this.avatarTheme, replies: replies ?? this.replies, ); diff --git a/lib/src/user_avatar.dart b/lib/src/user_avatar.dart index e0650b62..4c78b254 100644 --- a/lib/src/user_avatar.dart +++ b/lib/src/user_avatar.dart @@ -19,10 +19,12 @@ class UserAvatar extends StatelessWidget { return Container( padding: const EdgeInsets.all(4), constraints: - StreamChatTheme.of(context).messageTheme.avatarTheme.constraints, + StreamChatTheme.of(context).ownMessageTheme.avatarTheme.constraints, decoration: BoxDecoration( - borderRadius: - StreamChatTheme.of(context).messageTheme.avatarTheme.borderRadius, + borderRadius: StreamChatTheme.of(context) + .ownMessageTheme + .avatarTheme + .borderRadius, color: StreamChatTheme.of(context).accentColor, ), child: user.extraData?.containsKey('image') ?? false