Skip to content

Commit 41928c6

Browse files
authored
feat: improve joining indicators and spaces UI (#139)
* feat: improve joining indicators and spaces UI * feat: enhance chat room functionality and improve direct chat handling
1 parent 0d7a29f commit 41928c6

23 files changed

Lines changed: 535 additions & 488 deletions

lib/chat_master/view/chat_master_list_filter_bar.dart

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class ChatMasterListFilterBar extends StatelessWidget with WatchItMixin {
2525
clearOnSelect: false,
2626
selectedFirst: false,
2727
style: YaruChoiceChipBarStyle.stack,
28-
labels: RoomsFilter.shownValues
28+
labels: RoomsFilter.values
2929
.map(
3030
(e) => Tooltip(
3131
message: e.localize(context.l10n),
@@ -36,11 +36,10 @@ class ChatMasterListFilterBar extends StatelessWidget with WatchItMixin {
3636
),
3737
)
3838
.toList(),
39-
isSelected: RoomsFilter.shownValues
40-
.map((e) => e == roomsFilter)
41-
.toList(),
42-
onSelected: (i) =>
43-
di<ChatManager>().setRoomsFilter(RoomsFilter.shownValues[i]),
39+
isSelected: RoomsFilter.values.map((e) => e == roomsFilter).toList(),
40+
onSelected: (i) => di<ChatManager>().setRoomsFilter(
41+
roomsFilter == RoomsFilter.values[i] ? null : RoomsFilter.values[i],
42+
),
4443
),
4544
);
4645
}

lib/chat_master/view/chat_rooms_list.dart

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@ import 'package:flutter/material.dart';
22
import 'package:flutter_it/flutter_it.dart';
33

44
import '../../common/chat_manager.dart';
5+
import '../../common/rooms_filter.dart';
6+
import '../../common/view/sliver_sticky_panel.dart';
7+
import '../../common/view/ui_constants.dart';
58
import 'chat_room_master_tile.dart';
9+
import 'chat_space_discover_button.dart';
10+
import 'chat_spaces_search_list.dart';
611

712
class ChatRoomsList extends StatelessWidget with WatchItMixin {
813
const ChatRoomsList({super.key});
@@ -27,7 +32,7 @@ class ChatRoomsList extends StatelessWidget with WatchItMixin {
2732
di<ChatManager>().filteredRooms;
2833

2934
watchPropertyValue((ChatManager m) => m.filteredRoomsQuery);
30-
watchPropertyValue((ChatManager m) => m.roomsFilter);
35+
final roomsFilter = watchPropertyValue((ChatManager m) => m.roomsFilter);
3136
watchPropertyValue((ChatManager m) => m.archiveActive);
3237
watchPropertyValue((ChatManager m) => m.activeSpace);
3338

@@ -40,6 +45,25 @@ class ChatRoomsList extends StatelessWidget with WatchItMixin {
4045
return ChatRoomMasterTile(key: ValueKey(room.id), room: room);
4146
},
4247
),
48+
if (roomsFilter == RoomsFilter.spaces && filteredRooms.isNotEmpty)
49+
const SliverPadding(
50+
padding: EdgeInsets.symmetric(vertical: kMediumPadding),
51+
sliver: SliverToBoxAdapter(
52+
child: Divider(
53+
endIndent: kMediumPlusPadding,
54+
indent: kMediumPlusPadding,
55+
),
56+
),
57+
),
58+
if (roomsFilter == RoomsFilter.spaces)
59+
const SliverStickyPanel(
60+
padding: EdgeInsets.only(bottom: kBigPadding, top: kMediumPadding),
61+
child: ChatSpaceDiscoverButton(),
62+
),
63+
const SliverPadding(
64+
padding: EdgeInsets.only(top: kSmallPadding),
65+
sliver: ChatSpacesSearchList.sliver(),
66+
),
4367
],
4468
);
4569
}
Lines changed: 102 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import 'package:flutter/material.dart';
22
import 'package:flutter_it/flutter_it.dart';
3+
import 'package:matrix/matrix_api_lite/generated/model.dart';
34
import 'package:yaru/yaru.dart';
45

56
import '../../chat_room/create_or_edit/edit_room_manager.dart';
@@ -12,8 +13,16 @@ import '../../common/view/confirm.dart';
1213
import '../../common/view/ui_constants.dart';
1314
import '../../l10n/l10n.dart';
1415

