Add search only scaffold for assistant activity

This commit is contained in:
MM20 2022-09-03 16:43:59 +02:00
parent 2d60797830
commit 8be8875462
No known key found for this signature in database
GPG Key ID: 0B61A8F2DEAFA389
4 changed files with 192 additions and 31 deletions

View File

@ -0,0 +1,151 @@
package de.mm20.launcher2.ui.assistant
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.*
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import com.google.accompanist.systemuicontroller.rememberSystemUiController
import de.mm20.launcher2.preferences.Settings
import de.mm20.launcher2.ui.launcher.LauncherScaffoldVM
import de.mm20.launcher2.ui.launcher.search.SearchBar
import de.mm20.launcher2.ui.launcher.search.SearchBarLevel
import de.mm20.launcher2.ui.launcher.search.SearchColumn
import de.mm20.launcher2.ui.launcher.search.SearchVM
import kotlinx.coroutines.flow.map
@Composable
fun AssistantScaffold(
modifier: Modifier = Modifier,
darkStatusBarIcons: Boolean = false,
darkNavBarIcons: Boolean = false,
) {
val viewModel: LauncherScaffoldVM = viewModel()
val bottomSearchBar by remember {
viewModel.dataStore.data.map { it.appearance.layout != Settings.AppearanceSettings.Layout.PullDown }
}.collectAsState(null)
val reverseResults by remember {
viewModel.dataStore.data.map { it.appearance.layout != Settings.AppearanceSettings.Layout.PullDown }
}.collectAsState(null)
val searchBarFocused by viewModel.searchBarFocused.observeAsState(false)
val searchState = rememberLazyListState()
val isSearchAtStart by remember {
derivedStateOf {
searchState.firstVisibleItemIndex == 0 && searchState.firstVisibleItemScrollOffset == 0
}
}
val isSearchAtEnd by remember {
derivedStateOf {
val lastItem = searchState.layoutInfo.visibleItemsInfo.lastOrNull() ?: return@derivedStateOf true
lastItem.offset + lastItem.size <= searchState.layoutInfo.viewportEndOffset - searchState.layoutInfo.afterContentPadding
}
}
if (reverseResults == null || bottomSearchBar == null) return
val searchBarLevel by remember {
derivedStateOf {
when {
reverseResults == bottomSearchBar && isSearchAtStart -> SearchBarLevel.Active
reverseResults != bottomSearchBar && isSearchAtEnd -> SearchBarLevel.Active
else -> SearchBarLevel.Raised
}
}
}
val systemUiController = rememberSystemUiController()
val showStatusBarScrim by remember {
derivedStateOf {
if (reverseResults == true) {
!isSearchAtEnd
} else {
!isSearchAtStart
}
}
}
val showNavBarScrim by remember {
derivedStateOf {
if (reverseResults == true) {
!isSearchAtStart
} else {
!isSearchAtEnd
}
}
}
val colorSurface = MaterialTheme.colorScheme.surface
LaunchedEffect(darkStatusBarIcons, colorSurface, showStatusBarScrim) {
if (showStatusBarScrim) {
systemUiController.setStatusBarColor(
colorSurface.copy(0.7f),
)
} else {
systemUiController.setStatusBarColor(
Color.Transparent,
darkIcons = darkStatusBarIcons
)
}
}
LaunchedEffect(darkNavBarIcons, showNavBarScrim) {
if (showNavBarScrim) {
systemUiController.setNavigationBarColor(
colorSurface.copy(0.7f),
)
} else {
systemUiController.setNavigationBarColor(
Color.Transparent,
darkIcons = darkNavBarIcons,
navigationBarContrastEnforced = false
)
}
}
val searchVM: SearchVM = viewModel()
val websearches by searchVM.websearchResults.observeAsState(emptyList())
val webSearchPadding by animateDpAsState(
if (websearches.isEmpty()) 0.dp else 48.dp
)
val windowInsets = WindowInsets.safeDrawing.asPaddingValues()
Box(modifier = Modifier.fillMaxSize()) {
SearchColumn(
modifier = Modifier.fillMaxSize(),
paddingValues = PaddingValues(
top = (if (bottomSearchBar == true) 0.dp else 56.dp + webSearchPadding) + 4.dp + windowInsets.calculateTopPadding(),
bottom = (if (bottomSearchBar == true) 56.dp + webSearchPadding else 0.dp) + 4.dp + windowInsets.calculateBottomPadding()
),
reverse = reverseResults == true,
state = searchState
)
SearchBar(
level = { searchBarLevel },
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight()
.align(if (bottomSearchBar == true) Alignment.BottomCenter else Alignment.TopCenter)
.windowInsetsPadding(WindowInsets.safeDrawing)
.padding(8.dp),
focused = searchBarFocused,
onFocusChange = {
if (it) viewModel.openSearch()
viewModel.setSearchbarFocus(it)
},
reverse = bottomSearchBar == true
)
}
}

