import 'package:comunic/helpers/search_helper.dart'; import 'package:comunic/lists/users_list.dart'; import 'package:comunic/models/user.dart'; import 'package:comunic/ui/tiles/simple_user_tile.dart'; import 'package:comunic/utils/intl_utils.dart'; import 'package:flutter/material.dart'; /// Pick user widget /// /// Allows to choose a user by starting to type his name and tapping on it /// when his name appear /// /// @author Pierre HUBERT typedef OnSelectUserCallback = void Function(User); class PickUserWidget extends StatefulWidget { final OnSelectUserCallback onSelectUser; const PickUserWidget({Key key, @required this.onSelectUser}) : assert(onSelectUser != null), super(key: key); @override State createState() => _PickUserWidgetState(); } class _PickUserWidgetState extends State { // Helper final SearchHelper _searchHelper = SearchHelper(); // Widget properties final FocusNode _focusNode = FocusNode(); final TextEditingController _controller = TextEditingController(); OverlayEntry _overlayEntry; UsersList _suggestions; @override void initState() { super.initState(); _focusNode.addListener(() { if (_focusNode.hasFocus) { //Check for focus _overlayEntry = _createOverlayEntry(); Overlay.of(context).insert(_overlayEntry); } else { //Remove overlay _removeOverlay(); } }); } @override Widget build(BuildContext context) { return TextField( focusNode: _focusNode, onChanged: (s) => _updateSuggestions(), controller: _controller, decoration: InputDecoration(labelText: tr("Select user")), ); } OverlayEntry _createOverlayEntry() { RenderBox renderBox = context.findRenderObject(); final size = renderBox.size; final offset = renderBox.localToGlobal(Offset.zero); return OverlayEntry(builder: (c) { return Positioned( left: offset.dx, top: offset.dy + size.height + 5.0, width: size.width, child: Material( elevation: 4.0, child: ListView.builder( padding: EdgeInsets.zero, shrinkWrap: true, itemCount: _suggestions == null ? 0 : _suggestions.length, itemBuilder: (c, i) => SimpleUserTile( user: _suggestions[i], onTap: _userTapped, ), ), ), ); }); } void _removeOverlay() { if (_overlayEntry != null) { _overlayEntry.remove(); _overlayEntry = null; } } /// This method get called each time the input value is updated Future _updateSuggestions() async { if (_controller.value.text.length == 0) return; final results = await _searchHelper.searchUser(_controller.value.text); if (results == null) return; _suggestions = results; if (_overlayEntry != null) _overlayEntry.markNeedsBuild(); } /// Method called each time a user is tapped (selected) void _userTapped(User user) { _controller.text = user.fullName; _removeOverlay(); _focusNode.unfocus(); widget.onSelectUser(user); } }