Merge pull request #194 from GetStream/fix/channel-list

Fix/channel list
This commit is contained in:
Salvatore Giordano
2021-01-06 16:45:25 +01:00
committed by GitHub
7 changed files with 235 additions and 45 deletions
+2
View File
@@ -73,6 +73,8 @@ class _ChannelBottomSheetState extends State<ChannelBottomSheet> {
maxWidth: 64.0, maxWidth: 64.0,
), ),
borderRadius: BorderRadius.circular(32.0), borderRadius: BorderRadius.circular(32.0),
onlineIndicatorConstraints:
BoxConstraints.tight(Size(16.0, 16.0)),
), ),
SizedBox( SizedBox(
height: 6.0, height: 6.0,
+14 -3
View File
@@ -9,6 +9,7 @@ import 'package:stream_chat/stream_chat.dart';
import 'package:stream_chat_flutter/src/channels_bloc.dart'; import 'package:stream_chat_flutter/src/channels_bloc.dart';
import 'package:stream_chat_flutter/src/stream_svg_icon.dart'; import 'package:stream_chat_flutter/src/stream_svg_icon.dart';
import 'package:stream_chat_flutter/src/utils.dart'; import 'package:stream_chat_flutter/src/utils.dart';
import 'dart:ui' as ui;
import '../stream_chat_flutter.dart'; import '../stream_chat_flutter.dart';
import 'channel_bottom_sheet.dart'; import 'channel_bottom_sheet.dart';
@@ -157,6 +158,7 @@ class ChannelListView extends StatefulWidget {
class _ChannelListViewState extends State<ChannelListView> class _ChannelListViewState extends State<ChannelListView>
with WidgetsBindingObserver { with WidgetsBindingObserver {
final ScrollController _scrollController = ScrollController(); final ScrollController _scrollController = ScrollController();
final SlidableController _slideController = SlidableController();
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@@ -562,6 +564,7 @@ class _ChannelListViewState extends State<ChannelListView>
final backgroundColor = final backgroundColor =
StreamChatTheme.of(context).colorTheme.whiteSmoke; StreamChatTheme.of(context).colorTheme.whiteSmoke;
child = Slidable( child = Slidable(
controller: _slideController,
enabled: widget.swipeToAction, enabled: widget.swipeToAction,
actionPane: SlidableBehindActionPane(), actionPane: SlidableBehindActionPane(),
actionExtentRatio: 0.12, actionExtentRatio: 0.12,
@@ -726,9 +729,17 @@ class _ChannelListViewState extends State<ChannelListView>
} }
Widget _separatorBuilder(context, i) { Widget _separatorBuilder(context, i) {
return Container( var effect = StreamChatTheme.of(context).colorTheme.borderTop;
height: 1,
color: StreamChatTheme.of(context).colorTheme.black.withOpacity(0.08), return BackdropFilter(
filter: ui.ImageFilter.blur(
sigmaX: effect.sigmaX,
sigmaY: effect.sigmaY,
),
child: Container(
height: 1,
color: effect.color.withOpacity(0.08),
),
); );
} }
+63 -15
View File
@@ -104,8 +104,7 @@ class ChannelPreview extends StatelessWidget {
message: channel.state.lastMessage, message: channel.state.lastMessage,
size: StreamChatTheme.of(context) size: StreamChatTheme.of(context)
.channelPreviewTheme .channelPreviewTheme
.lastMessageAt .indicatorIconSize,
.fontSize,
isMessageRead: channel.state.read isMessageRead: channel.state.read
?.where((element) => ?.where((element) =>
element.user.id != element.user.id !=
@@ -220,7 +219,9 @@ class ChannelPreview extends StatelessWidget {
} else if (e.type == 'giphy') { } else if (e.type == 'giphy') {
return '[GIF]'; return '[GIF]';
} }
return null; return e == lastMessage.attachments.last
? (e.title ?? 'File')
: '${e.title ?? 'File'} , ';
}).where((e) => e != null), }).where((e) => e != null),
lastMessage.text ?? '', lastMessage.text ?? '',
]; ];
@@ -228,22 +229,69 @@ class ChannelPreview extends StatelessWidget {
text = parts.join(' '); text = parts.join(' ');
} }
return Text( return Text.rich(
text, _getDisplayText(
text,
lastMessage.mentionedUsers,
lastMessage.attachments,
StreamChatTheme.of(context).channelPreviewTheme.subtitle.copyWith(
color: StreamChatTheme.of(context)
.channelPreviewTheme
.subtitle
.color,
fontStyle: (lastMessage.isSystem || lastMessage.isDeleted)
? FontStyle.italic
: FontStyle.normal),
StreamChatTheme.of(context).channelPreviewTheme.subtitle.copyWith(
color: StreamChatTheme.of(context)
.channelPreviewTheme
.subtitle
.color,
fontStyle: (lastMessage.isSystem || lastMessage.isDeleted)
? FontStyle.italic
: FontStyle.normal,
fontWeight: FontWeight.bold),
),
maxLines: 1, maxLines: 1,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style:
StreamChatTheme.of(context).channelPreviewTheme.subtitle.copyWith(
color: StreamChatTheme.of(context)
.channelPreviewTheme
.subtitle
.color,
fontStyle: (lastMessage.isSystem || lastMessage.isDeleted)
? FontStyle.italic
: FontStyle.normal,
),
); );
}, },
); );
} }
TextSpan _getDisplayText(
String text,
List<User> mentions,
List<Attachment> attachments,
TextStyle normalTextStyle,
TextStyle mentionsTextStyle) {
var textList = text.split(' ');
List<TextSpan> resList = [];
for (var e in textList) {
if (mentions != null &&
mentions.isNotEmpty &&
mentions.any((element) => '@${element.name}' == e)) {
resList.add(TextSpan(
text: '$e ',
style: mentionsTextStyle,
));
} else if (attachments != null &&
attachments.isNotEmpty &&
attachments
.where((e) => e.title != null)
.any((element) => element.title == e)) {
resList.add(TextSpan(
text: '$e ',
style: normalTextStyle.copyWith(fontStyle: FontStyle.italic),
));
} else {
resList.add(TextSpan(
text: e == textList.last ? '$e' : '$e ',
style: normalTextStyle,
));
}
}
return TextSpan(children: resList);
}
} }
+56 -8
View File
@@ -113,7 +113,9 @@ class MessageSearchItem extends StatelessWidget {
} else if (e.type == 'giphy') { } else if (e.type == 'giphy') {
return '[GIF]'; return '[GIF]';
} }
return null; return e == message.attachments.last
? (e.title ?? 'File')
: '${e.title ?? 'File'} , ';
}).where((e) => e != null), }).where((e) => e != null),
message.text ?? '', message.text ?? '',
]; ];
@@ -121,15 +123,61 @@ class MessageSearchItem extends StatelessWidget {
text = parts.join(' '); text = parts.join(' ');
} }
return Text( return Text.rich(
text, _getDisplayText(
text,
message.mentionedUsers,
message.attachments,
StreamChatTheme.of(context).channelPreviewTheme.subtitle.copyWith(
fontStyle: (message.isSystem || message.isDeleted)
? FontStyle.italic
: FontStyle.normal,
),
StreamChatTheme.of(context).channelPreviewTheme.subtitle.copyWith(
fontStyle: (message.isSystem || message.isDeleted)
? FontStyle.italic
: FontStyle.normal,
fontWeight: FontWeight.bold,
),
),
maxLines: 1, maxLines: 1,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: StreamChatTheme.of(context).channelPreviewTheme.subtitle.copyWith(
fontStyle: (message.isSystem || message.isDeleted)
? FontStyle.italic
: FontStyle.normal,
),
); );
} }
TextSpan _getDisplayText(
String text,
List<User> mentions,
List<Attachment> attachments,
TextStyle normalTextStyle,
TextStyle mentionsTextStyle) {
var textList = text.split(' ');
List<TextSpan> resList = [];
for (var e in textList) {
if (mentions != null &&
mentions.isNotEmpty &&
mentions.any((element) => '@${element.name}' == e)) {
resList.add(TextSpan(
text: '$e ',
style: mentionsTextStyle,
));
} else if (attachments != null &&
attachments.isNotEmpty &&
attachments
.where((e) => e.title != null)
.any((element) => element.title == e)) {
resList.add(TextSpan(
text: '$e ',
style: normalTextStyle.copyWith(fontStyle: FontStyle.italic),
));
} else {
resList.add(TextSpan(
text: e == textList.last ? '$e' : '$e ',
style: normalTextStyle,
));
}
}
return TextSpan(children: resList);
}
} }
+2 -4
View File
@@ -17,15 +17,13 @@ class SendingIndicator extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (isMessageRead) { if (isMessageRead) {
return Icon( return StreamSvgIcon.checkAll(
Icons.done_all_rounded,
size: size, size: size,
color: StreamChatTheme.of(context).colorTheme.accentBlue, color: StreamChatTheme.of(context).colorTheme.accentBlue,
); );
} }
if (message.status == MessageSendingStatus.SENT || message.status == null) { if (message.status == MessageSendingStatus.SENT || message.status == null) {
return Icon( return StreamSvgIcon.check(
Icons.done,
size: size, size: size,
color: IconTheme.of(context).color.withOpacity(0.5), color: IconTheme.of(context).color.withOpacity(0.5),
); );
+86 -15
View File
@@ -187,22 +187,22 @@ class StreamChatThemeData {
), ),
), ),
channelPreviewTheme: ChannelPreviewTheme( channelPreviewTheme: ChannelPreviewTheme(
unreadCounterColor: colorTheme.accentRed, unreadCounterColor: colorTheme.accentRed,
avatarTheme: AvatarTheme( avatarTheme: AvatarTheme(
borderRadius: BorderRadius.circular(20), borderRadius: BorderRadius.circular(20),
constraints: BoxConstraints.tightFor( constraints: BoxConstraints.tightFor(
height: 40, height: 40,
width: 40, width: 40,
),
), ),
), title: textTheme.bodyBold,
title: textTheme.bodyBold, subtitle: textTheme.footnote.copyWith(
subtitle: textTheme.footnote.copyWith( color: Color(0xff7A7A7A),
color: Color(0xff7A7A7A), ),
), lastMessageAt: textTheme.footnote.copyWith(
lastMessageAt: textTheme.footnote.copyWith( color: colorTheme.black.withOpacity(.5),
color: colorTheme.black.withOpacity(.5), ),
), indicatorIconSize: 16.0),
),
channelTheme: ChannelTheme( channelTheme: ChannelTheme(
messageInputButtonIconTheme: theme.iconTheme.copyWith( messageInputButtonIconTheme: theme.iconTheme.copyWith(
color: accentColor, color: accentColor,
@@ -478,6 +478,10 @@ class ColorTheme {
final Color accentBlue; final Color accentBlue;
final Color accentRed; final Color accentRed;
final Color accentGreen; final Color accentGreen;
final Effect borderTop;
final Effect borderBottom;
final Effect shadowIconButton;
final Effect modalShadow;
final Color highlight; final Color highlight;
final Color overlay; final Color overlay;
final Color overlayDark; final Color overlayDark;
@@ -504,6 +508,14 @@ class ColorTheme {
colors: [const Color(0xfff7f7f7), const Color(0xfffcfcfc)], colors: [const Color(0xfff7f7f7), const Color(0xfffcfcfc)],
stops: [0, 1], stops: [0, 1],
), ),
this.borderTop = const Effect(
sigmaX: 0, sigmaY: -1, color: Color(0xff141924), blur: 0.0),
this.borderBottom =
const Effect(sigmaX: 0, sigmaY: 1, color: Color(0xff141924), blur: 0.0),
this.shadowIconButton = const Effect(
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),
}); });
ColorTheme.dark({ ColorTheme.dark({
@@ -518,6 +530,14 @@ 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.borderTop = const Effect(
sigmaX: 0, sigmaY: -1, color: Color(0xff141924), blur: 0.0),
this.borderBottom =
const Effect(sigmaX: 0, sigmaY: 1, color: Color(0xff141924), blur: 0.0),
this.shadowIconButton = const Effect(
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.highlight = const Color(0xff302d22),
this.overlay = const Color.fromRGBO(0, 0, 0, 0.4), this.overlay = const Color.fromRGBO(0, 0, 0, 0.4),
this.overlayDark = const Color.fromRGBO(255, 255, 255, 0.6), this.overlayDark = const Color.fromRGBO(255, 255, 255, 0.6),
@@ -542,6 +562,10 @@ class ColorTheme {
Color accentBlue, Color accentBlue,
Color accentRed, Color accentRed,
Color accentGreen, Color accentGreen,
Effect borderTop,
Effect borderBottom,
Effect shadowIconButton,
Effect modalShadow,
Color highlight, Color highlight,
Color overlay, Color overlay,
Color overlayDark, Color overlayDark,
@@ -560,6 +584,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,
borderTop: borderTop ?? this.borderTop,
borderBottom: borderBottom ?? this.borderBottom,
shadowIconButton: shadowIconButton ?? this.shadowIconButton,
modalShadow: modalShadow ?? this.modalShadow,
highlight: highlight ?? this.highlight, highlight: highlight ?? this.highlight,
overlay: overlay ?? this.overlay, overlay: overlay ?? this.overlay,
overlayDark: overlayDark ?? this.overlayDark, overlayDark: overlayDark ?? this.overlayDark,
@@ -577,6 +605,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,
borderTop: borderTop ?? this.borderTop,
borderBottom: borderBottom ?? this.borderBottom,
shadowIconButton: shadowIconButton ?? this.shadowIconButton,
modalShadow: modalShadow ?? this.modalShadow,
highlight: highlight ?? this.highlight, highlight: highlight ?? this.highlight,
overlay: overlay ?? this.overlay, overlay: overlay ?? this.overlay,
overlayDark: overlayDark ?? this.overlayDark, overlayDark: overlayDark ?? this.overlayDark,
@@ -602,6 +634,10 @@ class ColorTheme {
overlay: other.overlay, overlay: other.overlay,
overlayDark: other.overlayDark, overlayDark: other.overlayDark,
bgGradient: other.bgGradient, bgGradient: other.bgGradient,
borderTop: other.borderTop,
borderBottom: other.borderBottom,
shadowIconButton: other.shadowIconButton,
modalShadow: other.modalShadow,
); );
} }
} }
@@ -761,6 +797,7 @@ class ChannelPreviewTheme {
final TextStyle lastMessageAt; final TextStyle lastMessageAt;
final AvatarTheme avatarTheme; final AvatarTheme avatarTheme;
final Color unreadCounterColor; final Color unreadCounterColor;
final double indicatorIconSize;
const ChannelPreviewTheme({ const ChannelPreviewTheme({
this.title, this.title,
@@ -768,6 +805,7 @@ class ChannelPreviewTheme {
this.lastMessageAt, this.lastMessageAt,
this.avatarTheme, this.avatarTheme,
this.unreadCounterColor, this.unreadCounterColor,
this.indicatorIconSize,
}); });
ChannelPreviewTheme copyWith({ ChannelPreviewTheme copyWith({
@@ -776,6 +814,7 @@ class ChannelPreviewTheme {
TextStyle lastMessageAt, TextStyle lastMessageAt,
AvatarTheme avatarTheme, AvatarTheme avatarTheme,
Color unreadCounterColor, Color unreadCounterColor,
double indicatorIconSize,
}) => }) =>
ChannelPreviewTheme( ChannelPreviewTheme(
title: title ?? this.title, title: title ?? this.title,
@@ -783,6 +822,7 @@ class ChannelPreviewTheme {
lastMessageAt: lastMessageAt ?? this.lastMessageAt, lastMessageAt: lastMessageAt ?? this.lastMessageAt,
avatarTheme: avatarTheme ?? this.avatarTheme, avatarTheme: avatarTheme ?? this.avatarTheme,
unreadCounterColor: unreadCounterColor ?? this.unreadCounterColor, unreadCounterColor: unreadCounterColor ?? this.unreadCounterColor,
indicatorIconSize: indicatorIconSize ?? this.indicatorIconSize,
); );
ChannelPreviewTheme merge(ChannelPreviewTheme other) { ChannelPreviewTheme merge(ChannelPreviewTheme other) {
@@ -835,3 +875,34 @@ class ChannelHeaderTheme {
); );
} }
} }
class Effect {
final double sigmaX;
final double sigmaY;
final Color color;
final double alpha;
final double blur;
const Effect({
this.sigmaX,
this.sigmaY,
this.color,
this.alpha,
this.blur,
});
Effect copyWith({
double sigmaX,
double sigmaY,
Color color,
double alpha,
double blur,
}) =>
Effect(
sigmaX: sigmaX ?? this.sigmaX,
sigmaY: sigmaY ?? this.sigmaY,
color: color ?? this.color,
alpha: color ?? this.alpha,
blur: blur ?? this.blur,
);
}
+12
View File
@@ -194,6 +194,18 @@ class StreamSvgIcon extends StatelessWidget {
); );
} }
factory StreamSvgIcon.checkAll({
double size,
Color color,
}) {
return StreamSvgIcon(
assetName: 'Icon_check_all.svg',
color: color,
width: size,
height: size,
);
}
factory StreamSvgIcon.checkSend({ factory StreamSvgIcon.checkSend({
double size, double size,
Color color, Color color,