diff --git a/lib/helpers/groups_helper.dart b/lib/helpers/groups_helper.dart index 6e8adaf..8524511 100644 --- a/lib/helpers/groups_helper.dart +++ b/lib/helpers/groups_helper.dart @@ -126,6 +126,17 @@ class GroupsHelper { .map((f) => cast(f)) .toSet(); + /// Create a new group + /// + /// Throws in case of failure + static Future create(String name) async { + final result = await APIRequest.withLogin("groups/create") + .addString("name", name) + .execWithThrow(); + + return result.getObject()["id"]; + } + /// Perform a simple membership request Future _simpleMembershipRequest(int groupID, String uri, {Map args}) async => diff --git a/lib/ui/screens/groups_list_screen.dart b/lib/ui/screens/groups_list_screen.dart index 7574332..6d50601 100644 --- a/lib/ui/screens/groups_list_screen.dart +++ b/lib/ui/screens/groups_list_screen.dart @@ -54,28 +54,38 @@ class _GroupsListScreenState extends SafeState { onRefresh: () => this._refreshList(), child: _groups == null ? Container() - : ListView( - children: _groups.values - .map((g) => ListTile( - leading: GroupIcon(group: g), - title: Text(g.displayName), - subtitle: GroupMembershipWidget( - group: g, - onUpdated: () => - _refreshIndicatorKey.currentState.show(), - ), - trailing: IconButton( - icon: Icon(Icons.delete), - onPressed: () => _deleteGroup(g)), - onTap: () => MainController.of(context).openGroup(g.id), - )) - .toList(), - ), + : Stack(children: [_buildGroupsList(), _buildCreateButton()]), )) ], ); } + Widget _buildGroupsList() => ListView( + children: _groups.values + .map((g) => ListTile( + leading: GroupIcon(group: g), + title: Text(g.displayName), + subtitle: GroupMembershipWidget( + group: g, + onUpdated: () => _refreshIndicatorKey.currentState.show(), + ), + trailing: IconButton( + icon: Icon(Icons.delete), + onPressed: () => _deleteGroup(g)), + onTap: () => MainController.of(context).openGroup(g.id), + )) + .toList(), + ); + + Widget _buildCreateButton() => Positioned( + right: 15, + bottom: 15, + child: FloatingActionButton( + child: Icon(Icons.add), + onPressed: _createGroup, + ), + ); + /// Refresh the list of groups Future _refreshList() async { try { @@ -109,4 +119,27 @@ class _GroupsListScreenState extends SafeState { // Refresh the list of groups _refreshIndicatorKey.currentState.show(); } + + /// Add a group + void _createGroup() async { + try { + final name = await askUserString( + context: context, + title: tr("Group name"), + message: tr("Name of the group to create"), + defaultValue: "", + hint: tr("Name of the group"), + maxLength: 50, + ); + + if (name == null) return; + + final groupID = await GroupsHelper.create(name); + + MainController.of(context).openGroup(groupID); + } catch (e, s) { + print("Could not create a new group! $e\n$s"); + showSimpleSnack(context, tr("Could not create a new group!")); + } + } } diff --git a/lib/utils/ui_utils.dart b/lib/utils/ui_utils.dart index 3c2364b..aeb3a78 100644 --- a/lib/utils/ui_utils.dart +++ b/lib/utils/ui_utils.dart @@ -1,5 +1,6 @@ import 'package:comunic/helpers/preferences_helper.dart'; import 'package:comunic/ui/routes/full_screen_image.dart'; +import 'package:comunic/ui/widgets/dialogs/auto_sized_dialog_content_widget.dart'; import 'package:comunic/utils/intl_utils.dart'; import 'package:flutter/material.dart'; import 'package:html/parser.dart'; @@ -86,12 +87,14 @@ Future askUserString({ @required String message, @required String defaultValue, @required String hint, + int maxLength = 200, }) async { assert(context != null); assert(title != null); assert(message != null); assert(defaultValue != null); assert(hint != null); + assert(maxLength != null); TextEditingController controller = TextEditingController(text: defaultValue); @@ -99,24 +102,21 @@ Future askUserString({ context: context, builder: (c) => AlertDialog( title: Text(title), - content: Container( - height: MediaQuery.of(context).size.height - 50, - child: SingleChildScrollView( - child: Column( - children: [ - Text(message), - TextField( - controller: controller, - maxLines: null, - maxLength: 200, - keyboardType: TextInputType.text, - decoration: InputDecoration( - labelText: hint, - alignLabelWithHint: true, - ), - ) - ], - ), + content: AutoSizeDialogContentWidget( + child: Column( + children: [ + Text(message), + TextField( + controller: controller, + maxLines: null, + maxLength: maxLength, + keyboardType: TextInputType.text, + decoration: InputDecoration( + labelText: hint, + alignLabelWithHint: true, + ), + ) + ], ), ), actions: [