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,
),
borderRadius: BorderRadius.circular(32.0),
onlineIndicatorConstraints:
BoxConstraints.tight(Size(16.0, 16.0)),
),
SizedBox(
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/stream_svg_icon.dart';
import 'package:stream_chat_flutter/src/utils.dart';
import 'dart:ui' as ui;
import '../stream_chat_flutter.dart';
import 'channel_bottom_sheet.dart';
@@ -157,6 +158,7 @@ class ChannelListView extends StatefulWidget {
class _ChannelListViewState extends State<ChannelListView>
with WidgetsBindingObserver {
final ScrollController _scrollController = ScrollController();
final SlidableController _slideController = SlidableController();
@override
Widget build(BuildContext context) {
@@ -562,6 +564,7 @@ class _ChannelListViewState extends State<ChannelListView>
final backgroundColor =
StreamChatTheme.of(context).colorTheme.whiteSmoke;
child = Slidable(
controller: _slideController,
enabled: widget.swipeToAction,
actionPane: SlidableBehindActionPane(),
actionExtentRatio: 0.12,
@@ -726,9 +729,17 @@ class _ChannelListViewState extends State<ChannelListView>
}
Widget _separatorBuilder(context, i) {
return Container(
height: 1,
color: StreamChatTheme.of(context).colorTheme.black.withOpacity(0.08),
var effect = StreamChatTheme.of(context).colorTheme.borderTop;
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,
size: StreamChatTheme.of(context)
.channelPreviewTheme
.lastMessageAt
.fontSize,
.indicatorIconSize,
isMessageRead: channel.state.read
?.where((element) =>
element.user.id !=
@@ -220,7 +219,9 @@ class ChannelPreview extends StatelessWidget {
} else if (e.type == 'giphy') {
return '[GIF]';
}
return null;
return e == lastMessage.attachments.last
? (e.title ?? 'File')
: '${e.title ?? 'File'} , ';
}).where((e) => e != null),
lastMessage.text ?? '',
];
@@ -228,22 +229,69 @@ class ChannelPreview extends StatelessWidget {
text = parts.join(' ');
}
return Text(
text,
return Text.rich(
_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,
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') {
return '[GIF]';
}
return null;
return e == message.attachments.last
? (e.title ?? 'File')
: '${e.title ?? 'File'} , ';
}).where((e) => e != null),
message.text ?? '',
];
@@ -121,15 +123,61 @@ class MessageSearchItem extends StatelessWidget {
text = parts.join(' ');
}
return Text(
text,
return Text.rich(
_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,
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
Widget build(BuildContext context) {
if (isMessageRead) {
return Icon(
Icons.done_all_rounded,
return StreamSvgIcon.checkAll(
size: size,
color: StreamChatTheme.of(context).colorTheme.accentBlue,
);
}
if (message.status == MessageSendingStatus.SENT || message.status == null) {
return Icon(
Icons.done,
return StreamSvgIcon.check(
size: size,
color: IconTheme.of(context).color.withOpacity(0.5),
);
+86 -15
View File
@@ -187,22 +187,22 @@ class StreamChatThemeData {
),
),
channelPreviewTheme: ChannelPreviewTheme(
unreadCounterColor: colorTheme.accentRed,
avatarTheme: AvatarTheme(
borderRadius: BorderRadius.circular(20),
constraints: BoxConstraints.tightFor(
height: 40,
width: 40,
unreadCounterColor: colorTheme.accentRed,
avatarTheme: AvatarTheme(
borderRadius: BorderRadius.circular(20),
constraints: BoxConstraints.tightFor(
height: 40,
width: 40,
),
),
),
title: textTheme.bodyBold,
subtitle: textTheme.footnote.copyWith(
color: Color(0xff7A7A7A),
),
lastMessageAt: textTheme.footnote.copyWith(
color: colorTheme.black.withOpacity(.5),
),
),
title: textTheme.bodyBold,
subtitle: textTheme.footnote.copyWith(
color: Color(0xff7A7A7A),
),
lastMessageAt: textTheme.footnote.copyWith(
color: colorTheme.black.withOpacity(.5),
),
indicatorIconSize: 16.0),
channelTheme: ChannelTheme(
messageInputButtonIconTheme: theme.iconTheme.copyWith(
color: accentColor,
@@ -478,6 +478,10 @@ class ColorTheme {
final Color accentBlue;
final Color accentRed;
final Color accentGreen;
final Effect borderTop;
final Effect borderBottom;
final Effect shadowIconButton;
final Effect modalShadow;
final Color highlight;
final Color overlay;
final Color overlayDark;
@@ -504,6 +508,14 @@ class ColorTheme {
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(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({
@@ -518,6 +530,14 @@ class ColorTheme {
this.accentBlue = const Color(0xff005FFF),
this.accentRed = const Color(0xffFF3742),
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.overlay = const Color.fromRGBO(0, 0, 0, 0.4),
this.overlayDark = const Color.fromRGBO(255, 255, 255, 0.6),
@@ -542,6 +562,10 @@ class ColorTheme {
Color accentBlue,
Color accentRed,
Color accentGreen,
Effect borderTop,
Effect borderBottom,
Effect shadowIconButton,
Effect modalShadow,
Color highlight,
Color overlay,
Color overlayDark,
@@ -560,6 +584,10 @@ class ColorTheme {
accentBlue: accentBlue ?? this.accentBlue,
accentRed: accentRed ?? this.accentRed,
accentGreen: accentGreen ?? this.accentGreen,
borderTop: borderTop ?? this.borderTop,
borderBottom: borderBottom ?? this.borderBottom,
shadowIconButton: shadowIconButton ?? this.shadowIconButton,
modalShadow: modalShadow ?? this.modalShadow,
highlight: highlight ?? this.highlight,
overlay: overlay ?? this.overlay,
overlayDark: overlayDark ?? this.overlayDark,
@@ -577,6 +605,10 @@ class ColorTheme {
accentBlue: accentBlue ?? this.accentBlue,
accentRed: accentRed ?? this.accentRed,
accentGreen: accentGreen ?? this.accentGreen,
borderTop: borderTop ?? this.borderTop,
borderBottom: borderBottom ?? this.borderBottom,
shadowIconButton: shadowIconButton ?? this.shadowIconButton,
modalShadow: modalShadow ?? this.modalShadow,
highlight: highlight ?? this.highlight,
overlay: overlay ?? this.overlay,
overlayDark: overlayDark ?? this.overlayDark,
@@ -602,6 +634,10 @@ class ColorTheme {
overlay: other.overlay,
overlayDark: other.overlayDark,
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 AvatarTheme avatarTheme;
final Color unreadCounterColor;
final double indicatorIconSize;
const ChannelPreviewTheme({
this.title,
@@ -768,6 +805,7 @@ class ChannelPreviewTheme {
this.lastMessageAt,
this.avatarTheme,
this.unreadCounterColor,
this.indicatorIconSize,
});
ChannelPreviewTheme copyWith({
@@ -776,6 +814,7 @@ class ChannelPreviewTheme {
TextStyle lastMessageAt,
AvatarTheme avatarTheme,
Color unreadCounterColor,
double indicatorIconSize,
}) =>
ChannelPreviewTheme(
title: title ?? this.title,
@@ -783,6 +822,7 @@ class ChannelPreviewTheme {
lastMessageAt: lastMessageAt ?? this.lastMessageAt,
avatarTheme: avatarTheme ?? this.avatarTheme,
unreadCounterColor: unreadCounterColor ?? this.unreadCounterColor,
indicatorIconSize: indicatorIconSize ?? this.indicatorIconSize,
);
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({
double size,
Color color,