Add alternative layout
This commit is contained in:
parent
78593e0391
commit
7fda28aedd
@ -10,7 +10,7 @@
|
||||
android:exported="true"
|
||||
android:launchMode="singleTask"
|
||||
android:theme="@style/LauncherTheme"
|
||||
android:windowSoftInputMode="stateHidden">
|
||||
android:windowSoftInputMode="stateHidden|adjustNothing">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
|
||||
@ -71,7 +71,7 @@ class LauncherActivity : BaseActivity() {
|
||||
contentAlignment = Alignment.BottomCenter
|
||||
) {
|
||||
NavBarEffects(modifier = Modifier.fillMaxSize())
|
||||
PullDownScaffold(
|
||||
PagerScaffold(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.systemBarsPadding()
|
||||
|
||||
180
ui/src/main/java/de/mm20/launcher2/ui/launcher/PagerScaffold.kt
Normal file
180
ui/src/main/java/de/mm20/launcher2/ui/launcher/PagerScaffold.kt
Normal file
@ -0,0 +1,180 @@
|
||||
package de.mm20.launcher2.ui.launcher
|
||||
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.core.animateDpAsState
|
||||
import androidx.compose.animation.slideIn
|
||||
import androidx.compose.animation.slideOut
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.rounded.Done
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.layout.onSizeChanged
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.IntOffset
|
||||
import androidx.compose.ui.unit.IntSize
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import com.google.accompanist.pager.ExperimentalPagerApi
|
||||
import com.google.accompanist.pager.HorizontalPager
|
||||
import com.google.accompanist.pager.rememberPagerState
|
||||
import de.mm20.launcher2.ui.R
|
||||
import de.mm20.launcher2.ui.ktx.toDp
|
||||
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 de.mm20.launcher2.ui.launcher.widgets.WidgetColumn
|
||||
|
||||
@OptIn(ExperimentalPagerApi::class)
|
||||
@Composable
|
||||
fun PagerScaffold(
|
||||
modifier: Modifier = Modifier,
|
||||
darkStatusBarIcons: Boolean = false,
|
||||
darkNavBarIcons: Boolean = false,
|
||||
) {
|
||||
val viewModel: LauncherScaffoldVM = viewModel()
|
||||
val searchVM: SearchVM = viewModel()
|
||||
val context = LocalContext.current
|
||||
|
||||
val isSearchOpen by viewModel.isSearchOpen.observeAsState(false)
|
||||
val isWidgetEditMode by viewModel.isWidgetEditMode.observeAsState(false)
|
||||
|
||||
val pagerState = rememberPagerState()
|
||||
val widgetsScrollState = rememberScrollState()
|
||||
val searchScrollState = rememberScrollState()
|
||||
|
||||
val currentPage = pagerState.currentPage
|
||||
LaunchedEffect(currentPage) {
|
||||
if (currentPage == 1) viewModel.openSearch()
|
||||
else viewModel.closeSearch()
|
||||
}
|
||||
|
||||
LaunchedEffect(isSearchOpen) {
|
||||
if (isSearchOpen) pagerState.animateScrollToPage(1)
|
||||
else {
|
||||
pagerState.animateScrollToPage(0)
|
||||
searchVM.search("")
|
||||
}
|
||||
}
|
||||
|
||||
BackHandler {
|
||||
when {
|
||||
isSearchOpen -> {
|
||||
viewModel.closeSearch()
|
||||
searchVM.search("")
|
||||
}
|
||||
isWidgetEditMode -> {
|
||||
viewModel.setWidgetEditMode(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Box(
|
||||
modifier = modifier
|
||||
) {
|
||||
var size by remember { mutableStateOf(IntSize.Zero) }
|
||||
|
||||
HorizontalPager(
|
||||
count = 2,
|
||||
state = pagerState,
|
||||
modifier = Modifier
|
||||
.fillMaxSize(),
|
||||
userScrollEnabled = !isWidgetEditMode
|
||||
) {
|
||||
if (it == 1) {
|
||||
val websearches by searchVM.websearchResults.observeAsState(emptyList())
|
||||
val webSearchPadding by animateDpAsState(
|
||||
if (websearches.isEmpty()) 0.dp else 48.dp
|
||||
)
|
||||
SearchColumn(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.onSizeChanged {
|
||||
size = it
|
||||
}
|
||||
.verticalScroll(searchScrollState, reverseScrolling = true)
|
||||
.padding(start = 8.dp, end = 8.dp, top = 8.dp, bottom = 56.dp)
|
||||
.padding(bottom = webSearchPadding)
|
||||
)
|
||||
}
|
||||
|
||||
if (it == 0) {
|
||||
val editModePadding by animateDpAsState(if (isWidgetEditMode) 56.dp else 0.dp)
|
||||
|
||||
val showClockPadding by derivedStateOf {
|
||||
widgetsScrollState.value == 0
|
||||
}
|
||||
val clockPadding by animateDpAsState(
|
||||
if (showClockPadding) 64.dp else 0.dp
|
||||
)
|
||||
WidgetColumn(
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxSize()
|
||||
.verticalScroll(widgetsScrollState)
|
||||
.padding(start = 8.dp, end = 8.dp, top = 8.dp, bottom = 64.dp)
|
||||
.padding(top = editModePadding),
|
||||
clockHeight = size.height.toDp() - (64.dp - clockPadding),
|
||||
clockBottomPadding = clockPadding,
|
||||
editMode = isWidgetEditMode,
|
||||
onEditModeChange = {
|
||||
viewModel.setWidgetEditMode(it)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
AnimatedVisibility(visible = isWidgetEditMode,
|
||||
enter = slideIn { IntOffset(0, -it.height) },
|
||||
exit = slideOut { IntOffset(0, -it.height) }
|
||||
) {
|
||||
CenterAlignedTopAppBar(
|
||||
title = {
|
||||
Text(stringResource(R.string.menu_edit_widgets))
|
||||
},
|
||||
navigationIcon = {
|
||||
IconButton(onClick = { viewModel.setWidgetEditMode(false) }) {
|
||||
Icon(imageVector = Icons.Rounded.Done, contentDescription = null)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
val searchBarLevel by derivedStateOf {
|
||||
when {
|
||||
pagerState.isScrollInProgress -> SearchBarLevel.Raised
|
||||
!isSearchOpen && widgetsScrollState.value == 0 -> SearchBarLevel.Resting
|
||||
isSearchOpen && searchScrollState.value == 0 -> SearchBarLevel.Active
|
||||
else -> SearchBarLevel.Raised
|
||||
}
|
||||
}
|
||||
|
||||
val focusSearchBar by viewModel.searchBarFocused.observeAsState(false)
|
||||
|
||||
val widgetEditModeOffset by animateDpAsState(
|
||||
if (isWidgetEditMode) 128.dp else 0.dp
|
||||
)
|
||||
|
||||
SearchBar(
|
||||
modifier = Modifier
|
||||
.align(Alignment.BottomCenter)
|
||||
.padding(start = 8.dp, end = 8.dp, bottom = 8.dp)
|
||||
.offset(y = widgetEditModeOffset),
|
||||
level = searchBarLevel, focused = focusSearchBar, onFocusChange = {
|
||||
if (it) viewModel.openSearch()
|
||||
viewModel.setSearchbarFocus(it)
|
||||
},
|
||||
reverse = true
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
@ -7,10 +7,7 @@ import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.core.animateDpAsState
|
||||
import androidx.compose.animation.slideIn
|
||||
import androidx.compose.animation.slideOut
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.offset
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
@ -298,7 +295,10 @@ fun PullDownScaffold(
|
||||
SearchBar(
|
||||
level = searchBarLevel,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentHeight()
|
||||
.clipToBounds()
|
||||
.padding(8.dp)
|
||||
.offset { IntOffset(0, searchBarOffset.value.toInt()) }
|
||||
.offset(y = editModeSearchBarOffset),
|
||||
focused = searchBarFocused,
|
||||
|
||||
@ -46,6 +46,7 @@ import de.mm20.launcher2.search.data.Websearch
|
||||
import de.mm20.launcher2.ui.R
|
||||
import de.mm20.launcher2.ui.component.LauncherCard
|
||||
import de.mm20.launcher2.ui.launcher.LauncherActivityVM
|
||||
import de.mm20.launcher2.ui.layout.BottomReversed
|
||||
import de.mm20.launcher2.ui.locals.LocalCardStyle
|
||||
import de.mm20.launcher2.ui.settings.SettingsActivity
|
||||
import kotlinx.coroutines.awaitCancellation
|
||||
@ -58,7 +59,8 @@ fun SearchBar(
|
||||
modifier: Modifier = Modifier,
|
||||
level: SearchBarLevel,
|
||||
focused: Boolean,
|
||||
onFocusChange: (Boolean) -> Unit
|
||||
onFocusChange: (Boolean) -> Unit,
|
||||
reverse: Boolean = false,
|
||||
) {
|
||||
val searchViewModel: SearchVM = viewModel()
|
||||
val activityViewModel: LauncherActivityVM = viewModel()
|
||||
@ -150,7 +152,8 @@ fun SearchBar(
|
||||
},
|
||||
onUnfocus = {
|
||||
onFocusChange(false)
|
||||
}
|
||||
},
|
||||
reverse = reverse
|
||||
)
|
||||
}
|
||||
|
||||
@ -166,7 +169,8 @@ fun SearchBar(
|
||||
onValueChange: (String) -> Unit,
|
||||
onFocus: () -> Unit = {},
|
||||
onUnfocus: () -> Unit = {},
|
||||
focusRequester: FocusRequester = remember { FocusRequester() }
|
||||
focusRequester: FocusRequester = remember { FocusRequester() },
|
||||
reverse: Boolean = false,
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
|
||||
@ -241,14 +245,13 @@ fun SearchBar(
|
||||
|
||||
LauncherCard(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentHeight()
|
||||
.alpha(opacity)
|
||||
.padding(8.dp),
|
||||
.alpha(opacity),
|
||||
backgroundOpacity = backgroundOpacity,
|
||||
elevation = elevation
|
||||
) {
|
||||
Column {
|
||||
Column(
|
||||
verticalArrangement = if (reverse) Arrangement.BottomReversed else Arrangement.Top
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier.height(48.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
|
||||
@ -1,9 +1,6 @@
|
||||
package de.mm20.launcher2.ui.launcher.search
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.wrapContentHeight
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
@ -17,23 +14,26 @@ import de.mm20.launcher2.ui.launcher.search.files.FileResults
|
||||
import de.mm20.launcher2.ui.launcher.search.unitconverter.UnitConverterResults
|
||||
import de.mm20.launcher2.ui.launcher.search.website.WebsiteResults
|
||||
import de.mm20.launcher2.ui.launcher.search.wikipedia.WikipediaResults
|
||||
import de.mm20.launcher2.ui.layout.BottomReversed
|
||||
|
||||
@Composable
|
||||
fun SearchColumn(
|
||||
modifier: Modifier = Modifier,
|
||||
reverse: Boolean = false,
|
||||
) {
|
||||
Column(
|
||||
modifier = modifier
|
||||
modifier = modifier,
|
||||
verticalArrangement = if (reverse) Arrangement.Top else Arrangement.BottomReversed
|
||||
) {
|
||||
FavoritesResults()
|
||||
AppResults()
|
||||
AppShortcutResults()
|
||||
UnitConverterResults()
|
||||
CalculatorResults()
|
||||
CalendarResults()
|
||||
ContactResults()
|
||||
WikipediaResults()
|
||||
WebsiteResults()
|
||||
FileResults()
|
||||
FavoritesResults(reverse)
|
||||
AppResults(reverse)
|
||||
AppShortcutResults(reverse)
|
||||
UnitConverterResults(reverse)
|
||||
CalculatorResults(reverse)
|
||||
CalendarResults(reverse)
|
||||
ContactResults(reverse)
|
||||
WikipediaResults(reverse)
|
||||
WebsiteResults(reverse)
|
||||
FileResults(reverse)
|
||||
}
|
||||
}
|
||||
@ -14,15 +14,16 @@ import de.mm20.launcher2.ui.launcher.search.SearchVM
|
||||
import de.mm20.launcher2.ui.launcher.search.common.grid.SearchResultGrid
|
||||
|
||||
@Composable
|
||||
fun ColumnScope.AppResults() {
|
||||
fun ColumnScope.AppResults(reverse: Boolean = false) {
|
||||
val viewModel: SearchVM = viewModel()
|
||||
val apps by viewModel.appResults.observeAsState(emptyList())
|
||||
|
||||
AnimatedVisibility(apps.isNotEmpty()) {
|
||||
LauncherCard(
|
||||
modifier = Modifier.padding(bottom = 8.dp)
|
||||
modifier = Modifier
|
||||
.padding(bottom = if (reverse) 0.dp else 8.dp, top = if (reverse) 8.dp else 0.dp)
|
||||
) {
|
||||
SearchResultGrid(items = apps)
|
||||
SearchResultGrid(items = apps, reverse = reverse)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -24,7 +24,7 @@ import de.mm20.launcher2.ui.launcher.search.SearchVM
|
||||
import de.mm20.launcher2.ui.launcher.search.common.list.SearchResultList
|
||||
|
||||
@Composable
|
||||
fun ColumnScope.AppShortcutResults() {
|
||||
fun ColumnScope.AppShortcutResults(reverse: Boolean = false) {
|
||||
val viewModel: SearchVM = viewModel()
|
||||
val shortcuts by viewModel.appShortcutResults.observeAsState(emptyList())
|
||||
val context = LocalContext.current
|
||||
@ -34,7 +34,8 @@ fun ColumnScope.AppShortcutResults() {
|
||||
|
||||
AnimatedVisibility(shortcuts.isNotEmpty() || (!isSearchEmpty && missingPermission)) {
|
||||
LauncherCard(
|
||||
modifier = Modifier.padding(bottom = 8.dp)
|
||||
modifier = Modifier
|
||||
.padding(bottom = if (reverse) 0.dp else 8.dp, top = if (reverse) 8.dp else 0.dp)
|
||||
) {
|
||||
Column {
|
||||
AnimatedVisibility(!isSearchEmpty && missingPermission) {
|
||||
@ -58,7 +59,8 @@ fun ColumnScope.AppShortcutResults() {
|
||||
items = shortcuts,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(12.dp)
|
||||
.padding(12.dp),
|
||||
reverse = reverse
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,13 +14,14 @@ import de.mm20.launcher2.ui.launcher.search.SearchVM
|
||||
import de.mm20.launcher2.ui.search.CalculatorItem
|
||||
|
||||
@Composable
|
||||
fun ColumnScope.CalculatorResults() {
|
||||
fun ColumnScope.CalculatorResults(reverse: Boolean = false) {
|
||||
val viewModel: SearchVM = viewModel()
|
||||
val calculator by viewModel.calculatorResult.observeAsState(null)
|
||||
|
||||
AnimatedVisibility(calculator != null) {
|
||||
LauncherCard(
|
||||
modifier = Modifier.padding(bottom = 8.dp)
|
||||
modifier = Modifier
|
||||
.padding(bottom = if (reverse) 0.dp else 8.dp, top = if (reverse) 8.dp else 0.dp)
|
||||
) {
|
||||
calculator?.let { CalculatorItem(calculator = it) }
|
||||
}
|
||||
|
||||
@ -24,7 +24,7 @@ import de.mm20.launcher2.ui.launcher.search.SearchVM
|
||||
import de.mm20.launcher2.ui.launcher.search.common.list.SearchResultList
|
||||
|
||||
@Composable
|
||||
fun ColumnScope.CalendarResults() {
|
||||
fun ColumnScope.CalendarResults(reverse: Boolean = false) {
|
||||
val viewModel: SearchVM = viewModel()
|
||||
val calendarEvents by viewModel.calendarResults.observeAsState(emptyList())
|
||||
val context = LocalContext.current
|
||||
@ -34,7 +34,7 @@ fun ColumnScope.CalendarResults() {
|
||||
AnimatedVisibility(calendarEvents.isNotEmpty() || (!isSearchEmpty && missingPermission)) {
|
||||
LauncherCard(
|
||||
modifier = Modifier
|
||||
.padding(bottom = 8.dp)
|
||||
.padding(bottom = if (reverse) 0.dp else 8.dp, top = if (reverse) 8.dp else 0.dp)
|
||||
.fillMaxWidth()
|
||||
) {
|
||||
Column {
|
||||
@ -59,7 +59,8 @@ fun ColumnScope.CalendarResults() {
|
||||
items = calendarEvents,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(12.dp)
|
||||
.padding(12.dp),
|
||||
reverse = reverse
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import de.mm20.launcher2.search.data.Searchable
|
||||
import de.mm20.launcher2.ui.launcher.search.common.GridItem
|
||||
import de.mm20.launcher2.ui.layout.BottomReversed
|
||||
import de.mm20.launcher2.ui.locals.LocalGridColumns
|
||||
import kotlin.math.ceil
|
||||
|
||||
@ -16,12 +17,14 @@ fun SearchResultGrid(
|
||||
modifier: Modifier = Modifier,
|
||||
showLabels: Boolean = true,
|
||||
columns: Int = LocalGridColumns.current,
|
||||
reverse: Boolean = false
|
||||
) {
|
||||
Column(
|
||||
modifier = modifier
|
||||
.animateContentSize()
|
||||
.fillMaxWidth()
|
||||
.padding(4.dp)
|
||||
.padding(4.dp),
|
||||
verticalArrangement = if (reverse) Arrangement.Top else Arrangement.BottomReversed
|
||||
) {
|
||||
for (i in 0 until ceil(items.size / columns.toFloat()).toInt()) {
|
||||
Row {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
package de.mm20.launcher2.ui.launcher.search.common.list
|
||||
|
||||
import androidx.compose.animation.animateContentSize
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
@ -9,14 +9,17 @@ import androidx.compose.runtime.key
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import de.mm20.launcher2.search.data.Searchable
|
||||
import de.mm20.launcher2.ui.layout.BottomReversed
|
||||
|
||||
@Composable
|
||||
fun SearchResultList(
|
||||
items: List<Searchable>,
|
||||
modifier: Modifier = Modifier
|
||||
modifier: Modifier = Modifier,
|
||||
reverse: Boolean = false
|
||||
) {
|
||||
Column(
|
||||
modifier = modifier
|
||||
modifier = modifier,
|
||||
verticalArrangement = if (reverse) Arrangement.Top else Arrangement.BottomReversed
|
||||
) {
|
||||
for (item in items) {
|
||||
key(item.key) {
|
||||
|
||||
@ -24,7 +24,7 @@ import de.mm20.launcher2.ui.launcher.search.SearchVM
|
||||
import de.mm20.launcher2.ui.launcher.search.common.list.SearchResultList
|
||||
|
||||
@Composable
|
||||
fun ColumnScope.ContactResults() {
|
||||
fun ColumnScope.ContactResults(reverse: Boolean = false) {
|
||||
val viewModel: SearchVM = viewModel()
|
||||
val context = LocalContext.current
|
||||
val contacts by viewModel.contactResults.observeAsState(emptyList())
|
||||
@ -34,7 +34,7 @@ fun ColumnScope.ContactResults() {
|
||||
AnimatedVisibility(contacts.isNotEmpty() || (!isSearchEmpty && missingPermission)) {
|
||||
LauncherCard(
|
||||
modifier = Modifier
|
||||
.padding(bottom = 8.dp)
|
||||
.padding(bottom = if (reverse) 0.dp else 8.dp, top = if (reverse) 8.dp else 0.dp)
|
||||
.fillMaxWidth()
|
||||
) {
|
||||
Column {
|
||||
@ -58,7 +58,8 @@ fun ColumnScope.ContactResults() {
|
||||
items = contacts,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(12.dp)
|
||||
.padding(12.dp),
|
||||
reverse = reverse
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,7 +14,9 @@ import de.mm20.launcher2.ui.launcher.search.SearchVM
|
||||
import de.mm20.launcher2.ui.launcher.search.common.grid.SearchResultGrid
|
||||
|
||||
@Composable
|
||||
fun ColumnScope.FavoritesResults() {
|
||||
fun ColumnScope.FavoritesResults(
|
||||
reverse: Boolean = false,
|
||||
) {
|
||||
val viewModel: SearchVM = viewModel()
|
||||
val favorites by viewModel.favorites.observeAsState(emptyList())
|
||||
|
||||
@ -22,9 +24,10 @@ fun ColumnScope.FavoritesResults() {
|
||||
|
||||
AnimatedVisibility(!hide && favorites.isNotEmpty()) {
|
||||
LauncherCard(
|
||||
modifier = Modifier.padding(bottom = 8.dp)
|
||||
modifier = Modifier
|
||||
.padding(bottom = if (reverse) 0.dp else 8.dp, top = if (reverse) 8.dp else 0.dp)
|
||||
) {
|
||||
SearchResultGrid(items = favorites)
|
||||
SearchResultGrid(items = favorites, reverse = reverse)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -24,7 +24,7 @@ import de.mm20.launcher2.ui.launcher.search.SearchVM
|
||||
import de.mm20.launcher2.ui.launcher.search.common.list.SearchResultList
|
||||
|
||||
@Composable
|
||||
fun ColumnScope.FileResults() {
|
||||
fun ColumnScope.FileResults(reverse: Boolean = false) {
|
||||
val viewModel: SearchVM = viewModel()
|
||||
val files by viewModel.fileResults.observeAsState(emptyList())
|
||||
val context = LocalContext.current
|
||||
@ -34,7 +34,7 @@ fun ColumnScope.FileResults() {
|
||||
AnimatedVisibility(files.isNotEmpty() || (!isSearchEmpty && missingPermission)) {
|
||||
LauncherCard(
|
||||
modifier = Modifier
|
||||
.padding(bottom = 8.dp)
|
||||
.padding(bottom = if (reverse) 0.dp else 8.dp, top = if (reverse) 8.dp else 0.dp)
|
||||
.fillMaxWidth()
|
||||
) {
|
||||
Column {
|
||||
@ -58,7 +58,8 @@ fun ColumnScope.FileResults() {
|
||||
items = files,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(12.dp)
|
||||
.padding(12.dp),
|
||||
reverse = reverse
|
||||
)}
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,13 +14,14 @@ import de.mm20.launcher2.ui.launcher.search.SearchVM
|
||||
import de.mm20.launcher2.ui.search.UnitConverterItem
|
||||
|
||||
@Composable
|
||||
fun ColumnScope.UnitConverterResults() {
|
||||
fun ColumnScope.UnitConverterResults(reverse: Boolean = false) {
|
||||
val viewModel: SearchVM = viewModel()
|
||||
val unitConverter by viewModel.unitConverterResult.observeAsState(null)
|
||||
|
||||
AnimatedVisibility(unitConverter != null) {
|
||||
LauncherCard(
|
||||
modifier = Modifier.padding(bottom = 8.dp)
|
||||
modifier = Modifier
|
||||
.padding(bottom = if (reverse) 0.dp else 8.dp, top = if (reverse) 8.dp else 0.dp)
|
||||
) {
|
||||
unitConverter?.let { UnitConverterItem(unitConverter = it) }
|
||||
}
|
||||
|
||||
@ -13,13 +13,14 @@ import de.mm20.launcher2.ui.component.LauncherCard
|
||||
import de.mm20.launcher2.ui.launcher.search.SearchVM
|
||||
|
||||
@Composable
|
||||
fun ColumnScope.WebsiteResults() {
|
||||
fun ColumnScope.WebsiteResults(reverse: Boolean = false) {
|
||||
val viewModel: SearchVM = viewModel()
|
||||
val website by viewModel.websiteResult.observeAsState(null)
|
||||
|
||||
AnimatedVisibility(website != null) {
|
||||
LauncherCard(
|
||||
modifier = Modifier.padding(bottom = 8.dp)
|
||||
modifier = Modifier
|
||||
.padding(bottom = if (reverse) 0.dp else 8.dp, top = if (reverse) 8.dp else 0.dp)
|
||||
) {
|
||||
website?.let { WebsiteItem(website = it) }
|
||||
}
|
||||
|
||||
@ -13,13 +13,14 @@ import de.mm20.launcher2.ui.component.LauncherCard
|
||||
import de.mm20.launcher2.ui.launcher.search.SearchVM
|
||||
|
||||
@Composable
|
||||
fun ColumnScope.WikipediaResults() {
|
||||
fun ColumnScope.WikipediaResults(reverse: Boolean = false) {
|
||||
val viewModel: SearchVM = viewModel()
|
||||
val wikipedia by viewModel.wikipediaResult.observeAsState(null)
|
||||
|
||||
AnimatedVisibility(wikipedia != null) {
|
||||
LauncherCard(
|
||||
modifier = Modifier.padding(bottom = 8.dp)
|
||||
modifier = Modifier
|
||||
.padding(bottom = if (reverse) 0.dp else 8.dp, top = if (reverse) 8.dp else 0.dp)
|
||||
) {
|
||||
wikipedia?.let { WikipediaItem(wikipedia = it) }
|
||||
}
|
||||
|
||||
@ -49,6 +49,7 @@ import kotlinx.coroutines.launch
|
||||
fun WidgetColumn(
|
||||
modifier: Modifier = Modifier,
|
||||
clockHeight: Dp = 0.dp,
|
||||
clockBottomPadding: Dp = 0.dp,
|
||||
editMode: Boolean = false,
|
||||
onEditModeChange: (Boolean) -> Unit,
|
||||
) {
|
||||
@ -91,7 +92,8 @@ fun WidgetColumn(
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(clockHeight),
|
||||
.height(clockHeight)
|
||||
.padding(bottom = clockBottomPadding),
|
||||
contentAlignment = Alignment.BottomCenter
|
||||
) {
|
||||
ClockWidget(
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user