Merge pull request #193 from GetStream/qa-fixes

QA fixes
This commit is contained in:
Salvatore Giordano
2021-01-06 14:59:23 +01:00
committed by GitHub
21 changed files with 735 additions and 885 deletions
+22 -59
View File
@@ -60,15 +60,11 @@ class _AdvancedOptionsPageState extends State<AdvancedOptionsPage> {
body: Builder( body: Builder(
builder: (context) { builder: (context) {
return Padding( return Padding(
padding: const EdgeInsets.fromLTRB( padding: const EdgeInsets.fromLTRB(16, 16, 16, 0),
16,
16,
16,
0,
),
child: Form( child: Form(
key: _formKey, key: _formKey,
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [ children: [
TextFormField( TextFormField(
controller: _apiKeyController, controller: _apiKeyController,
@@ -93,16 +89,13 @@ class _AdvancedOptionsPageState extends State<AdvancedOptionsPage> {
color: StreamChatTheme.of(context).colorTheme.black, color: StreamChatTheme.of(context).colorTheme.black,
), ),
decoration: InputDecoration( decoration: InputDecoration(
errorStyle: TextStyle(fontSize: 0), errorStyle: TextStyle(height: 0, fontSize: 0),
labelStyle: TextStyle( labelStyle: TextStyle(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: _apiKeyError != null color: _apiKeyError != null
? StreamChatTheme.of(context).colorTheme.accentRed ? StreamChatTheme.of(context).colorTheme.accentRed
: StreamChatTheme.of(context) : StreamChatTheme.of(context).colorTheme.grey,
.colorTheme
.black
.withOpacity(.5),
), ),
border: UnderlineInputBorder( border: UnderlineInputBorder(
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
@@ -116,9 +109,8 @@ class _AdvancedOptionsPageState extends State<AdvancedOptionsPage> {
), ),
textInputAction: TextInputAction.next, textInputAction: TextInputAction.next,
), ),
Padding( SizedBox(height: 8),
padding: const EdgeInsets.only(top: 8.0), TextFormField(
child: TextFormField(
controller: _userIdController, controller: _userIdController,
onChanged: (_) { onChanged: (_) {
if (_userIdError != null) { if (_userIdError != null) {
@@ -142,16 +134,13 @@ class _AdvancedOptionsPageState extends State<AdvancedOptionsPage> {
), ),
textInputAction: TextInputAction.next, textInputAction: TextInputAction.next,
decoration: InputDecoration( decoration: InputDecoration(
errorStyle: TextStyle(fontSize: 0), errorStyle: TextStyle(height: 0, fontSize: 0),
labelStyle: TextStyle( labelStyle: TextStyle(
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
fontSize: 14, fontSize: 14,
color: _userIdError != null color: _userIdError != null
? StreamChatTheme.of(context).colorTheme.accentRed ? StreamChatTheme.of(context).colorTheme.accentRed
: StreamChatTheme.of(context) : StreamChatTheme.of(context).colorTheme.grey,
.colorTheme
.black
.withOpacity(.5),
), ),
border: UnderlineInputBorder( border: UnderlineInputBorder(
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
@@ -164,10 +153,8 @@ class _AdvancedOptionsPageState extends State<AdvancedOptionsPage> {
'User ID ${_userIdError != null ? ': $_userIdError' : ''}', 'User ID ${_userIdError != null ? ': $_userIdError' : ''}',
), ),
), ),
), SizedBox(height: 8),
Padding( TextFormField(
padding: const EdgeInsets.only(top: 8.0),
child: TextFormField(
onChanged: (_) { onChanged: (_) {
if (_userTokenError != null) { if (_userTokenError != null) {
setState(() { setState(() {
@@ -191,16 +178,13 @@ class _AdvancedOptionsPageState extends State<AdvancedOptionsPage> {
), ),
textInputAction: TextInputAction.next, textInputAction: TextInputAction.next,
decoration: InputDecoration( decoration: InputDecoration(
errorStyle: TextStyle(fontSize: 0), errorStyle: TextStyle(height: 0, fontSize: 0),
labelStyle: TextStyle( labelStyle: TextStyle(
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
fontSize: 14, fontSize: 14,
color: _userTokenError != null color: _userTokenError != null
? StreamChatTheme.of(context).colorTheme.accentRed ? StreamChatTheme.of(context).colorTheme.accentRed
: StreamChatTheme.of(context) : StreamChatTheme.of(context).colorTheme.grey,
.colorTheme
.black
.withOpacity(.5),
), ),
border: UnderlineInputBorder( border: UnderlineInputBorder(
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
@@ -213,20 +197,15 @@ class _AdvancedOptionsPageState extends State<AdvancedOptionsPage> {
'User Token ${_userTokenError != null ? ': $_userTokenError' : ''}', 'User Token ${_userTokenError != null ? ': $_userTokenError' : ''}',
), ),
), ),
), SizedBox(height: 8),
Padding( TextFormField(
padding: const EdgeInsets.only(top: 8.0),
child: TextFormField(
controller: _usernameController, controller: _usernameController,
textInputAction: TextInputAction.done, textInputAction: TextInputAction.done,
decoration: InputDecoration( decoration: InputDecoration(
labelStyle: TextStyle( labelStyle: TextStyle(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: StreamChatTheme.of(context) color: StreamChatTheme.of(context).colorTheme.grey,
.colorTheme
.black
.withOpacity(.5),
), ),
border: UnderlineInputBorder( border: UnderlineInputBorder(
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
@@ -238,25 +217,10 @@ class _AdvancedOptionsPageState extends State<AdvancedOptionsPage> {
labelText: 'Username (optional)', labelText: 'Username (optional)',
), ),
), ),
), Spacer(),
Expanded( RaisedButton(
child: Align( elevation: 0,
alignment: Alignment.bottomCenter, child: Text('Login', style: TextStyle(fontSize: 16)),
child: FlatButton(
color:
StreamChatTheme.of(context).colorTheme.accentBlue,
minWidth: double.infinity,
height: 48,
child: Text(
'Login',
style: TextStyle(
color: StreamChatTheme.of(context).colorTheme.white,
fontSize: 16,
),
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(26),
),
onPressed: () async { onPressed: () async {
if (loading) { if (loading) {
return; return;
@@ -271,6 +235,8 @@ class _AdvancedOptionsPageState extends State<AdvancedOptionsPage> {
showDialog( showDialog(
barrierDismissible: false, barrierDismissible: false,
context: context, context: context,
barrierColor:
StreamChatTheme.of(context).colorTheme.overlay,
builder: (context) => Center( builder: (context) => Center(
child: Container( child: Container(
decoration: BoxDecoration( decoration: BoxDecoration(
@@ -291,8 +257,7 @@ class _AdvancedOptionsPageState extends State<AdvancedOptionsPage> {
final client = Client( final client = Client(
apiKey, apiKey,
logLevel: Level.INFO, logLevel: Level.INFO,
showLocalNotification: showLocalNotification: (!kIsWeb && Platform.isAndroid)
(!kIsWeb && Platform.isAndroid)
? showLocalNotification ? showLocalNotification
: null, : null,
persistenceEnabled: true, persistenceEnabled: true,
@@ -366,8 +331,6 @@ class _AdvancedOptionsPageState extends State<AdvancedOptionsPage> {
} }
}, },
), ),
),
),
StreamVersion(), StreamVersion(),
], ],
), ),
+9 -6
View File
@@ -72,6 +72,7 @@ class ChooseUserPage extends StatelessWidget {
child: SvgPicture.asset( child: SvgPicture.asset(
'assets/logo.svg', 'assets/logo.svg',
height: 40, height: 40,
color: StreamChatTheme.of(context).colorTheme.accentBlue,
), ),
), ),
), ),
@@ -92,9 +93,8 @@ class ChooseUserPage extends StatelessWidget {
child: ListView.separated( child: ListView.separated(
separatorBuilder: (context, i) { separatorBuilder: (context, i) {
return Container( return Container(
width: double.infinity,
color: Colors.black12,
height: 1, height: 1,
color: StreamChatTheme.of(context).colorTheme.greyWhisper,
); );
}, },
itemCount: users.length + 1, itemCount: users.length + 1,
@@ -108,6 +108,9 @@ class ChooseUserPage extends StatelessWidget {
showDialog( showDialog(
barrierDismissible: false, barrierDismissible: false,
context: context, context: context,
barrierColor: StreamChatTheme.of(context)
.colorTheme
.overlay,
builder: (context) => Center( builder: (context) => Center(
child: Container( child: Container(
decoration: BoxDecoration( decoration: BoxDecoration(
@@ -177,10 +180,10 @@ class ChooseUserPage extends StatelessWidget {
.grey, .grey,
), ),
), ),
trailing: SvgPicture.asset( trailing: StreamSvgIcon.arrow_right(
'assets/icon_arrow_right.svg', color: StreamChatTheme.of(context)
height: 24, .colorTheme
width: 24, .accentBlue,
), ),
); );
}), }),
+15 -14
View File
@@ -39,19 +39,11 @@ class MyApp extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final theme = ThemeData( final themeData = ThemeData(primarySwatch: Colors.green);
primarySwatch: Colors.green, final defaultTheme = StreamChatThemeData.fromTheme(themeData);
); final customTheme = defaultTheme.merge(StreamChatThemeData(
return MaterialApp(
theme: theme,
builder: (context, child) => StreamChat(
child: child,
client: client,
streamChatThemeData: StreamChatThemeData.fromTheme(theme).copyWith(
ownMessageTheme: MessageTheme( ownMessageTheme: MessageTheme(
messageBackgroundColor: messageBackgroundColor: StreamChatTheme.of(context).colorTheme.black,
StreamChatTheme.of(context).colorTheme.black,
messageText: TextStyle( messageText: TextStyle(
color: StreamChatTheme.of(context).colorTheme.white, color: StreamChatTheme.of(context).colorTheme.white,
), ),
@@ -59,8 +51,17 @@ class MyApp extends StatelessWidget {
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
), ),
), ),
), ));
),
return MaterialApp(
theme: themeData,
builder: (context, child) {
return StreamChat(
child: child,
client: client,
streamChatThemeData: customTheme,
);
},
home: ChannelListPage(), home: ChannelListPage(),
); );
} }
+9 -36
View File
@@ -83,10 +83,7 @@ class _GroupChatDetailsScreenState extends State<GroupChatDetailsScreen> {
'NAME', 'NAME',
style: TextStyle( style: TextStyle(
fontSize: 12, fontSize: 12,
color: StreamChatTheme.of(context) color: StreamChatTheme.of(context).colorTheme.grey,
.colorTheme
.black
.withOpacity(0.5),
), ),
), ),
SizedBox(width: 16), SizedBox(width: 16),
@@ -104,10 +101,8 @@ class _GroupChatDetailsScreenState extends State<GroupChatDetailsScreen> {
hintText: 'Choose a group chat name', hintText: 'Choose a group chat name',
hintStyle: TextStyle( hintStyle: TextStyle(
fontSize: 14, fontSize: 14,
color: StreamChatTheme.of(context) color: StreamChatTheme.of(context).colorTheme.grey,
.colorTheme ),
.black
.withOpacity(.5)),
), ),
), ),
), ),
@@ -122,7 +117,7 @@ class _GroupChatDetailsScreenState extends State<GroupChatDetailsScreen> {
icon: StreamSvgIcon.check( icon: StreamSvgIcon.check(
size: 24, size: 24,
color: _isGroupNameEmpty color: _isGroupNameEmpty
? Colors.grey ? StreamChatTheme.of(context).colorTheme.grey
: StreamChatTheme.of(context).colorTheme.accentBlue, : StreamChatTheme.of(context).colorTheme.accentBlue,
), ),
onPressed: _isGroupNameEmpty onPressed: _isGroupNameEmpty
@@ -155,14 +150,7 @@ class _GroupChatDetailsScreenState extends State<GroupChatDetailsScreen> {
Container( Container(
width: double.maxFinite, width: double.maxFinite,
decoration: BoxDecoration( decoration: BoxDecoration(
gradient: LinearGradient( gradient: StreamChatTheme.of(context).colorTheme.bgGradient,
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
StreamChatTheme.of(context).colorTheme.whiteSmoke,
StreamChatTheme.of(context).colorTheme.whiteSnow,
],
),
), ),
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric( padding: const EdgeInsets.symmetric(
@@ -172,7 +160,7 @@ class _GroupChatDetailsScreenState extends State<GroupChatDetailsScreen> {
child: Text( child: Text(
'$_totalUsers ${_totalUsers > 1 ? 'Members' : 'Member'}', '$_totalUsers ${_totalUsers > 1 ? 'Members' : 'Member'}',
style: TextStyle( style: TextStyle(
fontWeight: FontWeight.w500, color: StreamChatTheme.of(context).colorTheme.grey,
), ),
), ),
), ),
@@ -185,29 +173,14 @@ class _GroupChatDetailsScreenState extends State<GroupChatDetailsScreen> {
itemCount: _selectedUsers.length + 1, itemCount: _selectedUsers.length + 1,
separatorBuilder: (_, __) => Container( separatorBuilder: (_, __) => Container(
height: 1, height: 1,
color: Theme.of(context).brightness == Brightness.dark color: StreamChatTheme.of(context).colorTheme.greyWhisper,
? StreamChatTheme.of(context)
.colorTheme
.white
.withOpacity(0.1)
: StreamChatTheme.of(context)
.colorTheme
.black
.withOpacity(0.1),
), ),
itemBuilder: (_, index) { itemBuilder: (_, index) {
if (index == _selectedUsers.length) { if (index == _selectedUsers.length) {
return Container( return Container(
height: 1, height: 1,
color: Theme.of(context).brightness == Brightness.dark color:
? StreamChatTheme.of(context) StreamChatTheme.of(context).colorTheme.greyWhisper,
.colorTheme
.white
.withOpacity(0.1)
: StreamChatTheme.of(context)
.colorTheme
.black
.withOpacity(0.1),
); );
} }
final user = _selectedUsers[index]; final user = _selectedUsers[index];
+1
View File
@@ -589,6 +589,7 @@ class _GroupInfoScreenState extends State<GroupInfoScreen> {
showDialog( showDialog(
context: context, context: context,
barrierColor: StreamChatTheme.of(context).colorTheme.overlay,
builder: (context) { builder: (context) {
return StatefulBuilder(builder: (context, modalSetState) { return StatefulBuilder(builder: (context, modalSetState) {
modalSetStateCallback = modalSetState; modalSetStateCallback = modalSetState;
+12 -27
View File
@@ -157,8 +157,7 @@ class _NewChatScreenState extends State<NewChatScreen> {
decoration: BoxDecoration( decoration: BoxDecoration(
color: StreamChatTheme.of(context) color: StreamChatTheme.of(context)
.colorTheme .colorTheme
.black .greyGainsboro,
.withOpacity(0.05),
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
), ),
padding: const EdgeInsets.only(left: 24), padding: const EdgeInsets.only(left: 24),
@@ -166,15 +165,19 @@ class _NewChatScreenState extends State<NewChatScreen> {
padding: const EdgeInsets.fromLTRB(8, 4, 12, 4), padding: const EdgeInsets.fromLTRB(8, 4, 12, 4),
child: Text( child: Text(
user.name, user.name,
maxLines: 1,
style: TextStyle( style: TextStyle(
color: StreamChatTheme.of(context) color:
.colorTheme StreamChatTheme.of(context).colorTheme.black,
.black),
), ),
), ),
), ),
Opacity( ),
opacity: .8, Container(
foregroundDecoration: BoxDecoration(
color: StreamChatTheme.of(context).colorTheme.overlay,
shape: BoxShape.circle,
),
child: UserAvatar( child: UserAvatar(
showOnlineStatus: false, showOnlineStatus: false,
user: user, user: user,
@@ -184,11 +187,7 @@ class _NewChatScreenState extends State<NewChatScreen> {
), ),
), ),
), ),
Positioned( StreamSvgIcon.close(),
child: StreamSvgIcon.close(
color: StreamChatTheme.of(context).colorTheme.white,
),
),
], ],
), ),
); );
@@ -237,21 +236,7 @@ class _NewChatScreenState extends State<NewChatScreen> {
Container( Container(
width: double.maxFinite, width: double.maxFinite,
decoration: BoxDecoration( decoration: BoxDecoration(
gradient: LinearGradient( gradient: StreamChatTheme.of(context).colorTheme.bgGradient,
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],
),
), ),
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric( padding: const EdgeInsets.symmetric(
+13 -34
View File
@@ -52,15 +52,7 @@ class _NewGroupChatScreenState extends State<NewGroupChatScreen> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
backgroundColor: StreamChatTheme.of(context).colorTheme.whiteSnow, backgroundColor: StreamChatTheme.of(context).colorTheme.whiteSnow,
body: SafeArea( appBar: AppBar(
child: NestedScrollView(
floatHeaderSlivers: true,
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverAppBar(
brightness: Theme.of(context).brightness,
pinned: true,
forceElevated: true,
elevation: 1, elevation: 1,
backgroundColor: StreamChatTheme.of(context).colorTheme.white, backgroundColor: StreamChatTheme.of(context).colorTheme.white,
leading: const StreamBackButton(), leading: const StreamBackButton(),
@@ -76,8 +68,7 @@ class _NewGroupChatScreenState extends State<NewGroupChatScreen> {
if (_selectedUsers.isNotEmpty) if (_selectedUsers.isNotEmpty)
IconButton( IconButton(
icon: StreamSvgIcon.arrow_right( icon: StreamSvgIcon.arrow_right(
color: color: StreamChatTheme.of(context).colorTheme.accentBlue,
StreamChatTheme.of(context).colorTheme.accentBlue,
), ),
onPressed: () async { onPressed: () async {
final updatedList = await Navigator.pushNamed( final updatedList = await Navigator.pushNamed(
@@ -96,6 +87,10 @@ class _NewGroupChatScreenState extends State<NewGroupChatScreen> {
) )
], ],
), ),
body: NestedScrollView(
floatHeaderSlivers: true,
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverToBoxAdapter( SliverToBoxAdapter(
child: SearchTextField( child: SearchTextField(
controller: _controller, controller: _controller,
@@ -180,21 +175,7 @@ class _NewGroupChatScreenState extends State<NewGroupChatScreen> {
child: Container( child: Container(
width: double.maxFinite, width: double.maxFinite,
decoration: BoxDecoration( decoration: BoxDecoration(
gradient: LinearGradient( gradient: StreamChatTheme.of(context).colorTheme.bgGradient,
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],
),
), ),
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric( padding: const EdgeInsets.symmetric(
@@ -206,10 +187,7 @@ class _NewGroupChatScreenState extends State<NewGroupChatScreen> {
? 'Matches for \"$_userNameQuery\"' ? 'Matches for \"$_userNameQuery\"'
: 'On the platform', : 'On the platform',
style: TextStyle( style: TextStyle(
color: StreamChatTheme.of(context) color: StreamChatTheme.of(context).colorTheme.grey,
.colorTheme
.black
.withOpacity(0.5),
), ),
), ),
), ),
@@ -271,7 +249,9 @@ class _NewGroupChatScreenState extends State<NewGroupChatScreen> {
padding: const EdgeInsets.all(24), padding: const EdgeInsets.all(24),
child: StreamSvgIcon.search( child: StreamSvgIcon.search(
size: 96, size: 96,
color: Colors.grey, color: StreamChatTheme.of(context)
.colorTheme
.grey,
), ),
), ),
Text( Text(
@@ -282,8 +262,8 @@ class _NewGroupChatScreenState extends State<NewGroupChatScreen> {
.copyWith( .copyWith(
color: StreamChatTheme.of(context) color: StreamChatTheme.of(context)
.colorTheme .colorTheme
.black .grey,
.withOpacity(.5)), ),
), ),
], ],
), ),
@@ -297,7 +277,6 @@ class _NewGroupChatScreenState extends State<NewGroupChatScreen> {
), ),
), ),
), ),
),
); );
} }
} }
+2 -3
View File
@@ -28,9 +28,8 @@ class StreamVersion extends StatelessWidget {
return Text( return Text(
'Stream SDK v ${streamChatDep}', 'Stream SDK v ${streamChatDep}',
style: TextStyle( style: TextStyle(
fontSize: 14.5, fontSize: 14,
color: color: StreamChatTheme.of(context).colorTheme.greyGainsboro,
StreamChatTheme.of(context).colorTheme.black.withOpacity(.13),
), ),
); );
}, },
+12 -74
View File
@@ -29,27 +29,8 @@ class ImageActionsModal extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return GestureDetector( return GestureDetector(
behavior: HitTestBehavior.translucent, behavior: HitTestBehavior.translucent,
onTap: () { onTap: () => Navigator.maybePop(context),
Navigator.pop(context); child: _buildPage(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),
],
),
); );
} }
@@ -57,54 +38,15 @@ class ImageActionsModal extends StatelessWidget {
return Material( return Material(
color: Colors.transparent, color: Colors.transparent,
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [ children: [
Row( SizedBox(
mainAxisAlignment: MainAxisAlignment.spaceBetween, height: kToolbarHeight,
children: [ child: IconButton(
Padding( icon: StreamSvgIcon.close(),
padding: const EdgeInsets.all(8.0), onPressed: () => Navigator.maybePop(context),
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);
},
),
],
),
Align( Align(
alignment: Alignment.centerRight, alignment: Alignment.centerRight,
child: Container( child: Container(
@@ -127,10 +69,8 @@ class ImageActionsModal extends StatelessWidget {
'Reply', 'Reply',
StreamSvgIcon.Icon_curve_line_left_up( StreamSvgIcon.Icon_curve_line_left_up(
size: 24.0, size: 24.0,
color: StreamChatTheme.of(context) color:
.colorTheme StreamChatTheme.of(context).colorTheme.grey,
.black
.withOpacity(0.5),
), ),
() {}), () {}),
_buildButton( _buildButton(
@@ -147,10 +87,8 @@ class ImageActionsModal extends StatelessWidget {
'Save ${urls[currentIndex].type == 'video' ? 'Video' : 'Image'}', 'Save ${urls[currentIndex].type == 'video' ? 'Video' : 'Image'}',
StreamSvgIcon.Icon_save( StreamSvgIcon.Icon_save(
size: 24.0, size: 24.0,
color: StreamChatTheme.of(context) color:
.colorTheme StreamChatTheme.of(context).colorTheme.grey,
.black
.withOpacity(0.5),
), () async { ), () async {
var url = urls[currentIndex].imageUrl ?? var url = urls[currentIndex].imageUrl ??
urls[currentIndex].assetUrl ?? urls[currentIndex].assetUrl ??
+4 -7
View File
@@ -157,9 +157,7 @@ class _ImageFooterState extends State<ImageFooter> {
icon: StreamSvgIcon.Icon_grid( icon: StreamSvgIcon.Icon_grid(
color: StreamChatTheme.of(context).colorTheme.black, color: StreamChatTheme.of(context).colorTheme.black,
), ),
onPressed: () { onPressed: () => _showPhotosModal(context),
_buildPhotosModal(context);
},
), ),
], ],
), ),
@@ -168,13 +166,14 @@ class _ImageFooterState extends State<ImageFooter> {
); );
} }
Widget _buildPhotosModal(context) { void _showPhotosModal(context) {
var videoAttachments = widget.mediaAttachments var videoAttachments = widget.mediaAttachments
.where((element) => element.type == 'video') .where((element) => element.type == 'video')
.toList(); .toList();
showModalBottomSheet( showModalBottomSheet(
context: context, context: context,
barrierColor: StreamChatTheme.of(context).colorTheme.overlay,
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16.0), borderRadius: BorderRadius.circular(16.0),
), ),
@@ -207,9 +206,7 @@ class _ImageFooterState extends State<ImageFooter> {
icon: StreamSvgIcon.close( icon: StreamSvgIcon.close(
color: StreamChatTheme.of(context).colorTheme.black, color: StreamChatTheme.of(context).colorTheme.black,
), ),
onPressed: () { onPressed: () => Navigator.maybePop(context),
Navigator.pop(context);
},
), ),
), ),
], ],
+1
View File
@@ -106,6 +106,7 @@ class ImageHeader extends StatelessWidget implements PreferredSizeWidget {
showDialog( showDialog(
context: context, context: context,
barrierColor: StreamChatTheme.of(context).colorTheme.overlay,
builder: (context) { builder: (context) {
return StreamChannel( return StreamChannel(
channel: channel, channel: channel,
+4 -4
View File
@@ -73,17 +73,17 @@ class MessageActionsModal extends StatelessWidget {
return GestureDetector( return GestureDetector(
behavior: HitTestBehavior.translucent, behavior: HitTestBehavior.translucent,
onTap: () => Navigator.pop(context), onTap: () => Navigator.maybePop(context),
child: Stack( child: Stack(
children: [ children: [
Positioned.fill( Positioned.fill(
child: BackdropFilter( child: BackdropFilter(
filter: ImageFilter.blur( filter: ImageFilter.blur(
sigmaX: 10.8731, sigmaX: 10,
sigmaY: 10.8731, sigmaY: 10,
), ),
child: Container( child: Container(
color: Colors.black.withOpacity(.2), color: StreamChatTheme.of(context).colorTheme.overlay,
), ),
), ),
), ),
+13 -18
View File
@@ -122,6 +122,7 @@ class MessageListView extends StatefulWidget {
this.itemPositionListener, this.itemPositionListener,
this.onMessageSwiped, this.onMessageSwiped,
this.highlightInitialMessage = false, this.highlightInitialMessage = false,
this.messageHighlightColor,
this.onShowMessage, this.onShowMessage,
}) : super(key: key); }) : super(key: key);
@@ -175,6 +176,9 @@ class MessageListView extends StatefulWidget {
/// Also See [StreamChannel] /// Also See [StreamChannel]
final bool highlightInitialMessage; final bool highlightInitialMessage;
/// Color used while highlighting initial message
final Color messageHighlightColor;
final ShowMessageCallback onShowMessage; final ShowMessageCallback onShowMessage;
@override @override
@@ -346,18 +350,9 @@ class _MessageListViewState extends State<MessageListView> {
buildParentMessage(widget.parentMessage), buildParentMessage(widget.parentMessage),
Container( Container(
decoration: BoxDecoration( decoration: BoxDecoration(
gradient: LinearGradient( gradient: StreamChatTheme.of(context)
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
StreamChatTheme.of(context)
.colorTheme .colorTheme
.whiteSmoke, .bgGradient,
StreamChatTheme.of(context)
.colorTheme
.whiteSnow,
],
),
), ),
child: Padding( child: Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
@@ -845,17 +840,17 @@ class _MessageListViewState extends State<MessageListView> {
if (!initialMessageHighlightComplete && if (!initialMessageHighlightComplete &&
widget.highlightInitialMessage && widget.highlightInitialMessage &&
_isInitialMessage(message.id)) { _isInitialMessage(message.id)) {
final accentColor = Theme.of(context).accentColor; final colorTheme = StreamChatTheme.of(context).colorTheme;
final highlightColor =
widget.messageHighlightColor ?? colorTheme.highlight;
child = TweenAnimationBuilder<Color>( child = TweenAnimationBuilder<Color>(
tween: ColorTween( tween: ColorTween(
begin: accentColor.withOpacity(0.7), begin: highlightColor,
end: Colors.transparent, end: colorTheme.white.withOpacity(0),
), ),
duration: const Duration(seconds: 2), duration: const Duration(seconds: 3),
child: child, child: child,
onEnd: () { onEnd: () => initialMessageHighlightComplete = true,
initialMessageHighlightComplete = true;
},
builder: (_, color, child) { builder: (_, color, child) {
return Container( return Container(
color: color, color: color,
+15 -7
View File
@@ -40,27 +40,35 @@ class MessageReactionsModal extends StatelessWidget {
final user = StreamChat.of(context).user; final user = StreamChat.of(context).user;
final roughMaxSize = 2 * size.width / 3; 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 = final roughSentenceSize =
message.text.length * messageTheme.messageText.fontSize * 1.2; messageTextLength * messageTheme.messageText.fontSize * 1.2;
final divFactor = message.attachments?.isNotEmpty == true final divFactor = message.attachments?.isNotEmpty == true
? 1 ? 1
: (roughSentenceSize == 0 ? 1 : (roughSentenceSize / roughMaxSize)); : (roughSentenceSize == 0 ? 1 : (roughSentenceSize / roughMaxSize));
return GestureDetector( return GestureDetector(
behavior: HitTestBehavior.translucent, behavior: HitTestBehavior.translucent,
onTap: () { onTap: () => Navigator.maybePop(context),
Navigator.pop(context);
},
child: Stack( child: Stack(
children: [ children: [
Positioned.fill( Positioned.fill(
child: BackdropFilter( child: BackdropFilter(
filter: ImageFilter.blur( filter: ImageFilter.blur(
sigmaX: 10.8731, sigmaX: 10,
sigmaY: 10.8731, sigmaY: 10,
), ),
child: Container( 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( Container(
width: double.maxFinite, width: double.maxFinite,
decoration: BoxDecoration( decoration: BoxDecoration(
gradient: LinearGradient( gradient: StreamChatTheme.of(context).colorTheme.bgGradient,
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],
),
), ),
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric( padding: const EdgeInsets.symmetric(
@@ -337,10 +323,7 @@ class _MessageSearchListViewState extends State<MessageSearchListView> {
child: Text( child: Text(
'${items.length} results', '${items.length} results',
style: TextStyle( style: TextStyle(
color: StreamChatTheme.of(context) color: StreamChatTheme.of(context).colorTheme.grey,
.colorTheme
.black
.withOpacity(0.5),
), ),
), ),
), ),
+5 -1
View File
@@ -374,7 +374,9 @@ class _MessageWidgetState extends State<MessageWidget> {
elevation: 0.0, elevation: 0.0,
shape: widget.shape ?? shape: widget.shape ??
RoundedRectangleBorder( RoundedRectangleBorder(
side: isOnlyEmoji side: isOnlyEmoji &&
!(showThreadReplyIndicator ||
showInChannel)
? BorderSide.none ? BorderSide.none
: widget.borderSide ?? : widget.borderSide ??
BorderSide( BorderSide(
@@ -676,6 +678,7 @@ class _MessageWidgetState extends State<MessageWidget> {
final channel = StreamChannel.of(context).channel; final channel = StreamChannel.of(context).channel;
showDialog( showDialog(
context: context, context: context,
barrierColor: StreamChatTheme.of(context).colorTheme.overlay,
builder: (context) { builder: (context) {
return StreamChannel( return StreamChannel(
channel: channel, channel: channel,
@@ -716,6 +719,7 @@ class _MessageWidgetState extends State<MessageWidget> {
final channel = StreamChannel.of(context).channel; final channel = StreamChannel.of(context).channel;
showDialog( showDialog(
context: context, context: context,
barrierColor: StreamChatTheme.of(context).colorTheme.overlay,
builder: (context) { builder: (context) {
return StreamChannel( return StreamChannel(
channel: channel, channel: channel,
+2 -70
View File
@@ -78,6 +78,7 @@ class StreamChatState extends State<StreamChat> with WidgetsBindingObserver {
primaryIconTheme: streamTheme.primaryIconTheme, primaryIconTheme: streamTheme.primaryIconTheme,
accentColor: streamTheme.colorTheme.accentBlue, accentColor: streamTheme.colorTheme.accentBlue,
scaffoldBackgroundColor: streamTheme.colorTheme.white, scaffoldBackgroundColor: streamTheme.colorTheme.white,
buttonTheme: streamTheme.buttonTheme,
), ),
child: widget.child, child: widget.child,
); );
@@ -91,76 +92,7 @@ class StreamChatState extends State<StreamChat> with WidgetsBindingObserver {
StreamChatThemeData themeData, StreamChatThemeData themeData,
) { ) {
final defaultTheme = StreamChatThemeData.getDefaultTheme(Theme.of(context)); final defaultTheme = StreamChatThemeData.getDefaultTheme(Theme.of(context));
final theme = defaultTheme.copyWith( return defaultTheme.merge(themeData) ?? themeData;
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;
} }
/// The current user /// The current user
+190 -104
View File
@@ -45,6 +45,9 @@ class StreamChatThemeData {
/// The text themes used in the widgets /// The text themes used in the widgets
final TextTheme textTheme; final TextTheme textTheme;
/// The button themes used in the widgets
final ButtonThemeData buttonTheme;
/// The text themes used in the widgets /// The text themes used in the widgets
final ColorTheme colorTheme; final ColorTheme colorTheme;
@@ -73,8 +76,9 @@ class StreamChatThemeData {
final List<ReactionIcon> reactionIcons; final List<ReactionIcon> reactionIcons;
/// Create a theme from scratch /// Create a theme from scratch
StreamChatThemeData({ const StreamChatThemeData({
this.textTheme, this.textTheme,
this.buttonTheme,
this.colorTheme, this.colorTheme,
this.channelPreviewTheme, this.channelPreviewTheme,
this.channelTheme, this.channelTheme,
@@ -89,32 +93,24 @@ class StreamChatThemeData {
/// Create a theme from a Material [Theme] /// Create a theme from a Material [Theme]
factory StreamChatThemeData.fromTheme(ThemeData theme) { factory StreamChatThemeData.fromTheme(ThemeData theme) {
final defaultTheme = getDefaultTheme(theme); final defaultTheme = getDefaultTheme(theme);
final customizedTheme = StreamChatThemeData(
return defaultTheme.copyWith(
primaryIconTheme: theme.primaryIconTheme, primaryIconTheme: theme.primaryIconTheme,
channelTheme: defaultTheme.channelTheme, ownMessageTheme: MessageTheme(
ownMessageTheme: defaultTheme.ownMessageTheme.copyWith( replies: TextStyle(color: theme.accentColor),
replies: defaultTheme.ownMessageTheme.replies.copyWith( messageLinks: TextStyle(color: theme.accentColor),
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. /// Creates a copy of [StreamChatThemeData] with specified attributes overridden.
StreamChatThemeData copyWith({ StreamChatThemeData copyWith({
TextTheme textTheme, TextTheme textTheme,
ButtonThemeData buttonTheme,
ColorTheme colorTheme, ColorTheme colorTheme,
ChannelPreviewTheme channelPreviewTheme, ChannelPreviewTheme channelPreviewTheme,
ChannelTheme channelTheme, ChannelTheme channelTheme,
@@ -126,88 +122,41 @@ class StreamChatThemeData {
List<ReactionIcon> reactionIcons, List<ReactionIcon> reactionIcons,
}) => }) =>
StreamChatThemeData( StreamChatThemeData(
textTheme: this.textTheme?.copyWith( textTheme: textTheme ?? this.textTheme,
title: textTheme?.title, buttonTheme: buttonTheme ?? this.buttonTheme,
body: textTheme?.body, colorTheme: colorTheme ?? this.colorTheme,
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,
),
primaryIconTheme: primaryIconTheme ?? this.primaryIconTheme, primaryIconTheme: primaryIconTheme ?? this.primaryIconTheme,
defaultChannelImage: defaultChannelImage ?? this.defaultChannelImage, defaultChannelImage: defaultChannelImage ?? this.defaultChannelImage,
defaultUserImage: defaultUserImage ?? this.defaultUserImage, defaultUserImage: defaultUserImage ?? this.defaultUserImage,
channelPreviewTheme: this.channelPreviewTheme?.copyWith( channelPreviewTheme: channelPreviewTheme ?? this.channelPreviewTheme,
title: channelPreviewTheme.title, channelTheme: channelTheme ?? this.channelTheme,
subtitle: channelPreviewTheme.subtitle, ownMessageTheme: ownMessageTheme ?? this.ownMessageTheme,
lastMessageAt: channelPreviewTheme.lastMessageAt, otherMessageTheme: otherMessageTheme ?? this.otherMessageTheme,
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,
reactionIcons: reactionIcons ?? this.reactionIcons, 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 /// Get the default Stream Chat theme
static StreamChatThemeData getDefaultTheme(ThemeData theme) { static StreamChatThemeData getDefaultTheme(ThemeData theme) {
final accentColor = Color(0xff006cff); final accentColor = Color(0xff006cff);
@@ -217,6 +166,17 @@ class StreamChatThemeData {
return StreamChatThemeData( return StreamChatThemeData(
textTheme: textTheme, textTheme: textTheme,
colorTheme: colorTheme, 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)), primaryIconTheme: IconThemeData(color: colorTheme.black.withOpacity(.5)),
defaultChannelImage: (context, channel) => SizedBox(), defaultChannelImage: (context, channel) => SizedBox(),
defaultUserImage: (context, user) => Center( defaultUserImage: (context, user) => Center(
@@ -483,6 +443,22 @@ class TextTheme {
captionBold: captionBold ?? this.captionBold, 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 { enum ColorThemeType {
@@ -502,6 +478,10 @@ class ColorTheme {
final Color accentBlue; final Color accentBlue;
final Color accentRed; final Color accentRed;
final Color accentGreen; final Color accentGreen;
final Color highlight;
final Color overlay;
final Color overlayDark;
final Gradient bgGradient;
ColorTheme.light({ ColorTheme.light({
this.black = const Color(0xff000000), this.black = const Color(0xff000000),
@@ -513,8 +493,17 @@ class ColorTheme {
this.white = const Color(0xffffffff), this.white = const Color(0xffffffff),
this.blueAlice = const Color(0xffe9f2ff), this.blueAlice = const Color(0xffe9f2ff),
this.accentBlue = const Color(0xff005FFF), this.accentBlue = const Color(0xff005FFF),
this.accentRed = const Color(0xffFF3742), this.accentRed = const Color(0xffFF3842),
this.accentGreen = const Color(0xff20E070), 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],
),
}); });
ColorTheme.dark({ ColorTheme.dark({
@@ -529,6 +518,15 @@ class ColorTheme {
this.accentBlue = const Color(0xff005FFF), this.accentBlue = const Color(0xff005FFF),
this.accentRed = const Color(0xffFF3742), this.accentRed = const Color(0xffFF3742),
this.accentGreen = const Color(0xff20E070), this.accentGreen = const Color(0xff20E070),
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({ ColorTheme copyWith({
@@ -544,6 +542,10 @@ class ColorTheme {
Color accentBlue, Color accentBlue,
Color accentRed, Color accentRed,
Color accentGreen, Color accentGreen,
Color highlight,
Color overlay,
Color overlayDark,
Gradient bgGradient,
}) { }) {
return type == ColorThemeType.light return type == ColorThemeType.light
? ColorTheme.light( ? ColorTheme.light(
@@ -558,6 +560,10 @@ class ColorTheme {
accentBlue: accentBlue ?? this.accentBlue, accentBlue: accentBlue ?? this.accentBlue,
accentRed: accentRed ?? this.accentRed, accentRed: accentRed ?? this.accentRed,
accentGreen: accentGreen ?? this.accentGreen, accentGreen: accentGreen ?? this.accentGreen,
highlight: highlight ?? this.highlight,
overlay: overlay ?? this.overlay,
overlayDark: overlayDark ?? this.overlayDark,
bgGradient: bgGradient ?? this.bgGradient,
) )
: ColorTheme.dark( : ColorTheme.dark(
black: black ?? this.black, black: black ?? this.black,
@@ -571,6 +577,31 @@ class ColorTheme {
accentBlue: accentBlue ?? this.accentBlue, accentBlue: accentBlue ?? this.accentBlue,
accentRed: accentRed ?? this.accentRed, accentRed: accentRed ?? this.accentRed,
accentGreen: accentGreen ?? this.accentGreen, accentGreen: accentGreen ?? this.accentGreen,
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,
); );
} }
} }
@@ -604,20 +635,26 @@ class ChannelTheme {
Color inputBackground, Color inputBackground,
}) => }) =>
ChannelTheme( ChannelTheme(
channelHeaderTheme: channelHeaderTheme?.copyWith( channelHeaderTheme: channelHeaderTheme ?? this.channelHeaderTheme,
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,
messageInputButtonIconTheme: messageInputButtonIconTheme:
messageInputButtonIconTheme ?? this.messageInputButtonIconTheme, messageInputButtonIconTheme ?? this.messageInputButtonIconTheme,
messageInputButtonTheme: messageInputButtonTheme:
messageInputButtonTheme ?? this.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 { class AvatarTheme {
@@ -637,6 +674,14 @@ class AvatarTheme {
constraints: constraints ?? this.constraints, constraints: constraints ?? this.constraints,
borderRadius: borderRadius ?? this.borderRadius, borderRadius: borderRadius ?? this.borderRadius,
); );
AvatarTheme merge(AvatarTheme other) {
if (other == null) return this;
return copyWith(
constraints: other.constraints,
borderRadius: other.borderRadius,
);
}
} }
class MessageTheme { class MessageTheme {
@@ -690,6 +735,24 @@ class MessageTheme {
reactionsBackgroundColor ?? this.reactionsBackgroundColor, reactionsBackgroundColor ?? this.reactionsBackgroundColor,
reactionsBorderColor: reactionsBorderColor ?? this.reactionsBorderColor, 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 { class ChannelPreviewTheme {
@@ -721,6 +784,18 @@ class ChannelPreviewTheme {
avatarTheme: avatarTheme ?? this.avatarTheme, avatarTheme: avatarTheme ?? this.avatarTheme,
unreadCounterColor: unreadCounterColor ?? this.unreadCounterColor, unreadCounterColor: unreadCounterColor ?? this.unreadCounterColor,
); );
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 { class ChannelHeaderTheme {
@@ -748,4 +823,15 @@ class ChannelHeaderTheme {
avatarTheme: avatarTheme ?? this.avatarTheme, avatarTheme: avatarTheme ?? this.avatarTheme,
color: color ?? this.color, 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,
);
}
} }
+12
View File
@@ -194,6 +194,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({ factory StreamSvgIcon.penWrite({
double size, double size,
Color color, Color color,
+2 -8
View File
@@ -73,14 +73,8 @@ class UserItem extends StatelessWidget {
), ),
), ),
trailing: selected trailing: selected
? CircleAvatar( ? StreamSvgIcon.checkSend(
backgroundColor: color: StreamChatTheme.of(context).colorTheme.accentBlue,
StreamChatTheme.of(context).colorTheme.accentBlue,
child: StreamSvgIcon.check(
size: 20,
color: StreamChatTheme.of(context).colorTheme.white,
),
radius: 10,
) )
: null, : null,
title: Text( title: Text(
+3 -7
View File
@@ -365,10 +365,8 @@ class _UserListViewState extends State<UserListView>
style: TextStyle( style: TextStyle(
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
fontSize: 14.5, fontSize: 14.5,
color: StreamChatTheme.of(context) color: StreamChatTheme.of(context).colorTheme.grey,
.colorTheme ),
.black
.withOpacity(0.3)),
), ),
), ),
); );
@@ -478,9 +476,7 @@ class _UserListViewState extends State<UserListView>
Widget _separatorBuilder(context, i) { Widget _separatorBuilder(context, i) {
return Container( return Container(
height: 1, height: 1,
color: Theme.of(context).brightness == Brightness.dark color: StreamChatTheme.of(context).colorTheme.greyWhisper,
? StreamChatTheme.of(context).colorTheme.white.withOpacity(0.1)
: StreamChatTheme.of(context).colorTheme.black.withOpacity(0.1),
); );
} }