1
0
mirror of https://gitlab.com/comunic/comunicmobile synced 2024-11-22 12:59:21 +00:00

Create pick user dialog

This commit is contained in:
Pierre HUBERT 2020-05-02 15:30:19 +02:00
parent 1227ef283c
commit 804457c761
5 changed files with 153 additions and 15 deletions

View File

@ -0,0 +1,63 @@
import 'package:comunic/models/user.dart';
import 'package:comunic/ui/widgets/dialogs/cancel_dialog_button.dart';
import 'package:comunic/ui/widgets/dialogs/confirm_dialog_button.dart';
import 'package:comunic/ui/widgets/pick_user_widget.dart';
import 'package:comunic/ui/widgets/safe_state.dart';
import 'package:comunic/utils/intl_utils.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
/// Pick user dialog
///
/// @author Pierre HUBERT
/// Ask the user to pick a user
///
/// Returns null if no user was selected
Future<int> showPickUserDialog(BuildContext context) async {
return await showDialog(context: context, builder: (c) => _PickUserDialog());
}
class _PickUserDialog extends StatefulWidget {
@override
__PickUserDialogState createState() => __PickUserDialogState();
}
class __PickUserDialogState extends SafeState<_PickUserDialog> {
User _user;
bool get _isValid => _user != null;
@override
Widget build(BuildContext context) {
return AlertDialog(
title: Text(tr("Choose a user")),
content: _buildContent(),
actions: <Widget>[
CancelDialogButton(),
ConfirmDialogButton(
value: _isValid ? _user.id : null,
enabled: _isValid,
),
],
);
}
Widget _buildContent() {
final size = MediaQuery.of(context).size;
print(size);
return Container(
width: size.width,
height: size.height,
child: Column(
children: <Widget>[
PickUserWidget(
onSelectUser: (u) => setState(() => _user = u),
label: tr("Search user..."),
onValueChange: (u) => setState(() => _user = null),
),
],
),
);
}
}

View File

@ -6,6 +6,7 @@ import 'package:comunic/models/group.dart';
import 'package:comunic/models/group_membership.dart';
import 'package:comunic/models/user.dart';
import 'package:comunic/ui/dialogs/multi_choices_dialog.dart';
import 'package:comunic/ui/dialogs/pick_user_dialog.dart';
import 'package:comunic/ui/widgets/account_image_widget.dart';
import 'package:comunic/ui/widgets/async_screen_widget.dart';
import 'package:comunic/ui/widgets/comunic_back_button_widget.dart';
@ -61,8 +62,11 @@ class _GroupMembersScreenState extends State<GroupMembersScreen> {
);
Widget _buildBodyContent() {
return ListView(
children: _members.map(_buildGroupMemberTile).toList(),
return Stack(
children: [
ListView(children: _members.map(_buildGroupMemberTile).toList()),
_buildInvitationFAB()
],
);
}
@ -75,6 +79,29 @@ class _GroupMembersScreenState extends State<GroupMembersScreen> {
onUpdated: () => _key.currentState.refresh(),
);
}
Widget _buildInvitationFAB() {
return Positioned(
right: 20,
bottom: 20,
child: FloatingActionButton(
onPressed: _inviteMember,
child: Icon(Icons.add),
),
);
}
void _inviteMember() async {
try {
final userID = await showPickUserDialog(context);
if (userID == null) return;
print("Invite user: $userID");
} catch (e, s) {
print("Could not invite a user! $e\n$s");
showSimpleSnack(context, tr("Could not invite a user!"));
}
}
}
List<MultiChoiceEntry<GroupMembershipLevel>> get _membershipLevels => [

View File

@ -0,0 +1,17 @@
import 'package:comunic/utils/intl_utils.dart';
import 'package:flutter/material.dart';
/// Render a cancel button for an alert dialog
///
/// @author Pierre HUBERT
class CancelDialogButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialButton(
onPressed: () => Navigator.of(context).pop(),
child: Text(tr("Cancel").toUpperCase()),
textColor: Colors.red,
);
}
}

View File

@ -0,0 +1,27 @@
import 'package:comunic/utils/intl_utils.dart';
import 'package:flutter/material.dart';
/// Confirm dialog button
///
/// @author Pierre HUBERT
class ConfirmDialogButton<T> extends StatelessWidget {
final bool enabled;
final T value;
const ConfirmDialogButton({
Key key,
this.enabled = true,
@required this.value,
}) : assert(enabled != null),
super(key: key);
@override
Widget build(BuildContext context) {
return MaterialButton(
onPressed: enabled ? () => Navigator.of(context).pop(value) : null,
child: Text(tr("Confirm").toUpperCase()),
textColor: Colors.green,
);
}
}

View File

@ -15,19 +15,21 @@ typedef OnSelectUserCallback = void Function(User);
class PickUserWidget extends StatefulWidget {
final OnSelectUserCallback onSelectUser;
final void Function(String) onValueChange;
final String label;
final bool resetOnChoose;
final bool keepFocusOnChoose;
final bool enabled;
const PickUserWidget(
{Key key,
@required this.onSelectUser,
@required this.label,
this.resetOnChoose = false,
this.keepFocusOnChoose = false,
this.enabled = true})
: assert(onSelectUser != null),
const PickUserWidget({
Key key,
@required this.onSelectUser,
@required this.label,
this.resetOnChoose = false,
this.keepFocusOnChoose = false,
this.onValueChange,
this.enabled = true,
}) : assert(onSelectUser != null),
assert(label != null),
assert(resetOnChoose != null),
assert(keepFocusOnChoose != null),
@ -93,9 +95,9 @@ class _PickUserWidgetState extends State<PickUserWidget> {
shrinkWrap: true,
itemCount: _suggestions == null ? 0 : _suggestions.length,
itemBuilder: (c, i) => SimpleUserTile(
user: _suggestions[i],
onTap: _userTapped,
),
user: _suggestions[i],
onTap: _userTapped,
),
),
),
);
@ -116,9 +118,11 @@ class _PickUserWidgetState extends State<PickUserWidget> {
/// This method get called each time the input value is updated
Future<void> _updateSuggestions() async {
if (_controller.value.text.length == 0) return _removeOverlay();
if (widget.onValueChange != null) widget.onValueChange(_controller.text);
final results = await _searchHelper.searchUser(_controller.value.text);
if (_controller.text.length == 0) return _removeOverlay();
final results = await _searchHelper.searchUser(_controller.text);
if (results == null) return;