mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-01-15 13:08:42 +00:00
fix #189
This commit is contained in:
parent
d488e4db2c
commit
24cf6e552f
6 changed files with 271 additions and 307 deletions
|
|
@ -1,100 +0,0 @@
|
|||
import 'dart:convert';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:twonly/src/views/chats/chat_messages_components/chat_message_entry_components/chat_media_entry.dart';
|
||||
import 'package:twonly/src/views/chats/chat_messages_components/chat_message_entry_components/chat_reaction_row.dart';
|
||||
import 'package:twonly/src/views/chats/chat_messages_components/chat_message_entry_components/chat_text_entry.dart';
|
||||
import 'package:twonly/src/views/chats/chat_messages_components/chat_message_entry_components/chat_text_response_columns.dart';
|
||||
import 'package:twonly/src/views/chats/chat_messages_components/sliding_response.dart';
|
||||
import 'package:twonly/src/database/twonly_database.dart';
|
||||
import 'package:twonly/src/model/json/message.dart';
|
||||
|
||||
class ChatListEntry extends StatefulWidget {
|
||||
const ChatListEntry(
|
||||
this.message,
|
||||
this.contact,
|
||||
this.lastMessageFromSameUser,
|
||||
this.textReactions,
|
||||
this.otherReactions, {
|
||||
super.key,
|
||||
required this.onResponseTriggered,
|
||||
});
|
||||
final Message message;
|
||||
final Contact contact;
|
||||
final bool lastMessageFromSameUser;
|
||||
final List<Message> textReactions;
|
||||
final List<Message> otherReactions;
|
||||
final Function(Message) onResponseTriggered;
|
||||
|
||||
@override
|
||||
State<ChatListEntry> createState() => _ChatListEntryState();
|
||||
}
|
||||
|
||||
class _ChatListEntryState extends State<ChatListEntry> {
|
||||
MessageContent? content;
|
||||
String? textMessage;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
final msgContent = MessageContent.fromJson(
|
||||
widget.message.kind, jsonDecode(widget.message.contentJson!));
|
||||
if (msgContent is TextMessageContent) {
|
||||
textMessage = msgContent.text;
|
||||
}
|
||||
content = msgContent;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (content == null) return Container();
|
||||
bool right = widget.message.messageOtherId == null;
|
||||
|
||||
return Align(
|
||||
alignment: right ? Alignment.centerRight : Alignment.centerLeft,
|
||||
child: Padding(
|
||||
padding: widget.lastMessageFromSameUser
|
||||
? EdgeInsets.only(top: 5, bottom: 0, right: 10, left: 10)
|
||||
: EdgeInsets.only(top: 5, bottom: 20, right: 10, left: 10),
|
||||
child: Column(
|
||||
mainAxisAlignment:
|
||||
right ? MainAxisAlignment.end : MainAxisAlignment.start,
|
||||
crossAxisAlignment:
|
||||
right ? CrossAxisAlignment.end : CrossAxisAlignment.start,
|
||||
children: [
|
||||
SlidingResponse(
|
||||
child: Stack(
|
||||
alignment: right ? Alignment.centerRight : Alignment.centerLeft,
|
||||
children: [
|
||||
(textMessage != null)
|
||||
? ChatTextEntry(
|
||||
message: widget.message, text: textMessage!)
|
||||
: ChatMediaEntry(
|
||||
message: widget.message,
|
||||
contact: widget.contact,
|
||||
content: content!,
|
||||
),
|
||||
Positioned(
|
||||
bottom: 5,
|
||||
left: 5,
|
||||
right: 5,
|
||||
child: ReactionRow(
|
||||
otherReactions: widget.otherReactions,
|
||||
message: widget.message,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
onResponseTriggered: () {
|
||||
widget.onResponseTriggered(widget.message);
|
||||
},
|
||||
),
|
||||
ChatTextResponseColumns(
|
||||
textReactions: widget.textReactions,
|
||||
right: right,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -7,11 +7,13 @@ import 'package:twonly/src/views/chats/chat_messages_components/chat_message_ent
|
|||
import 'package:twonly/src/views/chats/chat_messages_components/sliding_response.dart';
|
||||
import 'package:twonly/src/database/twonly_database.dart';
|
||||
import 'package:twonly/src/model/json/message.dart';
|
||||
import 'package:twonly/src/views/gallery/gallery_main_view.dart';
|
||||
|
||||
class ChatListEntry extends StatefulWidget {
|
||||
const ChatListEntry(
|
||||
this.message,
|
||||
this.contact,
|
||||
this.galleryItems,
|
||||
this.lastMessageFromSameUser,
|
||||
this.textReactions,
|
||||
this.otherReactions, {
|
||||
|
|
@ -23,6 +25,7 @@ class ChatListEntry extends StatefulWidget {
|
|||
final bool lastMessageFromSameUser;
|
||||
final List<Message> textReactions;
|
||||
final List<Message> otherReactions;
|
||||
final List<GalleryItem> galleryItems;
|
||||
final Function(Message) onResponseTriggered;
|
||||
|
||||
@override
|
||||
|
|
@ -49,52 +52,56 @@ class _ChatListEntryState extends State<ChatListEntry> {
|
|||
if (content == null) return Container();
|
||||
bool right = widget.message.messageOtherId == null;
|
||||
|
||||
return Align(
|
||||
alignment: right ? Alignment.centerRight : Alignment.centerLeft,
|
||||
child: Padding(
|
||||
padding: widget.lastMessageFromSameUser
|
||||
? EdgeInsets.only(top: 5, bottom: 0, right: 10, left: 10)
|
||||
: EdgeInsets.only(top: 5, bottom: 20, right: 10, left: 10),
|
||||
child: Column(
|
||||
mainAxisAlignment:
|
||||
right ? MainAxisAlignment.end : MainAxisAlignment.start,
|
||||
crossAxisAlignment:
|
||||
right ? CrossAxisAlignment.end : CrossAxisAlignment.start,
|
||||
children: [
|
||||
SlidingResponse(
|
||||
child: Stack(
|
||||
alignment: right ? Alignment.centerRight : Alignment.centerLeft,
|
||||
children: [
|
||||
(textMessage != null)
|
||||
? ChatTextEntry(
|
||||
message: widget.message, text: textMessage!)
|
||||
: ChatMediaEntry(
|
||||
return Hero(
|
||||
tag: "${widget.message.mediaUploadId ?? widget.message.messageId}",
|
||||
child: Align(
|
||||
alignment: right ? Alignment.centerRight : Alignment.centerLeft,
|
||||
child: Padding(
|
||||
padding: widget.lastMessageFromSameUser
|
||||
? EdgeInsets.only(top: 5, bottom: 0, right: 10, left: 10)
|
||||
: EdgeInsets.only(top: 5, bottom: 20, right: 10, left: 10),
|
||||
child: Column(
|
||||
mainAxisAlignment:
|
||||
right ? MainAxisAlignment.end : MainAxisAlignment.start,
|
||||
crossAxisAlignment:
|
||||
right ? CrossAxisAlignment.end : CrossAxisAlignment.start,
|
||||
children: [
|
||||
SlidingResponse(
|
||||
child: Stack(
|
||||
alignment:
|
||||
right ? Alignment.centerRight : Alignment.centerLeft,
|
||||
children: [
|
||||
(textMessage != null)
|
||||
? ChatTextEntry(
|
||||
message: widget.message, text: textMessage!)
|
||||
: ChatMediaEntry(
|
||||
message: widget.message,
|
||||
contact: widget.contact,
|
||||
galleryItems: widget.galleryItems,
|
||||
content: content!,
|
||||
),
|
||||
Positioned(
|
||||
bottom: 5,
|
||||
left: 5,
|
||||
right: 5,
|
||||
child: ReactionRow(
|
||||
otherReactions: widget.otherReactions,
|
||||
message: widget.message,
|
||||
contact: widget.contact,
|
||||
content: content!,
|
||||
),
|
||||
Positioned(
|
||||
bottom: 5,
|
||||
left: 5,
|
||||
right: 5,
|
||||
child: ReactionRow(
|
||||
otherReactions: widget.otherReactions,
|
||||
message: widget.message,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
onResponseTriggered: () {
|
||||
widget.onResponseTriggered(widget.message);
|
||||
},
|
||||
onResponseTriggered: () {
|
||||
widget.onResponseTriggered(widget.message);
|
||||
},
|
||||
),
|
||||
ChatTextResponseColumns(
|
||||
textReactions: widget.textReactions,
|
||||
right: right,
|
||||
)
|
||||
],
|
||||
),
|
||||
ChatTextResponseColumns(
|
||||
textReactions: widget.textReactions,
|
||||
right: right,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import 'package:twonly/src/providers/api/api.dart';
|
|||
import 'package:twonly/src/providers/api/media_received.dart' as received;
|
||||
import 'package:twonly/src/services/notification_service.dart';
|
||||
import 'package:twonly/src/views/chats/media_viewer_view.dart';
|
||||
import 'package:twonly/src/views/gallery/gallery_main_view.dart';
|
||||
|
||||
class ChatMediaEntry extends StatelessWidget {
|
||||
const ChatMediaEntry({
|
||||
|
|
@ -16,11 +17,13 @@ class ChatMediaEntry extends StatelessWidget {
|
|||
required this.message,
|
||||
required this.contact,
|
||||
required this.content,
|
||||
required this.galleryItems,
|
||||
});
|
||||
|
||||
final Message message;
|
||||
final Contact contact;
|
||||
final MessageContent content;
|
||||
final List<GalleryItem> galleryItems;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
@ -70,15 +73,8 @@ class ChatMediaEntry extends StatelessWidget {
|
|||
}
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
child: SizedBox(
|
||||
width: 150,
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
color: color,
|
||||
width: 1.0,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(12.0),
|
||||
),
|
||||
child: Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: ClipRRect(
|
||||
|
|
@ -86,6 +82,8 @@ class ChatMediaEntry extends StatelessWidget {
|
|||
child: InChatMediaViewer(
|
||||
message: message,
|
||||
contact: contact,
|
||||
color: color,
|
||||
galleryItems: galleryItems,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -14,110 +14,121 @@ import 'package:twonly/src/database/twonly_database.dart';
|
|||
import 'package:twonly/src/database/tables/messages_table.dart';
|
||||
import 'package:twonly/src/model/json/message.dart';
|
||||
import 'package:twonly/src/providers/api/media_received.dart' as received;
|
||||
import 'package:twonly/src/views/gallery/gallery_main_view.dart';
|
||||
import 'package:video_player/video_player.dart';
|
||||
|
||||
class ChatMediaViewerFullScreen extends StatefulWidget {
|
||||
const ChatMediaViewerFullScreen(
|
||||
{super.key, required this.message, required this.contact});
|
||||
final Message message;
|
||||
final Contact contact;
|
||||
// class ChatMediaViewerFullScreen extends StatefulWidget {
|
||||
// const ChatMediaViewerFullScreen({
|
||||
// super.key,
|
||||
// required this.message,
|
||||
// required this.contact,
|
||||
// required this.color,
|
||||
// });
|
||||
// final Message message;
|
||||
// final Contact contact;
|
||||
// final Color color;
|
||||
|
||||
@override
|
||||
State<ChatMediaViewerFullScreen> createState() =>
|
||||
_ChatMediaViewerFullScreenState();
|
||||
}
|
||||
// @override
|
||||
// State<ChatMediaViewerFullScreen> createState() =>
|
||||
// _ChatMediaViewerFullScreenState();
|
||||
// }
|
||||
|
||||
class _ChatMediaViewerFullScreenState extends State<ChatMediaViewerFullScreen> {
|
||||
bool hideMediaFile = false;
|
||||
// class _ChatMediaViewerFullScreenState extends State<ChatMediaViewerFullScreen> {
|
||||
// bool hideMediaFile = false;
|
||||
|
||||
Future deleteFiles(context) async {
|
||||
bool confirmed = await showAlertDialog(
|
||||
context, "Are you sure?", "The image will be irrevocably deleted.");
|
||||
// Future deleteFiles(context) async {
|
||||
// bool confirmed = await showAlertDialog(
|
||||
// context, "Are you sure?", "The image will be irrevocably deleted.");
|
||||
|
||||
if (!confirmed) return;
|
||||
// if (!confirmed) return;
|
||||
|
||||
await twonlyDatabase.messagesDao.updateMessageByMessageId(
|
||||
widget.message.messageId,
|
||||
MessagesCompanion(mediaStored: Value(false)),
|
||||
);
|
||||
await send.purgeSendMediaFiles();
|
||||
await received.purgeReceivedMediaFiles();
|
||||
if (context.mounted) {
|
||||
Navigator.pop(context, true);
|
||||
}
|
||||
}
|
||||
// await twonlyDatabase.messagesDao.updateMessageByMessageId(
|
||||
// widget.message.messageId,
|
||||
// MessagesCompanion(mediaStored: Value(false)),
|
||||
// );
|
||||
// await send.purgeSendMediaFiles();
|
||||
// await received.purgeReceivedMediaFiles();
|
||||
// if (context.mounted) {
|
||||
// Navigator.pop(context, true);
|
||||
// }
|
||||
// }
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: MediaViewSizing(
|
||||
bottomNavigation: Positioned(
|
||||
bottom: 10,
|
||||
left: 0,
|
||||
right: 0,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
IconButton.outlined(
|
||||
onPressed: () {
|
||||
deleteFiles(context);
|
||||
},
|
||||
icon: FaIcon(FontAwesomeIcons.trashCan),
|
||||
style: ButtonStyle(
|
||||
padding: WidgetStateProperty.all<EdgeInsets>(
|
||||
EdgeInsets.symmetric(vertical: 10, horizontal: 20),
|
||||
),
|
||||
),
|
||||
),
|
||||
IconButton.filled(
|
||||
icon: FaIcon(FontAwesomeIcons.camera),
|
||||
onPressed: () async {
|
||||
setState(() {
|
||||
hideMediaFile = true;
|
||||
});
|
||||
await Navigator.push(context, MaterialPageRoute(
|
||||
builder: (context) {
|
||||
return CameraSendToView(widget.contact);
|
||||
},
|
||||
));
|
||||
setState(() {
|
||||
hideMediaFile = false;
|
||||
});
|
||||
},
|
||||
style: ButtonStyle(
|
||||
padding: WidgetStateProperty.all<EdgeInsets>(
|
||||
EdgeInsets.symmetric(vertical: 10, horizontal: 30),
|
||||
),
|
||||
backgroundColor: WidgetStateProperty.all<Color>(
|
||||
Theme.of(context).colorScheme.primary,
|
||||
)),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
child: (hideMediaFile)
|
||||
? Container()
|
||||
: InChatMediaViewer(
|
||||
message: widget.message,
|
||||
contact: widget.contact,
|
||||
isInFullscreen: true,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
// @override
|
||||
// Widget build(BuildContext context) {
|
||||
// return Scaffold(
|
||||
// body: MediaViewSizing(
|
||||
// bottomNavigation: Positioned(
|
||||
// bottom: 10,
|
||||
// left: 0,
|
||||
// right: 0,
|
||||
// child: Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
// children: [
|
||||
// IconButton.outlined(
|
||||
// onPressed: () {
|
||||
// deleteFiles(context);
|
||||
// },
|
||||
// icon: FaIcon(FontAwesomeIcons.trashCan),
|
||||
// style: ButtonStyle(
|
||||
// padding: WidgetStateProperty.all<EdgeInsets>(
|
||||
// EdgeInsets.symmetric(vertical: 10, horizontal: 20),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// IconButton.filled(
|
||||
// icon: FaIcon(FontAwesomeIcons.camera),
|
||||
// onPressed: () async {
|
||||
// setState(() {
|
||||
// hideMediaFile = true;
|
||||
// });
|
||||
// await Navigator.push(context, MaterialPageRoute(
|
||||
// builder: (context) {
|
||||
// return CameraSendToView(widget.contact);
|
||||
// },
|
||||
// ));
|
||||
// setState(() {
|
||||
// hideMediaFile = false;
|
||||
// });
|
||||
// },
|
||||
// style: ButtonStyle(
|
||||
// padding: WidgetStateProperty.all<EdgeInsets>(
|
||||
// EdgeInsets.symmetric(vertical: 10, horizontal: 30),
|
||||
// ),
|
||||
// backgroundColor: WidgetStateProperty.all<Color>(
|
||||
// Theme.of(context).colorScheme.primary,
|
||||
// )),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// child: (hideMediaFile)
|
||||
// ? Container()
|
||||
// : Hero(
|
||||
// tag: "chat_entry_${widget.message.messageId}",
|
||||
// child: InChatMediaViewer(
|
||||
// message: widget.message,
|
||||
// contact: widget.contact,
|
||||
// color: widget.color,
|
||||
// isInFullscreen: true,
|
||||
// ),
|
||||
// )),
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
||||
class InChatMediaViewer extends StatefulWidget {
|
||||
const InChatMediaViewer({
|
||||
super.key,
|
||||
required this.message,
|
||||
required this.contact,
|
||||
this.isInFullscreen = false,
|
||||
required this.color,
|
||||
required this.galleryItems,
|
||||
});
|
||||
|
||||
final Message message;
|
||||
final Contact contact;
|
||||
final bool isInFullscreen;
|
||||
final List<GalleryItem> galleryItems;
|
||||
final Color color;
|
||||
|
||||
@override
|
||||
State<InChatMediaViewer> createState() => _InChatMediaViewerState();
|
||||
|
|
@ -184,13 +195,10 @@ class _InChatMediaViewerState extends State<InChatMediaViewer> {
|
|||
}
|
||||
videoController = VideoPlayerController.file(
|
||||
videoPath,
|
||||
videoPlayerOptions:
|
||||
VideoPlayerOptions(mixWithOthers: !widget.isInFullscreen),
|
||||
videoPlayerOptions: VideoPlayerOptions(mixWithOthers: true),
|
||||
);
|
||||
videoController?.initialize().then((_) {
|
||||
if (!widget.isInFullscreen) {
|
||||
videoController!.setVolume(0);
|
||||
}
|
||||
videoController!.setVolume(0);
|
||||
videoController!.play();
|
||||
videoController!.setLooping(true);
|
||||
});
|
||||
|
|
@ -209,51 +217,84 @@ class _InChatMediaViewerState extends State<InChatMediaViewer> {
|
|||
}
|
||||
|
||||
Future onTap() async {
|
||||
bool? removed = await Navigator.push(
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) {
|
||||
return ChatMediaViewerFullScreen(
|
||||
message: widget.message,
|
||||
contact: widget.contact,
|
||||
);
|
||||
}),
|
||||
MaterialPageRoute(
|
||||
builder: (context) => GalleryPhotoViewWrapper(
|
||||
galleryItems: widget.galleryItems,
|
||||
// backgroundDecoration: const BoxDecoration(
|
||||
// color: Colors.black,
|
||||
// ),
|
||||
initialIndex: widget.galleryItems.indexWhere((x) =>
|
||||
x.id ==
|
||||
(widget.message.mediaUploadId ?? widget.message.messageId)
|
||||
.toString()),
|
||||
scrollDirection: Axis.horizontal,
|
||||
),
|
||||
),
|
||||
);
|
||||
// bool? removed = await Navigator.push(
|
||||
// context,
|
||||
// MaterialPageRoute(builder: (context) {
|
||||
// return ChatMediaViewerFullScreen(
|
||||
// message: widget.message,
|
||||
// contact: widget.contact,
|
||||
// color: widget.color,
|
||||
// );
|
||||
// }),
|
||||
// );
|
||||
|
||||
if (removed != null && removed) {
|
||||
image = null;
|
||||
videoController?.dispose();
|
||||
videoController = null;
|
||||
if (isMounted) setState(() {});
|
||||
}
|
||||
// if (removed != null && removed) {
|
||||
// image = null;
|
||||
// videoController?.dispose();
|
||||
// videoController = null;
|
||||
// if (isMounted) setState(() {});
|
||||
// }
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (image == null && video == null) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
child: MessageSendStateIcon(
|
||||
[widget.message],
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
color: widget.color,
|
||||
width: 1.0,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(12.0),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
child: MessageSendStateIcon(
|
||||
[widget.message],
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
return GestureDetector(
|
||||
onTap:
|
||||
((image == null && videoController == null) || widget.isInFullscreen)
|
||||
? null
|
||||
: onTap,
|
||||
child: Stack(
|
||||
children: [
|
||||
if (image != null) Image.file(image!),
|
||||
if (videoController != null)
|
||||
Positioned.fill(
|
||||
child: Transform.flip(
|
||||
flipX: mirrorVideo,
|
||||
child: VideoPlayer(videoController!),
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
color: Colors.transparent,
|
||||
width: 1.0,
|
||||
),
|
||||
color: Colors.transparent,
|
||||
borderRadius: BorderRadius.circular(12.0),
|
||||
),
|
||||
child: GestureDetector(
|
||||
onTap: ((image == null && videoController == null)) ? null : onTap,
|
||||
child: Stack(
|
||||
children: [
|
||||
if (image != null) Image.file(image!),
|
||||
if (videoController != null)
|
||||
Positioned.fill(
|
||||
child: Transform.flip(
|
||||
flipX: mirrorVideo,
|
||||
child: VideoPlayer(videoController!),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import 'package:twonly/src/services/notification_service.dart';
|
|||
import 'package:twonly/src/views/camera/camera_send_to_view.dart';
|
||||
import 'package:twonly/src/utils/misc.dart';
|
||||
import 'package:twonly/src/views/contact/contact_view.dart';
|
||||
import 'package:twonly/src/views/gallery/gallery_main_view.dart';
|
||||
|
||||
Color getMessageColor(Message message) {
|
||||
return (message.messageOtherId == null)
|
||||
|
|
@ -43,6 +44,7 @@ class _ChatMessagesViewState extends State<ChatMessagesView> {
|
|||
late StreamSubscription<Contact> userSub;
|
||||
late StreamSubscription<List<Message>> messageSub;
|
||||
List<Message> messages = [];
|
||||
List<GalleryItem> galleryItems = [];
|
||||
Map<int, List<Message>> textReactionsToMessageId = {};
|
||||
Map<int, List<Message>> emojiReactionsToMessageId = {};
|
||||
Message? responseToMessage;
|
||||
|
|
@ -76,7 +78,7 @@ class _ChatMessagesViewState extends State<ChatMessagesView> {
|
|||
|
||||
Stream<List<Message>> msgStream =
|
||||
twonlyDatabase.messagesDao.watchAllMessagesFrom(widget.contact.userId);
|
||||
messageSub = msgStream.listen((msgs) {
|
||||
messageSub = msgStream.listen((msgs) async {
|
||||
// if (!context.mounted) return;
|
||||
if (Platform.isAndroid) {
|
||||
flutterLocalNotificationsPlugin.cancel(widget.contact.userId);
|
||||
|
|
@ -131,6 +133,7 @@ class _ChatMessagesViewState extends State<ChatMessagesView> {
|
|||
displayedMessages.add(msg);
|
||||
}
|
||||
}
|
||||
|
||||
if (openedMessageOtherIds.isNotEmpty) {
|
||||
notifyContactAboutOpeningMessage(
|
||||
widget.contact.userId, openedMessageOtherIds);
|
||||
|
|
@ -145,7 +148,15 @@ class _ChatMessagesViewState extends State<ChatMessagesView> {
|
|||
emojiReactionsToMessageId = tmpEmojiReactionsToMessageId;
|
||||
messages = displayedMessages;
|
||||
});
|
||||
// }
|
||||
Map<int, GalleryItem> items = await GalleryItem.convertFromMessages(
|
||||
displayedMessages
|
||||
.where((x) => x.kind == MessageKind.media)
|
||||
.toList()
|
||||
.reversed
|
||||
.toList());
|
||||
setState(() {
|
||||
galleryItems = items.values.toList();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -299,6 +310,7 @@ class _ChatMessagesViewState extends State<ChatMessagesView> {
|
|||
key: Key(messages[i].messageId.toString()),
|
||||
messages[i],
|
||||
user,
|
||||
galleryItems,
|
||||
isLastMessageFromSameUser(messages, i),
|
||||
textReactionsToMessageId[messages[i].messageId] ?? [],
|
||||
emojiReactionsToMessageId[messages[i].messageId] ?? [],
|
||||
|
|
|
|||
|
|
@ -26,6 +26,40 @@ class GalleryItem {
|
|||
final DateTime date;
|
||||
final File? imagePath;
|
||||
final File? videoPath;
|
||||
|
||||
static Future<Map<int, GalleryItem>> convertFromMessages(
|
||||
List<Message> messages) async {
|
||||
Map<int, GalleryItem> items = {};
|
||||
for (final message in messages) {
|
||||
bool isSend = message.messageOtherId == null;
|
||||
int id = message.mediaUploadId ?? message.messageId;
|
||||
final basePath = await send.getMediaFilePath(
|
||||
isSend ? message.mediaUploadId! : message.messageId,
|
||||
isSend ? "send" : "received",
|
||||
);
|
||||
File? imagePath;
|
||||
File? videoPath;
|
||||
if (await File("$basePath.mp4").exists()) {
|
||||
videoPath = File("$basePath.mp4");
|
||||
} else if (await File("$basePath.png").exists()) {
|
||||
imagePath = File("$basePath.png");
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
items
|
||||
.putIfAbsent(
|
||||
id,
|
||||
() => GalleryItem(
|
||||
id: id.toString(),
|
||||
messages: [],
|
||||
date: message.sendAt,
|
||||
imagePath: imagePath,
|
||||
videoPath: videoPath))
|
||||
.messages
|
||||
.add(message);
|
||||
}
|
||||
return items;
|
||||
}
|
||||
}
|
||||
|
||||
class GalleryItemGrid {
|
||||
|
|
@ -180,40 +214,12 @@ class GalleryMainViewState extends State<GalleryMainView> {
|
|||
List<Message> storedMediaFiles =
|
||||
await twonlyDatabase.messagesDao.getAllStoredMediaFiles();
|
||||
|
||||
Map<int, GalleryItem> items = {};
|
||||
for (final message in storedMediaFiles) {
|
||||
bool isSend = message.messageOtherId == null;
|
||||
int id = message.mediaUploadId ?? message.messageId;
|
||||
final basePath = await send.getMediaFilePath(
|
||||
isSend ? message.mediaUploadId! : message.messageId,
|
||||
isSend ? "send" : "received",
|
||||
);
|
||||
File? imagePath;
|
||||
File? videoPath;
|
||||
if (await File("$basePath.mp4").exists()) {
|
||||
videoPath = File("$basePath.mp4");
|
||||
} else if (await File("$basePath.png").exists()) {
|
||||
imagePath = File("$basePath.png");
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
items
|
||||
.putIfAbsent(
|
||||
id,
|
||||
() => GalleryItem(
|
||||
id: id.toString(),
|
||||
messages: [],
|
||||
date: message.sendAt,
|
||||
imagePath: imagePath,
|
||||
videoPath: videoPath))
|
||||
.messages
|
||||
.add(message);
|
||||
}
|
||||
Map<int, GalleryItem> items =
|
||||
await GalleryItem.convertFromMessages(storedMediaFiles);
|
||||
|
||||
// Group items by month
|
||||
orderedByMonth = {};
|
||||
months = [];
|
||||
|
||||
String lastMonth = "";
|
||||
galleryItems = await loadMemoriesDirectory();
|
||||
galleryItems += items.values.toList();
|
||||
|
|
|
|||
Loading…
Reference in a new issue