migrate app
This commit is contained in:
@@ -4,7 +4,7 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart' show Channel;
|
||||
import 'package:imessage/utils.dart';
|
||||
|
||||
class ChannelImage extends StatelessWidget {
|
||||
const ChannelImage({Key key, @required this.channel, @required this.size})
|
||||
const ChannelImage({Key? key, required this.channel, required this.size})
|
||||
: super(key: key);
|
||||
|
||||
final Channel channel;
|
||||
@@ -14,7 +14,7 @@ class ChannelImage extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
final avatarUrl = channel.extraData.containsKey('image') &&
|
||||
(channel.extraData['image'] as String).isNotEmpty
|
||||
? channel.extraData['image'] as String
|
||||
? channel.extraData['image'] as String?
|
||||
: 'https://4.bp.blogspot.com/-Jx21kNqFSTU/UXemtqPhZCI/AAAAAAAAh74/BMGSzpU6F48/s1600/funny-cat-pictures-047-001.jpg';
|
||||
|
||||
return CupertinoCircleAvatar(
|
||||
|
||||
@@ -6,7 +6,7 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart'
|
||||
show Channel, StreamChannel;
|
||||
|
||||
class ChannelListView extends StatelessWidget {
|
||||
const ChannelListView({Key key, @required this.channels}) : super(key: key);
|
||||
const ChannelListView({Key? key, required this.channels}) : super(key: key);
|
||||
final List<Channel> channels;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -36,10 +36,10 @@ class ChannelListView extends StatelessWidget {
|
||||
child,
|
||||
) =>
|
||||
SharedAxisTransition(
|
||||
child: child,
|
||||
animation: animation,
|
||||
secondaryAnimation: secondaryAnimation,
|
||||
transitionType: SharedAxisTransitionType.horizontal,
|
||||
child: child,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -3,8 +3,8 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart' show Channel;
|
||||
|
||||
class ChannelNameText extends StatelessWidget {
|
||||
const ChannelNameText({
|
||||
Key key,
|
||||
@required this.channel,
|
||||
Key? key,
|
||||
required this.channel,
|
||||
this.size = 17,
|
||||
}) : super(key: key);
|
||||
|
||||
@@ -14,7 +14,7 @@ class ChannelNameText extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Text(
|
||||
channel.extraData['name'] as String ?? 'No name',
|
||||
channel.extraData['name'] as String? ?? 'No name',
|
||||
style: TextStyle(
|
||||
fontSize: size,
|
||||
fontWeight: FontWeight.bold,
|
||||
|
||||
@@ -2,7 +2,7 @@ import 'package:flutter/cupertino.dart';
|
||||
|
||||
class ChannelPageAppBar extends StatelessWidget {
|
||||
const ChannelPageAppBar({
|
||||
Key key,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
|
||||
@@ -11,19 +11,20 @@ class ChannelPreview extends StatelessWidget {
|
||||
final Channel channel;
|
||||
|
||||
const ChannelPreview({
|
||||
Key key,
|
||||
@required this.onTap,
|
||||
@required this.channel,
|
||||
Key? key,
|
||||
required this.onTap,
|
||||
required this.channel,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final lastMessage =
|
||||
channel.state.messages.isNotEmpty ? channel.state.messages.last : null;
|
||||
final lastMessage = channel.state!.messages.isNotEmpty
|
||||
? channel.state!.messages.last
|
||||
: null;
|
||||
|
||||
final prefix = lastMessage?.attachments != null
|
||||
? lastMessage?.attachments //TODO: ugly
|
||||
?.map((e) {
|
||||
.map((e) {
|
||||
if (e.type == 'image') {
|
||||
return '📷 ';
|
||||
} else if (e.type == 'video') {
|
||||
@@ -31,8 +32,8 @@ class ChannelPreview extends StatelessWidget {
|
||||
}
|
||||
return null;
|
||||
})
|
||||
?.where((e) => e != null)
|
||||
?.join(' ')
|
||||
.where((e) => e != null)
|
||||
.join(' ')
|
||||
: '';
|
||||
return GestureDetector(
|
||||
onTap: onTap,
|
||||
@@ -76,9 +77,9 @@ class ChannelPreview extends StatelessWidget {
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
isSameWeek(channel.lastMessageAt)
|
||||
? formatDateSameWeek(channel.lastMessageAt)
|
||||
: formatDate(channel.lastMessageAt),
|
||||
isSameWeek(channel.lastMessageAt!)
|
||||
? formatDateSameWeek(channel.lastMessageAt!)
|
||||
: formatDate(channel.lastMessageAt!),
|
||||
style: TextStyle(
|
||||
fontSize: 15,
|
||||
color: CupertinoColors.systemGrey,
|
||||
|
||||
@@ -2,10 +2,10 @@ import 'package:flutter/cupertino.dart';
|
||||
|
||||
class ChatBubble extends CustomPainter {
|
||||
final Color color;
|
||||
final Alignment alignment;
|
||||
final Alignment? alignment;
|
||||
|
||||
ChatBubble({
|
||||
@required this.color,
|
||||
required this.color,
|
||||
this.alignment,
|
||||
});
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ Future<void> main() async {
|
||||
|
||||
class IMessage extends StatelessWidget {
|
||||
final StreamChatClient client;
|
||||
IMessage({@required this.client});
|
||||
IMessage({required this.client});
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
initializeDateFormatting('en_US', null);
|
||||
@@ -41,14 +41,14 @@ class IMessage extends StatelessWidget {
|
||||
|
||||
class ChatLoader extends StatelessWidget {
|
||||
ChatLoader({
|
||||
Key key,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
final channelListController = ChannelListController();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final user = StreamChatCore.of(context).user;
|
||||
final user = StreamChatCore.of(context).user!;
|
||||
return CupertinoPageScaffold(
|
||||
child: ChannelsBloc(
|
||||
child: ChannelListCore(
|
||||
@@ -87,12 +87,12 @@ class ChatLoader extends StatelessWidget {
|
||||
) =>
|
||||
LazyLoadScrollView(
|
||||
onEndOfPage: () async {
|
||||
return channelListController.paginateData();
|
||||
return channelListController.paginateData!();
|
||||
},
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
CupertinoSliverRefreshControl(onRefresh: () async {
|
||||
return channelListController.loadData();
|
||||
return channelListController.loadData!();
|
||||
}),
|
||||
ChannelPageAppBar(),
|
||||
SliverPadding(
|
||||
|
||||
@@ -4,7 +4,7 @@ import 'package:imessage/utils.dart';
|
||||
|
||||
class MessageHeader extends StatelessWidget {
|
||||
final String rawTimeStamp;
|
||||
const MessageHeader({Key key, @required this.rawTimeStamp}) : super(key: key);
|
||||
const MessageHeader({Key? key, required this.rawTimeStamp}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
@@ -3,11 +3,11 @@ import 'dart:io';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import 'package:stream_chat_flutter/stream_chat_flutter.dart'
|
||||
show Attachment, AttachmentFile, Message, MultipartFile, StreamChannel;
|
||||
show Attachment, AttachmentFile, Message, StreamChannel;
|
||||
|
||||
class MessageInput extends StatefulWidget {
|
||||
const MessageInput({
|
||||
Key key,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
@@ -16,7 +16,6 @@ class MessageInput extends StatefulWidget {
|
||||
|
||||
class _MessageInputState extends State<MessageInput> {
|
||||
final textController = TextEditingController();
|
||||
File _image;
|
||||
final picker = ImagePicker();
|
||||
|
||||
@override
|
||||
@@ -39,16 +38,25 @@ class _MessageInputState extends State<MessageInput> {
|
||||
GestureDetector(
|
||||
onTap: () async {
|
||||
final pickedFile =
|
||||
await picker.getImage(source: ImageSource.gallery);
|
||||
await (picker.getImage(source: ImageSource.gallery));
|
||||
if (pickedFile == null) {
|
||||
return;
|
||||
}
|
||||
final bytes = await File(pickedFile.path).readAsBytes();
|
||||
final channel = StreamChannel.of(context).channel;
|
||||
final message =
|
||||
Message(text: textController.value.text, attachments: [
|
||||
Attachment(
|
||||
type: 'image',
|
||||
file: AttachmentFile(bytes: bytes, path: pickedFile.path),
|
||||
),
|
||||
]);
|
||||
final message = Message(
|
||||
text: textController.value.text,
|
||||
attachments: [
|
||||
Attachment(
|
||||
type: 'image',
|
||||
file: AttachmentFile(
|
||||
bytes: bytes,
|
||||
path: pickedFile.path,
|
||||
size: bytes.length,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
await channel.sendMessage(message);
|
||||
},
|
||||
child: Padding(
|
||||
@@ -68,10 +76,11 @@ class _MessageInputState extends State<MessageInput> {
|
||||
},
|
||||
placeholder: 'Text Message',
|
||||
prefix: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(
|
||||
"") //trick to add padding around placeholder iMessage text
|
||||
),
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(
|
||||
'',
|
||||
), //trick to add padding around placeholder iMessage text
|
||||
),
|
||||
suffix: GestureDetector(
|
||||
onTap: () async {
|
||||
if (textController.value.text.isNotEmpty) {
|
||||
|
||||
@@ -7,12 +7,12 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart'
|
||||
show Message, StreamChatCore;
|
||||
|
||||
class MessageListView extends StatelessWidget {
|
||||
const MessageListView({Key key, this.messages}) : super(key: key);
|
||||
final List<Message> messages;
|
||||
const MessageListView({Key? key, this.messages}) : super(key: key);
|
||||
final List<Message>? messages;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final entries = groupBy(messages,
|
||||
final entries = groupBy(messages!,
|
||||
(Message message) => message.createdAt.toString().substring(0, 10))
|
||||
.entries
|
||||
.toList();
|
||||
@@ -64,8 +64,8 @@ class MessageListView extends StatelessWidget {
|
||||
}
|
||||
|
||||
bool isReceived(Message message, BuildContext context) {
|
||||
final currentUserId = StreamChatCore.of(context).user.id;
|
||||
return message.user.id == currentUserId;
|
||||
final currentUserId = StreamChatCore.of(context).user!.id;
|
||||
return message.user!.id == currentUserId;
|
||||
}
|
||||
|
||||
bool isSameDay(Message message) =>
|
||||
|
||||
@@ -53,7 +53,7 @@ class MessagePage extends StatelessWidget {
|
||||
},
|
||||
messageListBuilder: (context, messages) => LazyLoadScrollView(
|
||||
onStartOfPage: () async {
|
||||
messageListController.paginateData();
|
||||
await messageListController.paginateData!();
|
||||
},
|
||||
child: MessageListView(
|
||||
messages: messages,
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:imessage/cutom_painter.dart';
|
||||
import 'package:stream_chat_flutter/stream_chat_flutter.dart'
|
||||
show Message, AttachmentUploadStateBuilder;
|
||||
import 'package:stream_chat_flutter/stream_chat_flutter.dart' show Message;
|
||||
|
||||
class MessageWidget extends StatelessWidget {
|
||||
final Alignment alignment;
|
||||
@@ -11,16 +10,16 @@ class MessageWidget extends StatelessWidget {
|
||||
final Color messageColor;
|
||||
|
||||
const MessageWidget(
|
||||
{Key key,
|
||||
@required this.alignment,
|
||||
@required this.message,
|
||||
@required this.color,
|
||||
@required this.messageColor})
|
||||
{Key? key,
|
||||
required this.alignment,
|
||||
required this.message,
|
||||
required this.color,
|
||||
required this.messageColor})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (message.attachments?.isNotEmpty == true &&
|
||||
if (message.attachments.isNotEmpty == true &&
|
||||
message.attachments.first.type == 'image') {
|
||||
return MessageImage(
|
||||
color: color, message: message, messageColor: messageColor);
|
||||
@@ -36,10 +35,10 @@ class MessageWidget extends StatelessWidget {
|
||||
|
||||
class MessageImage extends StatelessWidget {
|
||||
const MessageImage({
|
||||
Key key,
|
||||
@required this.color,
|
||||
@required this.message,
|
||||
@required this.messageColor,
|
||||
Key? key,
|
||||
required this.color,
|
||||
required this.message,
|
||||
required this.messageColor,
|
||||
}) : super(key: key);
|
||||
|
||||
final Color color;
|
||||
@@ -61,23 +60,23 @@ class MessageImage extends StatelessWidget {
|
||||
children: [
|
||||
if (message.attachments.first.file != null)
|
||||
Image.memory(
|
||||
message.attachments.first.file.bytes,
|
||||
message.attachments.first.file!.bytes!,
|
||||
fit: BoxFit.cover,
|
||||
)
|
||||
else
|
||||
CachedNetworkImage(
|
||||
imageUrl: message.attachments.first.thumbUrl ??
|
||||
message.attachments.first.imageUrl ??
|
||||
message.attachments.first.assetUrl,
|
||||
message.attachments.first.assetUrl!,
|
||||
),
|
||||
if (message.attachments.first?.title != null)
|
||||
if (message.attachments.first.title != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(message.attachments.first.title,
|
||||
child: Text(message.attachments.first.title!,
|
||||
style: TextStyle(color: messageColor)),
|
||||
),
|
||||
message.attachments.first.pretext != null
|
||||
? Text(message.attachments.first.pretext)
|
||||
? Text(message.attachments.first.pretext!)
|
||||
: Container()
|
||||
],
|
||||
),
|
||||
@@ -92,7 +91,7 @@ class MessageImage extends StatelessWidget {
|
||||
child: Container(
|
||||
color: color,
|
||||
child: CachedNetworkImage(
|
||||
imageUrl: message.attachments.first.thumbUrl,
|
||||
imageUrl: message.attachments.first.thumbUrl!,
|
||||
)),
|
||||
);
|
||||
}
|
||||
@@ -101,11 +100,11 @@ class MessageImage extends StatelessWidget {
|
||||
|
||||
class MessageText extends StatelessWidget {
|
||||
const MessageText({
|
||||
Key key,
|
||||
@required this.alignment,
|
||||
@required this.color,
|
||||
@required this.message,
|
||||
@required this.messageColor,
|
||||
Key? key,
|
||||
required this.alignment,
|
||||
required this.color,
|
||||
required this.message,
|
||||
required this.messageColor,
|
||||
}) : super(key: key);
|
||||
|
||||
final Alignment alignment;
|
||||
@@ -133,7 +132,7 @@ class MessageText extends StatelessWidget {
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(4.0),
|
||||
child: Text(
|
||||
message.text,
|
||||
message.text!,
|
||||
style: TextStyle(color: messageColor),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -26,24 +26,26 @@ bool isSameWeek(DateTime timestamp) =>
|
||||
DateTime.now().difference(timestamp).inDays < 7;
|
||||
|
||||
class CupertinoCircleAvatar extends StatelessWidget {
|
||||
final String url;
|
||||
final double size;
|
||||
const CupertinoCircleAvatar({Key key, this.url, this.size}) : super(key: key);
|
||||
final String? url;
|
||||
final double? size;
|
||||
const CupertinoCircleAvatar({Key? key, this.url, this.size})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ClipRRect(
|
||||
borderRadius: BorderRadius.circular(size / 2),
|
||||
borderRadius: BorderRadius.circular(size! / 2),
|
||||
child: CachedNetworkImage(
|
||||
imageUrl: url,
|
||||
imageUrl: url!,
|
||||
height: size,
|
||||
width: size,
|
||||
fit: BoxFit.cover,
|
||||
errorWidget: (context, url, error) {
|
||||
//TODO: this crash the app when getting 404 and in debug mode, see :https://github.com/Baseflow/flutter_cached_network_image/issues/504
|
||||
return CachedNetworkImage(
|
||||
imageUrl:
|
||||
"https://4.bp.blogspot.com/-Jx21kNqFSTU/UXemtqPhZCI/AAAAAAAAh74/BMGSzpU6F48/s1600/funny-cat-pictures-047-001.jpg");
|
||||
imageUrl:
|
||||
'https://4.bp.blogspot.com/-Jx21kNqFSTU/UXemtqPhZCI/AAAAAAAAh74/BMGSzpU6F48/s1600/funny-cat-pictures-047-001.jp',
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
@@ -51,18 +53,18 @@ class CupertinoCircleAvatar extends StatelessWidget {
|
||||
|
||||
class Divider extends StatelessWidget {
|
||||
const Divider({
|
||||
Key key,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Expanded(
|
||||
child: Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: Container(
|
||||
height: 1,
|
||||
color: CupertinoColors.systemGrey5,
|
||||
),
|
||||
alignment: Alignment.bottomCenter,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||
version: 1.0.0+1
|
||||
|
||||
environment:
|
||||
sdk: ">=2.7.0 <3.0.0"
|
||||
sdk: '>=2.12.0 <3.0.0'
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
|
||||
Reference in New Issue
Block a user