16+
enum ChatSpacesSearchType { regular, sliver }
17+
1518
class ChatSpacesSearchList extends StatelessWidget with WatchItMixin {
16-
const ChatSpacesSearchList({super.key});
19+
const ChatSpacesSearchList({super.key})
20+
: _type = ChatSpacesSearchType.regular;
21+
22+
const ChatSpacesSearchList.sliver({super.key})
23+
: _type = ChatSpacesSearchType.sliver;
24+
25+
final ChatSpacesSearchType _type;
1726

1827
@override
1928
Widget build(BuildContext context) {
@@ -27,66 +36,108 @@ class ChatSpacesSearchList extends StatelessWidget with WatchItMixin {
2736
(SearchManager m) => m.spaceSearch?.length ?? 0,
2837
);
2938
if (spaceSearch == null) {
30-
return const Center(
31-
child: Padding(padding: EdgeInsets.all(kBigPadding), child: Progress()),
32-
);
39+
return _type == ChatSpacesSearchType.sliver
40+
? const SliverToBoxAdapter(
41+
child: Center(
42+
child: Padding(
43+
padding: EdgeInsets.all(kBigPadding),
44+
child: Progress(),
45+
),
46+
),
47+
)
48+
: const Center(
49+
child: Padding(
50+
padding: EdgeInsets.all(kBigPadding),
51+
child: Progress(),
52+
),
53+
);
3354
}
3455

3556
if (archiveActive ||
3657
roomsFilter != RoomsFilter.spaces ||
3758
spaceSearchL == 0) {
38-
return const SizedBox.shrink();
59+
return _type == ChatSpacesSearchType.sliver
60+
? const SliverToBoxAdapter(child: SizedBox.shrink())
61+
: const SizedBox.shrink();
62+
}
63+
64+
if (_type == ChatSpacesSearchType.sliver) {
65+
return SliverList(
66+
delegate: SliverChildBuilderDelegate(
67+
(context, index) => _itemBuilder(context, index, spaceSearch),
68+
childCount: spaceSearchL,
69+
),
70+
);
3971
}
4072

4173
return ListView.builder(
4274
itemCount: spaceSearchL,
43-
itemBuilder: (context, index) {
44-
final chunk = spaceSearch.elementAt(index);
45-
return Padding(
46-
padding: const EdgeInsets.only(bottom: 5),
47-
child: YaruMasterTile(
48-
key: ValueKey(chunk.roomId),
49-
leading: ChatAvatar(avatarUri: chunk.avatarUrl),
50-
title: Text(
51-
'${chunk.roomType == 'm.space' ? '(${context.l10n.space}) ' : ''}'
52-
'${chunk.name ?? chunk.canonicalAlias ?? ''}',
53-
),
54-
subtitle: Tooltip(
55-
margin: const EdgeInsets.all(kBigPadding),
56-
message: chunk.topic ?? ' ',
57-
child: Text(chunk.canonicalAlias ?? chunk.topic ?? ''),
58-
),
59-
onTap: () => ConfirmationDialog.show(
60-
title: Text(
61-
chunk.joinRule == 'knock'
62-
? context.l10n.knock
63-
: context.l10n.joinRoom,
64-
),
65-
content: Column(
66-
mainAxisSize: MainAxisSize.min,
67-
spacing: kMediumPadding,
68-
children: [
69-
ChatAvatar(avatarUri: chunk.avatarUrl),
70-
Padding(
71-
padding: const EdgeInsets.only(top: 8.0),
72-
child: Text(
73-
chunk.canonicalAlias ?? chunk.name ?? chunk.roomId,
74-
),
75-
),
76-
],
77-
),
78-
context: context,
79-
onConfirm: () async {
80-
Navigator.of(context).pop();
81-
di<EditRoomManager>().knockOrJoinCommand.run((
82-
roomId: chunk.roomId,
83-
knock: chunk.joinRule == 'knock',
84-
));
85-
},
75+
itemBuilder: (context, index) =>
76+
_itemBuilder(context, index, spaceSearch),
77+
);
78+
}
79+
80+
Widget? _itemBuilder(
81+
BuildContext context,
82+
int index,
83+
List<PublishedRoomsChunk>? spaceSearch,
84+
) {
85+
final chunk = spaceSearch?.elementAtOrNull(index);
86+
if (chunk == null) {
87+
return const SizedBox.shrink();
88+
}
89+
return Padding(
90+
padding: const EdgeInsets.only(bottom: 5),
91+
child: ChatSpacesDiscoverTile(chunk: chunk),
92+
);
93+
}
94+
}
95+
96+
class ChatSpacesDiscoverTile extends StatelessWidget {
97+
const ChatSpacesDiscoverTile({super.key, required this.chunk});
98+
99+
final PublishedRoomsChunk chunk;
100+
101+
@override
102+
Widget build(BuildContext context) {
103+
return YaruMasterTile(
104+
key: ValueKey(chunk.roomId),
105+
leading: ChatAvatar(avatarUri: chunk.avatarUrl),
106+
title: Text(
107+
'${chunk.roomType == 'm.space' ? '(${context.l10n.space}) ' : ''}'
108+
'${chunk.name ?? chunk.canonicalAlias ?? ''}',
109+
),
110+
subtitle: Tooltip(
111+
margin: const EdgeInsets.all(kBigPadding),
112+
message: chunk.topic ?? ' ',
113+
child: Text(chunk.canonicalAlias ?? chunk.topic ?? ''),
114+
),
115+
onTap: () => ConfirmationDialog.show(
116+
title: Text(
117+
chunk.joinRule == 'knock'
118+
? context.l10n.knock
119+
: context.l10n.joinRoom,
120+
),
121+
content: Column(
122+
mainAxisSize: MainAxisSize.min,
123+
spacing: kMediumPadding,
124+
children: [
125+
ChatAvatar(avatarUri: chunk.avatarUrl),
126+
Padding(
127+
padding: const EdgeInsets.only(top: 8.0),
128+
child: Text(chunk.canonicalAlias ?? chunk.name ?? chunk.roomId),
86129
),
87-
),
88-
);
89-
},
130+
],
131+
),
132+
context: context,
133+
onConfirm: () async {
134+
Navigator.of(context).pop();
135+
di<EditRoomManager>().knockOrJoinCommand.run((
136+
roomId: chunk.roomId,
137+
knock: chunk.joinRule == 'knock',
138+
));
139+
},
140+
),
90141
);
91142
}
92143
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:flutter_it/flutter_it.dart';
3+
4+
import '../../../common/chat_manager.dart';
5+
import '../../../common/logging.dart';
6+
import '../../create_or_edit/create_room_manager.dart';
7+
import '../../create_or_edit/edit_room_manager.dart';
8+
9+
mixin ChatJoinMixin {
10+
void registerJoinHandlers(BuildContext context) {
11+
registerHandler(
12+
select: (CreateRoomManager m) => m.createOrGetDirectChatCommand.results,
13+
handler: (_, newValue, _) {
14+
if (newValue.error != null) {
15+
printMessageInDebugMode(
16+
'Error creating direct chat: ${newValue.error}',
17+
);
18+
ScaffoldMessenger.of(
19+
context,
20+
).showSnackBar(SnackBar(content: Text(newValue.error.toString())));
21+
return;
22+
}
23+
24+
final room = newValue.data;
25+
26+
if (room != null) {
27+
printMessageInDebugMode('Joining room ${room.id}');
28+
di<ChatManager>().setSelectedRoom(room);
29+
}
30+
},
31+
);
32+
33+
registerHandler(
34+
select: (EditRoomManager m) => m.knockOrJoinCommand,
35+
handler: (context, room, cancel) {
36+
if (room != null) {
37+
di<ChatManager>().setSelectedRoom(room);
38+
if (room.isSpace) {
39+
di<ChatManager>().setActiveSpace(room);
40+
}
41+
}
42+
},
43+
);
44+
45+
registerHandler(
46+
select: (EditRoomManager m) => m.joinRoomCommand,
47+
handler: (context, room, cancel) {
48+
if (room != null) {
49+
di<ChatManager>().setSelectedRoom(room);
50+
if (room.isSpace) {
51+
di<ChatManager>().setActiveSpace(room);
52+
}
53+
}
54+
},
55+
);
56+
}
57+
}

0 commit comments

Comments
 (0)