Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SearchVM, SearchService: improve search UX by reducing flickering #1117

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ fun AssistantScaffold(
val density = LocalDensity.current
val maxSearchBarOffset = with(density) { 128.dp.toPx() }
var searchBarOffset by remember {
mutableStateOf(0f)
mutableFloatStateOf(0f)
}

val nestedScrollConnection = remember {
Expand All @@ -159,7 +159,7 @@ fun AssistantScaffold(
}
}
}
val actions by searchVM.searchActionResults
val actions = searchVM.searchActionResults
val webSearchPadding by animateDpAsState(
if (actions.isEmpty()) 0.dp else 48.dp
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
Expand Down Expand Up @@ -124,7 +124,7 @@ fun PagerScaffold(
val isSearchOpen by viewModel.isSearchOpen
val isWidgetEditMode by viewModel.isWidgetEditMode

val actions by searchVM.searchActionResults
val actions = searchVM.searchActionResults

val widgetsScrollState = rememberScrollState()
val searchState = rememberLazyListState()
Expand Down Expand Up @@ -272,7 +272,7 @@ fun PagerScaffold(
}
}

val searchBarOffset = remember { mutableStateOf(0f) }
val searchBarOffset = remember { mutableFloatStateOf(0f) }

val scope = rememberCoroutineScope()

Expand Down Expand Up @@ -341,8 +341,8 @@ fun PagerScaffold(
}
val deltaSearchBarOffset =
consumed.y * if (isSearchOpen && reverseSearchResults) 1 else -1
searchBarOffset.value =
(searchBarOffset.value + deltaSearchBarOffset).coerceIn(0f, maxSearchBarOffset)
searchBarOffset.floatValue =
(searchBarOffset.floatValue + deltaSearchBarOffset).coerceIn(0f, maxSearchBarOffset)
return super.onPostScroll(consumed, available, source)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
Expand Down Expand Up @@ -106,7 +107,7 @@ fun PullDownScaffold(
val density = LocalDensity.current
val context = LocalContext.current

val actions by searchVM.searchActionResults
val actions = searchVM.searchActionResults

val isSearchOpen by viewModel.isSearchOpen
val isWidgetEditMode by viewModel.isWidgetEditMode
Expand All @@ -116,7 +117,7 @@ fun PullDownScaffold(

val pagerState = rememberPagerState { 2 }

val offsetY = remember { mutableStateOf(0f) }
val offsetY = remember { mutableFloatStateOf(0f) }
val maxOffset = with(density) { 64.dp.toPx() }
val toggleSearchThreshold = with(density) { 48.dp.toPx() }

Expand Down Expand Up @@ -153,13 +154,13 @@ fun PullDownScaffold(

val isOverThreshold by remember {
derivedStateOf {
offsetY.value.absoluteValue > toggleSearchThreshold
offsetY.floatValue.absoluteValue > toggleSearchThreshold
}
}

val dragProgress by remember {
derivedStateOf {
(offsetY.value.absoluteValue / toggleSearchThreshold).coerceAtMost(1f)
(offsetY.floatValue.absoluteValue / toggleSearchThreshold).coerceAtMost(1f)
}
}

Expand Down Expand Up @@ -236,7 +237,7 @@ fun PullDownScaffold(
}
}

val searchBarOffset = remember { mutableStateOf(0f) }
val searchBarOffset = remember { mutableFloatStateOf(0f) }

val maxSearchBarOffset = with(density) { 128.dp.toPx() }

Expand Down Expand Up @@ -281,7 +282,7 @@ fun PullDownScaffold(
}

LaunchedEffect(isWidgetEditMode) {
if (!isWidgetEditMode) searchBarOffset.value = 0f
if (!isWidgetEditMode) searchBarOffset.floatValue = 0f
}

val handleBackOrHomeEvent = {
Expand Down Expand Up @@ -321,7 +322,7 @@ fun PullDownScaffold(
LaunchedEffect(isOverThreshold) {
if (isOverThreshold) {
view.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY)
} else if (offsetY.value != 0f) {
} else if (offsetY.floatValue != 0f) {
view.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY_RELEASE)
}
}
Expand All @@ -342,15 +343,15 @@ fun PullDownScaffold(
val canPullUp = isSearchOpen && isSearchAtBottom

val consumed = when {
canPullUp && available.y < 0 || offsetY.value < 0 -> {
canPullUp && available.y < 0 || offsetY.floatValue < 0 -> {
val consumed = available.y
offsetY.value = (offsetY.value + (consumed * 0.5f)).coerceIn(-maxOffset, 0f)
offsetY.floatValue = (offsetY.floatValue + (consumed * 0.5f)).coerceIn(-maxOffset, 0f)
consumed
}

canPullDown && available.y > 0 || offsetY.value > 0 -> {
canPullDown && available.y > 0 || offsetY.floatValue > 0 -> {
val consumed = available.y
offsetY.value = (offsetY.value + (consumed * 0.5f)).coerceIn(0f, maxOffset)
offsetY.floatValue = (offsetY.floatValue + (consumed * 0.5f)).coerceIn(0f, maxOffset)
consumed
}

Expand All @@ -367,17 +368,17 @@ fun PullDownScaffold(
): Offset {
val deltaSearchBarOffset =
consumed.y * if (isSearchOpen && reverseSearchResults) 1 else -1
searchBarOffset.value =
(searchBarOffset.value + deltaSearchBarOffset).coerceIn(0f, maxSearchBarOffset)
searchBarOffset.floatValue =
(searchBarOffset.floatValue + deltaSearchBarOffset).coerceIn(0f, maxSearchBarOffset)
return super.onPostScroll(consumed, available, source)
}

override suspend fun onPreFling(available: Velocity): Velocity {
if (offsetY.value > toggleSearchThreshold || offsetY.value < -toggleSearchThreshold) {
if (offsetY.floatValue > toggleSearchThreshold || offsetY.floatValue < -toggleSearchThreshold) {
viewModel.toggleSearch()
}
if (!isWidgetEditMode) gestureManager.dispatchDragEnd()
if (offsetY.value != 0f) {
if (offsetY.floatValue != 0f) {
offsetY.animateTo(0f)
return available
}
Expand Down Expand Up @@ -406,7 +407,7 @@ fun PullDownScaffold(
}
)
}
.offset { IntOffset(0, offsetY.value.toInt()) },
.offset { IntOffset(0, offsetY.floatValue.toInt()) },
contentAlignment = Alignment.TopCenter
) {
BoxWithConstraints(
Expand Down Expand Up @@ -576,7 +577,7 @@ fun PullDownScaffold(
val searchBarLevel by remember {
derivedStateOf {
when {
offsetY.value != 0f -> SearchBarLevel.Raised
offsetY.floatValue != 0f -> SearchBarLevel.Raised
!isSearchOpen && isWidgetsAtStart && (fillClockHeight || !bottomSearchBar) -> SearchBarLevel.Resting
isSearchOpen && isSearchAtTop && !bottomSearchBar -> SearchBarLevel.Active
isSearchOpen && isSearchAtBottom && bottomSearchBar -> SearchBarLevel.Active
Expand Down Expand Up @@ -613,7 +614,7 @@ fun PullDownScaffold(
darkColors = LocalPreferDarkContentOverWallpaper.current && searchBarColor == SearchBarColors.Auto || searchBarColor == SearchBarColors.Dark,
bottomSearchBar = bottomSearchBar,
searchBarOffset = {
(if (searchBarFocused || fixedSearchBar) 0 else searchBarOffset.value.toInt() * (if (bottomSearchBar) 1 else -1)) +
(if (searchBarFocused || fixedSearchBar) 0 else searchBarOffset.floatValue.toInt() * (if (bottomSearchBar) 1 else -1)) +
with(density) {
(editModeSearchBarOffset - if (bottomSearchBar) keyboardFilterBarPadding else 0.dp)
.toPx()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package de.mm20.launcher2.ui.launcher.search

import android.util.Log
import androidx.activity.compose.BackHandler
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.animation.AnimatedContent
Expand Down Expand Up @@ -75,22 +74,22 @@ fun SearchColumn(
val hideFavs by viewModel.hideFavorites
val favoritesEnabled by viewModel.favoritesEnabled.collectAsState(false)

val apps by viewModel.appResults
val workApps by viewModel.workAppResults
val privateApps by viewModel.privateSpaceAppResults
val apps = viewModel.appResults
val workApps = viewModel.workAppResults
val privateApps = viewModel.privateSpaceAppResults
val profiles by viewModel.profiles.collectAsState(emptyList())
val profileStates by viewModel.profileStates.collectAsState(emptyList())

val appShortcuts by viewModel.appShortcutResults
val contacts by viewModel.contactResults
val files by viewModel.fileResults
val events by viewModel.calendarResults
val unitConverter by viewModel.unitConverterResults
val calculator by viewModel.calculatorResults
val wikipedia by viewModel.articleResults
val locations by viewModel.locationResults
val website by viewModel.websiteResults
val hiddenResults by viewModel.hiddenResults
val appShortcuts = viewModel.appShortcutResults
val contacts = viewModel.contactResults
val files = viewModel.fileResults
val events = viewModel.calendarResults
val unitConverter = viewModel.unitConverterResults
val calculator = viewModel.calculatorResults
val wikipedia = viewModel.articleResults
val locations = viewModel.locationResults
val website = viewModel.websiteResults
val hiddenResults = viewModel.hiddenResults

val bestMatch by viewModel.bestMatch

Expand Down
Loading