@@ -22,6 +22,13 @@ class PackageList extends ConsumerStatefulWidget {
22
22
23
23
class _PackageListState extends ConsumerState <PackageList > {
24
24
bool _dragging = false ;
25
+ TextEditingController filterController = TextEditingController ();
26
+
27
+ @override
28
+ void dispose () {
29
+ super .dispose ();
30
+ filterController.dispose ();
31
+ }
25
32
26
33
@override
27
34
Widget build (BuildContext context) {
@@ -33,13 +40,32 @@ class _PackageListState extends ConsumerState<PackageList> {
33
40
automaticallyImplyLeading: true ,
34
41
actions: [
35
42
IconButton (
36
- onPressed: () async {
37
- final file = await openFile ();
38
- if (file == null ) return ;
43
+ onPressed: () async {
44
+ final file = await openFile ();
45
+ if (file == null ) return ;
39
46
40
- await uploadAndInstallAPK (file.path);
41
- },
42
- icon: const Icon (FluentIcons .arrow_upload_32_regular))
47
+ await uploadAndInstallAPK (file.path);
48
+ },
49
+ icon: const Icon (
50
+ FluentIcons .arrow_upload_32_regular,
51
+ ),
52
+ ),
53
+ Padding (
54
+ padding: const EdgeInsets .symmetric (horizontal: 8.0 ),
55
+ child: ConstrainedBox (
56
+ constraints: const BoxConstraints .tightFor (width: 200 ),
57
+ child: TextField (
58
+ autocorrect: false ,
59
+ enableSuggestions: false ,
60
+ decoration: const InputDecoration (hintText: "Search" ),
61
+ controller: filterController,
62
+ onChanged: (s) => setState (() {}),
63
+ ),
64
+ ),
65
+ ),
66
+ const SizedBox (
67
+ width: 25 ,
68
+ ),
43
69
],
44
70
),
45
71
body: ADBQueueIndicator (
@@ -63,12 +89,26 @@ class _PackageListState extends ConsumerState<PackageList> {
63
89
});
64
90
},
65
91
child: packageListFuture.when (
66
- data: (packageList) => ListView .separated (
67
- itemBuilder: (c, i) => itemBuilder (c, i, packageList),
68
- itemCount: packageList.length,
69
- shrinkWrap: true ,
70
- separatorBuilder: (context, index) => const Divider (),
71
- ),
92
+ data: (packageList) {
93
+ final filteredList = packageList
94
+ .where ((x) => x
95
+ .toLowerCase ()
96
+ .contains (filterController.text.toLowerCase ()))
97
+ .toList ();
98
+
99
+ return ListView .separated (
100
+ itemBuilder: (c, i) => itemBuilder (c, i, filteredList),
101
+ itemCount: filteredList.length,
102
+ shrinkWrap: true ,
103
+ separatorBuilder: (context, index) => const Divider (),
104
+ addAutomaticKeepAlives: true ,
105
+ findChildIndexCallback: (Key key) {
106
+ var index =
107
+ filteredList.indexOf ((key as ValueKey <String >).value);
108
+ if (index == - 1 ) return null ;
109
+ return index;
110
+ });
111
+ },
72
112
error: (error, stackTrace) {
73
113
debugPrint (error.toString ());
74
114
debugPrint (stackTrace.toString ());
@@ -94,6 +134,7 @@ class _PackageListState extends ConsumerState<PackageList> {
94
134
95
135
return packageMetadataFuture.when (
96
136
data: (packageMetadata) => ListTile (
137
+ key: ValueKey (packageId),
97
138
title: Text (packageMetadata.packageName),
98
139
subtitle:
99
140
Text ("${packageMetadata .packageId } - ${packageMetadata .version }" ),
@@ -117,10 +158,12 @@ class _PackageListState extends ConsumerState<PackageList> {
117
158
),
118
159
),
119
160
error: (error, stackTrace) => ListTile (
161
+ key: ValueKey (packageId),
120
162
title: Text (packageId),
121
163
subtitle: Text ("Suffered error: $error " ),
122
164
),
123
165
loading: () => ListTile (
166
+ key: ValueKey (packageId),
124
167
title: Text (packageId),
125
168
leading: const CircularProgressIndicator (),
126
169
),
0 commit comments