Skip to content

Commit 9b58fa0

Browse files
committed
Add message read status like Telegram
1 parent dfce55f commit 9b58fa0

4 files changed

Lines changed: 132 additions & 32 deletions

File tree

.vscode/settings.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}

lib/pages/chat/chat_event_list.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,3 +192,4 @@ class ChatEventList extends StatelessWidget {
192192
);
193193
}
194194
}
195+
// Assuming 'client' is your Matrix client instance and 'event' is the last visible message event.

lib/pages/chat/events/message.dart

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,14 @@ import 'message_reactions.dart';
2525
import 'reply_content.dart';
2626
import 'state_message.dart';
2727

28+
enum MessageStatus {
29+
pending,
30+
sent,
31+
seen,
32+
error,
33+
}
34+
35+
2836
class Message extends StatelessWidget {
2937
final Event event;
3038
final Event? nextEvent;
@@ -587,15 +595,48 @@ class Message extends StatelessWidget {
587595
);
588596
},
589597
),
590-
MessageContent(
591-
displayEvent,
592-
textColor: textColor,
593-
linkColor: linkColor,
594-
onInfoTab: onInfoTab,
595-
borderRadius:
596-
borderRadius,
597-
timeline: timeline,
598-
selected: selected,
598+
Builder(
599+
builder: (context) {
600+
MessageStatus? myMessageStatus;
601+
602+
debugPrint("message status: ${displayEvent.status}");
603+
604+
switch(displayEvent.status) {
605+
case EventStatus.sending: {
606+
myMessageStatus = MessageStatus.pending;
607+
break;
608+
}
609+
case EventStatus.error: {
610+
myMessageStatus = MessageStatus.error;
611+
break;
612+
}
613+
case EventStatus.sent: case EventStatus.synced : {
614+
if (displayEvent.receipts.isNotEmpty) {
615+
myMessageStatus = MessageStatus.seen;
616+
} else {
617+
myMessageStatus = MessageStatus.sent;
618+
}
619+
620+
break;
621+
}
622+
}
623+
624+
if (!ownMessage) {
625+
myMessageStatus = null;
626+
}
627+
628+
return MessageContent(
629+
displayEvent,
630+
textColor: textColor,
631+
linkColor: linkColor,
632+
onInfoTab: onInfoTab,
633+
borderRadius:
634+
borderRadius,
635+
timeline: timeline,
636+
selected: selected,
637+
messageStatus: myMessageStatus,
638+
);
639+
},
599640
),
600641
if (event
601642
.hasAggregatedEvents(
@@ -835,6 +876,8 @@ class Message extends StatelessWidget {
835876
: const SizedBox.shrink(),
836877
),
837878
),
879+
880+
838881
],
839882
),
840883
),

lib/pages/chat/events/message_content.dart

Lines changed: 78 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import 'dart:math';
22

3+
import 'package:fluffychat/config/themes.dart';
4+
import 'package:fluffychat/pages/chat/events/message.dart';
35
import 'package:flutter/material.dart';
46

57
import 'package:go_router/go_router.dart';
@@ -33,6 +35,7 @@ class MessageContent extends StatelessWidget {
3335
final BorderRadius borderRadius;
3436
final Timeline timeline;
3537
final bool selected;
38+
final MessageStatus? messageStatus;
3639

3740
const MessageContent(
3841
this.event, {
@@ -43,6 +46,7 @@ class MessageContent extends StatelessWidget {
4346
required this.linkColor,
4447
required this.borderRadius,
4548
required this.selected,
49+
required this.messageStatus,
4650
});
4751

4852
void _verifyOrRequestKey(BuildContext context) async {
@@ -252,29 +256,80 @@ class MessageContent extends StatelessWidget {
252256
event.numberEmotes <= 3;
253257
return Padding(
254258
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
255-
child: HtmlMessage(
256-
html: html,
257-
textColor: textColor,
258-
room: event.room,
259-
fontSize:
260-
AppSettings.fontSizeFactor.value *
261-
AppConfig.messageFontSize *
262-
(bigEmotes ? 5 : 1),
263-
limitHeight: !selected,
264-
linkStyle: TextStyle(
265-
color: linkColor,
266-
fontSize:
267-
AppSettings.fontSizeFactor.value *
268-
AppConfig.messageFontSize,
269-
decoration: TextDecoration.underline,
270-
decorationColor: linkColor,
271-
),
272-
onOpen: (url) => UrlLauncher(context, url.url).launchUrl(),
273-
eventId: event.eventId,
274-
checkboxCheckedEvents: event.aggregatedEvents(
275-
timeline,
276-
EventCheckboxRoomExtension.relationshipType,
277-
),
259+
child: Column(
260+
children: [
261+
Align(
262+
alignment: Alignment.centerLeft,
263+
child: HtmlMessage(
264+
html: html,
265+
textColor: textColor,
266+
room: event.room,
267+
fontSize:
268+
AppSettings.fontSizeFactor.value *
269+
AppConfig.messageFontSize *
270+
(bigEmotes ? 5 : 1),
271+
limitHeight: !selected,
272+
linkStyle: TextStyle(
273+
color: linkColor,
274+
fontSize:
275+
AppSettings.fontSizeFactor.value *
276+
AppConfig.messageFontSize,
277+
decoration: TextDecoration.underline,
278+
decorationColor: linkColor,
279+
),
280+
onOpen: (url) => UrlLauncher(context, url.url).launchUrl(),
281+
eventId: event.eventId,
282+
checkboxCheckedEvents: event.aggregatedEvents(
283+
timeline,
284+
EventCheckboxRoomExtension.relationshipType,
285+
),
286+
),
287+
),
288+
289+
Align(
290+
alignment: Alignment.centerRight,
291+
child: Padding(
292+
padding: const EdgeInsets.only(bottom: 6),
293+
child: Builder(
294+
builder: (context) {
295+
debugPrint(messageStatus.toString());
296+
297+
switch (messageStatus) {
298+
case null: {
299+
return SizedBox.shrink();
300+
}
301+
case MessageStatus.seen: {
302+
return Icon(
303+
Icons.done_all,
304+
size: 16,
305+
);
306+
}
307+
case MessageStatus.pending: {
308+
return Icon(
309+
Icons.schedule,
310+
size: 16,
311+
);
312+
}
313+
case MessageStatus.sent: {
314+
return Icon(
315+
Icons.check,
316+
size: 16,
317+
);
318+
}
319+
case MessageStatus.error: {
320+
return Icon(
321+
Icons.error,
322+
size: 16,
323+
color: Theme.of(context).colorScheme.error,
324+
);
325+
}
326+
}
327+
328+
},
329+
),
330+
)
331+
)
332+
],
278333
),
279334
);
280335
}

0 commit comments

Comments
 (0)