mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-01-15 13:08:42 +00:00
starting with message info page
This commit is contained in:
parent
8f8f2cabe0
commit
4f68d22e07
10 changed files with 342 additions and 111 deletions
|
|
@ -191,13 +191,13 @@ class MessagesDao extends DatabaseAccessor<TwonlyDB> with _$MessagesDaoMixin {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> handleTextEdit(
|
Future<void> handleTextEdit(
|
||||||
int contactId,
|
int? contactId,
|
||||||
String messageId,
|
String messageId,
|
||||||
String text,
|
String text,
|
||||||
DateTime timestamp,
|
DateTime timestamp,
|
||||||
) async {
|
) async {
|
||||||
final msg = await getMessageById(messageId).getSingleOrNull();
|
final msg = await getMessageById(messageId).getSingleOrNull();
|
||||||
if (msg == null || msg.content == null || msg.senderId == contactId) {
|
if (msg == null || msg.content == null || msg.senderId != contactId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await into(messageHistories).insert(
|
await into(messageHistories).insert(
|
||||||
|
|
@ -209,11 +209,12 @@ class MessagesDao extends DatabaseAccessor<TwonlyDB> with _$MessagesDaoMixin {
|
||||||
);
|
);
|
||||||
await (update(messages)
|
await (update(messages)
|
||||||
..where(
|
..where(
|
||||||
(t) => t.messageId.equals(messageId) & t.senderId.equals(contactId),
|
(t) => t.messageId.equals(messageId),
|
||||||
))
|
))
|
||||||
.write(
|
.write(
|
||||||
MessagesCompanion(
|
MessagesCompanion(
|
||||||
content: Value(text),
|
content: Value(text),
|
||||||
|
modifiedAt: Value(timestamp),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -174,6 +174,7 @@
|
||||||
"submit": "Abschicken",
|
"submit": "Abschicken",
|
||||||
"close": "Schließen",
|
"close": "Schließen",
|
||||||
"cancel": "Abbrechen",
|
"cancel": "Abbrechen",
|
||||||
|
"edit": "Bearbeiten",
|
||||||
"ok": "Ok",
|
"ok": "Ok",
|
||||||
"now": "Jetzt",
|
"now": "Jetzt",
|
||||||
"you": "Du",
|
"you": "Du",
|
||||||
|
|
|
||||||
|
|
@ -307,6 +307,7 @@
|
||||||
"react": "React",
|
"react": "React",
|
||||||
"reply": "Reply",
|
"reply": "Reply",
|
||||||
"copy": "Copy",
|
"copy": "Copy",
|
||||||
|
"edit": "Edit",
|
||||||
"delete": "Delete",
|
"delete": "Delete",
|
||||||
"info": "Info",
|
"info": "Info",
|
||||||
"ok": "Ok",
|
"ok": "Ok",
|
||||||
|
|
|
||||||
|
|
@ -1106,6 +1106,12 @@ abstract class AppLocalizations {
|
||||||
/// **'Copy'**
|
/// **'Copy'**
|
||||||
String get copy;
|
String get copy;
|
||||||
|
|
||||||
|
/// No description provided for @edit.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Edit'**
|
||||||
|
String get edit;
|
||||||
|
|
||||||
/// No description provided for @delete.
|
/// No description provided for @delete.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
|
|
|
||||||
|
|
@ -560,6 +560,9 @@ class AppLocalizationsDe extends AppLocalizations {
|
||||||
@override
|
@override
|
||||||
String get copy => 'Kopieren';
|
String get copy => 'Kopieren';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get edit => 'Bearbeiten';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get delete => 'Löschen';
|
String get delete => 'Löschen';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -555,6 +555,9 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||||
@override
|
@override
|
||||||
String get copy => 'Copy';
|
String get copy => 'Copy';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get edit => 'Edit';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get delete => 'Delete';
|
String get delete => 'Delete';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ class ChatListEntry extends StatefulWidget {
|
||||||
required this.nextMessage,
|
required this.nextMessage,
|
||||||
required this.onResponseTriggered,
|
required this.onResponseTriggered,
|
||||||
required this.scrollToMessage,
|
required this.scrollToMessage,
|
||||||
|
this.disableContextMenu = false,
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
final Message? prevMessage;
|
final Message? prevMessage;
|
||||||
|
|
@ -32,6 +33,7 @@ class ChatListEntry extends StatefulWidget {
|
||||||
final List<MemoryItem> galleryItems;
|
final List<MemoryItem> galleryItems;
|
||||||
final void Function(String) scrollToMessage;
|
final void Function(String) scrollToMessage;
|
||||||
final void Function() onResponseTriggered;
|
final void Function() onResponseTriggered;
|
||||||
|
final bool disableContextMenu;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<ChatListEntry> createState() => _ChatListEntryState();
|
State<ChatListEntry> createState() => _ChatListEntryState();
|
||||||
|
|
@ -96,81 +98,84 @@ class _ChatListEntryState extends State<ChatListEntry> {
|
||||||
reactions.where((t) => seen.add(t.emoji)).toList().length;
|
reactions.where((t) => seen.add(t.emoji)).toList().length;
|
||||||
if (reactionsForWidth > 4) reactionsForWidth = 4;
|
if (reactionsForWidth > 4) reactionsForWidth = 4;
|
||||||
|
|
||||||
return Align(
|
Widget child = Column(
|
||||||
alignment: right ? Alignment.centerRight : Alignment.centerLeft,
|
mainAxisAlignment:
|
||||||
child: Padding(
|
right ? MainAxisAlignment.end : MainAxisAlignment.start,
|
||||||
padding: padding,
|
crossAxisAlignment:
|
||||||
child: MessageContextMenu(
|
right ? CrossAxisAlignment.end : CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
MessageActions(
|
||||||
message: widget.message,
|
message: widget.message,
|
||||||
onResponseTriggered: widget.onResponseTriggered,
|
onResponseTriggered: widget.onResponseTriggered,
|
||||||
child: Column(
|
child: Stack(
|
||||||
mainAxisAlignment:
|
// overflow: Overflow.visible,
|
||||||
right ? MainAxisAlignment.end : MainAxisAlignment.start,
|
// clipBehavior: Clip.none,
|
||||||
crossAxisAlignment:
|
alignment: right ? Alignment.centerRight : Alignment.centerLeft,
|
||||||
right ? CrossAxisAlignment.end : CrossAxisAlignment.start,
|
|
||||||
children: [
|
children: [
|
||||||
MessageActions(
|
if (widget.message.isDeletedFromSender)
|
||||||
message: widget.message,
|
ChatTextEntry(
|
||||||
onResponseTriggered: widget.onResponseTriggered,
|
message: widget.message,
|
||||||
child: Stack(
|
nextMessage: widget.nextMessage,
|
||||||
// overflow: Overflow.visible,
|
borderRadius: borderRadius,
|
||||||
// clipBehavior: Clip.none,
|
minWidth: reactionsForWidth * 43,
|
||||||
alignment:
|
)
|
||||||
right ? Alignment.centerRight : Alignment.centerLeft,
|
else
|
||||||
|
Column(
|
||||||
children: [
|
children: [
|
||||||
if (widget.message.isDeletedFromSender)
|
ResponseContainer(
|
||||||
ChatTextEntry(
|
msg: widget.message,
|
||||||
message: widget.message,
|
group: widget.group,
|
||||||
nextMessage: widget.nextMessage,
|
mediaService: mediaService,
|
||||||
borderRadius: borderRadius,
|
borderRadius: borderRadius,
|
||||||
minWidth: reactionsForWidth * 43,
|
scrollToMessage: widget.scrollToMessage,
|
||||||
)
|
child: (widget.message.type == MessageType.text)
|
||||||
else
|
? ChatTextEntry(
|
||||||
Column(
|
message: widget.message,
|
||||||
children: [
|
nextMessage: widget.nextMessage,
|
||||||
ResponseContainer(
|
borderRadius: borderRadius,
|
||||||
msg: widget.message,
|
minWidth: reactionsForWidth * 43,
|
||||||
group: widget.group,
|
)
|
||||||
mediaService: mediaService,
|
: (mediaService == null)
|
||||||
borderRadius: borderRadius,
|
? null
|
||||||
scrollToMessage: widget.scrollToMessage,
|
: ChatMediaEntry(
|
||||||
child: (widget.message.type == MessageType.text)
|
message: widget.message,
|
||||||
? ChatTextEntry(
|
group: widget.group,
|
||||||
message: widget.message,
|
mediaService: mediaService!,
|
||||||
nextMessage: widget.nextMessage,
|
galleryItems: widget.galleryItems,
|
||||||
borderRadius: borderRadius,
|
),
|
||||||
minWidth: reactionsForWidth * 43,
|
),
|
||||||
)
|
if (reactionsForWidth > 0)
|
||||||
: (mediaService == null)
|
const SizedBox(height: 20, width: 10),
|
||||||
? null
|
|
||||||
: ChatMediaEntry(
|
|
||||||
message: widget.message,
|
|
||||||
group: widget.group,
|
|
||||||
mediaService: mediaService!,
|
|
||||||
galleryItems: widget.galleryItems,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (reactionsForWidth > 0)
|
|
||||||
const SizedBox(height: 20, width: 10),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
if (!widget.message.isDeletedFromSender)
|
|
||||||
Positioned(
|
|
||||||
bottom: -20,
|
|
||||||
left: 5,
|
|
||||||
right: 5,
|
|
||||||
child: ReactionRow(
|
|
||||||
message: widget.message,
|
|
||||||
reactions: reactions,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
if (!widget.message.isDeletedFromSender)
|
||||||
|
Positioned(
|
||||||
|
bottom: -20,
|
||||||
|
left: 5,
|
||||||
|
right: 5,
|
||||||
|
child: ReactionRow(
|
||||||
|
message: widget.message,
|
||||||
|
reactions: reactions,
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!widget.disableContextMenu) {
|
||||||
|
child = MessageContextMenu(
|
||||||
|
message: widget.message,
|
||||||
|
group: widget.group,
|
||||||
|
onResponseTriggered: widget.onResponseTriggered,
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Align(
|
||||||
|
alignment: right ? Alignment.centerRight : Alignment.centerLeft,
|
||||||
|
child: Padding(padding: padding, child: child),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
import 'package:intl/intl.dart' hide TextDirection;
|
import 'package:intl/intl.dart' hide TextDirection;
|
||||||
import 'package:twonly/src/database/tables/messages.table.dart';
|
import 'package:twonly/src/database/tables/messages.table.dart';
|
||||||
import 'package:twonly/src/database/twonly.db.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
|
|
@ -89,12 +90,28 @@ class ChatTextEntry extends StatelessWidget {
|
||||||
alignment: AlignmentGeometry.centerRight,
|
alignment: AlignmentGeometry.centerRight,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.only(left: 6),
|
padding: const EdgeInsets.only(left: 6),
|
||||||
child: Text(
|
child: Row(
|
||||||
friendlyTime(context, message.createdAt),
|
children: [
|
||||||
style: TextStyle(
|
if (message.modifiedAt != null)
|
||||||
fontSize: 10,
|
Padding(
|
||||||
color: Colors.white.withAlpha(150),
|
padding: const EdgeInsets.only(right: 5),
|
||||||
),
|
child: SizedBox(
|
||||||
|
height: 10,
|
||||||
|
child: FaIcon(
|
||||||
|
FontAwesomeIcons.pencil,
|
||||||
|
color: Colors.white.withAlpha(150),
|
||||||
|
size: 10,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
friendlyTime(context, message.createdAt),
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 10,
|
||||||
|
color: Colors.white.withAlpha(150),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
// ignore_for_file: inference_failure_on_function_invocation
|
// ignore_for_file: inference_failure_on_function_invocation
|
||||||
|
|
||||||
|
import 'package:fixnum/fixnum.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
import 'package:pie_menu/pie_menu.dart';
|
import 'package:pie_menu/pie_menu.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
|
import 'package:twonly/src/database/tables/messages.table.dart';
|
||||||
import 'package:twonly/src/database/twonly.db.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
import 'package:twonly/src/model/protobuf/client/generated/messages.pbserver.dart'
|
import 'package:twonly/src/model/protobuf/client/generated/messages.pbserver.dart'
|
||||||
as pb;
|
as pb;
|
||||||
|
|
@ -12,15 +14,18 @@ import 'package:twonly/src/services/api/messages.dart';
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
import 'package:twonly/src/views/camera/image_editor/data/layer.dart';
|
import 'package:twonly/src/views/camera/image_editor/data/layer.dart';
|
||||||
import 'package:twonly/src/views/camera/image_editor/modules/all_emojis.dart';
|
import 'package:twonly/src/views/camera/image_editor/modules/all_emojis.dart';
|
||||||
|
import 'package:twonly/src/views/chats/message_info.view.dart';
|
||||||
import 'package:twonly/src/views/components/alert_dialog.dart';
|
import 'package:twonly/src/views/components/alert_dialog.dart';
|
||||||
|
|
||||||
class MessageContextMenu extends StatelessWidget {
|
class MessageContextMenu extends StatelessWidget {
|
||||||
const MessageContextMenu({
|
const MessageContextMenu({
|
||||||
required this.message,
|
required this.message,
|
||||||
|
required this.group,
|
||||||
required this.child,
|
required this.child,
|
||||||
required this.onResponseTriggered,
|
required this.onResponseTriggered,
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
final Group group;
|
||||||
final Widget child;
|
final Widget child;
|
||||||
final Message message;
|
final Message message;
|
||||||
final VoidCallback onResponseTriggered;
|
final VoidCallback onResponseTriggered;
|
||||||
|
|
@ -35,40 +40,52 @@ class MessageContextMenu extends StatelessWidget {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
actions: [
|
actions: [
|
||||||
PieAction(
|
if (!message.isDeletedFromSender)
|
||||||
tooltip: Text(context.lang.react),
|
PieAction(
|
||||||
onSelect: () async {
|
tooltip: Text(context.lang.react),
|
||||||
final layer = await showModalBottomSheet(
|
onSelect: () async {
|
||||||
context: context,
|
final layer = await showModalBottomSheet(
|
||||||
backgroundColor: Colors.black,
|
context: context,
|
||||||
builder: (BuildContext context) {
|
backgroundColor: Colors.black,
|
||||||
return const Emojis();
|
builder: (BuildContext context) {
|
||||||
},
|
return const Emojis();
|
||||||
) as EmojiLayerData?;
|
},
|
||||||
if (layer == null) return;
|
) as EmojiLayerData?;
|
||||||
|
if (layer == null) return;
|
||||||
|
|
||||||
await twonlyDB.reactionsDao
|
await twonlyDB.reactionsDao
|
||||||
.updateMyReaction(message.messageId, layer.text);
|
.updateMyReaction(message.messageId, layer.text);
|
||||||
|
|
||||||
await sendCipherTextToGroup(
|
await sendCipherTextToGroup(
|
||||||
message.groupId,
|
message.groupId,
|
||||||
pb.EncryptedContent(
|
pb.EncryptedContent(
|
||||||
reaction: pb.EncryptedContent_Reaction(
|
reaction: pb.EncryptedContent_Reaction(
|
||||||
targetMessageId: message.messageId,
|
targetMessageId: message.messageId,
|
||||||
emoji: layer.text,
|
emoji: layer.text,
|
||||||
remove: false,
|
remove: false,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
null,
|
||||||
null,
|
);
|
||||||
);
|
},
|
||||||
},
|
child: const FaIcon(FontAwesomeIcons.faceLaugh),
|
||||||
child: const FaIcon(FontAwesomeIcons.faceLaugh),
|
),
|
||||||
),
|
if (!message.isDeletedFromSender)
|
||||||
PieAction(
|
PieAction(
|
||||||
tooltip: Text(context.lang.reply),
|
tooltip: Text(context.lang.reply),
|
||||||
onSelect: onResponseTriggered,
|
onSelect: onResponseTriggered,
|
||||||
child: const FaIcon(FontAwesomeIcons.reply),
|
child: const FaIcon(FontAwesomeIcons.reply),
|
||||||
),
|
),
|
||||||
|
if (!message.isDeletedFromSender &&
|
||||||
|
message.senderId == null &&
|
||||||
|
message.type == MessageType.text)
|
||||||
|
PieAction(
|
||||||
|
tooltip: Text(context.lang.edit),
|
||||||
|
onSelect: () async {
|
||||||
|
await editTextMessage(context, message);
|
||||||
|
},
|
||||||
|
child: const FaIcon(FontAwesomeIcons.pencil),
|
||||||
|
),
|
||||||
if (message.content != null)
|
if (message.content != null)
|
||||||
PieAction(
|
PieAction(
|
||||||
tooltip: Text(context.lang.copy),
|
tooltip: Text(context.lang.copy),
|
||||||
|
|
@ -115,13 +132,107 @@ class MessageContextMenu extends StatelessWidget {
|
||||||
},
|
},
|
||||||
child: const FaIcon(FontAwesomeIcons.trash),
|
child: const FaIcon(FontAwesomeIcons.trash),
|
||||||
),
|
),
|
||||||
// PieAction(
|
if (!message.isDeletedFromSender)
|
||||||
// tooltip: Text(context.lang.info),
|
PieAction(
|
||||||
// onSelect: () {},
|
tooltip: Text(context.lang.info),
|
||||||
// child: const FaIcon(FontAwesomeIcons.circleInfo),
|
onSelect: () async {
|
||||||
// ),
|
await Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) {
|
||||||
|
return MessageInfoView(
|
||||||
|
message: message,
|
||||||
|
group: group,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: const FaIcon(FontAwesomeIcons.circleInfo),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
child: child,
|
child: child,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> editTextMessage(BuildContext context, Message message) async {
|
||||||
|
var newText = message.content;
|
||||||
|
final controller = TextEditingController(text: message.content);
|
||||||
|
await showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return AlertDialog(
|
||||||
|
content: StatefulBuilder(
|
||||||
|
builder: (BuildContext context, StateSetter setState) {
|
||||||
|
return SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 8),
|
||||||
|
child: TextField(
|
||||||
|
controller: controller,
|
||||||
|
autofocus: true,
|
||||||
|
keyboardType: TextInputType.multiline,
|
||||||
|
maxLines: 4,
|
||||||
|
minLines: 1,
|
||||||
|
onChanged: (value) => setState(() {
|
||||||
|
newText = value;
|
||||||
|
}),
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
border: OutlineInputBorder(),
|
||||||
|
),
|
||||||
|
textCapitalization: TextCapitalization.characters,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
child: Text(context.lang.cancel),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () async {
|
||||||
|
if (newText != null &&
|
||||||
|
newText != message.content &&
|
||||||
|
newText != '') {
|
||||||
|
final timestamp = DateTime.now();
|
||||||
|
|
||||||
|
await twonlyDB.messagesDao.handleTextEdit(
|
||||||
|
null,
|
||||||
|
message.messageId,
|
||||||
|
newText!,
|
||||||
|
timestamp,
|
||||||
|
);
|
||||||
|
await sendCipherTextToGroup(
|
||||||
|
message.groupId,
|
||||||
|
pb.EncryptedContent(
|
||||||
|
messageUpdate: pb.EncryptedContent_MessageUpdate(
|
||||||
|
type: pb.EncryptedContent_MessageUpdate_Type.EDIT_TEXT,
|
||||||
|
senderMessageId: message.messageId,
|
||||||
|
text: newText,
|
||||||
|
timestamp: Int64(
|
||||||
|
timestamp.millisecondsSinceEpoch,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (!context.mounted) return;
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
child: Text(context.lang.ok),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
||||||
83
lib/src/views/chats/message_info.view.dart
Normal file
83
lib/src/views/chats/message_info.view.dart
Normal file
|
|
@ -0,0 +1,83 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
|
import 'package:twonly/src/views/chats/chat_messages_components/chat_list_entry.dart';
|
||||||
|
|
||||||
|
class MessageInfoView extends StatefulWidget {
|
||||||
|
const MessageInfoView({
|
||||||
|
required this.message,
|
||||||
|
required this.group,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
final Message message;
|
||||||
|
final Group group;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<MessageInfoView> createState() => _MessageInfoViewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _MessageInfoViewState extends State<MessageInfoView> {
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
initAsync();
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> initAsync() async {
|
||||||
|
// watch message edit history
|
||||||
|
// watch message actions
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: const Text(''),
|
||||||
|
),
|
||||||
|
body: Padding(
|
||||||
|
padding: const EdgeInsets.all(8),
|
||||||
|
child: ListView(
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(8),
|
||||||
|
child: ChatListEntry(
|
||||||
|
group: widget.group,
|
||||||
|
galleryItems: const [],
|
||||||
|
prevMessage: null,
|
||||||
|
message: widget.message,
|
||||||
|
disableContextMenu: true,
|
||||||
|
nextMessage: null,
|
||||||
|
onResponseTriggered: () {},
|
||||||
|
scrollToMessage: (_) {},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
const Text('Versendet'),
|
||||||
|
const SizedBox(width: 13),
|
||||||
|
Text(formatDateTime(context, widget.message.createdAt)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
// Row(
|
||||||
|
// children: [
|
||||||
|
// Text("Empfangen"),
|
||||||
|
// SizedBox(width: 13),
|
||||||
|
// Text(formatDateTime(context, widget.message.ackByUser)),
|
||||||
|
// ],
|
||||||
|
// )
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
const Divider(),
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
const Text('Zugestelt an'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue