From a500a91b6bba6ec5ae411de473b76c75829baa2a Mon Sep 17 00:00:00 2001 From: krille-chan Date: Mon, 22 Jul 2024 20:06:07 +0200 Subject: [PATCH] chore: Follow up add chat or subspace UX --- lib/pages/chat_list/chat_list.dart | 107 ++---------------- lib/pages/chat_list/chat_list_view.dart | 6 +- lib/pages/chat_list/space_view.dart | 141 ++++++++++++++++++++++-- 3 files changed, 145 insertions(+), 109 deletions(-) diff --git a/lib/pages/chat_list/chat_list.dart b/lib/pages/chat_list/chat_list.dart index 13ce54053..befba299a 100644 --- a/lib/pages/chat_list/chat_list.dart +++ b/lib/pages/chat_list/chat_list.dart @@ -105,107 +105,18 @@ class ChatListController extends State String? _activeSpaceId; String? get activeSpaceId => _activeSpaceId; - void setActiveSpace(String spaceId) => setState(() { - _activeSpaceId = spaceId; - }); + void setActiveSpace(String spaceId) async { + await Matrix.of(context).client.getRoomById(spaceId)!.postLoad(); + + setState(() { + _activeSpaceId = spaceId; + }); + } + void clearActiveSpace() => setState(() { _activeSpaceId = null; }); - void addChatAction() async { - if (activeSpaceId == null) { - context.go('/rooms/newprivatechat'); - return; - } - - final roomType = await showConfirmationDialog( - context: context, - title: L10n.of(context)!.addChatOrSubSpace, - actions: [ - AlertDialogAction( - key: AddRoomType.subspace, - label: L10n.of(context)!.createNewSpace, - ), - AlertDialogAction( - key: AddRoomType.chat, - label: L10n.of(context)!.createGroup, - ), - ], - ); - if (roomType == null) return; - - final names = await showTextInputDialog( - context: context, - title: roomType == AddRoomType.subspace - ? L10n.of(context)!.createNewSpace - : L10n.of(context)!.createGroup, - textFields: [ - DialogTextField( - hintText: roomType == AddRoomType.subspace - ? L10n.of(context)!.spaceName - : L10n.of(context)!.groupName, - minLines: 1, - maxLines: 1, - maxLength: 64, - validator: (text) { - if (text == null || text.isEmpty) { - return L10n.of(context)!.pleaseChoose; - } - return null; - }, - ), - DialogTextField( - hintText: L10n.of(context)!.chatDescription, - minLines: 4, - maxLines: 8, - maxLength: 255, - ), - ], - okLabel: L10n.of(context)!.create, - cancelLabel: L10n.of(context)!.cancel, - ); - if (names == null) return; - final client = Matrix.of(context).client; - final result = await showFutureLoadingDialog( - context: context, - future: () async { - late final String roomId; - final activeSpace = client.getRoomById(activeSpaceId!)!; - await activeSpace.postLoad(); - - if (roomType == AddRoomType.subspace) { - roomId = await client.createSpace( - name: names.first, - topic: names.last.isEmpty ? null : names.last, - visibility: activeSpace.joinRules == JoinRules.public - ? sdk.Visibility.public - : sdk.Visibility.private, - ); - } else { - roomId = await client.createGroupChat( - groupName: names.first, - preset: activeSpace.joinRules == JoinRules.public - ? CreateRoomPreset.publicChat - : CreateRoomPreset.privateChat, - visibility: activeSpace.joinRules == JoinRules.public - ? sdk.Visibility.public - : sdk.Visibility.private, - initialState: names.length > 1 && names.last.isNotEmpty - ? [ - sdk.StateEvent( - type: sdk.EventTypes.RoomTopic, - content: {'topic': names.last}, - ), - ] - : null, - ); - } - await activeSpace.setSpaceChild(roomId); - }, - ); - if (result.error != null) return; - } - void onChatTap(Room room) async { if (room.membership == Membership.invite) { final inviterId = @@ -1004,8 +915,6 @@ enum InviteActions { block, } -enum AddRoomType { chat, subspace } - enum ChatContextAction { open, goToSpace, diff --git a/lib/pages/chat_list/chat_list_view.dart b/lib/pages/chat_list/chat_list_view.dart index 510c6c46d..a106e5dd7 100644 --- a/lib/pages/chat_list/chat_list_view.dart +++ b/lib/pages/chat_list/chat_list_view.dart @@ -146,9 +146,11 @@ class ChatListView extends StatelessWidget { onKeysPressed: () => context.go('/rooms/newprivatechat'), helpLabel: L10n.of(context)!.newChat, child: selectMode == SelectMode.normal && - !controller.isSearchMode + !controller.isSearchMode && + controller.activeSpaceId == null ? FloatingActionButton.extended( - onPressed: controller.addChatAction, + onPressed: () => + context.go('/rooms/newprivatechat'), icon: const Icon(Icons.add_outlined), label: Text( L10n.of(context)!.chat, diff --git a/lib/pages/chat_list/space_view.dart b/lib/pages/chat_list/space_view.dart index 3401aa1f1..5ad99faa8 100644 --- a/lib/pages/chat_list/space_view.dart +++ b/lib/pages/chat_list/space_view.dart @@ -5,6 +5,7 @@ import 'package:collection/collection.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:future_loading_dialog/future_loading_dialog.dart'; import 'package:go_router/go_router.dart'; +import 'package:matrix/matrix.dart' as sdk; import 'package:matrix/matrix.dart'; import 'package:fluffychat/config/app_config.dart'; @@ -15,6 +16,8 @@ import 'package:fluffychat/utils/stream_extension.dart'; import 'package:fluffychat/widgets/avatar.dart'; import 'package:fluffychat/widgets/matrix.dart'; +enum AddRoomType { chat, subspace } + class SpaceView extends StatefulWidget { final String spaceId; final void Function() onBack; @@ -160,6 +163,95 @@ class _SpaceViewState extends State { } } + void _addChatOrSubspace() async { + final roomType = await showConfirmationDialog( + context: context, + title: L10n.of(context)!.addChatOrSubSpace, + actions: [ + AlertDialogAction( + key: AddRoomType.subspace, + label: L10n.of(context)!.createNewSpace, + ), + AlertDialogAction( + key: AddRoomType.chat, + label: L10n.of(context)!.createGroup, + ), + ], + ); + if (roomType == null) return; + + final names = await showTextInputDialog( + context: context, + title: roomType == AddRoomType.subspace + ? L10n.of(context)!.createNewSpace + : L10n.of(context)!.createGroup, + textFields: [ + DialogTextField( + hintText: roomType == AddRoomType.subspace + ? L10n.of(context)!.spaceName + : L10n.of(context)!.groupName, + minLines: 1, + maxLines: 1, + maxLength: 64, + validator: (text) { + if (text == null || text.isEmpty) { + return L10n.of(context)!.pleaseChoose; + } + return null; + }, + ), + DialogTextField( + hintText: L10n.of(context)!.chatDescription, + minLines: 4, + maxLines: 8, + maxLength: 255, + ), + ], + okLabel: L10n.of(context)!.create, + cancelLabel: L10n.of(context)!.cancel, + ); + if (names == null) return; + final client = Matrix.of(context).client; + final result = await showFutureLoadingDialog( + context: context, + future: () async { + late final String roomId; + final activeSpace = client.getRoomById(widget.spaceId)!; + await activeSpace.postLoad(); + + if (roomType == AddRoomType.subspace) { + roomId = await client.createSpace( + name: names.first, + topic: names.last.isEmpty ? null : names.last, + visibility: activeSpace.joinRules == JoinRules.public + ? sdk.Visibility.public + : sdk.Visibility.private, + ); + } else { + roomId = await client.createGroupChat( + groupName: names.first, + preset: activeSpace.joinRules == JoinRules.public + ? CreateRoomPreset.publicChat + : CreateRoomPreset.privateChat, + visibility: activeSpace.joinRules == JoinRules.public + ? sdk.Visibility.public + : sdk.Visibility.private, + initialState: names.length > 1 && names.last.isNotEmpty + ? [ + StateEvent( + type: EventTypes.RoomTopic, + content: {'topic': names.last}, + ), + ] + : null, + ); + } + await activeSpace.setSpaceChild(roomId); + }, + ); + if (result.error != null) return; + } + @override Widget build(BuildContext context) { final room = Matrix.of(context).client.getRoomById(widget.spaceId); @@ -352,22 +444,55 @@ class _SpaceViewState extends State { itemCount: joinedRooms.length + 1, itemBuilder: (context, i) { if (i == 0) { - return SearchTitle( - title: L10n.of(context)!.joinedChats, - icon: const Icon(Icons.chat_outlined), + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + if (room.canChangeStateEvent( + EventTypes.SpaceChild, + ) && + filter.isEmpty) ...[ + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 8, + vertical: 1, + ), + child: Material( + borderRadius: BorderRadius.circular( + AppConfig.borderRadius, + ), + clipBehavior: Clip.hardEdge, + child: ListTile( + onTap: _addChatOrSubspace, + leading: const CircleAvatar( + radius: Avatar.defaultSize / 2, + child: Icon(Icons.add_outlined), + ), + title: Text( + L10n.of(context)!.addChatOrSubSpace, + style: const TextStyle(fontSize: 14), + ), + ), + ), + ), + ], + SearchTitle( + title: L10n.of(context)!.joinedChats, + icon: const Icon(Icons.chat_outlined), + ), + ], ); } i--; - final room = joinedRooms[i]; + final joinedRoom = joinedRooms[i]; return ChatListItem( - room, + joinedRoom, filter: filter, - onTap: () => widget.onChatTab(room), + onTap: () => widget.onChatTab(joinedRoom), onLongPress: (context) => widget.onChatContext( - room, + joinedRoom, context, ), - activeChat: widget.activeChat == room.id, + activeChat: widget.activeChat == joinedRoom.id, ); }, ),