Autocomplete container UI changes (#6690)
* add left & right padding to autocomplete peer and format Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> * handle max height for autocomplete equal padding, add box shadow and format Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com> --------- Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com>
This commit is contained in:
		
							parent
							
								
									79411430a5
								
							
						
					
					
						commit
						c168b7e979
					
				| @ -6,55 +6,55 @@ import 'package:flutter_hbb/models/peer_model.dart'; | ||||
| import 'package:flutter_hbb/common.dart'; | ||||
| import 'package:flutter_hbb/common/widgets/peer_card.dart'; | ||||
| 
 | ||||
| Future<List<Peer>> getAllPeers() async { | ||||
|   Map<String, dynamic> recentPeers = | ||||
|       jsonDecode(await bind.mainLoadRecentPeersSync()); | ||||
|   Map<String, dynamic> lanPeers = jsonDecode(await bind.mainLoadLanPeersSync()); | ||||
|   Map<String, dynamic> abPeers = jsonDecode(await bind.mainLoadAbSync()); | ||||
|   Map<String, dynamic> groupPeers = jsonDecode(await bind.mainLoadGroupSync()); | ||||
| 
 | ||||
|  Future<List<Peer>> getAllPeers() async { | ||||
|     Map<String, dynamic> recentPeers = jsonDecode(await bind.mainLoadRecentPeersSync()); | ||||
|     Map<String, dynamic> lanPeers = jsonDecode(await bind.mainLoadLanPeersSync()); | ||||
|     Map<String, dynamic> abPeers = jsonDecode(await bind.mainLoadAbSync()); | ||||
|     Map<String, dynamic> groupPeers = jsonDecode(await bind.mainLoadGroupSync()); | ||||
|   Map<String, dynamic> combinedPeers = {}; | ||||
| 
 | ||||
|     Map<String, dynamic> combinedPeers = {}; | ||||
|   void _mergePeers(Map<String, dynamic> peers) { | ||||
|     if (peers.containsKey("peers")) { | ||||
|       dynamic peerData = peers["peers"]; | ||||
| 
 | ||||
|     void _mergePeers(Map<String, dynamic> peers) { | ||||
|       if (peers.containsKey("peers")) { | ||||
|         dynamic peerData = peers["peers"]; | ||||
| 
 | ||||
|         if (peerData is String) { | ||||
|           try { | ||||
|             peerData = jsonDecode(peerData); | ||||
|           } catch (e) { | ||||
|             print("Error decoding peers: $e"); | ||||
|             return; | ||||
|           } | ||||
|       if (peerData is String) { | ||||
|         try { | ||||
|           peerData = jsonDecode(peerData); | ||||
|         } catch (e) { | ||||
|           print("Error decoding peers: $e"); | ||||
|           return; | ||||
|         } | ||||
|       } | ||||
| 
 | ||||
|         if (peerData is List) { | ||||
|           for (var peer in peerData) { | ||||
|             if (peer is Map && peer.containsKey("id")) { | ||||
|               String id = peer["id"]; | ||||
|               if (!combinedPeers.containsKey(id)) { | ||||
|                 combinedPeers[id] = peer; | ||||
|               } | ||||
|       if (peerData is List) { | ||||
|         for (var peer in peerData) { | ||||
|           if (peer is Map && peer.containsKey("id")) { | ||||
|             String id = peer["id"]; | ||||
|             if (!combinedPeers.containsKey(id)) { | ||||
|               combinedPeers[id] = peer; | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     _mergePeers(recentPeers); | ||||
|     _mergePeers(lanPeers); | ||||
|     _mergePeers(abPeers); | ||||
|     _mergePeers(groupPeers); | ||||
| 
 | ||||
|       List<Peer> parsedPeers = []; | ||||
| 
 | ||||
|     for (var peer in combinedPeers.values) { | ||||
|       parsedPeers.add(Peer.fromJson(peer)); | ||||
|     } | ||||
|     return  parsedPeers; | ||||
|   } | ||||
| 
 | ||||
|  class AutocompletePeerTile extends StatefulWidget { | ||||
|   _mergePeers(recentPeers); | ||||
|   _mergePeers(lanPeers); | ||||
|   _mergePeers(abPeers); | ||||
|   _mergePeers(groupPeers); | ||||
| 
 | ||||
|   List<Peer> parsedPeers = []; | ||||
| 
 | ||||
|   for (var peer in combinedPeers.values) { | ||||
|     parsedPeers.add(Peer.fromJson(peer)); | ||||
|   } | ||||
|   return parsedPeers; | ||||
| } | ||||
| 
 | ||||
| class AutocompletePeerTile extends StatefulWidget { | ||||
|   final VoidCallback onSelect; | ||||
|   final Peer peer; | ||||
| 
 | ||||
| @ -68,7 +68,7 @@ import 'package:flutter_hbb/common/widgets/peer_card.dart'; | ||||
|   _AutocompletePeerTileState createState() => _AutocompletePeerTileState(); | ||||
| } | ||||
| 
 | ||||
| class _AutocompletePeerTileState extends State<AutocompletePeerTile>{ | ||||
| class _AutocompletePeerTileState extends State<AutocompletePeerTile> { | ||||
|   List _frontN<T>(List list, int n) { | ||||
|     if (list.length <= n) { | ||||
|       return list; | ||||
| @ -76,99 +76,114 @@ class _AutocompletePeerTileState extends State<AutocompletePeerTile>{ | ||||
|       return list.sublist(0, n); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Widget build(BuildContext context){ | ||||
|   Widget build(BuildContext context) { | ||||
|     final double _tileRadius = 5; | ||||
|         final name = | ||||
|           '${widget.peer.username}${widget.peer.username.isNotEmpty && widget.peer.hostname.isNotEmpty ? '@' : ''}${widget.peer.hostname}'; | ||||
|         final greyStyle = TextStyle( | ||||
|           fontSize: 11, | ||||
|           color: Theme.of(context).textTheme.titleLarge?.color?.withOpacity(0.6)); | ||||
|         final child = GestureDetector( | ||||
|           onTap: () => widget.onSelect(), | ||||
|           child: | ||||
|         Container( | ||||
|           height: 42, | ||||
|           margin: EdgeInsets.only(bottom: 5), | ||||
|           child: Row( | ||||
|           mainAxisSize: MainAxisSize.max, | ||||
|           children: [ | ||||
|             Container( | ||||
|               decoration: BoxDecoration( | ||||
|                 color: str2color('${widget.peer.id}${widget.peer.platform}', 0x7f), | ||||
|                 borderRadius: BorderRadius.only( | ||||
|                         topLeft: Radius.circular(_tileRadius), | ||||
|                         bottomLeft: Radius.circular(_tileRadius), | ||||
|                       ), | ||||
|               ), | ||||
|               alignment: Alignment.center, | ||||
|               width: 42, | ||||
|               height: null, | ||||
|               child: Padding( | ||||
|                 padding: EdgeInsets.all(6), | ||||
|                 child: getPlatformImage(widget.peer.platform, size: 30) | ||||
|               ) | ||||
|             ), | ||||
|             Expanded( | ||||
|               child: Container( | ||||
|                 padding: EdgeInsets.only(left: 10), | ||||
|                 decoration: BoxDecoration( | ||||
|                   color: Theme.of(context).colorScheme.background, | ||||
|                   borderRadius: BorderRadius.only( | ||||
|                     topRight: Radius.circular(_tileRadius), | ||||
|                     bottomRight: Radius.circular(_tileRadius), | ||||
|                   ), | ||||
|                 ), | ||||
|             child: Row( | ||||
|               children: [ | ||||
|                 Expanded( | ||||
|                   child: Container( | ||||
|                     margin: EdgeInsets.only(top: 2), | ||||
|                     child: Container( | ||||
|                       margin: EdgeInsets.only(top: 2), | ||||
|                       child: Column( | ||||
|                     children: [ | ||||
|                       Container( | ||||
|                         margin: EdgeInsets.only(top: 2), | ||||
|                         child: Row(children: [ | ||||
|                           getOnline(8, widget.peer.online), | ||||
|                           Expanded( | ||||
|                               child: Text( | ||||
|                             widget.peer.alias.isEmpty ? formatID(widget.peer.id) : widget.peer.alias, | ||||
|                             overflow: TextOverflow.ellipsis, | ||||
|                             style: Theme.of(context).textTheme.titleSmall, | ||||
|                           )), | ||||
|                           !widget.peer.alias.isEmpty? | ||||
|                           Padding( | ||||
|                             padding: const EdgeInsets.only(left: 5, right: 5), | ||||
|                             child: Text( | ||||
|                               "(${widget.peer.id})", | ||||
|                               style: greyStyle, | ||||
|                               overflow: TextOverflow.ellipsis, | ||||
|                             ) | ||||
|                           ) | ||||
|                           : Container(), | ||||
|                       ])), | ||||
|                       Align( | ||||
|                         alignment: Alignment.centerLeft, | ||||
|                         child: Text( | ||||
|                           name, | ||||
|                           style: greyStyle, | ||||
|                           textAlign: TextAlign.start, | ||||
|                           overflow: TextOverflow.ellipsis, | ||||
|     final name = | ||||
|         '${widget.peer.username}${widget.peer.username.isNotEmpty && widget.peer.hostname.isNotEmpty ? '@' : ''}${widget.peer.hostname}'; | ||||
|     final greyStyle = TextStyle( | ||||
|         fontSize: 11, | ||||
|         color: Theme.of(context).textTheme.titleLarge?.color?.withOpacity(0.6)); | ||||
|     final child = GestureDetector( | ||||
|         onTap: () => widget.onSelect(), | ||||
|         child: Padding( | ||||
|             padding: EdgeInsets.only(left: 5, right: 5), | ||||
|             child: Container( | ||||
|                 height: 42, | ||||
|                 margin: EdgeInsets.only(bottom: 5), | ||||
|                 child: Row( | ||||
|                   mainAxisSize: MainAxisSize.max, | ||||
|                   children: [ | ||||
|                     Container( | ||||
|                         decoration: BoxDecoration( | ||||
|                           color: str2color( | ||||
|                               '${widget.peer.id}${widget.peer.platform}', 0x7f), | ||||
|                           borderRadius: BorderRadius.only( | ||||
|                             topLeft: Radius.circular(_tileRadius), | ||||
|                             bottomLeft: Radius.circular(_tileRadius), | ||||
|                           ), | ||||
|                         ), | ||||
|                       ), | ||||
|                     ], | ||||
|                   ) | ||||
|                 ))), | ||||
|               ], | ||||
|             ) | ||||
|             ), | ||||
|         ) | ||||
|       ], | ||||
|     ))); | ||||
|     final colors = | ||||
|         _frontN(widget.peer.tags, 25).map((e) => gFFI.abModel.getTagColor(e)).toList(); | ||||
|                         alignment: Alignment.center, | ||||
|                         width: 42, | ||||
|                         height: null, | ||||
|                         child: Padding( | ||||
|                             padding: EdgeInsets.all(6), | ||||
|                             child: getPlatformImage(widget.peer.platform, | ||||
|                                 size: 30))), | ||||
|                     Expanded( | ||||
|                       child: Container( | ||||
|                           padding: EdgeInsets.only(left: 10), | ||||
|                           decoration: BoxDecoration( | ||||
|                             color: Theme.of(context).colorScheme.background, | ||||
|                             borderRadius: BorderRadius.only( | ||||
|                               topRight: Radius.circular(_tileRadius), | ||||
|                               bottomRight: Radius.circular(_tileRadius), | ||||
|                             ), | ||||
|                           ), | ||||
|                           child: Row( | ||||
|                             children: [ | ||||
|                               Expanded( | ||||
|                                   child: Container( | ||||
|                                       margin: EdgeInsets.only(top: 2), | ||||
|                                       child: Container( | ||||
|                                           margin: EdgeInsets.only(top: 2), | ||||
|                                           child: Column( | ||||
|                                             children: [ | ||||
|                                               Container( | ||||
|                                                   margin: | ||||
|                                                       EdgeInsets.only(top: 2), | ||||
|                                                   child: Row(children: [ | ||||
|                                                     getOnline( | ||||
|                                                         8, widget.peer.online), | ||||
|                                                     Expanded( | ||||
|                                                         child: Text( | ||||
|                                                       widget.peer.alias.isEmpty | ||||
|                                                           ? formatID( | ||||
|                                                               widget.peer.id) | ||||
|                                                           : widget.peer.alias, | ||||
|                                                       overflow: | ||||
|                                                           TextOverflow.ellipsis, | ||||
|                                                       style: Theme.of(context) | ||||
|                                                           .textTheme | ||||
|                                                           .titleSmall, | ||||
|                                                     )), | ||||
|                                                     !widget.peer.alias.isEmpty | ||||
|                                                         ? Padding( | ||||
|                                                             padding: | ||||
|                                                                 const EdgeInsets | ||||
|                                                                     .only( | ||||
|                                                                     left: 5, | ||||
|                                                                     right: 5), | ||||
|                                                             child: Text( | ||||
|                                                               "(${widget.peer.id})", | ||||
|                                                               style: greyStyle, | ||||
|                                                               overflow: | ||||
|                                                                   TextOverflow | ||||
|                                                                       .ellipsis, | ||||
|                                                             )) | ||||
|                                                         : Container(), | ||||
|                                                   ])), | ||||
|                                               Align( | ||||
|                                                 alignment: Alignment.centerLeft, | ||||
|                                                 child: Text( | ||||
|                                                   name, | ||||
|                                                   style: greyStyle, | ||||
|                                                   textAlign: TextAlign.start, | ||||
|                                                   overflow: | ||||
|                                                       TextOverflow.ellipsis, | ||||
|                                                 ), | ||||
|                                               ), | ||||
|                                             ], | ||||
|                                           )))), | ||||
|                             ], | ||||
|                           )), | ||||
|                     ) | ||||
|                   ], | ||||
|                 )))); | ||||
|     final colors = _frontN(widget.peer.tags, 25) | ||||
|         .map((e) => gFFI.abModel.getTagColor(e)) | ||||
|         .toList(); | ||||
|     return Tooltip( | ||||
|       message: isMobile | ||||
|           ? '' | ||||
| @ -188,4 +203,4 @@ class _AutocompletePeerTileState extends State<AutocompletePeerTile>{ | ||||
|       ]), | ||||
|     ); | ||||
|   } | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -308,40 +308,59 @@ class _ConnectionPageState extends State<ConnectionPage> | ||||
|                       AutocompleteOnSelected<Peer> onSelected, | ||||
|                       Iterable<Peer> options) { | ||||
|                     double maxHeight = options.length * 50; | ||||
|                     maxHeight = maxHeight > 200 ? 200 : maxHeight; | ||||
|                     if (options.length == 1) { | ||||
|                       maxHeight = 52; | ||||
|                     } else if (options.length == 3) { | ||||
|                       maxHeight = 146; | ||||
|                     } else if (options.length == 4) { | ||||
|                       maxHeight = 193; | ||||
|                     } | ||||
|                     maxHeight = maxHeight.clamp(0, 200); | ||||
| 
 | ||||
|                     return Align( | ||||
|                       alignment: Alignment.topLeft, | ||||
|                       child: ClipRRect( | ||||
|                           borderRadius: BorderRadius.circular(5), | ||||
|                           child: Material( | ||||
|                             elevation: 4, | ||||
|                             child: ConstrainedBox( | ||||
|                               constraints: BoxConstraints( | ||||
|                                 maxHeight: maxHeight, | ||||
|                                 maxWidth: 319, | ||||
|                       child: Container( | ||||
|                           decoration: BoxDecoration( | ||||
|                             boxShadow: [ | ||||
|                               BoxShadow( | ||||
|                                 color: Colors.black.withOpacity(0.3), | ||||
|                                 blurRadius: 5, | ||||
|                                 spreadRadius: 1, | ||||
|                               ), | ||||
|                               child: peers.isEmpty && isPeersLoading | ||||
|                                   ? Container( | ||||
|                                       height: 80, | ||||
|                                       child: Center( | ||||
|                                         child: CircularProgressIndicator( | ||||
|                                           strokeWidth: 2, | ||||
|                             ], | ||||
|                           ), | ||||
|                           child: ClipRRect( | ||||
|                               borderRadius: BorderRadius.circular(5), | ||||
|                               child: Material( | ||||
|                                 elevation: 4, | ||||
|                                 child: ConstrainedBox( | ||||
|                                   constraints: BoxConstraints( | ||||
|                                     maxHeight: maxHeight, | ||||
|                                     maxWidth: 319, | ||||
|                                   ), | ||||
|                                   child: peers.isEmpty && isPeersLoading | ||||
|                                       ? Container( | ||||
|                                           height: 80, | ||||
|                                           child: Center( | ||||
|                                             child: CircularProgressIndicator( | ||||
|                                               strokeWidth: 2, | ||||
|                                             ), | ||||
|                                           )) | ||||
|                                       : Padding( | ||||
|                                           padding: | ||||
|                                               const EdgeInsets.only(top: 5), | ||||
|                                           child: ListView( | ||||
|                                             children: options | ||||
|                                                 .map((peer) => | ||||
|                                                     AutocompletePeerTile( | ||||
|                                                         onSelect: () => | ||||
|                                                             onSelected(peer), | ||||
|                                                         peer: peer)) | ||||
|                                                 .toList(), | ||||
|                                           ), | ||||
|                                         ), | ||||
|                                       )) | ||||
|                                   : Padding( | ||||
|                                       padding: const EdgeInsets.only(top: 5), | ||||
|                                       child: ListView( | ||||
|                                         children: options | ||||
|                                             .map((peer) => AutocompletePeerTile( | ||||
|                                                 onSelect: () => | ||||
|                                                     onSelected(peer), | ||||
|                                                 peer: peer)) | ||||
|                                             .toList(), | ||||
|                                       ), | ||||
|                                     ), | ||||
|                             ), | ||||
|                           )), | ||||
|                                 ), | ||||
|                               ))), | ||||
|                     ); | ||||
|                   }, | ||||
|                 )), | ||||
|  | ||||
| @ -52,6 +52,7 @@ class _ConnectionPageState extends State<ConnectionPage> { | ||||
|       return list.sublist(0, n); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   bool isPeersLoading = false; | ||||
|   bool isPeersLoaded = false; | ||||
|   StreamSubscription? _uniLinksSubscription; | ||||
| @ -137,9 +138,9 @@ class _ConnectionPageState extends State<ConnectionPage> { | ||||
|     await Future.delayed(Duration(milliseconds: 100)); | ||||
|     peers = await getAllPeers(); | ||||
|     setState(() { | ||||
|         isPeersLoading = false; | ||||
|         isPeersLoaded = true; | ||||
|       }); | ||||
|       isPeersLoading = false; | ||||
|       isPeersLoaded = true; | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   /// UI for the remote ID TextField. | ||||
| @ -163,9 +164,8 @@ class _ConnectionPageState extends State<ConnectionPage> { | ||||
|                     optionsBuilder: (TextEditingValue textEditingValue) { | ||||
|                       if (textEditingValue.text == '') { | ||||
|                         return const Iterable<Peer>.empty(); | ||||
|                       } | ||||
|                       else if (peers.isEmpty && !isPeersLoaded) { | ||||
|                          Peer emptyPeer = Peer( | ||||
|                       } else if (peers.isEmpty && !isPeersLoaded) { | ||||
|                         Peer emptyPeer = Peer( | ||||
|                           id: '', | ||||
|                           username: '', | ||||
|                           hostname: '', | ||||
| @ -179,9 +179,9 @@ class _ConnectionPageState extends State<ConnectionPage> { | ||||
|                           loginName: '', | ||||
|                         ); | ||||
|                         return [emptyPeer]; | ||||
|                       } | ||||
|                       else { | ||||
|                         String textWithoutSpaces = textEditingValue.text.replaceAll(" ", ""); | ||||
|                       } else { | ||||
|                         String textWithoutSpaces = | ||||
|                             textEditingValue.text.replaceAll(" ", ""); | ||||
|                         if (int.tryParse(textWithoutSpaces) != null) { | ||||
|                           textEditingValue = TextEditingValue( | ||||
|                             text: textWithoutSpaces, | ||||
| @ -190,62 +190,71 @@ class _ConnectionPageState extends State<ConnectionPage> { | ||||
|                         } | ||||
|                         String textToFind = textEditingValue.text.toLowerCase(); | ||||
| 
 | ||||
|                         return peers.where((peer) => | ||||
|                         peer.id.toLowerCase().contains(textToFind) || | ||||
|                         peer.username.toLowerCase().contains(textToFind) || | ||||
|                         peer.hostname.toLowerCase().contains(textToFind) || | ||||
|                         peer.alias.toLowerCase().contains(textToFind)) | ||||
|                         .toList(); | ||||
|                         return peers | ||||
|                             .where((peer) => | ||||
|                                 peer.id.toLowerCase().contains(textToFind) || | ||||
|                                 peer.username | ||||
|                                     .toLowerCase() | ||||
|                                     .contains(textToFind) || | ||||
|                                 peer.hostname | ||||
|                                     .toLowerCase() | ||||
|                                     .contains(textToFind) || | ||||
|                                 peer.alias.toLowerCase().contains(textToFind)) | ||||
|                             .toList(); | ||||
|                       } | ||||
|                     }, | ||||
|                     fieldViewBuilder: (BuildContext context, | ||||
|                       TextEditingController fieldTextEditingController, | ||||
|                       FocusNode fieldFocusNode, VoidCallback onFieldSubmitted) { | ||||
|                         TextEditingController fieldTextEditingController, | ||||
|                         FocusNode fieldFocusNode, | ||||
|                         VoidCallback onFieldSubmitted) { | ||||
|                       fieldTextEditingController.text = _idController.text; | ||||
|                       fieldFocusNode.addListener(() async{ | ||||
|                       _idEmpty.value = fieldTextEditingController.text.isEmpty; | ||||
|                         if (fieldFocusNode.hasFocus && !isPeersLoading){ | ||||
|                       fieldFocusNode.addListener(() async { | ||||
|                         _idEmpty.value = | ||||
|                             fieldTextEditingController.text.isEmpty; | ||||
|                         if (fieldFocusNode.hasFocus && !isPeersLoading) { | ||||
|                           _fetchPeers(); | ||||
|                         } | ||||
|                       }); | ||||
|                       final textLength = fieldTextEditingController.value.text.length; | ||||
|                       final textLength = | ||||
|                           fieldTextEditingController.value.text.length; | ||||
|                       // select all to facilitate removing text, just following the behavior of address input of chrome | ||||
|                       fieldTextEditingController.selection = TextSelection(baseOffset: 0, extentOffset: textLength); | ||||
|                     return AutoSizeTextField( | ||||
|                     controller: fieldTextEditingController, | ||||
|                     focusNode: fieldFocusNode, | ||||
|                     minFontSize: 18, | ||||
|                     autocorrect: false, | ||||
|                     enableSuggestions: false, | ||||
|                     keyboardType: TextInputType.visiblePassword, | ||||
|                     // keyboardType: TextInputType.number, | ||||
|                     onChanged: (String text) { | ||||
|                       _idController.id = text; | ||||
|                     }, | ||||
|                     style: const TextStyle( | ||||
|                       fontFamily: 'WorkSans', | ||||
|                       fontWeight: FontWeight.bold, | ||||
|                       fontSize: 30, | ||||
|                       color: MyTheme.idColor, | ||||
|                     ), | ||||
|                     decoration: InputDecoration( | ||||
|                       labelText: translate('Remote ID'), | ||||
|                       // hintText: 'Enter your remote ID', | ||||
|                       border: InputBorder.none, | ||||
|                       helperStyle: const TextStyle( | ||||
|                         fontWeight: FontWeight.bold, | ||||
|                         fontSize: 16, | ||||
|                         color: MyTheme.darkGray, | ||||
|                       ), | ||||
|                       labelStyle: const TextStyle( | ||||
|                         fontWeight: FontWeight.w600, | ||||
|                         fontSize: 16, | ||||
|                         letterSpacing: 0.2, | ||||
|                         color: MyTheme.darkGray, | ||||
|                       ), | ||||
|                     ), | ||||
|                     inputFormatters: [IDTextInputFormatter()], | ||||
|                      ); | ||||
|                       fieldTextEditingController.selection = TextSelection( | ||||
|                           baseOffset: 0, extentOffset: textLength); | ||||
|                       return AutoSizeTextField( | ||||
|                         controller: fieldTextEditingController, | ||||
|                         focusNode: fieldFocusNode, | ||||
|                         minFontSize: 18, | ||||
|                         autocorrect: false, | ||||
|                         enableSuggestions: false, | ||||
|                         keyboardType: TextInputType.visiblePassword, | ||||
|                         // keyboardType: TextInputType.number, | ||||
|                         onChanged: (String text) { | ||||
|                           _idController.id = text; | ||||
|                         }, | ||||
|                         style: const TextStyle( | ||||
|                           fontFamily: 'WorkSans', | ||||
|                           fontWeight: FontWeight.bold, | ||||
|                           fontSize: 30, | ||||
|                           color: MyTheme.idColor, | ||||
|                         ), | ||||
|                         decoration: InputDecoration( | ||||
|                           labelText: translate('Remote ID'), | ||||
|                           // hintText: 'Enter your remote ID', | ||||
|                           border: InputBorder.none, | ||||
|                           helperStyle: const TextStyle( | ||||
|                             fontWeight: FontWeight.bold, | ||||
|                             fontSize: 16, | ||||
|                             color: MyTheme.darkGray, | ||||
|                           ), | ||||
|                           labelStyle: const TextStyle( | ||||
|                             fontWeight: FontWeight.w600, | ||||
|                             fontSize: 16, | ||||
|                             letterSpacing: 0.2, | ||||
|                             color: MyTheme.darkGray, | ||||
|                           ), | ||||
|                         ), | ||||
|                         inputFormatters: [IDTextInputFormatter()], | ||||
|                       ); | ||||
|                     }, | ||||
|                     onSelected: (option) { | ||||
|                       setState(() { | ||||
| @ -253,32 +262,59 @@ class _ConnectionPageState extends State<ConnectionPage> { | ||||
|                         FocusScope.of(context).unfocus(); | ||||
|                       }); | ||||
|                     }, | ||||
|                     optionsViewBuilder: (BuildContext context, AutocompleteOnSelected<Peer> onSelected, Iterable<Peer> options) { | ||||
|                     optionsViewBuilder: (BuildContext context, | ||||
|                         AutocompleteOnSelected<Peer> onSelected, | ||||
|                         Iterable<Peer> options) { | ||||
|                       double maxHeight = options.length * 50; | ||||
|                       maxHeight = maxHeight > 200 ? 200 : maxHeight; | ||||
|                       if (options.length == 1) { | ||||
|                         maxHeight = 52; | ||||
|                       } else if (options.length == 3) { | ||||
|                         maxHeight = 146; | ||||
|                       } else if (options.length == 4) { | ||||
|                         maxHeight = 193; | ||||
|                       } | ||||
|                       maxHeight = maxHeight.clamp(0, 200); | ||||
|                       return Align( | ||||
|                         alignment: Alignment.topLeft, | ||||
|                         child: ClipRRect( | ||||
|                           borderRadius: BorderRadius.circular(5), | ||||
|                           child: Material( | ||||
|                           elevation: 4, | ||||
|                           child: ConstrainedBox( | ||||
|                             constraints: BoxConstraints( | ||||
|                               maxHeight: maxHeight, | ||||
|                               maxWidth: 320, | ||||
|                             ), | ||||
|                               child: peers.isEmpty && isPeersLoading | ||||
|                               ? Container( | ||||
|                                     height: 80, | ||||
|                                      child: Center(  | ||||
|                                       child: CircularProgressIndicator( | ||||
|                                         strokeWidth: 2, | ||||
|                                       ))) | ||||
|                               : ListView( | ||||
|                               padding: EdgeInsets.only(top: 5), | ||||
|                               children: options.map((peer) => AutocompletePeerTile(onSelect: () => onSelected(peer), peer: peer)).toList(), | ||||
|                             )))) | ||||
|                       ); | ||||
|                           alignment: Alignment.topLeft, | ||||
|                           child: Container( | ||||
|                               decoration: BoxDecoration( | ||||
|                                 boxShadow: [ | ||||
|                                   BoxShadow( | ||||
|                                     color: Colors.black.withOpacity(0.3), | ||||
|                                     blurRadius: 5, | ||||
|                                     spreadRadius: 1, | ||||
|                                   ), | ||||
|                                 ], | ||||
|                               ), | ||||
|                               child: ClipRRect( | ||||
|                                   borderRadius: BorderRadius.circular(5), | ||||
|                                   child: Material( | ||||
|                                       elevation: 4, | ||||
|                                       child: ConstrainedBox( | ||||
|                                           constraints: BoxConstraints( | ||||
|                                             maxHeight: maxHeight, | ||||
|                                             maxWidth: 320, | ||||
|                                           ), | ||||
|                                           child: peers.isEmpty && isPeersLoading | ||||
|                                               ? Container( | ||||
|                                                   height: 80, | ||||
|                                                   child: Center( | ||||
|                                                       child: | ||||
|                                                           CircularProgressIndicator( | ||||
|                                                     strokeWidth: 2, | ||||
|                                                   ))) | ||||
|                                               : ListView( | ||||
|                                                   padding: | ||||
|                                                       EdgeInsets.only(top: 5), | ||||
|                                                   children: options | ||||
|                                                       .map((peer) => | ||||
|                                                           AutocompletePeerTile( | ||||
|                                                               onSelect: () => | ||||
|                                                                   onSelected( | ||||
|                                                                       peer), | ||||
|                                                               peer: peer)) | ||||
|                                                       .toList(), | ||||
|                                                 )))))); | ||||
|                     }, | ||||
|                   ), | ||||
|                 ), | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user