Remove flutter chat #26

Manually merged
Henry-Hiles merged 108 commits from remove-flutter-chat into main 2026-05-22 15:26:28 -04:00
3 changed files with 81 additions and 35 deletions
Showing only changes of commit a72d696f49 - Show all commits

working reply rendering

Henry Hiles 2026-05-19 21:44:03 -04:00
Signed by: Henry-Hiles
SSH key fingerprint: SHA256:VKQUdS31Q90KvX7EkKMHMBpUspcmItAh86a+v7PGiIs

View file

@ -31,6 +31,7 @@ abstract class Event with _$Event {
String? redactedBy, String? redactedBy,
String? relatesTo, String? relatesTo,
String? relationType, String? relationType,
String? replyTo,
String? decryptionError, String? decryptionError,
String? sendError, String? sendError,
@Default(IMap.empty()) IMap<String, int> reactions, @Default(IMap.empty()) IMap<String, int> reactions,
@ -43,6 +44,10 @@ abstract class Event with _$Event {
factory Event.fromJson(Map<String, dynamic> json) => factory Event.fromJson(Map<String, dynamic> json) =>
_$EventFromJson(json).copyWith( _$EventFromJson(json).copyWith(
replyTo:
((json["decrypted"] ?? json["content"])["m.new_content"] ??
json["decrypted"] ??
json["content"])?["m.relates_to"]?["m.in_reply_to"]?["event_id"],
content: Content.fromEventJson( content: Content.fromEventJson(
(json["decrypted"] ?? json["content"])["m.new_content"] ?? (json["decrypted"] ?? json["content"])["m.new_content"] ??
json["decrypted"] ?? json["decrypted"] ??

View file

@ -21,7 +21,6 @@ import "package:nexus/models/event.dart";
import "package:nexus/models/requests/get_event_request.dart"; import "package:nexus/models/requests/get_event_request.dart";
import "package:nexus/widgets/expandable_image.dart"; import "package:nexus/widgets/expandable_image.dart";
import "package:nexus/widgets/html/html.dart"; import "package:nexus/widgets/html/html.dart";
import "package:nexus/widgets/html/quoted.dart";
import "package:nexus/widgets/lazy_loading/message_avatar.dart"; import "package:nexus/widgets/lazy_loading/message_avatar.dart";
import "package:nexus/widgets/lazy_loading/message_displayname.dart"; import "package:nexus/widgets/lazy_loading/message_displayname.dart";
import "package:nexus/widgets/link_preview.dart"; import "package:nexus/widgets/link_preview.dart";
@ -110,50 +109,76 @@ class EventRenderer extends ConsumerWidget {
], ],
), ),
Card( Card(
color: color: textOnly
ref.watch( ? Colors.transparent
ClientStateController.provider.select( : ref.watch(
(value) => value?.userId, ClientStateController.provider.select(
), (value) => value?.userId,
) == ),
event.sender ) ==
event.sender
? (event.eventId.startsWith("~") ? (event.eventId.startsWith("~")
? colorScheme.onPrimary ? colorScheme.onPrimary
: colorScheme.primaryContainer) : colorScheme.primaryContainer)
: colorScheme.surfaceContainer, : colorScheme.surfaceContainer,
elevation: textOnly ? 0 : null,
child: Padding( child: Padding(
padding: EdgeInsets.all(12), padding: textOnly
? EdgeInsets.zero
: EdgeInsets.all(12),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
if (event.relationType == "m.in_reply_to" && if (event.replyTo != null)
event.relatesTo != null) Card(
Quoted( margin: EdgeInsets.only(bottom: 8),
ref color: theme.colorScheme.surfaceContainer,
.watch( child: InkWell(
onTap: onTapReply,
child: Padding(
padding: EdgeInsetsGeometry.symmetric(
vertical: 8,
horizontal: 12,
),
child: switch (ref.watch(
EventController.provider( EventController.provider(
GetEventRequest( GetEventRequest(
roomId: event.roomId, roomId: event.roomId,
eventId: event.relatesTo!, eventId: event.replyTo!,
), ),
), ),
) )) {
.when( AsyncData(:final value?) ||
data: (replyEvent) => replyEvent == null AsyncLoading(:final value?) => Row(
? SizedBox.shrink() spacing: 8,
: EventRenderer( children: [
replyEvent, MessageAvatar(event, height: 24),
MessageDisplayname(
event,
style: TextStyle(
color:
theme.colorScheme.primary,
fontWeight: FontWeight.bold,
),
),
Expanded(
child: EventRenderer(
value,
textOnly: true, textOnly: true,
maxLines: 1, maxLines: 1,
), ),
error: (_, _) => Text( ),
],
),
AsyncError _ => Text(
"An error occurred while fetching the reply", "An error occurred while fetching the reply",
style: errorStyle, style: errorStyle,
), ),
loading: () => _ => Text("Fetching event..."),
Text("Fetching event..."), },
), ),
),
), ),
switch (event.content) { switch (event.content) {
EncryptedContent() => Text( EncryptedContent() => Text(
@ -408,6 +433,8 @@ class EventRenderer extends ConsumerWidget {
? textOnly ? textOnly
? Text("Unknown event type", style: errorStyle) ? Text("Unknown event type", style: errorStyle)
: SizedBox.shrink() : SizedBox.shrink()
: textOnly
? child
: GestureDetector( : GestureDetector(
onSecondaryTapUp: contextMenuCallback, onSecondaryTapUp: contextMenuCallback,
onLongPressStart: contextMenuCallback, onLongPressStart: contextMenuCallback,

View file

@ -41,6 +41,7 @@ class RoomChat extends HookConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final relatedEvent = useState<Event?>(null); final relatedEvent = useState<Event?>(null);
final relationType = useState(RelationType.reply); final relationType = useState(RelationType.reply);
final flashingEvent = useState<String?>(null);
final memberListOpened = useState<bool>(showMembersByDefault); final memberListOpened = useState<bool>(showMembersByDefault);
@ -329,21 +330,34 @@ class RoomChat extends HookConsumerWidget {
value[index], value[index],
EventRenderer( EventRenderer(
value[index], value[index],
onTapReply: () => onTapReply: () async {
listController.value.animateToItem( final replyId = value[index].replyTo;
index: index, listController.value.animateToItem(
scrollController: scrollController, index: value.indexWhere(
alignment: 0.5, (element) => element.eventId == replyId,
duration: (_) =>
Duration(milliseconds: 250),
curve: (_) => Curves.easeInOut,
), ),
scrollController: scrollController,
alignment: 0.5,
duration: (_) =>
Duration(milliseconds: 250),
curve: (_) => Curves.easeInOut,
);
flashingEvent.value = replyId;
await Future.delayed(
Duration(seconds: 1),
() {
if (flashingEvent.value == replyId) {
flashingEvent.value = null;
}
},
);
},
getEventOptions: getEventOptions, getEventOptions: getEventOptions,
// TODO: Reimplement grouping // TODO: Reimplement grouping
isGrouped: false, isGrouped: false,
), ),
// TODO: Reimplement flashing isFlashing:
isFlashing: false, flashingEvent.value == value[index].eventId,
), ),
), ),
], ],