Fix sending permission thingy

This commit is contained in:
Henry Hiles 2025-12-26 15:04:49 -05:00
commit 6215537f8e
No known key found for this signature in database
2 changed files with 148 additions and 137 deletions

View file

@ -7,6 +7,7 @@ import "package:nexus/controllers/avatar_controller.dart";
import "package:nexus/controllers/events_controller.dart";
import "package:nexus/helpers/extensions/event_to_message.dart";
import "package:nexus/helpers/extensions/list_to_messages.dart";
import "package:fluttertagger/fluttertagger.dart" as tagger;
class RoomChatController extends AsyncNotifier<ChatController> {
final Room room;
@ -93,11 +94,27 @@ class RoomChatController extends AsyncNotifier<ChatController> {
Future<void> updateMessage(Message message, Message newMessage) async =>
(await future).updateMessage(message, newMessage);
Future<void> send(String message, {Message? replyTo}) async =>
room.sendTextEvent(
message,
inReplyTo: replyTo == null ? null : await room.getEventById(replyTo.id),
Future<void> send(
String message, {
required Iterable<tagger.Tag> tags,
Message? replyTo,
}) async {
var taggedMessage = message;
for (final tag in tags) {
final escaped = RegExp.escape(tag.id.substring(1));
final pattern = RegExp(r"@@(" + escaped + r")#[^#]*#");
taggedMessage = taggedMessage.replaceAllMapped(
pattern,
(m) => "@${m.group(1)}",
);
}
await room.sendTextEvent(
taggedMessage,
inReplyTo: replyTo == null ? null : await room.getEventById(replyTo.id),
);
}
Future<chat.User> resolveUser(String id) async {
final user = await room.client.getUserProfile(id);

View file

@ -33,19 +33,25 @@ class ChatBox extends HookConsumerWidget {
final triggerCharacter = useState("");
final query = useState("");
Future<void> send() => ref
.watch(RoomChatController.provider(room).notifier)
.send(controller.value.text, replyTo: replyToMessage);
void send() {
ref
.watch(RoomChatController.provider(room).notifier)
.send(
controller.value.formattedText,
replyTo: replyToMessage,
tags: controller.value.tags,
);
controller.value.text = "";
}
final node = useFocusNode(
onKeyEvent: (_, event) {
if (event is! KeyDownEvent || Platform.isAndroid || Platform.isIOS) {
if (event is KeyDownEvent && !Platform.isAndroid && !Platform.isIOS) {
if (event.logicalKey == LogicalKeyboardKey.enter &&
!HardwareKeyboard.instance.isShiftPressed) {
send();
return KeyEventResult.handled;
}
if (event.logicalKey == LogicalKeyboardKey.escape) {
} else if (event.logicalKey == LogicalKeyboardKey.escape) {
onDismiss();
return KeyEventResult.handled;
}
@ -78,139 +84,127 @@ class ChatBox extends HookConsumerWidget {
Container(
color: theme.colorScheme.surfaceContainerHighest,
padding: EdgeInsets.symmetric(horizontal: 8),
child: room.canSendDefaultMessages
? Row(
spacing: 8,
children: [
PopupMenuButton(
itemBuilder: (context) => [],
icon: Icon(Icons.add),
),
Expanded(
child: FlutterTagger(
triggerStrategy: TriggerStrategy.eager,
overlay: Padding(
padding: EdgeInsets.all(8),
child: ClipRRect(
borderRadius: BorderRadius.all(
Radius.circular(12),
),
child: Container(
color:
theme.colorScheme.surfaceContainerHigh,
padding: EdgeInsets.all(8),
child: switch (triggerCharacter.value) {
"@" =>
ref
.watch(
MembersController.provider(room),
)
.betterWhen(
data: (members) => ListView(
children:
(query.value.isEmpty
? members
: members.where(
(member) =>
member
.senderId
.contains(
query
.value,
) ||
(member.content["displayname"]
as String?)
?.contains(
query.value,
) ==
true,
))
.map(
(member) => ListTile(
leading: AvatarOrHash(
ref
.watch(
AvatarController.provider(
member
.content["avatar_url"]
.toString(),
),
)
.whenOrNull(
data:
(
data,
) =>
data,
),
member
.content["displayname"]
.toString(),
headers: room
.client
.headers,
child: Row(
spacing: 8,
children: [
PopupMenuButton(
itemBuilder: (context) => [],
icon: Icon(Icons.add),
enabled: room.canSendDefaultMessages,
),
Expanded(
child: FlutterTagger(
triggerStrategy: TriggerStrategy.eager,
overlay: Padding(
padding: EdgeInsets.all(8),
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(12)),
child: Container(
color: theme.colorScheme.surfaceContainerHigh,
padding: EdgeInsets.all(8),
child: switch (triggerCharacter.value) {
"@" =>
ref
.watch(MembersController.provider(room))
.betterWhen(
data: (members) => ListView(
children:
(query.value.isEmpty
? members
: members.where(
(member) =>
member.senderId
.contains(
query.value,
) ||
(member.content["displayname"]
as String?)
?.contains(
query
.value,
) ==
true,
))
.map(
(member) => ListTile(
leading: AvatarOrHash(
ref
.watch(
AvatarController.provider(
member
.content["avatar_url"]
.toString(),
),
)
.whenOrNull(
data: (data) =>
data,
),
title: Text(
member.content["displayname"]
as String? ??
member
.senderId,
),
onTap: () => controller
.value
.addTag(
id: "member",
name: member
.senderId
.substring(
1,
)
.split(
":",
)
.first,
),
member
.content["displayname"]
.toString(),
headers:
room.client.headers,
),
title: Text(
member.content["displayname"]
as String? ??
member.senderId,
),
onTap: () => controller
.value
.addTag(
id: member.senderId,
name: member
.senderId
.substring(1)
.split(":")
.first,
),
)
.toList(),
),
),
"#" => Text("Todo"),
_ => Loading(),
},
),
),
),
controller: controller.value,
onSearch: (newQuery, newTriggerCharacter) {
triggerCharacter.value = newTriggerCharacter;
query.value = newQuery;
),
)
.toList(),
),
),
"#" => Text("Todo"),
_ => Loading(),
},
triggerCharacterAndStyles: {
"@": style,
"#": style,
":": style,
},
builder: (context, key) => TextFormField(
maxLines: 12,
minLines: 1,
decoration: InputDecoration(
hintText: "Your message here...",
border: InputBorder.none,
),
controller: controller.value,
key: key,
autofocus: true,
focusNode: node,
),
),
),
IconButton(onPressed: send, icon: Icon(Icons.send)),
],
)
: Text(
"You don't have permission to send messages here...",
),
controller: controller.value,
onSearch: (newQuery, newTriggerCharacter) {
triggerCharacter.value = newTriggerCharacter;
query.value = newQuery;
},
triggerCharacterAndStyles: {
"@": style,
"#": style,
":": style,
},
builder: (context, key) => TextFormField(
enabled: room.canSendDefaultMessages,
maxLines: 12,
minLines: 1,
decoration: InputDecoration(
hintText: room.canSendDefaultMessages
? "Your message here..."
: "You don't have permission to send messages in this room...",
border: InputBorder.none,
),
controller: controller.value,
key: key,
autofocus: true,
focusNode: node,
),
),
),
IconButton(
onPressed: room.canSendDefaultMessages ? send : null,
icon: Icon(Icons.send),
),
],
),
),
],
),