mirror of
				https://gitlab.com/comunic/comunicmobile
				synced 2025-11-04 04:04:18 +00:00 
			
		
		
		
	Created inline user picker
This commit is contained in:
		
							
								
								
									
										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);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user