Skip to content

Commit 857e588

Browse files
committed
bugfix: search screen v3
1 parent 20c84f7 commit 857e588

10 files changed

Lines changed: 123 additions & 106 deletions

File tree

app/src/main/kotlin/com/androidvip/sysctlgui/ui/main/AppNavHost.kt

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
package com.androidvip.sysctlgui.ui.main
22

3+
import androidx.compose.animation.fadeIn
4+
import androidx.compose.animation.fadeOut
5+
import androidx.compose.animation.scaleIn
6+
import androidx.compose.animation.scaleOut
37
import androidx.compose.foundation.layout.PaddingValues
48
import androidx.compose.foundation.layout.padding
59
import androidx.compose.runtime.Composable
@@ -9,21 +13,25 @@ import androidx.navigation.NavHostController
913
import androidx.navigation.compose.NavHost
1014
import androidx.navigation.compose.composable
1115
import com.androidvip.sysctlgui.core.navigation.UiRoute
12-
import com.androidvip.sysctlgui.ui.user.UserParamsScreen
1316
import com.androidvip.sysctlgui.ui.params.browse.ParamBrowseScreen
1417
import com.androidvip.sysctlgui.ui.params.browse.ParamBrowseScreenContentPreview
1518
import com.androidvip.sysctlgui.ui.params.edit.EditParamScreen
1619
import com.androidvip.sysctlgui.ui.presets.ImportPresetScreen
1720
import com.androidvip.sysctlgui.ui.presets.PresetsScreen
1821
import com.androidvip.sysctlgui.ui.search.SearchScreen
1922
import com.androidvip.sysctlgui.ui.settings.SettingsScreen
23+
import com.androidvip.sysctlgui.ui.user.UserParamsScreen
2024

