chore: Follow up add chat or subspace UX
This commit is contained in:
parent
0760acaa40
commit
a500a91b6b
3 changed files with 145 additions and 109 deletions
|
|
@ -105,107 +105,18 @@ class ChatListController extends State<ChatList>
|
|||
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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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<SpaceView> {
|
|||
}
|
||||
}
|
||||
|
||||
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<SpaceView> {
|
|||
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,
|
||||
);
|
||||
},
|
||||
),
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue