refactored direct chat logic into a shared utility, implemented direct message shortcuts in the participant list and message reactions, and added reaction visibility checks in the message options dialog

This commit is contained in:
2026-05-13 18:46:34 +02:00
parent a09817a975
commit d0ba7c0fd6
5 changed files with 121 additions and 77 deletions
+4 -1
View File
@@ -77,7 +77,10 @@ class _ChatInfoState extends State<ChatInfo> {
trailing: const Icon(Icons.arrow_right),
onTap: () => TalkNavigator.pushSplitView(
context,
ParticipantsListView(participants!),
ParticipantsListView(
participants!,
showDirectMessageAction: isGroup,
),
),
),
],
@@ -1,4 +1,3 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import '../../../../api/marianumcloud/talk/get_reactions/get_reactions.dart';
@@ -7,8 +6,8 @@ import '../../../../model/account_data.dart';
import '../../../../widget/centered_leading.dart';
import '../../../../widget/loading_spinner.dart';
import '../../../../widget/placeholder_view.dart';
import '../../../../widget/unimplemented_dialog.dart';
import '../../../../widget/user_avatar.dart';
import '../data/open_direct_chat.dart';
class MessageReactions extends StatefulWidget {
final String token;
@@ -63,25 +62,28 @@ class _MessageReactionsState extends State<MessageReactions> {
leading: CenteredLeading(Text(entry.key)),
title: Text('${entry.value.length} mal reagiert'),
children: entry.value.map((e) {
var isSelf = AccountData().getUsername() == e.actorId;
final isSelf = AccountData().getUsername() == e.actorId;
final isGuest =
e.actorType ==
GetReactionsResponseObjectActorType.guests;
return ListTile(
leading: UserAvatar(id: e.actorId, isGroup: false),
title: Text(e.actorDisplayName),
subtitle: isSelf
? const Text('Du')
: e.actorType ==
GetReactionsResponseObjectActorType.guests
: isGuest
? const Text('Gast')
: null,
trailing: isSelf
trailing: isSelf || isGuest
? null
: Visibility(
visible: kReleaseMode,
child: IconButton(
onPressed: () =>
UnimplementedDialog.show(context),
icon: const Icon(Icons.textsms_outlined),
: IconButton(
tooltip: 'Private Nachricht',
onPressed: () => openOrCreateDirectChat(
context,
actorId: e.actorId,
actorDisplayName: e.actorDisplayName,
),
icon: const Icon(Icons.textsms_outlined),
),
);
}).toList(),
@@ -2,11 +2,23 @@ import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import '../../../../api/marianumcloud/talk/get_participants/get_participants_response.dart';
import '../../../../model/account_data.dart';
import '../../../../widget/user_avatar.dart';
import '../data/open_direct_chat.dart';
class ParticipantsListView extends StatelessWidget {
final GetParticipantsResponse participantsResponse;
const ParticipantsListView(this.participantsResponse, {super.key});
/// Hide the per-participant direct-message shortcut: in a 1:1 chat the
/// only other participant *is* the current chat — the shortcut would
/// just navigate back to where the user already is.
final bool showDirectMessageAction;
const ParticipantsListView(
this.participantsResponse, {
this.showDirectMessageAction = true,
super.key,
});
@override
Widget build(BuildContext context) {
@@ -24,6 +36,7 @@ class ParticipantsListView extends StatelessWidget {
(participant) => participant.participantType,
);
final selfId = AccountData().getUsername();
return Scaffold(
appBar: AppBar(title: const Text('Mitglieder')),
body: ListView(
@@ -35,15 +48,30 @@ class ParticipantsListView extends StatelessWidget {
title: Text(entry.key.prettyName),
titleTextStyle: Theme.of(context).textTheme.titleMedium,
),
...entry.value.map(
(participant) => ListTile(
...entry.value.map((participant) {
final canDirectMessage =
showDirectMessageAction &&
participant.actorType == 'users' &&
participant.actorId != selfId;
return ListTile(
leading: UserAvatar(id: participant.actorId),
title: Text(participant.displayName),
subtitle: participant.statusMessage != null
? Text(participant.statusMessage!)
: null,
),
),
trailing: canDirectMessage
? IconButton(
tooltip: 'Private Nachricht',
onPressed: () => openOrCreateDirectChat(
context,
actorId: participant.actorId,
actorDisplayName: participant.displayName,
),
icon: const Icon(Icons.textsms_outlined),
)
: null,
);
}),
Divider(),
],
),