VancedManager/app/src/main/java/com/vanced/manager/ui/screens/InstallPreferencesScreen.kt

220 lines
9.1 KiB
Kotlin

package com.vanced.manager.ui.screens
import androidx.compose.animation.*
import androidx.compose.animation.core.tween
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.ArrowBackIosNew
import androidx.compose.material.icons.rounded.Done
import androidx.compose.material.icons.rounded.NavigateBefore
import androidx.compose.material.icons.rounded.NavigateNext
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import com.vanced.manager.R
import com.vanced.manager.domain.model.InstallationOption
import com.vanced.manager.ui.component.card.ManagerTonalCard
import com.vanced.manager.ui.component.layout.ManagerLazyColumn
import com.vanced.manager.ui.component.layout.ManagerScaffold
import com.vanced.manager.ui.component.progressindicator.ManagerProgressIndicator
import com.vanced.manager.ui.component.text.ManagerText
import com.vanced.manager.ui.component.topappbar.ManagerTopAppBar
import com.vanced.manager.ui.resources.managerString
import com.vanced.manager.ui.theme.LargeShape
import com.vanced.manager.ui.util.DefaultContentPaddingHorizontal
import com.vanced.manager.ui.util.DefaultContentPaddingVertical
import com.vanced.manager.ui.widget.list.CheckboxItem
import com.vanced.manager.ui.widget.list.RadiobuttonItem
@ExperimentalFoundationApi
@ExperimentalAnimationApi
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun InstallPreferencesScreen(
installationOptions: List<InstallationOption>,
onToolbarBackButtonClick: () -> Unit,
onDoneClick: () -> Unit,
) {
var currentOptionIndex by rememberSaveable { mutableStateOf(0) }
ManagerScaffold(
topBar = {
ManagerTopAppBar(
title = managerString(R.string.toolbar_installation_preferences),
navigationIcon = {
IconButton(
onClick = onToolbarBackButtonClick
) {
Icon(
imageVector = Icons.Rounded.ArrowBackIosNew,
contentDescription = "Back"
)
}
}
)
},
) { paddingValues ->
Column(
modifier = Modifier
.fillMaxSize()
.padding(paddingValues),
) {
AnimatedContent(
modifier = Modifier
.padding(
horizontal = DefaultContentPaddingHorizontal,
vertical = DefaultContentPaddingVertical
)
.weight(1f),
targetState = currentOptionIndex,
transitionSpec = {
getSlideAnimationSpec(
if (targetState > initialState) {
AnimatedContentScope.SlideDirection.Start
} else {
AnimatedContentScope.SlideDirection.End
}
)
}
) { optionIndex ->
val installationOption = installationOptions[optionIndex]
ManagerTonalCard(
modifier = Modifier
.wrapContentHeight(
align = Alignment.Top
),
shape = LargeShape
) {
Column {
ManagerText(
modifier = Modifier
.fillMaxWidth()
.padding(
horizontal = DefaultContentPaddingHorizontal,
vertical = DefaultContentPaddingVertical
),
text = managerString(installationOption.itemTitleId),
textStyle = MaterialTheme.typography.titleLarge,
)
ManagerLazyColumn {
when (installationOption) {
is InstallationOption.MultiSelect -> {
items(installationOption.items) { item ->
val preference = installationOption.getOption()
CheckboxItem(
modifier = Modifier.fillMaxWidth(),
text = item.displayText(item.key),
isChecked = preference.contains(item.key),
onCheck = {
if (it) {
installationOption.addOption(item.key)
} else {
installationOption.removeOption(item.key)
}
}
)
}
}
is InstallationOption.SingleSelect -> {
items(installationOption.items) { item ->
val preference = installationOption.getOption()
RadiobuttonItem(
modifier = Modifier.fillMaxWidth(),
text = item.displayText(item.key),
isSelected = preference == item.key,
onSelect = {
installationOption.setOption(item.key)
},
tag = item.key
)
}
}
}
}
}
}
}
Row(
modifier = Modifier
.fillMaxWidth()
.padding(
horizontal = DefaultContentPaddingHorizontal,
vertical = DefaultContentPaddingVertical
),
) {
AnimatedVisibility(
visible = currentOptionIndex > 0
) {
FloatingActionButton(
onClick = {
currentOptionIndex--
}
) {
Icon(
imageVector = Icons.Rounded.NavigateBefore,
contentDescription = "Back"
)
}
}
Spacer(modifier = Modifier.weight(1f))
AnimatedContent(
targetState = currentOptionIndex == installationOptions.lastIndex,
transitionSpec = {
getSlideAnimationSpec(
if (initialState && !targetState) {
AnimatedContentScope.SlideDirection.Up
} else {
AnimatedContentScope.SlideDirection.Down
}
)
}
) { lastIndex ->
if (lastIndex) {
FloatingActionButton(
onClick = onDoneClick
) {
Icon(
imageVector = Icons.Rounded.Done,
contentDescription = "Done"
)
}
} else {
FloatingActionButton(
onClick = {
currentOptionIndex++
}
) {
Icon(
imageVector = Icons.Rounded.NavigateNext,
contentDescription = "Next"
)
}
}
}
}
}
}
}
@ExperimentalAnimationApi
private fun <S> AnimatedContentScope<S>.getSlideAnimationSpec(
slideDirection: AnimatedContentScope.SlideDirection
) = slideIntoContainer(
towards = slideDirection,
animationSpec = tween(400)
) + fadeIn(
animationSpec = tween(400)
) with slideOutOfContainer(
towards = slideDirection,
animationSpec = tween(400)
) + fadeOut(
animationSpec = tween(400)
)