1
0
mirror of https://gitlab.com/comunic/comunicmobile synced 2024-10-23 15:03:22 +00:00
comunicmobile/lib/ui/widgets/pick_user_widget.dart

118 lines
3.1 KiB
Dart
Raw Normal View History

2019-04-27 12:40:27 +00:00
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<StatefulWidget> createState() => _PickUserWidgetState();
}
class _PickUserWidgetState extends State<PickUserWidget> {
// 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<void> _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);
}
}