View File

@ -73,7 +73,7 @@ fun PagerScaffold(
val isSearchAtEnd by remember {
derivedStateOf {
val lastItem = searchState.layoutInfo.visibleItemsInfo.last()
val lastItem = searchState.layoutInfo.visibleItemsInfo.lastOrNull() ?: return@derivedStateOf true
lastItem.offset + lastItem.size <= searchState.layoutInfo.viewportEndOffset - searchState.layoutInfo.afterContentPadding
}
}

View File

@ -69,7 +69,7 @@ fun PullDownScaffold(
val isSearchAtEnd by remember {
derivedStateOf {
val lastItem = searchState.layoutInfo.visibleItemsInfo.last()
val lastItem = searchState.layoutInfo.visibleItemsInfo.lastOrNull() ?: return@derivedStateOf true
lastItem.offset + lastItem.size <= searchState.layoutInfo.viewportEndOffset - searchState.layoutInfo.afterContentPadding
}
}

View File

@ -36,6 +36,7 @@ import com.android.launcher3.GestureNavContract
import com.google.accompanist.systemuicontroller.rememberSystemUiController
import de.mm20.launcher2.preferences.Settings
import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.assistant.AssistantScaffold
import de.mm20.launcher2.ui.base.BaseActivity
import de.mm20.launcher2.ui.base.ProvideCurrentTime
import de.mm20.launcher2.ui.base.ProvideSettings
@ -127,36 +128,45 @@ abstract class SharedLauncherActivity(
contentAlignment = Alignment.BottomCenter
) {
NavBarEffects(modifier = Modifier.fillMaxSize())
when (layout) {
Settings.AppearanceSettings.Layout.PullDown -> {
PullDownScaffold(
modifier = Modifier
.fillMaxSize()
.graphicsLayer {
scaleX = 0.5f + enterTransition.value * 0.5f
scaleY = 0.5f + enterTransition.value * 0.5f
alpha = enterTransition.value
},
darkStatusBarIcons = lightStatus,
darkNavBarIcons = lightNav,
)
if (mode == LauncherActivityMode.Assistant) {
AssistantScaffold(
modifier = Modifier
.fillMaxSize(),
darkStatusBarIcons = lightStatus,
darkNavBarIcons = lightNav,
)
} else {
when (layout) {
Settings.AppearanceSettings.Layout.PullDown -> {
PullDownScaffold(
modifier = Modifier
.fillMaxSize()
.graphicsLayer {
scaleX = 0.5f + enterTransition.value * 0.5f
scaleY = 0.5f + enterTransition.value * 0.5f
alpha = enterTransition.value
},
darkStatusBarIcons = lightStatus,
darkNavBarIcons = lightNav,
)
}
Settings.AppearanceSettings.Layout.Pager,
Settings.AppearanceSettings.Layout.PagerReversed -> {
PagerScaffold(
modifier = Modifier
.fillMaxSize()
.graphicsLayer {
scaleX = enterTransition.value
scaleY = enterTransition.value
alpha = enterTransition.value
},
darkStatusBarIcons = lightStatus,
darkNavBarIcons = lightNav,
reverse = layout == Settings.AppearanceSettings.Layout.PagerReversed
)
}
else -> {}
}
Settings.AppearanceSettings.Layout.Pager,
Settings.AppearanceSettings.Layout.PagerReversed -> {
PagerScaffold(
modifier = Modifier
.fillMaxSize()
.graphicsLayer {
scaleX = enterTransition.value
scaleY = enterTransition.value
alpha = enterTransition.value
},
darkStatusBarIcons = lightStatus,
darkNavBarIcons = lightNav,
reverse = layout == Settings.AppearanceSettings.Layout.PagerReversed
)
}
else -> {}
}
SnackbarHost(
snackbarHostState,