diff --git a/gomuks b/gomuks index 15ac73b..38e5033 160000 --- a/gomuks +++ b/gomuks @@ -1 +1 @@ -Subproject commit 15ac73be09155a7c5319a144f8af0e75a409fc51 +Subproject commit 38e5033c3a91db0cbea6cbd9f0feef9ff6441038 diff --git a/lib/models/requests/set_membership.dart b/lib/models/requests/set_membership.dart index 9d88da2..9b8a03f 100644 --- a/lib/models/requests/set_membership.dart +++ b/lib/models/requests/set_membership.dart @@ -10,7 +10,7 @@ class const SetMembershipRequest({ required final String userId, required final String roomId, final String? reason, - @JsonKey(name: "action") required final MembershipAction action, + required final MembershipAction action, @JsonKey(name: "msc4293_redact_events") final bool redact = false, }) with _$SetMembershipRequest { Map toJson() => _$SetMembershipRequestToJson(this); diff --git a/lib/widgets/room_appbar.dart b/lib/widgets/room_appbar.dart index 4248177..3b29129 100644 --- a/lib/widgets/room_appbar.dart +++ b/lib/widgets/room_appbar.dart @@ -3,7 +3,7 @@ import "package:hooks_riverpod/hooks_riverpod.dart"; import "package:nexus/controllers/rooms.dart"; import "package:nexus/widgets/appbar.dart"; import "package:nexus/widgets/avatar_or_hash.dart"; -import "package:nexus/widgets/room_menu.dart"; +import "package:nexus/widgets/room_menu_button.dart"; import "package:nexus/widgets/room_summary_dialog.dart"; final class const RoomAppbar({ @@ -72,21 +72,23 @@ final class const RoomAppbar({ ), ], ), - actions: room == null - ? .new() - : .new([ - IconButton( - onPressed: onOpenPinnedMessagesList?.call, - icon: Icon(Icons.push_pin), - tooltip: "Open pinned messages", - ), - IconButton( - onPressed: () => onOpenMemberList?.call(context), - tooltip: "Open member list", - icon: Icon(Icons.people), - ), - RoomMenu(room), - ]), + actions: .new( + room == null + ? [] + : [ + IconButton( + onPressed: onOpenPinnedMessagesList?.call, + icon: Icon(Icons.push_pin), + tooltip: "Open pinned messages", + ), + IconButton( + onPressed: () => onOpenMemberList?.call(context), + tooltip: "Open member list", + icon: Icon(Icons.people), + ), + RoomMenuButton(room), + ], + ), ); } } diff --git a/lib/widgets/room_list.dart b/lib/widgets/room_list.dart index 8b96cbf..b4f07f5 100644 --- a/lib/widgets/room_list.dart +++ b/lib/widgets/room_list.dart @@ -10,7 +10,7 @@ import "package:nexus/widgets/divider_widget.dart"; import "package:nexus/widgets/error_dialog.dart"; import "package:nexus/widgets/pages/settings.dart"; import "package:nexus/widgets/join_dialog.dart"; -import "package:nexus/widgets/room_menu.dart"; +import "package:nexus/widgets/room_menu_button.dart"; import "package:nexus/controllers/key.dart"; import "package:nexus/controllers/spaces.dart"; import "package:nexus/models/room.dart"; @@ -232,7 +232,10 @@ class const RoomsPane({super.key}) extends ConsumerWidget { title: Text(selectedSpace.title, overflow: .ellipsis), backgroundColor: Colors.transparent, actions: [ - RoomMenu(selectedSpace.room, children: selectedSpace.allChildRooms), + RoomMenuButton( + selectedSpace.room, + children: selectedSpace.allChildRooms, + ), ], ), body: MaterialUiCompatibilityBridge( diff --git a/lib/widgets/room_menu.dart b/lib/widgets/room_menu_button.dart similarity index 56% rename from lib/widgets/room_menu.dart rename to lib/widgets/room_menu_button.dart index 7488ada..7e6516d 100644 --- a/lib/widgets/room_menu.dart +++ b/lib/widgets/room_menu_button.dart @@ -5,8 +5,10 @@ import "package:flutter_riverpod/flutter_riverpod.dart"; import "package:nexus/controllers/client.dart"; import "package:nexus/controllers/via.dart"; import "package:nexus/models/room.dart"; +import "package:flutter_hooks/flutter_hooks.dart"; +import "package:nexus/main.dart"; -final class const RoomMenu( +final class const RoomMenuButton( final Room? room, { final IList children = const IList.empty(), super.key, @@ -44,6 +46,63 @@ final class const RoomMenu( title: Text("Copy Link"), ), ), + PopupMenuItem( + onTap: () => showDialog( + context: context, + builder: (context) => HookBuilder( + builder: (context) { + final userIdController = useTextEditingController(); + final text = useValueListenable(userIdController).text.trim(); + final valid = RegExp(r"^@[^:\s]+:[^\s]+$").hasMatch(text); + + void submit() { + if (!valid) return; + Navigator.of(context).pop(); + client + .setMembership( + .new( + userId: text, + roomId: room!.metadata!.id, + action: .invite, + ), + ) + .onError(showError); + } + + return AlertDialog( + title: Text("Invite User"), + content: TextField( + controller: userIdController, + autofocus: true, + keyboardType: .emailAddress, + onSubmitted: (_) => submit(), + decoration: .new( + labelText: "User ID", + hintText: "@user:example.com", + errorText: text.isEmpty || valid + ? null + : "Enter a valid user ID", + ), + ), + actions: [ + TextButton( + onPressed: Navigator.of(context).pop, + child: Text("Cancel"), + ), + TextButton( + onPressed: valid ? submit : null, + child: Text("Invite"), + ), + ], + ); + }, + ), + ), + child: ListTile( + leading: Icon(Icons.person_add), + title: Text("Invite"), + ), + ), PopupMenuItem( onTap: () => showDialog( context: context, @@ -81,54 +140,6 @@ final class const RoomMenu( ), ), ], - - // PopupMenuItem( - // onTap: () => showDialog( - // context: context, - // builder: (context) => HookBuilder( - // builder: (_) { - // final reasonController = useTextEditingController(); - // return AlertDialog( - // title: Text("Report"), - // content: Column( - // mainAxisSize: MainAxisSize.min, - // crossAxisAlignment: CrossAxisAlignment.start, - // children: [ - // Text( - // "Report this room to your server administrators, who can take action like banning this room.", - // ), - - // SizedBox(height: 12), - // FormTextInput( - // required: false, - // capitalize: true, - // controller: reasonController, - // title: "Reason for report (optional)", - // ), - // ], - // ), - // actions: [ - // TextButton( - // onPressed: Navigator.of(context).pop, - // child: Text("Cancel"), - // ), - // TextButton( - // onPressed: () { - // room.client.reportRoom(room.id, reasonController.text); - // Navigator.of(context).pop(); - // }, - // child: Text("Report"), - // ), - // ], - // ); - // }, - // ), - // ), - // child: ListTile( - // leading: Icon(Icons.report, color: danger), - // title: Text("Report", style: TextStyle(color: danger)), - // ), - // ), ], ); }