joining rooms from matrix uri or plaintext

This commit is contained in:
Henry Hiles 2026-01-30 20:22:51 +01:00
commit 82b6f2c647
No known key found for this signature in database
5 changed files with 99 additions and 68 deletions

View file

@ -32,8 +32,11 @@ A simple and user-friendly Matrix client made with Flutter and the Matrix Dart S
- [x] Mark as read button on rooms and spaces - [x] Mark as read button on rooms and spaces
- [ ] Searching - [ ] Searching
- [ ] Creating (Rooms, Spaces, and DMs) - [ ] Creating (Rooms, Spaces, and DMs)
- [ ] Joining - [x] Joining
- [ ] Using alias/id/link - [x] Using a text/uri/link
- [x] Plain text
- [x] `matrix:` Uri
- [ ] Matrix.to link: I just need to fix my regex
- [ ] From space - [ ] From space
- [ ] Exploring - [ ] Exploring
- [x] Leaving - [x] Leaving

View file

@ -16,6 +16,7 @@ import "package:nexus/models/paginate.dart";
import "package:nexus/models/requests/get_event_request.dart"; import "package:nexus/models/requests/get_event_request.dart";
import "package:nexus/models/requests/get_related_events_request.dart"; import "package:nexus/models/requests/get_related_events_request.dart";
import "package:nexus/models/requests/get_room_state_request.dart"; import "package:nexus/models/requests/get_room_state_request.dart";
import "package:nexus/models/requests/join_room_request.dart";
import "package:nexus/models/requests/login_request.dart"; import "package:nexus/models/requests/login_request.dart";
import "package:nexus/models/profile.dart"; import "package:nexus/models/profile.dart";
import "package:nexus/models/requests/paginate_request.dart"; import "package:nexus/models/requests/paginate_request.dart";
@ -138,6 +139,11 @@ class ClientController extends AsyncNotifier<int> {
} }
} }
Future<String> joinRoom(JoinRoomRequest request) async {
final response = await _sendCommand("join_room", request.toJson());
return response["room_id"];
}
Future<void> leaveRoom(Room room) async { Future<void> leaveRoom(Room room) async {
if (room.metadata == null) return; if (room.metadata == null) return;
await _sendCommand("leave_room", {"room_id": room.metadata!.id}); await _sendCommand("leave_room", {"room_id": room.metadata!.id});

View file

@ -1,9 +1,12 @@
import "package:collection/collection.dart"; import "package:collection/collection.dart";
import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:flutter/material.dart"; import "package:flutter/material.dart";
import "package:hooks_riverpod/hooks_riverpod.dart"; import "package:hooks_riverpod/hooks_riverpod.dart";
import "package:nexus/controllers/client_controller.dart"; import "package:nexus/controllers/client_controller.dart";
import "package:nexus/controllers/key_controller.dart"; import "package:nexus/controllers/key_controller.dart";
import "package:nexus/controllers/spaces_controller.dart"; import "package:nexus/controllers/spaces_controller.dart";
import "package:nexus/helpers/extensions/link_to_mention.dart";
import "package:nexus/models/requests/join_room_request.dart";
extension JoinRoomWithSnackbars on ClientController { extension JoinRoomWithSnackbars on ClientController {
Future<void> joinRoomWithSnackBars( Future<void> joinRoomWithSnackBars(
@ -11,77 +14,77 @@ extension JoinRoomWithSnackbars on ClientController {
String roomAlias, String roomAlias,
WidgetRef ref, WidgetRef ref,
) async { ) async {
// final parsed = roomAlias.parseIdentifierIntoParts(); final roomIdOrAlias = roomAlias.mention ?? roomAlias;
// final alias = parsed?.primaryIdentifier ?? roomAlias;
// final scaffoldMessenger = ScaffoldMessenger.of(context); final scaffoldMessenger = ScaffoldMessenger.of(context);
// final snackbar = scaffoldMessenger.showSnackBar( final snackbar = scaffoldMessenger.showSnackBar(
// SnackBar( SnackBar(
// content: Text("Joining room $alias."), content: Text("Joining room $roomIdOrAlias."),
// duration: Duration(days: 999), duration: Duration(days: 999),
// ), ),
// ); );
// try { try {
// final id = await joinRoom(alias, via: parsed?.via.toList()); final id = await joinRoom(
JoinRoomRequest(
roomIdOrAlias: roomIdOrAlias,
via: IList(Uri.tryParse(roomAlias)?.queryParametersAll["via"] ?? []),
),
);
// snackbar.close(); snackbar.close();
// scaffoldMessenger.showSnackBar( scaffoldMessenger.showSnackBar(
// SnackBar( SnackBar(
// content: Text("Room $alias successfully joined."), content: Text("Room $roomIdOrAlias successfully joined."),
// action: SnackBarAction( action: SnackBarAction(
// label: "Open", label: "Open",
// onPressed: () async { onPressed: () async {
// final spaces = await ref.refresh( final spaces = ref.watch(SpacesController.provider);
// SpacesController.provider.future, final space = spaces.firstWhereOrNull((space) => space.id == id);
// );
// final space = spaces.firstWhereOrNull((space) => space.id == id);
// await ref await ref
// .watch( .watch(
// KeyController.provider(KeyController.spaceKey).notifier, KeyController.provider(KeyController.spaceKey).notifier,
// ) )
// .set( .set(
// space?.id ?? space?.id ??
// spaces spaces
// .firstWhere( .firstWhere(
// (space) => (space) => space.children.any(
// space.children.firstWhereOrNull( (child) => child.metadata?.id == id,
// (child) => child.roomData.id == id, ),
// ) != )
// null, .id,
// ) );
// .id,
// );
// if (space == null) { if (space == null) {
// await ref await ref
// .watch( .watch(
// KeyController.provider(KeyController.roomKey).notifier, KeyController.provider(KeyController.roomKey).notifier,
// ) )
// .set(id); .set(id);
// } }
// }, },
// ), ),
// ), ),
// ); );
// } catch (error) { } catch (error) {
// snackbar.close(); snackbar.close();
// if (context.mounted) { if (context.mounted) {
// scaffoldMessenger.showSnackBar( scaffoldMessenger.showSnackBar(
// SnackBar( SnackBar(
// backgroundColor: Theme.of(context).colorScheme.errorContainer, backgroundColor: Theme.of(context).colorScheme.errorContainer,
// content: Text( content: Text(
// error.toString(), error.toString(),
// style: TextStyle( style: TextStyle(
// color: Theme.of(context).colorScheme.onErrorContainer, color: Theme.of(context).colorScheme.onErrorContainer,
// ), ),
// ), ),
// ), ),
// ); );
// } }
// } }
} }
} }

View file

@ -29,7 +29,11 @@ extension LinkToMention on String {
if (uri.pathSegments.isNotEmpty) { if (uri.pathSegments.isNotEmpty) {
final identifier = uri.pathSegments.last; final identifier = uri.pathSegments.last;
if (identifier.isNotEmpty) { if (identifier.isNotEmpty) {
return Uri.decodeComponent(identifier); return "${switch (uri.pathSegments.firstOrNull) {
"r" || "roomid" => "#",
"u" => "@",
_ => "",
}}${Uri.decodeComponent(identifier)}";
} }
} }
} catch (_) {} } catch (_) {}

View file

@ -0,0 +1,15 @@
import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:freezed_annotation/freezed_annotation.dart";
part "join_room_request.freezed.dart";
part "join_room_request.g.dart";
@freezed
abstract class JoinRoomRequest with _$JoinRoomRequest {
const factory JoinRoomRequest({
required String roomIdOrAlias,
required IList<String> via,
}) = _JoinRoomRequest;
factory JoinRoomRequest.fromJson(Map<String, Object?> json) =>
_$JoinRoomRequestFromJson(json);
}