add autocomplete feat
Signed-off-by: Sahil Yeole <sahilyeole93@gmail.com>
This commit is contained in:
parent
ff20acc367
commit
f6b5c752f4
@ -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(),
|
||||||
|
))))
|
||||||
|
);
|
||||||
|
},
|
||||||
|
)
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user