2125
@Composable
2226
internal fun AppNavHost(innerPadding: PaddingValues, navController: NavHostController) {
2327
NavHost(
2428
modifier = Modifier.padding(innerPadding),
2529
navController = navController,
26-
startDestination = UiRoute.BrowseParams
30+
startDestination = UiRoute.BrowseParams,
31+
enterTransition = { scaleIn(initialScale = 0.9f) + fadeIn() },
32+
exitTransition = { scaleOut(targetScale = 0.9f) + fadeOut() },
33+
popEnterTransition = { scaleIn(initialScale = 1.1f) + fadeIn() },
34+
popExitTransition = { scaleOut(targetScale = 1.1f) + fadeOut() }
2735
) {
2836
composable<UiRoute.BrowseParams> {
2937
if (LocalView.current.isInEditMode) {
@@ -63,10 +71,10 @@ internal fun AppNavHost(innerPadding: PaddingValues, navController: NavHostContr
6371

6472
composable<UiRoute.Search> {
6573
SearchScreen(
74+
outerScaffoldPadding = innerPadding,
6675
onParamSelected = {
6776
navController.navigate(UiRoute.EditParam(paramName = it.name))
68-
},
69-
onNavigateBack = { navController.popBackStack() }
77+
}
7078
)
7179
}
7280

app/src/main/kotlin/com/androidvip/sysctlgui/ui/search/SearchScreen.kt

Lines changed: 69 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
package com.androidvip.sysctlgui.ui.search
22

3+
import androidx.compose.animation.AnimatedContent
34
import androidx.compose.animation.AnimatedVisibility
45
import androidx.compose.animation.core.animateDpAsState
56
import androidx.compose.animation.core.tween
67
import androidx.compose.animation.expandHorizontally
7-
import androidx.compose.animation.expandVertically
88
import androidx.compose.animation.fadeIn
99
import androidx.compose.animation.fadeOut
1010
import androidx.compose.animation.shrinkHorizontally
11-
import androidx.compose.animation.shrinkVertically
1211
import androidx.compose.foundation.clickable
1312
import androidx.compose.foundation.layout.Box
13+
import androidx.compose.foundation.layout.PaddingValues
1414
import androidx.compose.foundation.layout.fillMaxSize
1515
import androidx.compose.foundation.layout.fillMaxWidth
1616
import androidx.compose.foundation.layout.offset
@@ -63,8 +63,8 @@ import org.koin.compose.viewmodel.koinViewModel
6363
fun SearchScreen(
6464
viewModel: SearchViewModel = koinViewModel(),
6565
mainViewModel: MainViewModel = koinViewModel(),
66-
onParamSelected: (UiKernelParam) -> Unit,
67-
onNavigateBack: () -> Unit
66+
outerScaffoldPadding: PaddingValues,
67+
onParamSelected: (UiKernelParam) -> Unit
6868
) {
6969
val state by viewModel.uiState.collectAsStateWithLifecycle()
7070
var searchQuery by remember { mutableStateOf("") }
@@ -81,29 +81,30 @@ fun SearchScreen(
8181
)
8282
}
8383

84-
LaunchedEffect(viewModel.effect) {
84+
LaunchedEffect(Unit) {
8585
viewModel.effect.collect { effect ->
8686
when (effect) {
8787
is SearchViewEffect.EditKernelParam -> onParamSelected(effect.param)
88-
SearchViewEffect.NavigateBack -> onNavigateBack()
8988
}
9089
}
9190
}
9291

9392
SearchScreenContent(
93+
outerScaffoldPadding = outerScaffoldPadding,
9494
searchQuery = searchQuery,
9595
onSearchQueryChange = {
9696
searchQuery = it
9797
viewModel.onEvent(SearchViewEvent.SearchQueryChange(it))
9898
},
9999
searchActive = searchActive,
100100
onSearchActiveChange = { searchActive = it },
101-
searchHints = state.searchHints,
102-
searchResults = state.searchResults,
103-
onNavigateBack = { viewModel.onEvent(SearchViewEvent.BackClicked) },
101+
state = state,
104102
onHistoryItemRemoveClicked = {
105103
viewModel.onEvent(SearchViewEvent.HistoryItemRemoveClicked(it))
106104
},
105+
onParamClicked = {
106+
viewModel.onEvent(SearchViewEvent.ParamClicked(it))
107+
},
107108
onSearch = { query ->
108109
searchActive = false
109110
viewModel.onEvent(SearchViewEvent.SearchRequested(query))
@@ -114,17 +115,18 @@ fun SearchScreen(
114115
@OptIn(ExperimentalMaterial3Api::class)
115116
@Composable
116117
private fun SearchScreenContent(
118+
state: SearchViewState,
119+
outerScaffoldPadding: PaddingValues = PaddingValues(),
117120
searchQuery: String,
118121
onSearchQueryChange: (String) -> Unit,
119122
searchActive: Boolean,
120123
onSearchActiveChange: (Boolean) -> Unit,
121-
searchHints: List<SearchHint>,
122-
searchResults: List<UiKernelParam>,
123124
onHistoryItemRemoveClicked: (SearchHint) -> Unit,
124-
onNavigateBack: () -> Unit,
125-
onSearch: (String) -> Unit
125+
onParamClicked: (UiKernelParam) -> Unit,
126+
onSearch: (String) -> Unit,
126127
) {
127128
val focusManager = LocalFocusManager.current
129+
val navHostTopPadding = outerScaffoldPadding.calculateTopPadding()
128130
val searchBarHorizontalPadding by animateDpAsState(
129131
targetValue = if (searchActive) 0.dp else 16.dp,
130132
label = "SearchBarHorizontalPadding",
@@ -137,6 +139,9 @@ private fun SearchScreenContent(
137139
)
138140

139141
Scaffold(
142+
modifier = Modifier
143+
.fillMaxSize()
144+
.offset(y = -navHostTopPadding),
140145
topBar = {
141146
val onActiveChange: (Boolean) -> Unit = { isActive ->
142147
if (searchActive != isActive) {
@@ -157,42 +162,25 @@ private fun SearchScreenContent(
157162
onExpandedChange = onActiveChange,
158163
placeholder = { Text("Search kernel parameters") },
159164
leadingIcon = {
160-
AnimatedVisibility(
161-
visible = searchActive,
162-
enter = expandVertically() + fadeIn(),
163-
exit = shrinkVertically() + fadeOut()
164-
) {
165-
IconButton(onClick = {
166-
focusManager.clearFocus()
167-
onSearchActiveChange(false)
168-
onSearchQueryChange("")
169-
if (searchQuery.isEmpty()) {
170-
onNavigateBack()
165+
AnimatedContent(
166+
targetState = searchActive,
167+
label = "SearchIconsAnimation"
168+
) { targetSearchActive ->
169+
if (targetSearchActive) {
170+
IconButton(onClick = {
171+
focusManager.clearFocus()
172+
onSearchActiveChange(false)
173+
onSearchQueryChange("")
174+
}) {
175+
Icon(
176+
Icons.AutoMirrored.Rounded.ArrowBack,
177+
contentDescription = "Back"
178+
)
171179
}
172-
}) {
173-
Icon(
174-
Icons.AutoMirrored.Rounded.ArrowBack,
175-
contentDescription = "Back"
176-
)
180+
} else {
181+
Icon(Icons.Rounded.Search, contentDescription = "Search Icon")
177182
}
178183
}
179-
180-
181-
AnimatedVisibility(
182-
visible = !searchActive,
183-
enter = expandVertically(
184-
animationSpec = tween(delayMillis = 200)
185-
) + fadeIn(
186-
animationSpec = tween(delayMillis = 200)
187-
),
188-
exit = shrinkVertically(
189-
animationSpec = tween(durationMillis = 0)
190-
) + fadeOut(
191-
animationSpec = tween(durationMillis = 0)
192-
)
193-
) {
194-
Icon(Icons.Rounded.Search, contentDescription = "Search Icon")
195-
}
196184
},
197185
trailingIcon = {
198186
AnimatedVisibility(
@@ -223,7 +211,7 @@ private fun SearchScreenContent(
223211
windowInsets = SearchBarDefaults.windowInsets,
224212
) {
225213
SearchViewContent(
226-
searchHints = searchHints,
214+
searchHints = state.searchHints,
227215
onHistoryItemRemoveClicked = onHistoryItemRemoveClicked,
228216
onSearchQueryChange = onSearchQueryChange,
229217
onSearch = onSearch,
@@ -233,12 +221,23 @@ private fun SearchScreenContent(
233221
}
234222
}
235223
) { innerPadding ->
236-
Box(modifier = Modifier.padding(innerPadding)) {
237-
if (!searchActive) {
238-
SearchResultsContent(searchResults, searchQuery)
224+
AnimatedContent(
225+
targetState = state.loading,
226+
modifier = Modifier
227+
.fillMaxSize()
228+
.padding(innerPadding)
229+
) {
230+
if (it) {
231+
Box(modifier = Modifier.fillMaxSize()) {
232+
CircularProgressIndicator(modifier = Modifier.align(Alignment.Center))
233+
}
234+
} else {
235+
SearchResultsContent(
236+
searchResults = state.searchResults,
237+
searchQuery = searchQuery,
238+
onParamClicked = onParamClicked
239+
)
239240
}
240-
241-
CircularProgressIndicator(modifier = Modifier.align(Alignment.Center))
242241
}
243242
}
244243
}
@@ -268,12 +267,12 @@ private fun SearchViewContent(
268267
.padding(horizontal = 16.dp, vertical = 12.dp)
269268
)
270269
}
271-
items(historyHints, key = { it.hint }) { hintItem ->
270+
items(historyHints, key = { "history:${it.hint}" }) { historyItem ->
272271
ListItem(
273272
colors = ListItemDefaults.colors(
274273
containerColor = MaterialTheme.colorScheme.surfaceContainerHigh
275274
),
276-
headlineContent = { Text(hintItem.hint) },
275+
headlineContent = { Text(historyItem.hint) },
277276
leadingContent = {
278277
Icon(
279278
painter = painterResource(R.drawable.ic_history),
@@ -282,7 +281,7 @@ private fun SearchViewContent(
282281
},
283282
trailingContent = {
284283
IconButton(
285-
onClick = { onHistoryItemRemoveClicked(hintItem) },
284+
onClick = { onHistoryItemRemoveClicked(historyItem) },
286285
modifier = Modifier.offset(16.dp)
287286
) {
288287
Icon(
@@ -293,8 +292,8 @@ private fun SearchViewContent(
293292
},
294293
modifier = Modifier
295294
.clickable {
296-
onSearchQueryChange(hintItem.hint)
297-
onSearch(hintItem.hint)
295+
onSearchQueryChange(historyItem.hint)
296+
onSearch(historyItem.hint)
298297
onSearchActiveChange(false)
299298
}
300299
.animateItem()
@@ -317,7 +316,7 @@ private fun SearchViewContent(
317316
modifier = Modifier.padding(horizontal = 16.dp, vertical = 12.dp)
318317
)
319318
}
320-
items(suggestionHints, key = { it.hint }) { hintItem ->
319+
items(suggestionHints, key = { "hint:${it.hint}" }) { hintItem ->
321320
ListItem(
322321
colors = ListItemDefaults.colors(
323322
containerColor = MaterialTheme.colorScheme.surfaceContainerHigh
@@ -351,7 +350,11 @@ private fun SearchViewContent(
351350
}
352351

353352
@Composable
354-
private fun SearchResultsContent(searchResults: List<UiKernelParam>, searchQuery: String) {
353+
private fun SearchResultsContent(
354+
searchResults: List<UiKernelParam>,
355+
searchQuery: String,
356+
onParamClicked: (UiKernelParam) -> Unit
357+
) {
355358
if (searchResults.isNotEmpty()) {
356359
LazyColumn(
357360
modifier = Modifier
@@ -363,7 +366,7 @@ private fun SearchResultsContent(searchResults: List<UiKernelParam>, searchQuery
363366
modifier = Modifier.animateItem(),
364367
param = param,
365368
showFullName = true,
366-
onParamClicked = {}
369+
onParamClicked = onParamClicked
367370
)
368371

369372
if (index < searchResults.lastIndex) {
@@ -448,15 +451,17 @@ private fun SearchScreenPreview() {
448451
onSearchQueryChange = { searchQuery = it },
449452
searchActive = searchActive,
450453
onSearchActiveChange = { searchActive = it },
451-
searchHints = searchHints,
452-
searchResults = searchResults,
453-
onNavigateBack = {},
454+
state = SearchViewState(
455+
searchHints = searchHints,
456+
searchResults = searchResults
457+
),
454458
onHistoryItemRemoveClicked = { searchHints = searchHints - it },
459+
onParamClicked = {},
455460
onSearch = {
456461
searchResults = searchResults.filter {
457462
it.name.contains(searchQuery, ignoreCase = true)
458463
}
459-
}
464+
},
460465
)
461466
}
462467
}

0 commit comments

Comments
 (0)