mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-01-15 14:48:41 +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/views/chats/chat_messages_components/sliding_response.dart';
|
||||||
import 'package:twonly/src/database/twonly_database.dart';
|
import 'package:twonly/src/database/twonly_database.dart';
|
||||||
import 'package:twonly/src/model/json/message.dart';
|
import 'package:twonly/src/model/json/message.dart';
|
||||||
|
import 'package:twonly/src/views/gallery/gallery_main_view.dart';
|
||||||
|
|
||||||
class ChatListEntry extends StatefulWidget {
|
class ChatListEntry extends StatefulWidget {
|
||||||
const ChatListEntry(
|
const ChatListEntry(
|
||||||
this.message,
|
this.message,
|
||||||
this.contact,
|
this.contact,
|
||||||
|
this.galleryItems,
|
||||||
this.lastMessageFromSameUser,
|
this.lastMessageFromSameUser,
|
||||||
this.textReactions,
|
this.textReactions,
|
||||||
this.otherReactions, {
|
this.otherReactions, {
|
||||||
|
|
@ -23,6 +25,7 @@ class ChatListEntry extends StatefulWidget {
|
||||||
final bool lastMessageFromSameUser;
|
final bool lastMessageFromSameUser;
|
||||||
final List<Message> textReactions;
|
final List<Message> textReactions;
|
||||||
final List<Message> otherReactions;
|
final List<Message> otherReactions;
|
||||||
|
final List<GalleryItem> galleryItems;
|
||||||
final Function(Message) onResponseTriggered;
|
final Function(Message) onResponseTriggered;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -49,7 +52,9 @@ class _ChatListEntryState extends State<ChatListEntry> {
|
||||||
if (content == null) return Container();
|
if (content == null) return Container();
|
||||||
bool right = widget.message.messageOtherId == null;
|
bool right = widget.message.messageOtherId == null;
|
||||||
|
|
||||||
return Align(
|
return Hero(
|
||||||
|
tag: "${widget.message.mediaUploadId ?? widget.message.messageId}",
|
||||||
|
child: Align(
|
||||||
alignment: right ? Alignment.centerRight : Alignment.centerLeft,
|
alignment: right ? Alignment.centerRight : Alignment.centerLeft,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: widget.lastMessageFromSameUser
|
padding: widget.lastMessageFromSameUser
|
||||||
|
|
@ -63,7 +68,8 @@ class _ChatListEntryState extends State<ChatListEntry> {
|
||||||
children: [
|
children: [
|
||||||
SlidingResponse(
|
SlidingResponse(
|
||||||
child: Stack(
|
child: Stack(
|
||||||
alignment: right ? Alignment.centerRight : Alignment.centerLeft,
|
alignment:
|
||||||
|
right ? Alignment.centerRight : Alignment.centerLeft,
|
||||||
children: [
|
children: [
|
||||||
(textMessage != null)
|
(textMessage != null)
|
||||||
? ChatTextEntry(
|
? ChatTextEntry(
|
||||||
|
|
@ -71,6 +77,7 @@ class _ChatListEntryState extends State<ChatListEntry> {
|
||||||
: ChatMediaEntry(
|
: ChatMediaEntry(
|
||||||
message: widget.message,
|
message: widget.message,
|
||||||
contact: widget.contact,
|
contact: widget.contact,
|
||||||
|
galleryItems: widget.galleryItems,
|
||||||
content: content!,
|
content: content!,
|
||||||
),
|
),
|
||||||
Positioned(
|
Positioned(
|
||||||
|
|
@ -95,6 +102,6 @@ class _ChatListEntryState extends State<ChatListEntry> {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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/providers/api/media_received.dart' as received;
|
||||||
import 'package:twonly/src/services/notification_service.dart';
|
import 'package:twonly/src/services/notification_service.dart';
|
||||||
import 'package:twonly/src/views/chats/media_viewer_view.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 {
|
class ChatMediaEntry extends StatelessWidget {
|
||||||
const ChatMediaEntry({
|
const ChatMediaEntry({
|
||||||
|
|
@ -16,11 +17,13 @@ class ChatMediaEntry extends StatelessWidget {
|
||||||
required this.message,
|
required this.message,
|
||||||
required this.contact,
|
required this.contact,
|
||||||
required this.content,
|
required this.content,
|
||||||
|
required this.galleryItems,
|
||||||
});
|
});
|
||||||
|
|
||||||
final Message message;
|
final Message message;
|
||||||
final Contact contact;
|
final Contact contact;
|
||||||
final MessageContent content;
|
final MessageContent content;
|
||||||
|
final List<GalleryItem> galleryItems;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|
@ -70,15 +73,8 @@ class ChatMediaEntry extends StatelessWidget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: Container(
|
child: SizedBox(
|
||||||
width: 150,
|
width: 150,
|
||||||
decoration: BoxDecoration(
|
|
||||||
border: Border.all(
|
|
||||||
color: color,
|
|
||||||
width: 1.0,
|
|
||||||
),
|
|
||||||
borderRadius: BorderRadius.circular(12.0),
|
|
||||||
),
|
|
||||||
child: Align(
|
child: Align(
|
||||||
alignment: Alignment.centerRight,
|
alignment: Alignment.centerRight,
|
||||||
child: ClipRRect(
|
child: ClipRRect(
|
||||||
|
|
@ -86,6 +82,8 @@ class ChatMediaEntry extends StatelessWidget {
|
||||||
child: InChatMediaViewer(
|
child: InChatMediaViewer(
|
||||||
message: message,
|
message: message,
|
||||||
contact: contact,
|
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/database/tables/messages_table.dart';
|
||||||
import 'package:twonly/src/model/json/message.dart';
|
import 'package:twonly/src/model/json/message.dart';
|
||||||
import 'package:twonly/src/providers/api/media_received.dart' as received;
|
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';
|
import 'package:video_player/video_player.dart';
|
||||||
|
|
||||||
class ChatMediaViewerFullScreen extends StatefulWidget {
|
// class ChatMediaViewerFullScreen extends StatefulWidget {
|
||||||
const ChatMediaViewerFullScreen(
|
// const ChatMediaViewerFullScreen({
|
||||||
{super.key, required this.message, required this.contact});
|
// super.key,
|
||||||
final Message message;
|
// required this.message,
|
||||||
final Contact contact;
|
// required this.contact,
|
||||||
|
// required this.color,
|
||||||
|
// });
|
||||||
|
// final Message message;
|
||||||
|
// final Contact contact;
|
||||||
|
// final Color color;
|
||||||
|
|
||||||
@override
|
// @override
|
||||||
State<ChatMediaViewerFullScreen> createState() =>
|
// State<ChatMediaViewerFullScreen> createState() =>
|
||||||
_ChatMediaViewerFullScreenState();
|
// _ChatMediaViewerFullScreenState();
|
||||||
}
|
// }
|
||||||
|
|
||||||
class _ChatMediaViewerFullScreenState extends State<ChatMediaViewerFullScreen> {
|
// class _ChatMediaViewerFullScreenState extends State<ChatMediaViewerFullScreen> {
|
||||||
bool hideMediaFile = false;
|
// bool hideMediaFile = false;
|
||||||
|
|
||||||
Future deleteFiles(context) async {
|
// Future deleteFiles(context) async {
|
||||||
bool confirmed = await showAlertDialog(
|
// bool confirmed = await showAlertDialog(
|
||||||
context, "Are you sure?", "The image will be irrevocably deleted.");
|
// context, "Are you sure?", "The image will be irrevocably deleted.");
|
||||||
|
|
||||||
if (!confirmed) return;
|
// if (!confirmed) return;
|
||||||
|
|
||||||
await twonlyDatabase.messagesDao.updateMessageByMessageId(
|
// await twonlyDatabase.messagesDao.updateMessageByMessageId(
|
||||||
widget.message.messageId,
|
// widget.message.messageId,
|
||||||
MessagesCompanion(mediaStored: Value(false)),
|
// MessagesCompanion(mediaStored: Value(false)),
|
||||||
);
|
// );
|
||||||
await send.purgeSendMediaFiles();
|
// await send.purgeSendMediaFiles();
|
||||||
await received.purgeReceivedMediaFiles();
|
// await received.purgeReceivedMediaFiles();
|
||||||
if (context.mounted) {
|
// if (context.mounted) {
|
||||||
Navigator.pop(context, true);
|
// Navigator.pop(context, true);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
@override
|
// @override
|
||||||
Widget build(BuildContext context) {
|
// Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
// return Scaffold(
|
||||||
body: MediaViewSizing(
|
// body: MediaViewSizing(
|
||||||
bottomNavigation: Positioned(
|
// bottomNavigation: Positioned(
|
||||||
bottom: 10,
|
// bottom: 10,
|
||||||
left: 0,
|
// left: 0,
|
||||||
right: 0,
|
// right: 0,
|
||||||
child: Row(
|
// child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
// mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
children: [
|
// children: [
|
||||||
IconButton.outlined(
|
// IconButton.outlined(
|
||||||
onPressed: () {
|
// onPressed: () {
|
||||||
deleteFiles(context);
|
// deleteFiles(context);
|
||||||
},
|
// },
|
||||||
icon: FaIcon(FontAwesomeIcons.trashCan),
|
// icon: FaIcon(FontAwesomeIcons.trashCan),
|
||||||
style: ButtonStyle(
|
// style: ButtonStyle(
|
||||||
padding: WidgetStateProperty.all<EdgeInsets>(
|
// padding: WidgetStateProperty.all<EdgeInsets>(
|
||||||
EdgeInsets.symmetric(vertical: 10, horizontal: 20),
|
// EdgeInsets.symmetric(vertical: 10, horizontal: 20),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
IconButton.filled(
|
// IconButton.filled(
|
||||||
icon: FaIcon(FontAwesomeIcons.camera),
|
// icon: FaIcon(FontAwesomeIcons.camera),
|
||||||
onPressed: () async {
|
// onPressed: () async {
|
||||||
setState(() {
|
// setState(() {
|
||||||
hideMediaFile = true;
|
// hideMediaFile = true;
|
||||||
});
|
// });
|
||||||
await Navigator.push(context, MaterialPageRoute(
|
// await Navigator.push(context, MaterialPageRoute(
|
||||||
builder: (context) {
|
// builder: (context) {
|
||||||
return CameraSendToView(widget.contact);
|
// return CameraSendToView(widget.contact);
|
||||||
},
|
// },
|
||||||
));
|
// ));
|
||||||
setState(() {
|
// setState(() {
|
||||||
hideMediaFile = false;
|
// hideMediaFile = false;
|
||||||
});
|
// });
|
||||||
},
|
// },
|
||||||
style: ButtonStyle(
|
// style: ButtonStyle(
|
||||||
padding: WidgetStateProperty.all<EdgeInsets>(
|
// padding: WidgetStateProperty.all<EdgeInsets>(
|
||||||
EdgeInsets.symmetric(vertical: 10, horizontal: 30),
|
// EdgeInsets.symmetric(vertical: 10, horizontal: 30),
|
||||||
),
|
// ),
|
||||||
backgroundColor: WidgetStateProperty.all<Color>(
|
// backgroundColor: WidgetStateProperty.all<Color>(
|
||||||
Theme.of(context).colorScheme.primary,
|
// Theme.of(context).colorScheme.primary,
|
||||||
)),
|
// )),
|
||||||
),
|
// ),
|
||||||
],
|
// ],
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
child: (hideMediaFile)
|
// child: (hideMediaFile)
|
||||||
? Container()
|
// ? Container()
|
||||||
: InChatMediaViewer(
|
// : Hero(
|
||||||
message: widget.message,
|
// tag: "chat_entry_${widget.message.messageId}",
|
||||||
contact: widget.contact,
|
// child: InChatMediaViewer(
|
||||||
isInFullscreen: true,
|
// message: widget.message,
|
||||||
),
|
// contact: widget.contact,
|
||||||
),
|
// color: widget.color,
|
||||||
);
|
// isInFullscreen: true,
|
||||||
}
|
// ),
|
||||||
}
|
// )),
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
class InChatMediaViewer extends StatefulWidget {
|
class InChatMediaViewer extends StatefulWidget {
|
||||||
const InChatMediaViewer({
|
const InChatMediaViewer({
|
||||||
super.key,
|
super.key,
|
||||||
required this.message,
|
required this.message,
|
||||||
required this.contact,
|
required this.contact,
|
||||||
this.isInFullscreen = false,
|
required this.color,
|
||||||
|
required this.galleryItems,
|
||||||
});
|
});
|
||||||
|
|
||||||
final Message message;
|
final Message message;
|
||||||
final Contact contact;
|
final Contact contact;
|
||||||
final bool isInFullscreen;
|
final List<GalleryItem> galleryItems;
|
||||||
|
final Color color;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<InChatMediaViewer> createState() => _InChatMediaViewerState();
|
State<InChatMediaViewer> createState() => _InChatMediaViewerState();
|
||||||
|
|
@ -184,13 +195,10 @@ class _InChatMediaViewerState extends State<InChatMediaViewer> {
|
||||||
}
|
}
|
||||||
videoController = VideoPlayerController.file(
|
videoController = VideoPlayerController.file(
|
||||||
videoPath,
|
videoPath,
|
||||||
videoPlayerOptions:
|
videoPlayerOptions: VideoPlayerOptions(mixWithOthers: true),
|
||||||
VideoPlayerOptions(mixWithOthers: !widget.isInFullscreen),
|
|
||||||
);
|
);
|
||||||
videoController?.initialize().then((_) {
|
videoController?.initialize().then((_) {
|
||||||
if (!widget.isInFullscreen) {
|
|
||||||
videoController!.setVolume(0);
|
videoController!.setVolume(0);
|
||||||
}
|
|
||||||
videoController!.play();
|
videoController!.play();
|
||||||
videoController!.setLooping(true);
|
videoController!.setLooping(true);
|
||||||
});
|
});
|
||||||
|
|
@ -209,40 +217,72 @@ class _InChatMediaViewerState extends State<InChatMediaViewer> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future onTap() async {
|
Future onTap() async {
|
||||||
bool? removed = await Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(builder: (context) {
|
MaterialPageRoute(
|
||||||
return ChatMediaViewerFullScreen(
|
builder: (context) => GalleryPhotoViewWrapper(
|
||||||
message: widget.message,
|
galleryItems: widget.galleryItems,
|
||||||
contact: widget.contact,
|
// 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) {
|
// if (removed != null && removed) {
|
||||||
image = null;
|
// image = null;
|
||||||
videoController?.dispose();
|
// videoController?.dispose();
|
||||||
videoController = null;
|
// videoController = null;
|
||||||
if (isMounted) setState(() {});
|
// if (isMounted) setState(() {});
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
if (image == null && video == null) {
|
if (image == null && video == null) {
|
||||||
return Padding(
|
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),
|
padding: const EdgeInsets.all(10.0),
|
||||||
child: MessageSendStateIcon(
|
child: MessageSendStateIcon(
|
||||||
[widget.message],
|
[widget.message],
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return GestureDetector(
|
return Container(
|
||||||
onTap:
|
decoration: BoxDecoration(
|
||||||
((image == null && videoController == null) || widget.isInFullscreen)
|
border: Border.all(
|
||||||
? null
|
color: Colors.transparent,
|
||||||
: onTap,
|
width: 1.0,
|
||||||
|
),
|
||||||
|
color: Colors.transparent,
|
||||||
|
borderRadius: BorderRadius.circular(12.0),
|
||||||
|
),
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: ((image == null && videoController == null)) ? null : onTap,
|
||||||
child: Stack(
|
child: Stack(
|
||||||
children: [
|
children: [
|
||||||
if (image != null) Image.file(image!),
|
if (image != null) Image.file(image!),
|
||||||
|
|
@ -255,6 +295,7 @@ class _InChatMediaViewerState extends State<InChatMediaViewer> {
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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/views/camera/camera_send_to_view.dart';
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
import 'package:twonly/src/views/contact/contact_view.dart';
|
import 'package:twonly/src/views/contact/contact_view.dart';
|
||||||
|
import 'package:twonly/src/views/gallery/gallery_main_view.dart';
|
||||||
|
|
||||||
Color getMessageColor(Message message) {
|
Color getMessageColor(Message message) {
|
||||||
return (message.messageOtherId == null)
|
return (message.messageOtherId == null)
|
||||||
|
|
@ -43,6 +44,7 @@ class _ChatMessagesViewState extends State<ChatMessagesView> {
|
||||||
late StreamSubscription<Contact> userSub;
|
late StreamSubscription<Contact> userSub;
|
||||||
late StreamSubscription<List<Message>> messageSub;
|
late StreamSubscription<List<Message>> messageSub;
|
||||||
List<Message> messages = [];
|
List<Message> messages = [];
|
||||||
|
List<GalleryItem> galleryItems = [];
|
||||||
Map<int, List<Message>> textReactionsToMessageId = {};
|
Map<int, List<Message>> textReactionsToMessageId = {};
|
||||||
Map<int, List<Message>> emojiReactionsToMessageId = {};
|
Map<int, List<Message>> emojiReactionsToMessageId = {};
|
||||||
Message? responseToMessage;
|
Message? responseToMessage;
|
||||||
|
|
@ -76,7 +78,7 @@ class _ChatMessagesViewState extends State<ChatMessagesView> {
|
||||||
|
|
||||||
Stream<List<Message>> msgStream =
|
Stream<List<Message>> msgStream =
|
||||||
twonlyDatabase.messagesDao.watchAllMessagesFrom(widget.contact.userId);
|
twonlyDatabase.messagesDao.watchAllMessagesFrom(widget.contact.userId);
|
||||||
messageSub = msgStream.listen((msgs) {
|
messageSub = msgStream.listen((msgs) async {
|
||||||
// if (!context.mounted) return;
|
// if (!context.mounted) return;
|
||||||
if (Platform.isAndroid) {
|
if (Platform.isAndroid) {
|
||||||
flutterLocalNotificationsPlugin.cancel(widget.contact.userId);
|
flutterLocalNotificationsPlugin.cancel(widget.contact.userId);
|
||||||
|
|
@ -131,6 +133,7 @@ class _ChatMessagesViewState extends State<ChatMessagesView> {
|
||||||
displayedMessages.add(msg);
|
displayedMessages.add(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (openedMessageOtherIds.isNotEmpty) {
|
if (openedMessageOtherIds.isNotEmpty) {
|
||||||
notifyContactAboutOpeningMessage(
|
notifyContactAboutOpeningMessage(
|
||||||
widget.contact.userId, openedMessageOtherIds);
|
widget.contact.userId, openedMessageOtherIds);
|
||||||
|
|
@ -145,7 +148,15 @@ class _ChatMessagesViewState extends State<ChatMessagesView> {
|
||||||
emojiReactionsToMessageId = tmpEmojiReactionsToMessageId;
|
emojiReactionsToMessageId = tmpEmojiReactionsToMessageId;
|
||||||
messages = displayedMessages;
|
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()),
|
key: Key(messages[i].messageId.toString()),
|
||||||
messages[i],
|
messages[i],
|
||||||
user,
|
user,
|
||||||
|
galleryItems,
|
||||||
isLastMessageFromSameUser(messages, i),
|
isLastMessageFromSameUser(messages, i),
|
||||||
textReactionsToMessageId[messages[i].messageId] ?? [],
|
textReactionsToMessageId[messages[i].messageId] ?? [],
|
||||||
emojiReactionsToMessageId[messages[i].messageId] ?? [],
|
emojiReactionsToMessageId[messages[i].messageId] ?? [],
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,40 @@ class GalleryItem {
|
||||||
final DateTime date;
|
final DateTime date;
|
||||||
final File? imagePath;
|
final File? imagePath;
|
||||||
final File? videoPath;
|
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 {
|
class GalleryItemGrid {
|
||||||
|
|
@ -180,40 +214,12 @@ class GalleryMainViewState extends State<GalleryMainView> {
|
||||||
List<Message> storedMediaFiles =
|
List<Message> storedMediaFiles =
|
||||||
await twonlyDatabase.messagesDao.getAllStoredMediaFiles();
|
await twonlyDatabase.messagesDao.getAllStoredMediaFiles();
|
||||||
|
|
||||||
Map<int, GalleryItem> items = {};
|
Map<int, GalleryItem> items =
|
||||||
for (final message in storedMediaFiles) {
|
await GalleryItem.convertFromMessages(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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Group items by month
|
// Group items by month
|
||||||
orderedByMonth = {};
|
orderedByMonth = {};
|
||||||
months = [];
|
months = [];
|
||||||
|
|
||||||
String lastMonth = "";
|
String lastMonth = "";
|
||||||
galleryItems = await loadMemoriesDirectory();
|
galleryItems = await loadMemoriesDirectory();
|
||||||
galleryItems += items.values.toList();
|
galleryItems += items.values.toList();
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue