migrate chatty
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class AvatarImageView extends StatelessWidget {
|
||||
const AvatarImageView({Key key, this.onTap, this.child}) : super(key: key);
|
||||
final Widget child;
|
||||
final VoidCallback onTap;
|
||||
const AvatarImageView({Key? key, this.onTap, this.child}) : super(key: key);
|
||||
final Widget? child;
|
||||
final VoidCallback? onTap;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
@@ -5,8 +5,8 @@ class LoadingView extends StatelessWidget {
|
||||
final Widget child;
|
||||
|
||||
const LoadingView({
|
||||
Key key,
|
||||
@required this.child,
|
||||
Key? key,
|
||||
required this.child,
|
||||
this.isLoading = false,
|
||||
}) : super(key: key);
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'package:collection/collection.dart' show IterableExtension;
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:jiffy/jiffy.dart';
|
||||
@@ -30,22 +31,22 @@ import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
|
||||
/// Modify it to change the widget appearance.
|
||||
class MyChannelPreview extends StatelessWidget {
|
||||
/// Function called when tapping this widget
|
||||
final void Function(Channel) onTap;
|
||||
final void Function(Channel)? onTap;
|
||||
|
||||
/// Function called when long pressing this widget
|
||||
final void Function(Channel) onLongPress;
|
||||
final void Function(Channel)? onLongPress;
|
||||
|
||||
/// Channel displayed
|
||||
final Channel channel;
|
||||
|
||||
/// The function called when the image is tapped
|
||||
final VoidCallback onImageTap;
|
||||
final VoidCallback? onImageTap;
|
||||
|
||||
final String heroTag;
|
||||
final String? heroTag;
|
||||
|
||||
MyChannelPreview({
|
||||
@required this.channel,
|
||||
Key key,
|
||||
required this.channel,
|
||||
Key? key,
|
||||
this.onTap,
|
||||
this.onLongPress,
|
||||
this.onImageTap,
|
||||
@@ -59,24 +60,24 @@ class MyChannelPreview extends StatelessWidget {
|
||||
initialData: channel.isMuted,
|
||||
builder: (context, snapshot) {
|
||||
return Opacity(
|
||||
opacity: snapshot.data ? 0.5 : 1,
|
||||
opacity: snapshot.data! ? 0.5 : 1,
|
||||
child: ListTile(
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
horizontal: 8,
|
||||
),
|
||||
onTap: () {
|
||||
if (onTap != null) {
|
||||
onTap(channel);
|
||||
onTap!(channel);
|
||||
}
|
||||
},
|
||||
onLongPress: () {
|
||||
if (onLongPress != null) {
|
||||
onLongPress(channel);
|
||||
onLongPress!(channel);
|
||||
}
|
||||
},
|
||||
leading: Material(
|
||||
child: Hero(
|
||||
tag: heroTag,
|
||||
tag: heroTag!,
|
||||
child: StreamChannel(
|
||||
channel: channel,
|
||||
child: ChannelImage(
|
||||
@@ -95,13 +96,13 @@ class MyChannelPreview extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
StreamBuilder<List<Member>>(
|
||||
stream: channel.state.membersStream,
|
||||
initialData: channel.state.members,
|
||||
stream: channel.state!.membersStream,
|
||||
initialData: channel.state!.members,
|
||||
builder: (context, snapshot) {
|
||||
if (!snapshot.hasData ||
|
||||
snapshot.data.isEmpty ||
|
||||
!snapshot.data.any((Member e) =>
|
||||
e.user.id == channel.client.state.user.id)) {
|
||||
snapshot.data!.isEmpty ||
|
||||
!snapshot.data!.any((Member e) =>
|
||||
e.user!.id == channel.client.state.user!.id)) {
|
||||
return SizedBox();
|
||||
}
|
||||
return ChannelUnreadIndicator(
|
||||
@@ -116,26 +117,26 @@ class MyChannelPreview extends StatelessWidget {
|
||||
Flexible(child: _buildSubtitle(context)),
|
||||
Builder(
|
||||
builder: (context) {
|
||||
final lastMessage = channel.state.messages.lastWhere(
|
||||
final lastMessage =
|
||||
channel.state!.messages.lastWhereOrNull(
|
||||
(m) => !m.isDeleted && m.shadowed != true,
|
||||
orElse: () => null,
|
||||
);
|
||||
if (lastMessage?.user?.id ==
|
||||
StreamChat.of(context).user.id) {
|
||||
StreamChat.of(context).user!.id) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(right: 4.0),
|
||||
child: SendingIndicator(
|
||||
message: lastMessage,
|
||||
message: lastMessage!,
|
||||
size: StreamChatTheme.of(context)
|
||||
.channelPreviewTheme
|
||||
.indicatorIconSize,
|
||||
isMessageRead: channel.state.read
|
||||
isMessageRead: channel.state!.read
|
||||
?.where((element) =>
|
||||
element.user.id !=
|
||||
channel.client.state.user.id)
|
||||
?.where((element) => element.lastRead
|
||||
channel.client.state.user!.id)
|
||||
.where((element) => element.lastRead
|
||||
.isAfter(lastMessage.createdAt))
|
||||
?.isNotEmpty ==
|
||||
.isNotEmpty ==
|
||||
true,
|
||||
),
|
||||
);
|
||||
@@ -152,14 +153,14 @@ class MyChannelPreview extends StatelessWidget {
|
||||
}
|
||||
|
||||
Widget _buildDate(BuildContext context) {
|
||||
return StreamBuilder<DateTime>(
|
||||
return StreamBuilder<DateTime?>(
|
||||
stream: channel.lastMessageAtStream,
|
||||
initialData: channel.lastMessageAt,
|
||||
builder: (context, snapshot) {
|
||||
if (!snapshot.hasData) {
|
||||
return SizedBox();
|
||||
}
|
||||
final lastMessageAt = snapshot.data.toLocal();
|
||||
final lastMessageAt = snapshot.data!.toLocal();
|
||||
|
||||
String stringDate;
|
||||
final now = DateTime.now();
|
||||
@@ -198,11 +199,11 @@ class MyChannelPreview extends StatelessWidget {
|
||||
' Channel is muted',
|
||||
style: StreamChatTheme.of(context)
|
||||
.channelPreviewTheme
|
||||
.subtitle
|
||||
.subtitle!
|
||||
.copyWith(
|
||||
color: StreamChatTheme.of(context)
|
||||
.channelPreviewTheme
|
||||
.subtitle
|
||||
.subtitle!
|
||||
.color,
|
||||
),
|
||||
),
|
||||
@@ -212,21 +213,20 @@ class MyChannelPreview extends StatelessWidget {
|
||||
return TypingIndicator(
|
||||
channel: channel,
|
||||
alternativeWidget: _buildLastMessage(context),
|
||||
style: StreamChatTheme.of(context).channelPreviewTheme.subtitle.copyWith(
|
||||
style: StreamChatTheme.of(context).channelPreviewTheme.subtitle!.copyWith(
|
||||
color:
|
||||
StreamChatTheme.of(context).channelPreviewTheme.subtitle.color,
|
||||
StreamChatTheme.of(context).channelPreviewTheme.subtitle!.color,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildLastMessage(BuildContext context) {
|
||||
return StreamBuilder<List<Message>>(
|
||||
stream: channel.state.messagesStream,
|
||||
initialData: channel.state.messages,
|
||||
return StreamBuilder<List<Message>?>(
|
||||
stream: channel.state!.messagesStream,
|
||||
initialData: channel.state!.messages,
|
||||
builder: (context, snapshot) {
|
||||
final lastMessage = snapshot.data?.lastWhere(
|
||||
(m) => m.shadowed != true && !m.isDeleted,
|
||||
orElse: () => null);
|
||||
final lastMessage = snapshot.data
|
||||
?.lastWhereOrNull((m) => m.shadowed != true && !m.isDeleted);
|
||||
if (lastMessage == null) {
|
||||
return SizedBox();
|
||||
}
|
||||
@@ -254,21 +254,21 @@ class MyChannelPreview extends StatelessWidget {
|
||||
|
||||
return Text.rich(
|
||||
_getDisplayText(
|
||||
text,
|
||||
text!,
|
||||
lastMessage.mentionedUsers,
|
||||
lastMessage.attachments,
|
||||
StreamChatTheme.of(context).channelPreviewTheme.subtitle.copyWith(
|
||||
StreamChatTheme.of(context).channelPreviewTheme.subtitle!.copyWith(
|
||||
color: StreamChatTheme.of(context)
|
||||
.channelPreviewTheme
|
||||
.subtitle
|
||||
.subtitle!
|
||||
.color,
|
||||
fontStyle: (lastMessage.isSystem || lastMessage.isDeleted)
|
||||
? FontStyle.italic
|
||||
: FontStyle.normal),
|
||||
StreamChatTheme.of(context).channelPreviewTheme.subtitle.copyWith(
|
||||
StreamChatTheme.of(context).channelPreviewTheme.subtitle!.copyWith(
|
||||
color: StreamChatTheme.of(context)
|
||||
.channelPreviewTheme
|
||||
.subtitle
|
||||
.subtitle!
|
||||
.color,
|
||||
fontStyle: (lastMessage.isSystem || lastMessage.isDeleted)
|
||||
? FontStyle.italic
|
||||
@@ -321,8 +321,8 @@ class MyChannelPreview extends StatelessWidget {
|
||||
|
||||
class ChannelUnreadIndicator extends StatelessWidget {
|
||||
const ChannelUnreadIndicator({
|
||||
Key key,
|
||||
@required this.channel,
|
||||
Key? key,
|
||||
required this.channel,
|
||||
}) : super(key: key);
|
||||
|
||||
final Channel channel;
|
||||
@@ -330,8 +330,8 @@ class ChannelUnreadIndicator extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return StreamBuilder<int>(
|
||||
stream: channel.state.unreadCountStream,
|
||||
initialData: channel.state.unreadCount,
|
||||
stream: channel.state!.unreadCountStream,
|
||||
initialData: channel.state!.unreadCount,
|
||||
builder: (context, snapshot) {
|
||||
if (!snapshot.hasData || snapshot.data == 0) {
|
||||
return SizedBox();
|
||||
@@ -351,7 +351,7 @@ class ChannelUnreadIndicator extends StatelessWidget {
|
||||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
'${snapshot.data > 99 ? '99+' : snapshot.data}',
|
||||
'${snapshot.data! > 99 ? '99+' : snapshot.data}',
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
color: Colors.white,
|
||||
|
||||
@@ -23,11 +23,10 @@ class ChatView extends StatelessWidget {
|
||||
),
|
||||
body: ChannelsBloc(
|
||||
child: ChannelListView(
|
||||
filter: {
|
||||
'members': {
|
||||
'\$in': [StreamChat.of(context).user?.id],
|
||||
}
|
||||
},
|
||||
filter: Filter.in_(
|
||||
'members',
|
||||
[StreamChat.of(context).user!.id],
|
||||
),
|
||||
sort: [SortOption('last_message_at')],
|
||||
channelPreviewBuilder: (context, channel) {
|
||||
return Container(
|
||||
@@ -36,22 +35,22 @@ class ChatView extends StatelessWidget {
|
||||
channel: channel,
|
||||
heroTag: channel.id,
|
||||
onImageTap: () {
|
||||
String name;
|
||||
String image;
|
||||
String? name;
|
||||
String? image;
|
||||
final currentUser = StreamChat.of(context).client.state.user;
|
||||
if (channel.isGroup) {
|
||||
name = channel.extraData['name'];
|
||||
image = channel.extraData['image'];
|
||||
} else {
|
||||
final friend = channel.state.members
|
||||
.where((element) => element.userId != currentUser.id)
|
||||
final friend = channel.state!.members
|
||||
.where((element) => element.userId != currentUser!.id)
|
||||
.first
|
||||
.user;
|
||||
.user!;
|
||||
name = friend.name;
|
||||
image = friend.extraData['image'];
|
||||
image = friend.extraData['image'] as String?;
|
||||
}
|
||||
|
||||
return Navigator.of(context).push(
|
||||
Navigator.of(context).push(
|
||||
PageRouteBuilder(
|
||||
barrierColor: Colors.black45,
|
||||
barrierDismissible: true,
|
||||
@@ -110,15 +109,15 @@ class ChannelPage extends StatelessWidget {
|
||||
|
||||
class ChatDetailView extends StatelessWidget {
|
||||
const ChatDetailView({
|
||||
Key key,
|
||||
Key? key,
|
||||
this.image,
|
||||
this.name,
|
||||
this.channelId,
|
||||
}) : super(key: key);
|
||||
|
||||
final String image;
|
||||
final String name;
|
||||
final String channelId;
|
||||
final String? image;
|
||||
final String? name;
|
||||
final String? channelId;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -135,10 +134,10 @@ class ChatDetailView extends StatelessWidget {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Hero(
|
||||
tag: channelId,
|
||||
tag: channelId!,
|
||||
child: ClipOval(
|
||||
child: Image.network(
|
||||
image,
|
||||
image!,
|
||||
height: 180,
|
||||
width: 180,
|
||||
fit: BoxFit.cover,
|
||||
@@ -146,7 +145,7 @@ class ChatDetailView extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
Text(
|
||||
name,
|
||||
name!,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w700,
|
||||
fontSize: 22,
|
||||
|
||||
@@ -143,9 +143,9 @@ class FriendsSelectionView extends StatelessWidget {
|
||||
CircleAvatar(
|
||||
radius: 30,
|
||||
backgroundImage: NetworkImage(
|
||||
chatUserState.chatUser.image),
|
||||
chatUserState.chatUser.image!),
|
||||
),
|
||||
Text(chatUserState.chatUser.name),
|
||||
Text(chatUserState.chatUser.name!),
|
||||
],
|
||||
),
|
||||
Positioned(
|
||||
@@ -178,9 +178,9 @@ class FriendsSelectionView extends StatelessWidget {
|
||||
},
|
||||
leading: CircleAvatar(
|
||||
backgroundImage:
|
||||
NetworkImage(chatUserState.chatUser.image),
|
||||
NetworkImage(chatUserState.chatUser.image!),
|
||||
),
|
||||
title: Text(chatUserState.chatUser.name),
|
||||
title: Text(chatUserState.chatUser.name!),
|
||||
trailing: isGroup
|
||||
? Checkbox(
|
||||
value: chatUserState.selected,
|
||||
|
||||
@@ -13,8 +13,8 @@ class GroupSelectionState {
|
||||
this.channel,
|
||||
this.isLoading = false,
|
||||
});
|
||||
final File file;
|
||||
final Channel channel;
|
||||
final File? file;
|
||||
final Channel? channel;
|
||||
final bool isLoading;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ class GroupSelectionView extends StatelessWidget {
|
||||
context,
|
||||
Scaffold(
|
||||
body: StreamChannel(
|
||||
channel: snapshot.channel,
|
||||
channel: snapshot.channel!,
|
||||
child: ChannelPage(),
|
||||
),
|
||||
),
|
||||
@@ -60,9 +60,9 @@ class GroupSelectionView extends StatelessWidget {
|
||||
children: [
|
||||
AvatarImageView(
|
||||
onTap: context.read<GroupSelectionCubit>().pickImage,
|
||||
child: snapshot?.file != null
|
||||
child: snapshot.file != null
|
||||
? Image.file(
|
||||
snapshot?.file,
|
||||
snapshot.file!,
|
||||
fit: BoxFit.cover,
|
||||
)
|
||||
: Icon(
|
||||
@@ -104,9 +104,9 @@ class GroupSelectionView extends StatelessWidget {
|
||||
CircleAvatar(
|
||||
radius: 30,
|
||||
backgroundImage:
|
||||
NetworkImage(chatUserState.chatUser.image),
|
||||
NetworkImage(chatUserState.chatUser.image!),
|
||||
),
|
||||
Text(chatUserState.chatUser.name),
|
||||
Text(chatUserState.chatUser.name!),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
@@ -36,7 +36,7 @@ class HomeView extends StatelessWidget {
|
||||
|
||||
class HomeNavigationBar extends StatelessWidget {
|
||||
const HomeNavigationBar({
|
||||
Key key,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
@@ -110,16 +110,16 @@ class HomeNavigationBar extends StatelessWidget {
|
||||
|
||||
class _HomeNavItem extends StatelessWidget {
|
||||
const _HomeNavItem({
|
||||
Key key,
|
||||
Key? key,
|
||||
this.iconData,
|
||||
this.text,
|
||||
this.onTap,
|
||||
this.selected = false,
|
||||
}) : super(key: key);
|
||||
|
||||
final IconData iconData;
|
||||
final String text;
|
||||
final VoidCallback onTap;
|
||||
final IconData? iconData;
|
||||
final String? text;
|
||||
final VoidCallback? onTap;
|
||||
final bool selected;
|
||||
|
||||
@override
|
||||
@@ -135,7 +135,7 @@ class _HomeNavItem extends StatelessWidget {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(iconData, color: color),
|
||||
Text(text, style: TextStyle(color: color)),
|
||||
Text(text!, style: TextStyle(color: color)),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
@@ -10,8 +10,8 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
||||
class SettingsView extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final user = StreamChat.of(context).client.state.user;
|
||||
final image = user?.extraData['image'];
|
||||
final user = StreamChat.of(context).client.state.user!;
|
||||
final image = user.extraData['image'];
|
||||
final textColor = Theme.of(context).appBarTheme.color;
|
||||
return MultiBlocProvider(
|
||||
providers: [
|
||||
@@ -48,7 +48,7 @@ class SettingsView extends StatelessWidget {
|
||||
onTap: () => null,
|
||||
child: image != null
|
||||
? Image.network(
|
||||
image,
|
||||
image as String,
|
||||
fit: BoxFit.cover,
|
||||
)
|
||||
: Icon(
|
||||
|
||||
@@ -11,7 +11,7 @@ class ProfileState {
|
||||
this.success = false,
|
||||
this.loading = false,
|
||||
});
|
||||
final File file;
|
||||
final File? file;
|
||||
final bool success;
|
||||
final bool loading;
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ class ProfileVerifyView extends StatelessWidget {
|
||||
onTap: context.read<ProfileVerifyCubit>().pickImage,
|
||||
child: snapshot.file != null
|
||||
? Image.file(
|
||||
snapshot.file,
|
||||
snapshot.file!,
|
||||
fit: BoxFit.cover,
|
||||
)
|
||||
: Icon(
|
||||
|
||||
Reference in New Issue
Block a user