Skip to content

Commit b3825bc

Browse files
authored
feat: implement room and avatar management commands and UI enhancements (#135)
1 parent 4cfc58a commit b3825bc

16 files changed

Lines changed: 389 additions & 221 deletions

lib/chat_master/view/chat_master_detail_page.dart

Lines changed: 48 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,11 @@ class ChatMasterDetailPage extends StatelessWidget with WatchItMixin {
5454
),
5555
);
5656
} else {
57-
_commandDoneCleanupSnackbars(context);
57+
Future.delayed(const Duration(seconds: 1), () {
58+
if (context.mounted) {
59+
ScaffoldMessenger.of(context).clearSnackBars();
60+
}
61+
});
5862
}
5963
},
6064
);
@@ -63,50 +67,56 @@ class ChatMasterDetailPage extends StatelessWidget with WatchItMixin {
6367
select: (EditRoomManager m) => m.globalLeaveRoomCommand.results,
6468
handler: (context, newValue, cancel) {
6569
if (newValue.isRunning) {
66-
_showInifniteSpinnerSnackbar(
70+
_showIndeterminateSpinnerSnackbar(
6771
context,
6872
'${context.l10n.leave} ${newValue.data?.getLocalizedDisplayname() ?? ''}',
6973
);
70-
} else if (newValue.hasData && newValue.data != null) {
74+
} else if (newValue.hasError) {
7175
ScaffoldMessenger.of(context)
7276
..clearSnackBars()
7377
..showSnackBar(
7478
SnackBar(
75-
duration: const Duration(seconds: 5),
7679
content: Text(
77-
'Left: ${newValue.data?.getLocalizedDisplayname() ?? ''}',
78-
),
79-
action: SnackBarAction(
80-
label: context.l10n.delete,
81-
onPressed: () {
82-
di<EditRoomManager>().globalForgetRoomCommand.run(
83-
newValue.data!,
84-
);
85-
},
80+
'${context.l10n.oopsSomethingWentWrong} ${newValue.data?.getLocalizedDisplayname() ?? ''}: ${newValue.error}',
8681
),
8782
),
8883
);
89-
} else if (newValue.hasError) {
90-
ScaffoldMessenger.of(context)
91-
..clearSnackBars()
92-
..showSnackBar(
84+
} else if (newValue.hasData) {
85+
ScaffoldMessenger.of(context).clearSnackBars();
86+
if (newValue.data != null) {
87+
ScaffoldMessenger.of(context).showSnackBar(
9388
SnackBar(
9489
content: Text(
95-
'${context.l10n.oopsSomethingWentWrong} ${newValue.data?.getLocalizedDisplayname() ?? ''}: ${newValue.error}',
90+
'Left: ${newValue.data?.getLocalizedDisplayname() ?? ''}',
91+
),
92+
action: SnackBarAction(
93+
label: context.l10n.delete,
94+
onPressed: () => di<EditRoomManager>().globalForgetRoomCommand
95+
.run(newValue.data!),
9696
),
9797
),
9898
);
99+
}
99100
} else {
100-
_commandDoneCleanupSnackbars(context);
101+
Future.delayed(const Duration(seconds: 4), () {
102+
if (context.mounted) {
103+
ScaffoldMessenger.of(context).clearSnackBars();
104+
}
105+
});
101106
}
102107
},
103108
);
104109

110+
registerHandler(
111+
select: (EditRoomManager m) => m.globalLeaveRoomCommand,
112+
handler: (context, newValue, cancel) {},
113+
);
114+
105115
registerHandler(
106116
select: (EditRoomManager m) => m.globalForgetRoomCommand.results,
107117
handler: (context, newValue, cancel) {
108118
if (newValue.isRunning) {
109-
_showInifniteSpinnerSnackbar(
119+
_showIndeterminateSpinnerSnackbar(
110120
context,
111121
'${context.l10n.delete} ${newValue.data?.getLocalizedDisplayname() ?? ''}',
112122
);
@@ -130,8 +140,6 @@ class ChatMasterDetailPage extends StatelessWidget with WatchItMixin {
130140
),
131141
),
132142
);
133-
} else {
134-
_commandDoneCleanupSnackbars(context);
135143
}
136144
},
137145
);
@@ -219,30 +227,24 @@ class ChatMasterDetailPage extends StatelessWidget with WatchItMixin {
219227
);
220228
}
221229

