Better replies
This commit is contained in:
parent
1e64512222
commit
cf2b2f0433
|
@ -1,6 +1,7 @@
|
||||||
import 'package:bubble/bubble.dart';
|
import 'package:bubble/bubble.dart';
|
||||||
import 'package:famedlysdk/famedlysdk.dart';
|
import 'package:famedlysdk/famedlysdk.dart';
|
||||||
import 'package:fluffychat/components/message_content.dart';
|
import 'package:fluffychat/components/message_content.dart';
|
||||||
|
import 'package:fluffychat/components/reply_content.dart';
|
||||||
import 'package:fluffychat/i18n/i18n.dart';
|
import 'package:fluffychat/i18n/i18n.dart';
|
||||||
import 'package:fluffychat/utils/app_route.dart';
|
import 'package:fluffychat/utils/app_route.dart';
|
||||||
import 'package:fluffychat/utils/date_time_extension.dart';
|
import 'package:fluffychat/utils/date_time_extension.dart';
|
||||||
|
@ -18,9 +19,14 @@ class Message extends StatelessWidget {
|
||||||
final Function(Event) onSelect;
|
final Function(Event) onSelect;
|
||||||
final bool longPressSelect;
|
final bool longPressSelect;
|
||||||
final bool selected;
|
final bool selected;
|
||||||
|
final Timeline timeline;
|
||||||
|
|
||||||
const Message(this.event,
|
const Message(this.event,
|
||||||
{this.nextEvent, this.longPressSelect, this.onSelect, this.selected});
|
{this.nextEvent,
|
||||||
|
this.longPressSelect,
|
||||||
|
this.onSelect,
|
||||||
|
this.selected,
|
||||||
|
this.timeline});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -88,6 +94,30 @@ class Message extends StatelessWidget {
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
if (event.isReply)
|
||||||
|
FutureBuilder<Event>(
|
||||||
|
future: timeline.getEventById(event.content['m.relates_to']
|
||||||
|
['m.in_reply_to']['event_id']),
|
||||||
|
builder: (BuildContext context, snapshot) {
|
||||||
|
final Event replyEvent = snapshot.hasData
|
||||||
|
? snapshot.data
|
||||||
|
: Event(
|
||||||
|
eventId: event.content['m.relates_to']
|
||||||
|
['m.in_reply_to']['event_id'],
|
||||||
|
content: {"msgtype": "m.text", "body": "..."},
|
||||||
|
senderId: event.senderId,
|
||||||
|
typeKey: "m.room.message",
|
||||||
|
room: event.room,
|
||||||
|
roomId: event.roomId,
|
||||||
|
status: 1,
|
||||||
|
time: DateTime.now(),
|
||||||
|
);
|
||||||
|
return Container(
|
||||||
|
margin: EdgeInsets.symmetric(vertical: 4.0),
|
||||||
|
child: ReplyContent(replyEvent, lightText: ownMessage),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
MessageContent(
|
MessageContent(
|
||||||
event,
|
event,
|
||||||
textColor: textColor,
|
textColor: textColor,
|
||||||
|
|
|
@ -130,7 +130,7 @@ class MessageContent extends StatelessWidget {
|
||||||
case MessageTypes.Notice:
|
case MessageTypes.Notice:
|
||||||
case MessageTypes.Emote:
|
case MessageTypes.Emote:
|
||||||
return LinkText(
|
return LinkText(
|
||||||
text: event.getLocalizedBody(context),
|
text: event.getLocalizedBody(context, hideQuotes: true),
|
||||||
textStyle: TextStyle(
|
textStyle: TextStyle(
|
||||||
color: textColor,
|
color: textColor,
|
||||||
decoration: event.redacted ? TextDecoration.lineThrough : null,
|
decoration: event.redacted ? TextDecoration.lineThrough : null,
|
||||||
|
|
52
lib/components/reply_content.dart
Normal file
52
lib/components/reply_content.dart
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
import 'package:famedlysdk/famedlysdk.dart';
|
||||||
|
import 'package:fluffychat/utils/event_extension.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class ReplyContent extends StatelessWidget {
|
||||||
|
final Event replyEvent;
|
||||||
|
final bool lightText;
|
||||||
|
|
||||||
|
const ReplyContent(this.replyEvent, {this.lightText = false, Key key})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Row(
|
||||||
|
children: <Widget>[
|
||||||
|
Container(
|
||||||
|
width: 3,
|
||||||
|
height: 36,
|
||||||
|
color: lightText ? Colors.white : Theme.of(context).primaryColor,
|
||||||
|
),
|
||||||
|
SizedBox(width: 6),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: <Widget>[
|
||||||
|
Text(
|
||||||
|
(replyEvent?.sender?.calcDisplayname() ?? "") + ":",
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color:
|
||||||
|
lightText ? Colors.white : Theme.of(context).primaryColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
replyEvent?.getLocalizedBody(context,
|
||||||
|
withSenderNamePrefix: false) ??
|
||||||
|
"",
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
maxLines: 1,
|
||||||
|
style:
|
||||||
|
TextStyle(color: lightText ? Colors.white : Colors.black),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,6 +8,7 @@ import 'package:fluffychat/components/chat_settings_popup_menu.dart';
|
||||||
import 'package:fluffychat/components/dialogs/confirm_dialog.dart';
|
import 'package:fluffychat/components/dialogs/confirm_dialog.dart';
|
||||||
import 'package:fluffychat/components/list_items/message.dart';
|
import 'package:fluffychat/components/list_items/message.dart';
|
||||||
import 'package:fluffychat/components/matrix.dart';
|
import 'package:fluffychat/components/matrix.dart';
|
||||||
|
import 'package:fluffychat/components/reply_content.dart';
|
||||||
import 'package:fluffychat/i18n/i18n.dart';
|
import 'package:fluffychat/i18n/i18n.dart';
|
||||||
import 'package:fluffychat/utils/app_route.dart';
|
import 'package:fluffychat/utils/app_route.dart';
|
||||||
import 'package:fluffychat/utils/event_extension.dart';
|
import 'package:fluffychat/utils/event_extension.dart';
|
||||||
|
@ -148,32 +149,11 @@ class _ChatState extends State<_Chat> {
|
||||||
|
|
||||||
void send() {
|
void send() {
|
||||||
if (sendController.text.isEmpty) return;
|
if (sendController.text.isEmpty) return;
|
||||||
Map<String, dynamic> textContent = {
|
room.sendTextEvent(sendController.text, inReplyTo: replyEvent);
|
||||||
"msgtype": "m.text",
|
sendController.text = "";
|
||||||
"body": sendController.text,
|
|
||||||
};
|
|
||||||
if (replyEvent != null) {
|
if (replyEvent != null) {
|
||||||
String replyText = "<${replyEvent.senderId}> " +
|
|
||||||
replyEvent.getLocalizedBody(
|
|
||||||
context,
|
|
||||||
withSenderNamePrefix: false,
|
|
||||||
hideQuotes: true,
|
|
||||||
);
|
|
||||||
List<String> replyTextLines = replyText.split("\n");
|
|
||||||
for (int i = 0; i < replyTextLines.length; i++) {
|
|
||||||
replyTextLines[i] = "> " + replyTextLines[i];
|
|
||||||
}
|
|
||||||
replyText = replyTextLines.join("\n");
|
|
||||||
textContent["body"] = replyText + "\n\n${sendController.text}";
|
|
||||||
textContent["m.relates_to"] = {
|
|
||||||
"m.in_reply_to": {
|
|
||||||
"event_id": replyEvent.eventId,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
setState(() => replyEvent = null);
|
setState(() => replyEvent = null);
|
||||||
}
|
}
|
||||||
room.sendEvent(textContent);
|
|
||||||
sendController.text = "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void sendFileAction(BuildContext context) async {
|
void sendFileAction(BuildContext context) async {
|
||||||
|
@ -454,6 +434,7 @@ class _ChatState extends State<_Chat> {
|
||||||
longPressSelect: selectedEvents.isEmpty,
|
longPressSelect: selectedEvents.isEmpty,
|
||||||
selected: selectedEvents
|
selected: selectedEvents
|
||||||
.contains(timeline.events[i - 1]),
|
.contains(timeline.events[i - 1]),
|
||||||
|
timeline: timeline,
|
||||||
nextEvent:
|
nextEvent:
|
||||||
i >= 2 ? timeline.events[i - 2] : null);
|
i >= 2 ? timeline.events[i - 2] : null);
|
||||||
});
|
});
|
||||||
|
@ -471,35 +452,8 @@ class _ChatState extends State<_Chat> {
|
||||||
icon: Icon(Icons.close),
|
icon: Icon(Icons.close),
|
||||||
onPressed: () => setState(() => replyEvent = null),
|
onPressed: () => setState(() => replyEvent = null),
|
||||||
),
|
),
|
||||||
Container(
|
|
||||||
width: 2,
|
|
||||||
height: 36,
|
|
||||||
color: Theme.of(context).primaryColor,
|
|
||||||
),
|
|
||||||
SizedBox(width: 6),
|
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Column(
|
child: ReplyContent(replyEvent),
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: <Widget>[
|
|
||||||
Text(
|
|
||||||
(replyEvent?.sender?.calcDisplayname() ?? "") + ":",
|
|
||||||
maxLines: 1,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
style: TextStyle(
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: Theme.of(context).primaryColor,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
replyEvent?.getLocalizedBody(context,
|
|
||||||
withSenderNamePrefix: false) ??
|
|
||||||
"",
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
maxLines: 1,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
|
@ -117,8 +117,8 @@ packages:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
path: "."
|
path: "."
|
||||||
ref: "38f7bf947610b9b19a81aa9db05d76b460d116d9"
|
ref: e2fde3fa924cb9a1bdccf5dd6b63aad8d820d20a
|
||||||
resolved-ref: "38f7bf947610b9b19a81aa9db05d76b460d116d9"
|
resolved-ref: e2fde3fa924cb9a1bdccf5dd6b63aad8d820d20a
|
||||||
url: "https://gitlab.com/famedly/famedlysdk.git"
|
url: "https://gitlab.com/famedly/famedlysdk.git"
|
||||||
source: git
|
source: git
|
||||||
version: "0.0.1"
|
version: "0.0.1"
|
||||||
|
|
|
@ -27,7 +27,7 @@ dependencies:
|
||||||
famedlysdk:
|
famedlysdk:
|
||||||
git:
|
git:
|
||||||
url: https://gitlab.com/famedly/famedlysdk.git
|
url: https://gitlab.com/famedly/famedlysdk.git
|
||||||
ref: 38f7bf947610b9b19a81aa9db05d76b460d116d9
|
ref: e2fde3fa924cb9a1bdccf5dd6b63aad8d820d20a
|
||||||
|
|
||||||
localstorage: ^3.0.1+4
|
localstorage: ^3.0.1+4
|
||||||
bubble: ^1.1.9+1
|
bubble: ^1.1.9+1
|
||||||
|
|
Loading…
Reference in a new issue