@@ -8,13 +8,16 @@ import androidx.compose.foundation.background
88import androidx.compose.foundation.layout.Box
99import androidx.compose.foundation.layout.Row
1010import androidx.compose.foundation.layout.fillMaxSize
11+ import androidx.compose.foundation.layout.fillMaxWidth
1112import androidx.compose.foundation.layout.height
1213import androidx.compose.foundation.layout.padding
1314import androidx.compose.foundation.layout.width
1415import androidx.compose.foundation.lazy.LazyColumn
1516import androidx.compose.foundation.lazy.items
1617import androidx.compose.material.icons.Icons
18+ import androidx.compose.material.icons.filled.Close
1719import androidx.compose.material.icons.filled.MoreVert
20+ import androidx.compose.material.icons.filled.Search
1821import androidx.compose.material3.AlertDialog
1922import androidx.compose.material3.Checkbox
2023import androidx.compose.material3.CircularProgressIndicator
@@ -23,6 +26,7 @@ import androidx.compose.material3.Icon
2326import androidx.compose.material3.IconButton
2427import androidx.compose.material3.ListItem
2528import androidx.compose.material3.MaterialTheme
29+ import androidx.compose.material3.OutlinedTextField
2630import androidx.compose.material3.Scaffold
2731import androidx.compose.material3.Text
2832import androidx.compose.material3.TextButton
@@ -49,6 +53,8 @@ fun SplitTunnelAppPickerView(
4953 model : SplitTunnelAppPickerViewModel = viewModel(),
5054) {
5155 val installedApps by model.installedApps.collectAsState()
56+ val filteredApps by model.filteredApps.collectAsState()
57+ val searchQuery by model.searchQuery.collectAsState()
5258 val selectedPackageNames by model.selectedPackageNames.collectAsState()
5359 val allowSelected by model.allowSelected.collectAsState()
5460 val builtInDisallowedPackageNames: List <String > = App .get().builtInDisallowedPackageNames
@@ -118,6 +124,28 @@ fun SplitTunnelAppPickerView(
118124 selectedPackageNames.count(),
119125 ))
120126 }
127+ item(" searchBar" ) {
128+ OutlinedTextField (
129+ value = searchQuery,
130+ onValueChange = { model.updateSearchQuery(it) },
131+ placeholder = { Text (stringResource(R .string.search_ellipsis)) },
132+ leadingIcon = {
133+ Icon (Icons .Default .Search , contentDescription = null )
134+ },
135+ trailingIcon = {
136+ if (searchQuery.isNotEmpty()) {
137+ IconButton (onClick = { model.updateSearchQuery(" " ) }) {
138+ Icon (
139+ Icons .Default .Close ,
140+ contentDescription = stringResource(R .string.clear_search))
141+ }
142+ }
143+ },
144+ singleLine = true ,
145+ modifier =
146+ Modifier .fillMaxWidth().padding(horizontal = 16 .dp, vertical = 4 .dp),
147+ )
148+ }
121149 if (installedApps.isEmpty()) {
122150 item(" spinner" ) {
123151 Box (
@@ -132,7 +160,7 @@ fun SplitTunnelAppPickerView(
132160 }
133161 }
134162 } else {
135- items(installedApps , key = { it.packageName }) { app ->
163+ items(filteredApps , key = { it.packageName }) { app ->
136164 ListItem (
137165 headlineContent = { Text (app.name, fontWeight = FontWeight .SemiBold ) },
138166 leadingContent = {
0 commit comments