222-
void _showInifniteSpinnerSnackbar(BuildContext context, String text) {
223-
ScaffoldMessenger.of(context).showSnackBar(
224-
SnackBar(
225-
duration: const Duration(seconds: 5),
226-
content: Row(
227-
children: [
228-
const SizedBox(
229-
width: 20,
230-
height: 20,
231-
child: CircularProgressIndicator(strokeWidth: 2),
232-
),
233-
const SizedBox(width: 16),
234-
Text(text),
235-
],
230+
void _showIndeterminateSpinnerSnackbar(BuildContext context, String text) {
231+
ScaffoldMessenger.of(context)
232+
..clearSnackBars()
233+
..showSnackBar(
234+
SnackBar(
235+
duration: const Duration(seconds: 100),
236+
content: Row(
237+
children: [
238+
const SizedBox(
239+
width: 20,
240+
height: 20,
241+
child: CircularProgressIndicator(strokeWidth: 2),
242+
),
243+
const SizedBox(width: 16),
244+
Text(text),
245+
],
246+
),
236247
),
237-
),
238-
);
239-
}
240-
241-
void _commandDoneCleanupSnackbars(BuildContext context) {
242-
Future.delayed(const Duration(seconds: 2), () {
243-
if (context.mounted) {
244-
ScaffoldMessenger.of(context).clearSnackBars();
245-
}
246-
});
248+
);
247249
}
248250
}

lib/chat_master/view/chat_master_new_chat_popup_menu_button.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class ChatMasterNewChatPopupMenuButton extends StatelessWidget {
3232
PopupMenuItem(
3333
onTap: () => showDialog(
3434
context: context,
35+
barrierDismissible: false,
3536
builder: (context) => const CreateOrEditRoomDialog(),
3637
),
3738
child: Row(
@@ -42,6 +43,7 @@ class ChatMasterNewChatPopupMenuButton extends StatelessWidget {
4243
PopupMenuItem(
4344
onTap: () => showDialog(
4445
context: context,
46+
barrierDismissible: false,
4547
builder: (context) => const CreateOrEditRoomDialog(space: true),
4648
),
4749
child: Row(

lib/chat_room/create_or_edit/create_room_manager.dart

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import 'package:collection/collection.dart';
22
import 'package:file_picker/file_picker.dart';
33
import 'package:file_selector/file_selector.dart';
4+
import 'package:flutter_it/flutter_it.dart';
45
import 'package:matrix/matrix.dart';
56
// import 'package:mime/mime.dart';
67
import 'package:safe_change_notifier/safe_change_notifier.dart';
@@ -19,7 +20,10 @@ class CreateRoomManager {
1920
CreateRoomDraft.empty(),
2021
);
2122

22-
void init({required Room? room}) => draft.value = CreateRoomDraft.empty();
23+
void init({required Room? room}) {
24+
draft.value = CreateRoomDraft.empty();
25+
createRoomOrSpaceCommand.clearErrors();
26+
}
2327

2428
void updateDraft({
2529
String? name,
@@ -55,10 +59,11 @@ class CreateRoomManager {
5559
updateDraft(profiles: {...draft.value.profiles..remove(profile)});
5660
}
5761

58-
Future<void> setRoomAvatar({
59-
required Room? room,
60-
required String wrongFormatString,
61-
}) async {
62+
late final Command<Room?, void> setRoomAvatarCommand = Command.createAsync(
63+
setRoomAvatar,
64+
initialValue: null,
65+
);
66+
Future<void> setRoomAvatar(Room? room) async {
6267
try {
6368
XFile? xFile;
6469
if (Platforms.isLinux) {
@@ -96,16 +101,13 @@ class CreateRoomManager {
96101
}
97102
}
98103

99-
Future<Room?> createRoomOrSpace({
100-
required bool space,
101-
bool waitForSync = true,
102-
List<StateEvent>? initialState,
103-
bool federated = true,
104-
Map<String, dynamic>? powerLevelContentOverride,
105-
}) async {
104+
late final Command<bool, Room?> createRoomOrSpaceCommand =
105+
Command.createAsync(createRoomOrSpace, initialValue: null);
106+
107+
Future<Room?> createRoomOrSpace(bool shallBeSpace) async {
106108
String? roomId;
107109
try {
108-
roomId = space
110+
roomId = shallBeSpace
109111
? await _client.createSpace(
110112
name: draft.value.name,
111113
visibility: draft.value.visibility,
@@ -115,7 +117,6 @@ class CreateRoomManager {
115117
invite3pid: null,
116118
roomVersion: null,
117119
topic: draft.value.topic,
118-
waitForSync: waitForSync,
119120
spaceAliasName: draft.value.name,
120121
)
121122
: await _client.createGroupChat(
@@ -124,14 +125,10 @@ class CreateRoomManager {
124125
invite: draft.value.profiles
125126
.map((p) => p.userId)
126127
.toList(growable: false),
127-
initialState: initialState,
128128
visibility: draft.value.visibility,
129129
preset: draft.value.createRoomPreset,
130130
historyVisibility: draft.value.historyVisibility,
131-
waitForSync: waitForSync,
132131
groupCall: draft.value.groupCall,
133-
federated: federated,
134-
powerLevelContentOverride: powerLevelContentOverride,
135132
);
136133
} catch (e, s) {
137134
printMessageInDebugMode(e, s);

lib/chat_room/create_or_edit/edit_room_manager.dart

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,7 @@ class EditRoomManager {
3232
late final Command<PublishedRoomsChunk, Room?> knockOrJoinCommand;
3333
late final Command<Room, Room?> globalLeaveRoomCommand;
3434
late final Command<Room, Room?> globalForgetRoomCommand;
35-
late final Command<void, void> leaveAllRoomsCommand =
36-
Command.createAsyncNoParamNoResultWithProgress((handle) async {
37-
final rooms = _editRoomService.rooms;
38-
for (final room in rooms) {
39-
await getLeaveRoomCommand(room).runAsync();
40-
}
41-
});
35+
4236
late final Command<void, void> forgetAllRoomsCommand =
4337
Command.createAsyncNoParamNoResultWithProgress((handle) async {
4438
handle.updateProgress(0);
@@ -56,12 +50,14 @@ class EditRoomManager {
5650
final total = list.length;
5751

5852
for (final entry in list) {
59-
await getForgetRoomCommand(entry.room).runAsync();
53+
await getForgetRoomCommand(entry.room, sync: false).runAsync();
6054

6155
handle.updateProgress(
6256
((list.indexOf(entry) + 1) / total).clamp(0, 1),
6357
);
6458
}
59+
60+
await _editRoomService.getOneShotSync();
6561
});
6662

6763
final Map<String, Command<void, Room?>> _leaveRoomCommands = {};
@@ -76,11 +72,11 @@ class EditRoomManager {
7672
);
7773

7874
final Map<String, Command<void, void>> _forgetRoomCommands = {};
79-
Command<void, void> getForgetRoomCommand(Room room) =>
75+
Command<void, void> getForgetRoomCommand(Room room, {bool sync = true}) =>
8076
_forgetRoomCommands.putIfAbsent(
8177
room.id,
8278
() => Command.createAsync((_) async {
83-
await _editRoomService.forgetRoom(room);
79+
await _editRoomService.forgetRoom(room, sync: sync);
8480
_forgetRoomCommands.remove(room.id);
8581
}, initialValue: null),
8682
);

lib/chat_room/create_or_edit/edit_room_service.dart

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import 'package:collection/collection.dart';
22
import 'package:file_picker/file_picker.dart';
33
import 'package:file_selector/file_selector.dart';
4+
import 'package:flutter_it/flutter_it.dart';
45
import 'package:matrix/matrix.dart';
56

67
import '../../common/constants.dart';
@@ -15,7 +16,7 @@ class EditRoomService {
1516

1617
final Client _client;
1718
List<ArchivedRoom> get archivedRooms => _client.archivedRooms;
18-
List<Room> get rooms => _client.rooms;
19+
Future<void> getOneShotSync() => _client.oneShotSync();
1920

2021
Stream<SyncUpdate> get _joinedUpdateStream =>
2122
_client.onSync.stream.where((e) => e.rooms?.join?.isNotEmpty ?? false);
@@ -312,10 +313,11 @@ class EditRoomService {
312313
)
313314
.map((e) => room?.avatar);
314315

315-
Future<void> setRoomAvatar({
316-
required Room? room,
317-
required String wrongFormatString,
318-
}) async {
316+
late final Command<Room, void> setRoomAvatarCommand = Command.createAsync(
317+
setRoomAvatar,
318+
initialValue: null,
319+
);
320+
Future<void> setRoomAvatar(Room room) async {
319321
try {
320322
MatrixImageFile? avatarDraft;
321323
XFile? xFile;
@@ -347,9 +349,7 @@ class EditRoomService {
347349
nativeImplementations: _client.nativeImplementations,
348350
);
349351

350-
if (room != null) {
351-
await room.setAvatar(avatarDraft);
352-
}
352+
await room.setAvatar(avatarDraft);
353353
} on Exception catch (e, s) {
354354
printMessageInDebugMode(e, s);
355355
rethrow;
@@ -395,10 +395,12 @@ class EditRoomService {
395395
}
396396
}
397397

398-
Future<void> forgetRoom(Room room) async {
398+
Future<void> forgetRoom(Room room, {bool sync = true}) async {
399399
try {
400400
await room.forget();
401-
await _client.oneShotSync();
401+
if (sync) {
402+
await _client.oneShotSync();
403+
}
402404
} on Exception catch (e, s) {
403405
printMessageInDebugMode(e, s);
404406
rethrow;

0 commit comments

Comments
 (0)