From 3e70dcbd742a288bda60b206cb498084f034a2ee Mon Sep 17 00:00:00 2001 From: Hank Grabowski Date: Thu, 20 Apr 2023 12:14:04 -0400 Subject: [PATCH] Add Group Editor ability to remove users from group --- lib/screens/group_editor_screen.dart | 78 ++++++++++++++++++++++++++- lib/services/connections_manager.dart | 14 ++--- pubspec.lock | 11 ++-- pubspec.yaml | 4 +- 4 files changed, 92 insertions(+), 15 deletions(-) diff --git a/lib/screens/group_editor_screen.dart b/lib/screens/group_editor_screen.dart index 69a4adf..f51b376 100644 --- a/lib/screens/group_editor_screen.dart +++ b/lib/screens/group_editor_screen.dart @@ -6,7 +6,9 @@ import 'package:result_monad/result_monad.dart'; import '../controls/linear_status_indicator.dart'; import '../controls/padding.dart'; import '../controls/standard_appbar.dart'; +import '../controls/status_and_refresh_button.dart'; import '../globals.dart'; +import '../models/connection.dart'; import '../models/group_data.dart'; import '../services/connections_manager.dart'; import '../services/network_status_service.dart'; @@ -26,6 +28,7 @@ class _GroupEditorScreenState extends State { final groupTextController = TextEditingController(); var processingUpdate = false; var allowNameEditing = false; + var filterText = ''; late GroupData groupData; Future updateGroupName( @@ -66,6 +69,24 @@ class _GroupEditorScreenState extends State { } } + Future removeUserFromGroup( + ConnectionsManager manager, + Connection connection, + ) async { + final messageBase = '${connection.name} from ${groupData.name}'; + final confirm = await showYesNoDialog(context, 'Remove $messageBase?'); + if (context.mounted && confirm == true) { + final message = + await manager.removeUserFromGroup(groupData, connection).fold( + onSuccess: (_) => 'Removed $messageBase', + onError: (error) => 'Error removing $messageBase: $error', + ); + if (context.mounted) { + buildSnackbar(context, message); + } + } + } + @override void initState() { super.initState(); @@ -89,7 +110,16 @@ class _GroupEditorScreenState extends State { .activeEntry .value; - final members = manager.getGroupMembers(groupData).getValueOrElse(() => []); + final filterTextLC = filterText.toLowerCase(); + final members = manager + .getGroupMembers(groupData) + .transform((ms) => ms + .where((m) => + filterText.isEmpty || + m.name.toLowerCase().contains(filterTextLC) || + m.handle.toLowerCase().contains(filterTextLC)) + .toList()) + .getValueOrElse(() => []); return Scaffold( appBar: StandardAppBar.build( @@ -161,13 +191,57 @@ class _GroupEditorScreenState extends State { const VerticalPadding(), ElevatedButton( onPressed: () {}, child: const Text('Add Users')), + Row( + children: [ + Expanded( + child: Padding( + padding: const EdgeInsets.all(8.0), + child: TextField( + onChanged: (value) { + setState(() { + filterText = value.toLowerCase(); + }); + }, + decoration: InputDecoration( + labelText: 'Filter By Name', + alignLabelWithHint: true, + border: OutlineInputBorder( + borderSide: BorderSide( + color: Theme.of(context).highlightColor, + ), + borderRadius: BorderRadius.circular(5.0), + ), + ), + ), + ), + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: StatusAndRefreshButton( + valueListenable: nss.connectionUpdateStatus, + refreshFunction: () async => + manager.refreshGroupMemberships(groupData), + ), + ) + ], + ), Expanded( child: ListView.separated( physics: const AlwaysScrollableScrollPhysics(), itemBuilder: (context, index) { final m = members[index]; return ListTile( - title: Text(m.name), + title: Text( + '${m.name} (${m.handle})', + softWrap: true, + ), + subtitle: Text( + 'Last Status: ${m.lastStatus?.toIso8601String() ?? "Unknown"}'), + trailing: IconButton( + onPressed: () async => + removeUserFromGroup(manager, m), + icon: const Icon(Icons.remove), + ), ); }, separatorBuilder: (_, __) => const Divider(), diff --git a/lib/services/connections_manager.dart b/lib/services/connections_manager.dart index 59e9925..6fc1115 100644 --- a/lib/services/connections_manager.dart +++ b/lib/services/connections_manager.dart @@ -312,17 +312,17 @@ class ConnectionsManager extends ChangeNotifier { FutureResult removeUserFromGroup( GroupData group, Connection connection) async { _logger.finest('Removing ${connection.name} from group: ${group.name}'); - final result = await GroupsClient(getIt().currentProfile) - .removeConnectionFromGroup(group, connection); - result.match( - onSuccess: (_) => _refreshGroupListData(connection.id, true), - onError: (error) { + return GroupsClient(getIt().currentProfile) + .removeConnectionFromGroup(group, connection) + .withResultAsync((_) async => refreshGroupMemberships(group)) + .withResultAsync((_) async => notifyListeners()) + .mapError( + (error) { _logger.severe( 'Error removing ${connection.name} from group: ${group.name}'); + return error; }, ); - - return result.execErrorCast(); } Result getById(String id) { diff --git a/pubspec.lock b/pubspec.lock index 3ab0072..52712b8 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -992,11 +992,12 @@ packages: result_monad: dependency: "direct main" description: - name: result_monad - sha256: "125e17cd16e2fd3716b67a9833eaaaaa5c4090a18e4eb96783fc165e57a57a9b" - url: "https://pub.dev" - source: hosted - version: "2.2.0" + path: "." + ref: HEAD + resolved-ref: "12a2ae1e0830f4aff32f1d94835901de545cf917" + url: "https://gitlab.com/HankG/dart-result-monad.git" + source: git + version: "2.3.0" rxdart: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 68ac4f9..fca9d5c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -38,7 +38,9 @@ dependencies: network_to_file_image: ^4.0.1 path: ^1.8.2 provider: ^6.0.4 - result_monad: ^2.2.0 + result_monad: + git: + url: https://gitlab.com/HankG/dart-result-monad.git scrollable_positioned_list: ^0.3.5 shared_preferences: ^2.0.15 sqlite3: ^1.9.1