mirror of
https://gitlab.com/comunic/comunicmobile
synced 2024-12-26 04:48:51 +00:00
Created inline user picker
This commit is contained in:
parent
09d43ab5c0
commit
765ca82300
31
lib/helpers/search_helper.dart
Normal file
31
lib/helpers/search_helper.dart
Normal file
@ -0,0 +1,31 @@
|
||||
import 'package:comunic/helpers/users_helper.dart';
|
||||
import 'package:comunic/lists/users_list.dart';
|
||||
import 'package:comunic/models/api_request.dart';
|
||||
import 'package:comunic/utils/list_utils.dart';
|
||||
|
||||
/// Search helper
|
||||
///
|
||||
/// @author Pierre HUBERT
|
||||
|
||||
class SearchHelper {
|
||||
|
||||
/// Search for user. This method returns information about the target users
|
||||
///
|
||||
/// Returns information about the target users or null if an error occurred
|
||||
Future<UsersList> searchUser(String query) async {
|
||||
// Execute the query on the server
|
||||
final response = await APIRequest(
|
||||
uri: "user/search",
|
||||
needLogin: true,
|
||||
args: {
|
||||
"query": query
|
||||
}
|
||||
).exec();
|
||||
|
||||
if (response.code != 200) return null;
|
||||
|
||||
return await UsersHelper().getUsersInfo(
|
||||
listToIntList(response.getArray()));
|
||||
}
|
||||
|
||||
}
|
31
lib/ui/tiles/simple_user_tile.dart
Normal file
31
lib/ui/tiles/simple_user_tile.dart
Normal file
@ -0,0 +1,31 @@
|
||||
import 'package:comunic/models/user.dart';
|
||||
import 'package:comunic/ui/widgets/account_image_widget.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// Simple user tile
|
||||
///
|
||||
/// Basically this only shows the name of the user + its account image
|
||||
///
|
||||
/// @author Pierre HUBERT
|
||||
|
||||
typedef OnUserTap = void Function(User);
|
||||
|
||||
class SimpleUserTile extends StatelessWidget {
|
||||
final User user;
|
||||
final OnUserTap onTap;
|
||||
|
||||
const SimpleUserTile({Key key, this.user, this.onTap})
|
||||
: assert(user != null),
|
||||
super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListTile(
|
||||
onTap: onTap == null ? null : () => onTap(user),
|
||||
leading: AccountImageWidget(
|
||||
user: user,
|
||||
),
|
||||
title: Text(user.fullName),
|
||||
);
|
||||
}
|
||||
}
|
117
lib/ui/widgets/pick_user_widget.dart
Normal file
117
lib/ui/widgets/pick_user_widget.dart
Normal file
@ -0,0 +1,117 @@
|
||||
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);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user