add autocomplete feat

Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com>
This commit is contained in:
Sahil Yeole 2023-10-13 23:10:31 +05:30
parent ff20acc367
commit f6b5c752f4

View File

@ -11,6 +11,7 @@ import 'package:flutter_hbb/models/state_model.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:url_launcher/url_launcher_string.dart'; import 'package:url_launcher/url_launcher_string.dart';
import 'package:window_manager/window_manager.dart'; import 'package:window_manager/window_manager.dart';
import 'package:flutter_hbb/models/peer_model.dart';
import '../../common.dart'; import '../../common.dart';
import '../../common/formatter/id_formatter.dart'; import '../../common/formatter/id_formatter.dart';
@ -41,6 +42,7 @@ class _ConnectionPageState extends State<ConnectionPage>
var svcIsUsingPublicServer = true.obs; var svcIsUsingPublicServer = true.obs;
bool isWindowMinimized = false; bool isWindowMinimized = false;
List<Peer> peers = [];
@override @override
void initState() { void initState() {
@ -145,6 +147,7 @@ class _ConnectionPageState extends State<ConnectionPage>
/// UI for the remote ID TextField. /// UI for the remote ID TextField.
/// Search for a peer and connect to it if the id exists. /// Search for a peer and connect to it if the id exists.
Widget _buildRemoteIDTextField(BuildContext context) { Widget _buildRemoteIDTextField(BuildContext context) {
final TextEditingController fieldTextEditingController = TextEditingController.fromValue(_idController.value);
var w = Container( var w = Container(
width: 320 + 20 * 2, width: 320 + 20 * 2,
padding: const EdgeInsets.fromLTRB(20, 24, 20, 22), padding: const EdgeInsets.fromLTRB(20, 24, 20, 22),
@ -171,36 +174,139 @@ class _ConnectionPageState extends State<ConnectionPage>
Row( Row(
children: [ children: [
Expanded( Expanded(
child: Obx( child:
() => TextField( Autocomplete<Peer>(
maxLength: 90, optionsBuilder: (TextEditingValue textEditingValue) {
autocorrect: false, if (textEditingValue.text == '') {
enableSuggestions: false, return const Iterable<Peer>.empty();
keyboardType: TextInputType.visiblePassword, }
focusNode: _idFocusNode, else {
style: const TextStyle( peers.clear();
fontFamily: 'WorkSans', Map<String, dynamic> recentPeers = jsonDecode(bind.mainLoadRecentPeersSync());
fontSize: 22, Map<String, dynamic> favPeers = jsonDecode(bind.mainLoadFavPeersSync());
height: 1.4, Map<String, dynamic> lanPeers = jsonDecode(bind.mainLoadLanPeersSync());
), Map<String, dynamic> abPeers = jsonDecode(bind.mainLoadAbSync());
maxLines: 1, Map<String, dynamic> groupPeers = jsonDecode(bind.mainLoadGroupSync());
cursorColor:
Theme.of(context).textTheme.titleLarge?.color, Map<String, dynamic> combinedPeers = {};
decoration: InputDecoration(
filled: false, void mergePeers(Map<String, dynamic> peers) {
counterText: '', if (peers.containsKey("peers")) {
hintText: _idInputFocused.value dynamic peerData = peers["peers"];
? null
: translate('Enter Remote ID'), if (peerData is String) {
contentPadding: const EdgeInsets.symmetric( try {
horizontal: 15, vertical: 13)), peerData = jsonDecode(peerData);
controller: _idController, } catch (e) {
inputFormatters: [IDTextInputFormatter()], print("Error decoding peers: $e");
onSubmitted: (s) { return;
onConnect(); }
}, }
),
), if (peerData is List) {
for (var peer in peerData) {
if (peer is Map && peer.containsKey("id")) {
String id = peer["id"];
if (id != null && !combinedPeers.containsKey(id)) {
combinedPeers[id] = peer;
}
}
}
}
}
}
mergePeers(recentPeers);
mergePeers(favPeers);
mergePeers(lanPeers);
mergePeers(abPeers);
mergePeers(groupPeers);
for (var peer in combinedPeers.values) {
peers.add(Peer.fromJson(peer));
}
return peers.where((peer) =>
peer.id.toLowerCase().contains(textEditingValue.text.toLowerCase()) ||
peer.username.toLowerCase().contains(textEditingValue.text.toLowerCase()) ||
peer.hostname.toLowerCase().contains(textEditingValue.text.toLowerCase()) ||
peer.platform.toLowerCase().contains(textEditingValue.text.toLowerCase()))
.toList();
}
},
fieldViewBuilder: (BuildContext context,
TextEditingController fieldTextEditingController,
FocusNode fieldFocusNode ,
VoidCallback onFieldSubmitted,
) {
return Obx(() =>
TextField(
maxLength: 90,
autocorrect: false,
enableSuggestions: false,
keyboardType: TextInputType.visiblePassword,
// focusNode: _idFocusNode,
focusNode: fieldFocusNode,
style: const TextStyle(
fontFamily: 'WorkSans',
fontSize: 22,
height: 1.4,
),
maxLines: 1,
cursorColor: Theme.of(context).textTheme.titleLarge?.color,
decoration: InputDecoration(
filled: false,
counterText: '',
hintText: _idInputFocused.value
? null
: translate('Enter Remote ID'),
contentPadding: const EdgeInsets.symmetric(
horizontal: 15, vertical: 13)),
// controller: _idController,
controller: fieldTextEditingController,
inputFormatters: [IDTextInputFormatter()],
onSubmitted: (s) {
onConnect();
},
));
},
optionsViewBuilder: (BuildContext context, AutocompleteOnSelected<Peer> onSelected, Iterable<Peer> options) {
return Align(
alignment: Alignment.topLeft,
child: Material(
elevation: 4.0,
child: ConstrainedBox(
constraints: BoxConstraints(
maxHeight: 200.0,
),
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: options.map((peer) {
return ListTile(
// title: Text(peer.id),
title: Text(peer.id.length <= 6 ? peer.id : peer.id.substring(0, 6)),
subtitle: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(peer.username),
Text(peer.hostname),
Text(peer.platform),
for (var tag in peer.tags)
Text(tag),
],
),
onTap: () {
onSelected(peer);
},
);
}).toList(),
))))
);
},
)
), ),
], ],
), ),