mirror of
				https://gitlab.com/comunic/comunicmobile
				synced 2025-11-03 19:54:12 +00:00 
			
		
		
		
	Create new conversations
This commit is contained in:
		@@ -8,6 +8,7 @@ import 'package:comunic/models/api_request.dart';
 | 
				
			|||||||
import 'package:comunic/models/api_response.dart';
 | 
					import 'package:comunic/models/api_response.dart';
 | 
				
			||||||
import 'package:comunic/models/conversation.dart';
 | 
					import 'package:comunic/models/conversation.dart';
 | 
				
			||||||
import 'package:comunic/models/conversation_message.dart';
 | 
					import 'package:comunic/models/conversation_message.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/models/conversation_settings.dart';
 | 
				
			||||||
import 'package:comunic/models/new_conversation_message.dart';
 | 
					import 'package:comunic/models/new_conversation_message.dart';
 | 
				
			||||||
import 'package:comunic/utils/account_utils.dart';
 | 
					import 'package:comunic/utils/account_utils.dart';
 | 
				
			||||||
import 'package:meta/meta.dart';
 | 
					import 'package:meta/meta.dart';
 | 
				
			||||||
@@ -24,6 +25,27 @@ class ConversationsHelper {
 | 
				
			|||||||
  final ConversationMessagesDatabaseHelper _conversationMessagesDatabaseHelper =
 | 
					  final ConversationMessagesDatabaseHelper _conversationMessagesDatabaseHelper =
 | 
				
			||||||
      ConversationMessagesDatabaseHelper();
 | 
					      ConversationMessagesDatabaseHelper();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Create a new conversation
 | 
				
			||||||
 | 
					  ///
 | 
				
			||||||
 | 
					  /// Return the ID of the newly created conversation or -1 in case of failure
 | 
				
			||||||
 | 
					  Future<int> createConversation(ConversationSettings settings) async {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    final response = await APIRequest(
 | 
				
			||||||
 | 
					      uri: "conversations/create",
 | 
				
			||||||
 | 
					      needLogin: true,
 | 
				
			||||||
 | 
					      args: {
 | 
				
			||||||
 | 
					        "name" : settings.hasName ? settings.name : "false",
 | 
				
			||||||
 | 
					        "follow" : settings.following ? "true" : "false",
 | 
				
			||||||
 | 
					        "users": settings.members.join(",")
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    ).exec();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(response.code != 200) return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return response.getObject()["conversationID"];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// Download the list of conversations from the server
 | 
					  /// Download the list of conversations from the server
 | 
				
			||||||
  Future<ConversationsList> downloadList() async {
 | 
					  Future<ConversationsList> downloadList() async {
 | 
				
			||||||
    final response =
 | 
					    final response =
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										27
									
								
								lib/models/conversation_settings.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								lib/models/conversation_settings.dart
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					import 'package:meta/meta.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Conversation settings model
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// Use this model to create / update a conversation
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// @author Pierre HUBERT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ConversationSettings {
 | 
				
			||||||
 | 
					  /// Set the ID to 0 if not required
 | 
				
			||||||
 | 
					  final int id;
 | 
				
			||||||
 | 
					  final String name;
 | 
				
			||||||
 | 
					  final bool following;
 | 
				
			||||||
 | 
					  final List<int> members;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ConversationSettings({
 | 
				
			||||||
 | 
					    @required this.id,
 | 
				
			||||||
 | 
					    @required this.name,
 | 
				
			||||||
 | 
					    @required this.following,
 | 
				
			||||||
 | 
					    @required this.members,
 | 
				
			||||||
 | 
					  })  : assert(members != null && members.length > 0),
 | 
				
			||||||
 | 
					        assert(following != null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool get hasName => name != null && name.length > 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool get hasId => id != null & id > 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										20
									
								
								lib/ui/routes/create_conversation_route.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								lib/ui/routes/create_conversation_route.dart
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					import 'package:comunic/ui/screens/update_conversation_screen.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/utils/intl_utils.dart';
 | 
				
			||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Create a new conversation route
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// @author Pierre HUBERT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CreateConversationRoute extends StatelessWidget {
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return Scaffold(
 | 
				
			||||||
 | 
					      appBar: AppBar(
 | 
				
			||||||
 | 
					        title: Text(tr("Create a conversation")),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      body: UpdateConversationScreen(),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -3,6 +3,7 @@ import 'package:comunic/helpers/conversations_helper.dart';
 | 
				
			|||||||
import 'package:comunic/helpers/users_helper.dart';
 | 
					import 'package:comunic/helpers/users_helper.dart';
 | 
				
			||||||
import 'package:comunic/lists/conversations_list.dart';
 | 
					import 'package:comunic/lists/conversations_list.dart';
 | 
				
			||||||
import 'package:comunic/ui/routes/conversation_route.dart';
 | 
					import 'package:comunic/ui/routes/conversation_route.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/ui/routes/create_conversation_route.dart';
 | 
				
			||||||
import 'package:comunic/ui/tiles/conversation_tile.dart';
 | 
					import 'package:comunic/ui/tiles/conversation_tile.dart';
 | 
				
			||||||
import 'package:comunic/utils/intl_utils.dart';
 | 
					import 'package:comunic/utils/intl_utils.dart';
 | 
				
			||||||
import 'package:comunic/utils/ui_utils.dart';
 | 
					import 'package:comunic/utils/ui_utils.dart';
 | 
				
			||||||
@@ -52,7 +53,7 @@ class _ConversationScreenState extends State<ConversationsListScreen> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    //Get the list of conversations
 | 
					    //Get the list of conversations
 | 
				
			||||||
    var list;
 | 
					    var list;
 | 
				
			||||||
    if(cached)
 | 
					    if (cached)
 | 
				
			||||||
      list = await _conversationsHelper.getCachedList();
 | 
					      list = await _conversationsHelper.getCachedList();
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
      list = await _conversationsHelper.downloadList();
 | 
					      list = await _conversationsHelper.downloadList();
 | 
				
			||||||
@@ -90,12 +91,20 @@ class _ConversationScreenState extends State<ConversationsListScreen> {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// Open a conversation
 | 
					  /// Open a conversation
 | 
				
			||||||
  void _openConversation(BuildContext context, int conversationId){
 | 
					  void _openConversation(BuildContext context, int conversationId) {
 | 
				
			||||||
    Navigator.of(context).push(MaterialPageRoute(builder: (c){
 | 
					    Navigator.of(context).push(MaterialPageRoute(builder: (c) {
 | 
				
			||||||
      return ConversationRoute(conversationID: conversationId,);
 | 
					      return ConversationRoute(
 | 
				
			||||||
 | 
					        conversationID: conversationId,
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
    }));
 | 
					    }));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Create a new conversation
 | 
				
			||||||
 | 
					  void _createConversation(BuildContext context) {
 | 
				
			||||||
 | 
					    Navigator.of(context)
 | 
				
			||||||
 | 
					        .push(MaterialPageRoute(builder: (c) => CreateConversationRoute()));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
    if (_error == LoadErrorLevel.MAJOR) return _buildErrorCard();
 | 
					    if (_error == LoadErrorLevel.MAJOR) return _buildErrorCard();
 | 
				
			||||||
@@ -116,7 +125,9 @@ class _ConversationScreenState extends State<ConversationsListScreen> {
 | 
				
			|||||||
                  return ConversationTile(
 | 
					                  return ConversationTile(
 | 
				
			||||||
                    conversation: _list.elementAt(index),
 | 
					                    conversation: _list.elementAt(index),
 | 
				
			||||||
                    usersList: _list.users,
 | 
					                    usersList: _list.users,
 | 
				
			||||||
                    onOpen: (c){_openConversation(context, c.id);},
 | 
					                    onOpen: (c) {
 | 
				
			||||||
 | 
					                      _openConversation(context, c.id);
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
                  );
 | 
					                  );
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
                itemCount: _list.length,
 | 
					                itemCount: _list.length,
 | 
				
			||||||
@@ -124,6 +135,18 @@ class _ConversationScreenState extends State<ConversationsListScreen> {
 | 
				
			|||||||
            ),
 | 
					            ),
 | 
				
			||||||
          ],
 | 
					          ],
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Add conversation button
 | 
				
			||||||
 | 
					        Positioned(
 | 
				
			||||||
 | 
					          right: 20.0,
 | 
				
			||||||
 | 
					          bottom: 20.0,
 | 
				
			||||||
 | 
					          child: FloatingActionButton(
 | 
				
			||||||
 | 
					            onPressed: () => _createConversation(context),
 | 
				
			||||||
 | 
					            child: Icon(Icons.add),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Loading indicator
 | 
				
			||||||
        Positioned(
 | 
					        Positioned(
 | 
				
			||||||
          top: 8.0,
 | 
					          top: 8.0,
 | 
				
			||||||
          left: 0.0,
 | 
					          left: 0.0,
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										132
									
								
								lib/ui/screens/update_conversation_screen.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								lib/ui/screens/update_conversation_screen.dart
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,132 @@
 | 
				
			|||||||
 | 
					import 'package:comunic/helpers/conversations_helper.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/lists/users_list.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/models/conversation_settings.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/ui/routes/conversation_route.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/ui/tiles/simple_user_tile.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/ui/widgets/pick_user_widget.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/utils/intl_utils.dart';
 | 
				
			||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Create / Update conversation screen
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// @author Pierre HUBERT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum _MembersMenuChoices { REMOVE }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class UpdateConversationScreen extends StatefulWidget {
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  State<StatefulWidget> createState() => _UpdateConversationScreen();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class _UpdateConversationScreen extends State<UpdateConversationScreen> {
 | 
				
			||||||
 | 
					  TextEditingController _nameController = TextEditingController();
 | 
				
			||||||
 | 
					  UsersList _members = UsersList();
 | 
				
			||||||
 | 
					  bool _followConversation = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return Container(
 | 
				
			||||||
 | 
					      padding: EdgeInsets.all(8.0),
 | 
				
			||||||
 | 
					      child: Column(
 | 
				
			||||||
 | 
					        children: <Widget>[
 | 
				
			||||||
 | 
					          // Conversation name
 | 
				
			||||||
 | 
					          TextField(
 | 
				
			||||||
 | 
					            controller: _nameController,
 | 
				
			||||||
 | 
					            decoration: InputDecoration(
 | 
				
			||||||
 | 
					                labelText: tr("Conversation name (optionnal)"),
 | 
				
			||||||
 | 
					                alignLabelWithHint: true),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          // Add a member to the conversation
 | 
				
			||||||
 | 
					          PickUserWidget(
 | 
				
			||||||
 | 
					            resetOnChoose: true,
 | 
				
			||||||
 | 
					            keepFocusOnChoose: true,
 | 
				
			||||||
 | 
					            label: tr("Add member"),
 | 
				
			||||||
 | 
					            onSelectUser: (user) => setState(() {
 | 
				
			||||||
 | 
					                  if (!_members.contains(user)) _members.add(user);
 | 
				
			||||||
 | 
					                }),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          //Conversation members
 | 
				
			||||||
 | 
					          Container(
 | 
				
			||||||
 | 
					            child: _members.length == 0
 | 
				
			||||||
 | 
					                ? null
 | 
				
			||||||
 | 
					                : Flexible(
 | 
				
			||||||
 | 
					                    child: ListView.builder(
 | 
				
			||||||
 | 
					                      itemCount: _members.length,
 | 
				
			||||||
 | 
					                      itemBuilder: (b, i) {
 | 
				
			||||||
 | 
					                        return SimpleUserTile(
 | 
				
			||||||
 | 
					                          user: _members[i],
 | 
				
			||||||
 | 
					                          trailing: PopupMenuButton<_MembersMenuChoices>(
 | 
				
			||||||
 | 
					                            onSelected: (choice) =>
 | 
				
			||||||
 | 
					                                _membersMenuItemSelected(i, choice),
 | 
				
			||||||
 | 
					                            itemBuilder: (c) =>
 | 
				
			||||||
 | 
					                                <PopupMenuEntry<_MembersMenuChoices>>[
 | 
				
			||||||
 | 
					                                  PopupMenuItem(
 | 
				
			||||||
 | 
					                                    child: Text(tr("Remove")),
 | 
				
			||||||
 | 
					                                    value: _MembersMenuChoices.REMOVE,
 | 
				
			||||||
 | 
					                                  )
 | 
				
			||||||
 | 
					                                ],
 | 
				
			||||||
 | 
					                          ),
 | 
				
			||||||
 | 
					                        );
 | 
				
			||||||
 | 
					                      },
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          // Follow conversation ?
 | 
				
			||||||
 | 
					          Row(
 | 
				
			||||||
 | 
					            children: <Widget>[
 | 
				
			||||||
 | 
					              Switch(
 | 
				
			||||||
 | 
					                value: _followConversation,
 | 
				
			||||||
 | 
					                onChanged: (b) => setState(() {
 | 
				
			||||||
 | 
					                      _followConversation = b;
 | 
				
			||||||
 | 
					                    }),
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					              Text(tr("Follow conversation"))
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          // Submit button
 | 
				
			||||||
 | 
					          RaisedButton(
 | 
				
			||||||
 | 
					            onPressed: _members.length < 1 ? null : _submitForm,
 | 
				
			||||||
 | 
					            child: Text(tr("Create the conversation")),
 | 
				
			||||||
 | 
					          )
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// An option of the members menu has been selected
 | 
				
			||||||
 | 
					  void _membersMenuItemSelected(int index, _MembersMenuChoices choice) {
 | 
				
			||||||
 | 
					    if (choice == null) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (choice == _MembersMenuChoices.REMOVE)
 | 
				
			||||||
 | 
					      return setState(() {
 | 
				
			||||||
 | 
					        _members.removeAt(index);
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Submit the conversation
 | 
				
			||||||
 | 
					  Future<void> _submitForm() async {
 | 
				
			||||||
 | 
					    final settings = ConversationSettings(
 | 
				
			||||||
 | 
					      id: 0,
 | 
				
			||||||
 | 
					      name: _nameController.text,
 | 
				
			||||||
 | 
					      following: _followConversation,
 | 
				
			||||||
 | 
					      members: _members.usersID,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Create the conversation
 | 
				
			||||||
 | 
					    final conversationID = await ConversationsHelper().createConversation(settings);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Check for errors
 | 
				
			||||||
 | 
					    if(conversationID < 1)
 | 
				
			||||||
 | 
					      return Scaffold.of(context).showSnackBar(
 | 
				
			||||||
 | 
					          SnackBar(content: Text(tr("Could not create the conversation!")), duration: Duration(seconds: 1),));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Open the conversation
 | 
				
			||||||
 | 
					    Navigator.of(context).pushReplacement(MaterialPageRoute(
 | 
				
			||||||
 | 
					      builder: (c) => ConversationRoute(conversationID: conversationID,)
 | 
				
			||||||
 | 
					    ));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -13,8 +13,9 @@ typedef OnUserTap = void Function(User);
 | 
				
			|||||||
class SimpleUserTile extends StatelessWidget {
 | 
					class SimpleUserTile extends StatelessWidget {
 | 
				
			||||||
  final User user;
 | 
					  final User user;
 | 
				
			||||||
  final OnUserTap onTap;
 | 
					  final OnUserTap onTap;
 | 
				
			||||||
 | 
					  final Widget trailing;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const SimpleUserTile({Key key, this.user, this.onTap})
 | 
					  const SimpleUserTile({Key key, this.user, this.onTap, this.trailing})
 | 
				
			||||||
      : assert(user != null),
 | 
					      : assert(user != null),
 | 
				
			||||||
        super(key: key);
 | 
					        super(key: key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -26,6 +27,7 @@ class SimpleUserTile extends StatelessWidget {
 | 
				
			|||||||
        user: user,
 | 
					        user: user,
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
      title: Text(user.fullName),
 | 
					      title: Text(user.fullName),
 | 
				
			||||||
 | 
					      trailing: trailing,
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,7 +2,6 @@ import 'package:comunic/helpers/search_helper.dart';
 | 
				
			|||||||
import 'package:comunic/lists/users_list.dart';
 | 
					import 'package:comunic/lists/users_list.dart';
 | 
				
			||||||
import 'package:comunic/models/user.dart';
 | 
					import 'package:comunic/models/user.dart';
 | 
				
			||||||
import 'package:comunic/ui/tiles/simple_user_tile.dart';
 | 
					import 'package:comunic/ui/tiles/simple_user_tile.dart';
 | 
				
			||||||
import 'package:comunic/utils/intl_utils.dart';
 | 
					 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Pick user widget
 | 
					/// Pick user widget
 | 
				
			||||||
@@ -16,9 +15,20 @@ typedef OnSelectUserCallback = void Function(User);
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class PickUserWidget extends StatefulWidget {
 | 
					class PickUserWidget extends StatefulWidget {
 | 
				
			||||||
  final OnSelectUserCallback onSelectUser;
 | 
					  final OnSelectUserCallback onSelectUser;
 | 
				
			||||||
 | 
					  final String label;
 | 
				
			||||||
 | 
					  final bool resetOnChoose;
 | 
				
			||||||
 | 
					  final bool keepFocusOnChoose;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const PickUserWidget({Key key, @required this.onSelectUser})
 | 
					  const PickUserWidget(
 | 
				
			||||||
 | 
					      {Key key,
 | 
				
			||||||
 | 
					      @required this.onSelectUser,
 | 
				
			||||||
 | 
					      @required this.label,
 | 
				
			||||||
 | 
					      this.resetOnChoose = false,
 | 
				
			||||||
 | 
					      this.keepFocusOnChoose = false})
 | 
				
			||||||
      : assert(onSelectUser != null),
 | 
					      : assert(onSelectUser != null),
 | 
				
			||||||
 | 
					        assert(label != null),
 | 
				
			||||||
 | 
					        assert(resetOnChoose != null),
 | 
				
			||||||
 | 
					        assert(keepFocusOnChoose != null),
 | 
				
			||||||
        super(key: key);
 | 
					        super(key: key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
@@ -42,8 +52,7 @@ class _PickUserWidgetState extends State<PickUserWidget> {
 | 
				
			|||||||
    _focusNode.addListener(() {
 | 
					    _focusNode.addListener(() {
 | 
				
			||||||
      if (_focusNode.hasFocus) {
 | 
					      if (_focusNode.hasFocus) {
 | 
				
			||||||
        //Check for focus
 | 
					        //Check for focus
 | 
				
			||||||
        _overlayEntry = _createOverlayEntry();
 | 
					        //_showOverlay();
 | 
				
			||||||
        Overlay.of(context).insert(_overlayEntry);
 | 
					 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        //Remove overlay
 | 
					        //Remove overlay
 | 
				
			||||||
        _removeOverlay();
 | 
					        _removeOverlay();
 | 
				
			||||||
@@ -57,7 +66,10 @@ class _PickUserWidgetState extends State<PickUserWidget> {
 | 
				
			|||||||
      focusNode: _focusNode,
 | 
					      focusNode: _focusNode,
 | 
				
			||||||
      onChanged: (s) => _updateSuggestions(),
 | 
					      onChanged: (s) => _updateSuggestions(),
 | 
				
			||||||
      controller: _controller,
 | 
					      controller: _controller,
 | 
				
			||||||
      decoration: InputDecoration(labelText: tr("Select user")),
 | 
					      decoration: InputDecoration(
 | 
				
			||||||
 | 
					        labelText: widget.label,
 | 
				
			||||||
 | 
					        alignLabelWithHint: true,
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -87,6 +99,11 @@ class _PickUserWidgetState extends State<PickUserWidget> {
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void _showOverlay() {
 | 
				
			||||||
 | 
					    _overlayEntry = _createOverlayEntry();
 | 
				
			||||||
 | 
					    Overlay.of(context).insert(_overlayEntry);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void _removeOverlay() {
 | 
					  void _removeOverlay() {
 | 
				
			||||||
    if (_overlayEntry != null) {
 | 
					    if (_overlayEntry != null) {
 | 
				
			||||||
      _overlayEntry.remove();
 | 
					      _overlayEntry.remove();
 | 
				
			||||||
@@ -96,22 +113,36 @@ class _PickUserWidgetState extends State<PickUserWidget> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  /// This method get called each time the input value is updated
 | 
					  /// This method get called each time the input value is updated
 | 
				
			||||||
  Future<void> _updateSuggestions() async {
 | 
					  Future<void> _updateSuggestions() async {
 | 
				
			||||||
    if (_controller.value.text.length == 0) return;
 | 
					    if (_controller.value.text.length == 0) return _removeOverlay();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    final results = await _searchHelper.searchUser(_controller.value.text);
 | 
					    final results = await _searchHelper.searchUser(_controller.value.text);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (results == null) return;
 | 
					    if (results == null) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    _suggestions = results;
 | 
					    _suggestions = results;
 | 
				
			||||||
    if (_overlayEntry != null) _overlayEntry.markNeedsBuild();
 | 
					    if (_overlayEntry != null)
 | 
				
			||||||
 | 
					      _overlayEntry.markNeedsBuild();
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					      _showOverlay();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// Method called each time a user is tapped (selected)
 | 
					  /// Method called each time a user is tapped (selected)
 | 
				
			||||||
  void _userTapped(User user) {
 | 
					  void _userTapped(User user) {
 | 
				
			||||||
    _controller.text = user.fullName;
 | 
					    // Hide overlay
 | 
				
			||||||
    _removeOverlay();
 | 
					    _removeOverlay();
 | 
				
			||||||
    _focusNode.unfocus();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Unfocus if required
 | 
				
			||||||
 | 
					    if (!widget.keepFocusOnChoose) {
 | 
				
			||||||
 | 
					      _focusNode.unfocus();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //Check if name has to remain in input
 | 
				
			||||||
 | 
					    if (widget.resetOnChoose) {
 | 
				
			||||||
 | 
					      _controller.text = "";
 | 
				
			||||||
 | 
					    } else
 | 
				
			||||||
 | 
					      _controller.text = user.fullName;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //Callback
 | 
				
			||||||
    widget.onSelectUser(user);
 | 
					    widget.onSelectUser(user);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user