Skip to content

Commit 5c2bd11

Browse files
Copilotluantak
andauthored
Fix app drawer search lifecycle, touch interception, launch-close sequencing, and label hierarchy (#17)
Co-authored-by: Paul Scheduikat <lu4p@pm.me>
1 parent 98d1353 commit 5c2bd11

File tree

5 files changed

+35
-13
lines changed

5 files changed

+35
-13
lines changed

app/src/main/java/com/lu4p/fokuslauncher/ui/components/CategoryChips.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import androidx.compose.ui.input.pointer.pointerInput
1818
import androidx.compose.ui.unit.dp
1919
import com.lu4p.fokuslauncher.ui.theme.ChipBackground
2020
import com.lu4p.fokuslauncher.ui.theme.ChipSelectedBackground
21+
import java.util.Locale
2122

2223
/**
2324
* Horizontal scrollable row of category filter chips.

app/src/main/java/com/lu4p/fokuslauncher/ui/drawer/AppDrawerScreen.kt

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ import androidx.lifecycle.compose.LocalLifecycleOwner
5353
import com.lu4p.fokuslauncher.data.model.AppInfo
5454
import com.lu4p.fokuslauncher.ui.components.CategoryChips
5555
import com.lu4p.fokuslauncher.ui.components.SearchBar
56+
import java.util.Locale
5657
import kotlinx.coroutines.delay
5758

5859
@Composable
@@ -83,6 +84,7 @@ fun AppDrawerScreen(
8384

8485
// Close the drawer after an app is auto-launched from search
8586
LaunchedEffect(Unit) {
87+
viewModel.resetSearchState()
8688
viewModel.refresh()
8789
viewModel.events.collect { event ->
8890
when (event) {
@@ -99,8 +101,9 @@ fun AppDrawerScreen(
99101
onCategorySelected = viewModel::onCategorySelected,
100102
onCategoryLongPress = viewModel::onCategoryLongPress,
101103
onAppClick = { target ->
102-
viewModel.launchTarget(target)
103-
closeAndReset()
104+
if (viewModel.launchTarget(target)) {
105+
closeAndReset()
106+
}
104107
},
105108
onAppLongPress = viewModel::onAppLongPress,
106109
onMenuToggle = viewModel::toggleMenu,
@@ -275,8 +278,8 @@ fun AppDrawerContent(
275278
if (uiState.filteredApps.isNotEmpty()) {
276279
item {
277280
Text(
278-
text = uiState.selectedCategory,
279-
style = MaterialTheme.typography.titleMedium,
281+
text = uiState.selectedCategory.uppercase(Locale.getDefault()),
282+
style = MaterialTheme.typography.labelLarge,
280283
color = MaterialTheme.colorScheme.primary,
281284
modifier = Modifier.padding(horizontal = 24.dp, vertical = 12.dp)
282285
)
@@ -303,8 +306,8 @@ fun AppDrawerContent(
303306
}
304307
item {
305308
Text(
306-
text = "Private Space",
307-
style = MaterialTheme.typography.titleMedium,
309+
text = "Private Space".uppercase(Locale.getDefault()),
310+
style = MaterialTheme.typography.labelLarge,
308311
color = MaterialTheme.colorScheme.primary,
309312
modifier = Modifier.padding(horizontal = 24.dp, vertical = 12.dp)
310313
)

app/src/main/java/com/lu4p/fokuslauncher/ui/drawer/AppDrawerViewModel.kt

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -219,9 +219,10 @@ constructor(
219219
)
220220
if (!browseMode && trimmed.isNotBlank() && allMatches.size == 1) {
221221
val target = allMatches[0]
222-
viewModelScope.launch { _events.emit(DrawerEvent.AutoLaunch(target)) }
223-
launchTarget(target)
224-
resetSearchState()
222+
if (launchTarget(target)) {
223+
resetSearchState()
224+
viewModelScope.launch { _events.emit(DrawerEvent.AutoLaunch(target)) }
225+
}
225226
}
226227
}
227228

@@ -271,12 +272,12 @@ constructor(
271272

272273
// --- Launch ---
273274

274-
fun launchApp(packageName: String) {
275-
launchTarget(LaunchTarget.MainApp(packageName))
275+
fun launchApp(packageName: String): Boolean {
276+
return launchTarget(LaunchTarget.MainApp(packageName))
276277
}
277278

278-
fun launchTarget(target: LaunchTarget) {
279-
when (target) {
279+
fun launchTarget(target: LaunchTarget): Boolean {
280+
return when (target) {
280281
is LaunchTarget.MainApp -> appRepository.launchApp(target.packageName)
281282
is LaunchTarget.PrivateApp ->
282283
privateSpaceManager.launchApp(target.componentName, target.userHandle)

app/src/main/java/com/lu4p/fokuslauncher/ui/navigation/NavGraph.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@ import androidx.compose.animation.slideInVertically
2020
import androidx.compose.animation.slideOutHorizontally
2121
import androidx.compose.animation.slideOutVertically
2222
import androidx.compose.foundation.background
23+
import androidx.compose.foundation.clickable
2324
import androidx.compose.foundation.gestures.detectHorizontalDragGestures
2425
import androidx.compose.foundation.gestures.detectVerticalDragGestures
26+
import androidx.compose.foundation.interaction.MutableInteractionSource
2527
import androidx.compose.foundation.layout.Box
2628
import androidx.compose.foundation.layout.BoxWithConstraints
2729
import androidx.compose.foundation.layout.fillMaxSize
@@ -329,6 +331,10 @@ fun FokusNavGraph(
329331
modifier = Modifier
330332
.fillMaxSize()
331333
.background(MaterialTheme.colorScheme.background)
334+
.clickable(
335+
interactionSource = remember { MutableInteractionSource() },
336+
indication = null
337+
) {}
332338
) {
333339
AppDrawerScreen(
334340
onSettingsClick = {

app/src/test/java/com/lu4p/fokuslauncher/ui/drawer/AppDrawerViewModelTest.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,11 @@ class AppDrawerViewModelTest {
6767
every { appRepository.getHiddenPackageNames() } returns hiddenFlow
6868
every { appRepository.getAllRenamedApps() } returns renamedFlow
6969
every { appRepository.getAllAppCategories() } returns categoriesFlow
70+
every { appRepository.launchApp(any()) } returns true
7071
every { preferencesManager.favoritesFlow } returns favoritesFlow
7172
every { privateSpaceManager.isSupported } returns false
7273
every { privateSpaceManager.isPrivateSpaceUnlocked() } returns false
74+
every { privateSpaceManager.launchApp(any(), any()) } returns true
7375
viewModel = AppDrawerViewModel(appRepository, privateSpaceManager, preferencesManager)
7476
testDispatcher.scheduler.advanceUntilIdle()
7577
}
@@ -122,6 +124,15 @@ class AppDrawerViewModelTest {
122124
assertEquals("", viewModel.uiState.value.searchQuery)
123125
}
124126

127+
@Test
128+
fun `single search result does not reset query when launch fails`() {
129+
every { appRepository.launchApp("com.lu4p.atom") } returns false
130+
131+
viewModel.onSearchQueryChanged("Atom")
132+
133+
assertEquals("Atom", viewModel.uiState.value.searchQuery)
134+
}
135+
125136
@Test
126137
fun `empty search query shows all apps`() {
127138
viewModel.onSearchQueryChanged("cal")

0 commit comments

Comments
 (0)