@@ -8,6 +8,10 @@ import androidx.activity.enableEdgeToEdge
8
8
import androidx.annotation.DrawableRes
9
9
import androidx.annotation.StringRes
10
10
import androidx.appcompat.app.AppCompatActivity
11
+ import androidx.compose.animation.AnimatedVisibility
12
+ import androidx.compose.animation.core.tween
13
+ import androidx.compose.animation.fadeIn
14
+ import androidx.compose.animation.fadeOut
11
15
import androidx.compose.foundation.background
12
16
import androidx.compose.foundation.layout.Box
13
17
import androidx.compose.foundation.layout.padding
@@ -19,7 +23,6 @@ import androidx.compose.runtime.Composable
19
23
import androidx.compose.runtime.mutableStateOf
20
24
import androidx.compose.runtime.remember
21
25
import androidx.compose.ui.Modifier
22
- import androidx.compose.ui.graphics.Color
23
26
import androidx.compose.ui.text.TextRange
24
27
import androidx.compose.ui.text.input.TextFieldValue
25
28
import androidx.navigation.compose.NavHost
@@ -34,6 +37,7 @@ import com.inspiredandroid.linuxcommandbibliotheca.ui.screens.basiccategories.Ba
34
37
import com.inspiredandroid.linuxcommandbibliotheca.ui.screens.basicgroups.BasicGroupsScreen
35
38
import com.inspiredandroid.linuxcommandbibliotheca.ui.screens.commanddetail.CommandDetailScreen
36
39
import com.inspiredandroid.linuxcommandbibliotheca.ui.screens.commandlist.CommandListScreen
40
+ import com.inspiredandroid.linuxcommandbibliotheca.ui.screens.search.SearchScreen
37
41
import com.inspiredandroid.linuxcommandbibliotheca.ui.screens.tips.TipsScreen
38
42
import com.inspiredandroid.linuxcommandbibliotheca.ui.theme.LinuxTheme
39
43
import com.inspiredandroid.linuxcommandbibliotheca.ui.theme.LocalCustomColors
@@ -64,9 +68,9 @@ class MainActivity : AppCompatActivity() {
64
68
enableEdgeToEdge(statusBarStyle = SystemBarStyle .dark(android.graphics.Color .TRANSPARENT ))
65
69
super .onCreate(savedInstanceState)
66
70
67
- if (! hasDatabase(this ) || ! preferenceManager.isDatabaseUpToDate(this )) {
71
+ if (! hasDatabase(this ) || ! preferenceManager.isDatabaseUpToDate()) {
68
72
startActivity(Intent (this , InitializeDatabaseActivity ::class .java))
69
- preferenceManager.updateDatabaseVersion(this )
73
+ preferenceManager.updateDatabaseVersion()
70
74
finish()
71
75
return
72
76
}
@@ -104,6 +108,7 @@ fun LinuxApp() {
104
108
TextFieldValue (text = " " , selection = TextRange (0 )),
105
109
)
106
110
}
111
+ val showSearch = remember { mutableStateOf(false ) }
107
112
val onNavigate: (String ) -> Unit = {
108
113
navController.navigate(it)
109
114
}
@@ -116,93 +121,123 @@ fun LinuxApp() {
116
121
onNavigateBack = {
117
122
navController.popBackStack()
118
123
},
124
+ showSearch = showSearch,
119
125
)
120
126
},
121
127
bottomBar = {
122
- BottomBar (navController)
128
+ BottomBar (
129
+ navController = navController,
130
+ resetSearch = {
131
+ searchTextValue.value = TextFieldValue (text = " " , selection = TextRange (0 ))
132
+ showSearch.value = false
133
+ },
134
+ )
123
135
},
124
136
) { innerPadding ->
125
-
126
- NavHost (
127
- navController = navController,
128
- startDestination = Screen .Basics .route,
137
+ Box (
129
138
modifier = Modifier .padding(innerPadding),
130
139
) {
131
- composable(
132
- Screen .Basics .route,
133
- deepLinks = listOf (
134
- navDeepLink { uriPattern = " $DEEPLINK_URI /basics" },
135
- navDeepLink { uriPattern = " $DEEPLINK_URI /basics.html" },
136
- ),
137
- ) {
138
- BasicCategoriesScreen (onNavigate)
139
- }
140
- composable(
141
- Screen .Commands .route,
142
- deepLinks = listOf (
143
- navDeepLink { uriPattern = " $DEEPLINK_URI /" },
144
- navDeepLink { uriPattern = " $DEEPLINK_URI /index.html" },
145
- ),
140
+ NavHost (
141
+ navController = navController,
142
+ startDestination = Screen .Basics .route,
146
143
) {
147
- CommandListScreen (
148
- searchText = searchTextValue.value.text,
149
- onNavigate = onNavigate,
150
- )
151
- }
152
- composable(
153
- Screen .Tips .route,
154
- deepLinks = listOf (
155
- navDeepLink { uriPattern = " $DEEPLINK_URI /tips" },
156
- navDeepLink { uriPattern = " $DEEPLINK_URI /tips.html" },
157
- ),
158
- ) {
159
- TipsScreen (onNavigate)
160
- }
161
- composable(
162
- " basicgroups?categoryId={categoryId}&categoryName={categoryName}" ,
163
- arguments = listOf (
164
- navArgument(" categoryId" ) { defaultValue = " " },
165
- navArgument(" categoryName" ) {},
166
- ),
167
- deepLinks = listOf (
168
- navDeepLink {
169
- uriPattern = " $DEEPLINK_URI /basic/{categoryName}.html"
170
- },
171
- navDeepLink { uriPattern = " $DEEPLINK_URI /basic/{categoryName}" },
172
- ),
173
- ) { backStackEntry ->
174
- val categoryId = backStackEntry.getCategoryId()
175
- if (categoryId != null ) {
176
- BasicGroupsScreen (
177
- categoryId = categoryId,
144
+ composable(
145
+ Screen .Basics .route,
146
+ deepLinks = listOf (
147
+ navDeepLink { uriPattern = " $DEEPLINK_URI /basics" },
148
+ navDeepLink { uriPattern = " $DEEPLINK_URI /basics.html" },
149
+ ),
150
+ ) {
151
+ BasicCategoriesScreen (
178
152
onNavigate = onNavigate,
179
153
)
180
- } else {
181
- // open tips screen on invalid deeplink parameters
182
- TipsScreen (onNavigate)
183
154
}
184
- }
185
- composable(
186
- " command?commandId={commandId}&commandName={commandName}" ,
187
- arguments = listOf (
188
- navArgument(" commandId" ) { defaultValue = " " },
189
- navArgument(" commandName" ) {},
190
- ),
191
- deepLinks = listOf (
192
- navDeepLink { uriPattern = " $DEEPLINK_URI /man/{commandName}.html" },
193
- navDeepLink { uriPattern = " $DEEPLINK_URI /man/{commandName}" },
194
- ),
195
- ) { backStackEntry ->
196
- val commandId = backStackEntry.getCommandId()
197
- if (commandId != null ) {
198
- CommandDetailScreen (
199
- commandId = commandId,
155
+ composable(
156
+ Screen .Commands .route,
157
+ deepLinks = listOf (
158
+ navDeepLink { uriPattern = " $DEEPLINK_URI /" },
159
+ navDeepLink { uriPattern = " $DEEPLINK_URI /index.html" },
160
+ ),
161
+ ) {
162
+ CommandListScreen (
200
163
onNavigate = onNavigate,
201
164
)
202
- } else {
203
- // open tips screen on invalid deeplink parameters
165
+ }
166
+ composable(
167
+ Screen .Tips .route,
168
+ deepLinks = listOf (
169
+ navDeepLink { uriPattern = " $DEEPLINK_URI /tips" },
170
+ navDeepLink { uriPattern = " $DEEPLINK_URI /tips.html" },
171
+ ),
172
+ ) {
204
173
TipsScreen (onNavigate)
205
174
}
175
+ composable(
176
+ " basicgroups?categoryId={categoryId}&categoryName={categoryName}" ,
177
+ arguments = listOf (
178
+ navArgument(" categoryId" ) { defaultValue = " " },
179
+ navArgument(" categoryName" ) {},
180
+ ),
181
+ deepLinks = listOf (
182
+ navDeepLink {
183
+ uriPattern = " $DEEPLINK_URI /basic/{categoryName}.html"
184
+ },
185
+ navDeepLink { uriPattern = " $DEEPLINK_URI /basic/{categoryName}" },
186
+ ),
187
+ ) { backStackEntry ->
188
+ val categoryId = backStackEntry.getCategoryId()
189
+ if (categoryId != null ) {
190
+ BasicGroupsScreen (
191
+ categoryId = categoryId,
192
+ onNavigate = onNavigate,
193
+ )
194
+ } else {
195
+ // open tips screen on invalid deeplink parameters
196
+ TipsScreen (onNavigate)
197
+ }
198
+ }
199
+ composable(
200
+ " command?commandId={commandId}&commandName={commandName}" ,
201
+ arguments = listOf (
202
+ navArgument(" commandId" ) { defaultValue = " " },
203
+ navArgument(" commandName" ) {},
204
+ ),
205
+ deepLinks = listOf (
206
+ navDeepLink { uriPattern = " $DEEPLINK_URI /man/{commandName}.html" },
207
+ navDeepLink { uriPattern = " $DEEPLINK_URI /man/{commandName}" },
208
+ ),
209
+ ) { backStackEntry ->
210
+ val commandId = backStackEntry.getCommandId()
211
+ if (commandId != null ) {
212
+ CommandDetailScreen (
213
+ commandId = commandId,
214
+ onNavigate = onNavigate,
215
+ )
216
+ } else {
217
+ // open tips screen on invalid deeplink parameters
218
+ TipsScreen (onNavigate)
219
+ }
220
+ }
221
+ }
222
+
223
+ val isSearchVisible = remember(
224
+ searchTextValue.value.text,
225
+ navBackStackEntry.value?.destination?.route,
226
+ ) {
227
+ searchTextValue.value.text.isNotEmpty() &&
228
+ navBackStackEntry.value?.destination?.route?.startsWith(" command?" ) == false
229
+ }
230
+ AnimatedVisibility (
231
+ visible = isSearchVisible,
232
+ enter = fadeIn(animationSpec = tween(300 )),
233
+ exit = fadeOut(animationSpec = tween(durationMillis = 300 , delayMillis = 300 )), // work around for navigation overlaps
234
+ ) {
235
+ SearchScreen (
236
+ searchText = searchTextValue.value.text,
237
+ onNavigate = {
238
+ navController.navigate(it)
239
+ },
240
+ )
206
241
}
207
242
}
208
243
}
0 commit comments