diff --git a/README.md b/README.md index 64ccb19..6a5f19a 100644 --- a/README.md +++ b/README.md @@ -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 - [ ] Searching - [ ] Creating (Rooms, Spaces, and DMs) - - [ ] Joining - - [ ] Using alias/id/link + - [x] Joining + - [x] Using a text/uri/link + - [x] Plain text + - [x] `matrix:` Uri + - [ ] Matrix.to link: I just need to fix my regex - [ ] From space - [ ] Exploring - [x] Leaving diff --git a/lib/controllers/client_controller.dart b/lib/controllers/client_controller.dart index fd7600f..abfdb72 100644 --- a/lib/controllers/client_controller.dart +++ b/lib/controllers/client_controller.dart @@ -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_related_events_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/profile.dart"; import "package:nexus/models/requests/paginate_request.dart"; @@ -138,6 +139,11 @@ class ClientController extends AsyncNotifier { } } + Future joinRoom(JoinRoomRequest request) async { + final response = await _sendCommand("join_room", request.toJson()); + return response["room_id"]; + } + Future leaveRoom(Room room) async { if (room.metadata == null) return; await _sendCommand("leave_room", {"room_id": room.metadata!.id}); diff --git a/lib/helpers/extensions/join_room_with_snackbars.dart b/lib/helpers/extensions/join_room_with_snackbars.dart index df89740..05b045d 100644 --- a/lib/helpers/extensions/join_room_with_snackbars.dart +++ b/lib/helpers/extensions/join_room_with_snackbars.dart @@ -1,9 +1,12 @@ import "package:collection/collection.dart"; +import "package:fast_immutable_collections/fast_immutable_collections.dart"; import "package:flutter/material.dart"; import "package:hooks_riverpod/hooks_riverpod.dart"; import "package:nexus/controllers/client_controller.dart"; import "package:nexus/controllers/key_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 { Future joinRoomWithSnackBars( @@ -11,77 +14,77 @@ extension JoinRoomWithSnackbars on ClientController { String roomAlias, WidgetRef ref, ) async { - // final parsed = roomAlias.parseIdentifierIntoParts(); - // final alias = parsed?.primaryIdentifier ?? roomAlias; + final roomIdOrAlias = roomAlias.mention ?? roomAlias; - // final scaffoldMessenger = ScaffoldMessenger.of(context); + final scaffoldMessenger = ScaffoldMessenger.of(context); - // final snackbar = scaffoldMessenger.showSnackBar( - // SnackBar( - // content: Text("Joining room $alias."), - // duration: Duration(days: 999), - // ), - // ); + final snackbar = scaffoldMessenger.showSnackBar( + SnackBar( + content: Text("Joining room $roomIdOrAlias."), + duration: Duration(days: 999), + ), + ); - // try { - // final id = await joinRoom(alias, via: parsed?.via.toList()); + try { + final id = await joinRoom( + JoinRoomRequest( + roomIdOrAlias: roomIdOrAlias, + via: IList(Uri.tryParse(roomAlias)?.queryParametersAll["via"] ?? []), + ), + ); - // snackbar.close(); + snackbar.close(); - // scaffoldMessenger.showSnackBar( - // SnackBar( - // content: Text("Room $alias successfully joined."), - // action: SnackBarAction( - // label: "Open", - // onPressed: () async { - // final spaces = await ref.refresh( - // SpacesController.provider.future, - // ); - // final space = spaces.firstWhereOrNull((space) => space.id == id); + scaffoldMessenger.showSnackBar( + SnackBar( + content: Text("Room $roomIdOrAlias successfully joined."), + action: SnackBarAction( + label: "Open", + onPressed: () async { + final spaces = ref.watch(SpacesController.provider); + final space = spaces.firstWhereOrNull((space) => space.id == id); - // await ref - // .watch( - // KeyController.provider(KeyController.spaceKey).notifier, - // ) - // .set( - // space?.id ?? - // spaces - // .firstWhere( - // (space) => - // space.children.firstWhereOrNull( - // (child) => child.roomData.id == id, - // ) != - // null, - // ) - // .id, - // ); + await ref + .watch( + KeyController.provider(KeyController.spaceKey).notifier, + ) + .set( + space?.id ?? + spaces + .firstWhere( + (space) => space.children.any( + (child) => child.metadata?.id == id, + ), + ) + .id, + ); - // if (space == null) { - // await ref - // .watch( - // KeyController.provider(KeyController.roomKey).notifier, - // ) - // .set(id); - // } - // }, - // ), - // ), - // ); - // } catch (error) { - // snackbar.close(); - // if (context.mounted) { - // scaffoldMessenger.showSnackBar( - // SnackBar( - // backgroundColor: Theme.of(context).colorScheme.errorContainer, - // content: Text( - // error.toString(), - // style: TextStyle( - // color: Theme.of(context).colorScheme.onErrorContainer, - // ), - // ), - // ), - // ); - // } - // } + if (space == null) { + await ref + .watch( + KeyController.provider(KeyController.roomKey).notifier, + ) + .set(id); + } + }, + ), + ), + ); + } catch (error) { + snackbar.close(); + if (context.mounted) { + scaffoldMessenger.showSnackBar( + SnackBar( + backgroundColor: Theme.of(context).colorScheme.errorContainer, + content: Text( + error.toString(), + style: TextStyle( + color: Theme.of(context).colorScheme.onErrorContainer, + ), + ), + ), + ); + } + } } } diff --git a/lib/helpers/extensions/link_to_mention.dart b/lib/helpers/extensions/link_to_mention.dart index 33d2bd2..8095132 100644 --- a/lib/helpers/extensions/link_to_mention.dart +++ b/lib/helpers/extensions/link_to_mention.dart @@ -29,7 +29,11 @@ extension LinkToMention on String { if (uri.pathSegments.isNotEmpty) { final identifier = uri.pathSegments.last; if (identifier.isNotEmpty) { - return Uri.decodeComponent(identifier); + return "${switch (uri.pathSegments.firstOrNull) { + "r" || "roomid" => "#", + "u" => "@", + _ => "", + }}${Uri.decodeComponent(identifier)}"; } } } catch (_) {} diff --git a/lib/models/requests/join_room_request.dart b/lib/models/requests/join_room_request.dart new file mode 100644 index 0000000..d6b411e --- /dev/null +++ b/lib/models/requests/join_room_request.dart @@ -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 via, + }) = _JoinRoomRequest; + + factory JoinRoomRequest.fromJson(Map json) => + _$JoinRoomRequestFromJson(json); +}