mirror of
https://github.com/YTVanced/VancedManager
synced 2024-11-28 22:13:01 +00:00
update configurations screen
This commit is contained in:
parent
4477180d2d
commit
db0f2b44c9
9 changed files with 309 additions and 240 deletions
|
@ -10,6 +10,7 @@ import com.vanced.manager.core.installer.impl.VancedInstaller
|
|||
import com.vanced.manager.repository.DataRepository
|
||||
import com.vanced.manager.repository.MainRepository
|
||||
import com.vanced.manager.repository.MirrorRepository
|
||||
import com.vanced.manager.ui.viewmodel.ConfigurationViewModel
|
||||
import com.vanced.manager.ui.viewmodel.InstallViewModel
|
||||
import com.vanced.manager.ui.viewmodel.MainViewModel
|
||||
import org.koin.android.ext.koin.androidApplication
|
||||
|
@ -34,6 +35,11 @@ val viewModelModule = module {
|
|||
microgInstaller: MicrogInstaller,
|
||||
) = InstallViewModel(vancedDownloader, musicDownloader, microgDownloader, vancedInstaller, musicInstaller, microgInstaller)
|
||||
|
||||
fun provideConfigurationViewModel(): ConfigurationViewModel {
|
||||
return ConfigurationViewModel()
|
||||
}
|
||||
|
||||
viewModel { provideMainViewModel(get(), get(), androidApplication()) }
|
||||
viewModel { provideInstallViewModel(get(), get(), get(), get(), get(), get()) }
|
||||
viewModel { provideConfigurationViewModel() }
|
||||
}
|
|
@ -1,29 +1,29 @@
|
|||
package com.vanced.manager.domain.model
|
||||
|
||||
import android.os.Parcelable
|
||||
import androidx.annotation.StringRes
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
sealed class InstallationOption(
|
||||
@StringRes val itemTitleId: Int,
|
||||
) : Parcelable {
|
||||
sealed class InstallationOption : Parcelable {
|
||||
|
||||
abstract val titleId: Int
|
||||
abstract val items: List<InstallationOptionItem>
|
||||
|
||||
@Parcelize
|
||||
data class MultiSelect(
|
||||
@StringRes val titleId: Int,
|
||||
val items: List<InstallationOptionItem>,
|
||||
override val titleId: Int,
|
||||
override val items: List<InstallationOptionItem>,
|
||||
val getOption: () -> Set<String>,
|
||||
val addOption: (String) -> Unit,
|
||||
val removeOption: (String) -> Unit
|
||||
) : InstallationOption(titleId)
|
||||
) : InstallationOption()
|
||||
|
||||
@Parcelize
|
||||
data class SingleSelect(
|
||||
@StringRes val titleId: Int,
|
||||
val items: List<InstallationOptionItem>,
|
||||
override val titleId: Int,
|
||||
override val items: List<InstallationOptionItem>,
|
||||
val getOption: () -> String,
|
||||
val setOption: (String) -> Unit,
|
||||
) : InstallationOption(titleId)
|
||||
) : InstallationOption()
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -89,7 +89,7 @@ class MainActivity : ComponentActivity() {
|
|||
onAppInstallPress = { appName, appVersions, installationOptions ->
|
||||
if (installationOptions != null) {
|
||||
backStack.push(
|
||||
Screen.InstallPreferences(
|
||||
Screen.Configuration(
|
||||
appName,
|
||||
appVersions,
|
||||
installationOptions
|
||||
|
@ -118,13 +118,13 @@ class MainActivity : ComponentActivity() {
|
|||
is Screen.Logs -> {
|
||||
|
||||
}
|
||||
is Screen.InstallPreferences -> {
|
||||
InstallPreferencesScreen(
|
||||
is Screen.Configuration -> {
|
||||
ConfigurationScreen(
|
||||
installationOptions = screen.appInstallationOptions,
|
||||
onToolbarBackButtonClick = {
|
||||
backStack.pop()
|
||||
},
|
||||
onDoneClick = {
|
||||
onFinishClick = {
|
||||
backStack.push(
|
||||
Screen.Install(
|
||||
screen.appName,
|
||||
|
|
|
@ -0,0 +1,259 @@
|
|||
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.LazyColumn
|
||||
import androidx.compose.material.ExperimentalMaterialApi
|
||||
import androidx.compose.material.ListItem
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.rounded.ArrowBackIosNew
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
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.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.viewmodel.ConfigurationViewModel
|
||||
import com.vanced.manager.ui.widget.layout.managerCategory
|
||||
import org.koin.androidx.compose.getViewModel
|
||||
|
||||
@ExperimentalFoundationApi
|
||||
@ExperimentalAnimationApi
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun ConfigurationScreen(
|
||||
installationOptions: List<InstallationOption>,
|
||||
onToolbarBackButtonClick: () -> Unit,
|
||||
onFinishClick: () -> Unit,
|
||||
) {
|
||||
val viewModel: ConfigurationViewModel = getViewModel()
|
||||
Scaffold(
|
||||
topBar = {
|
||||
ManagerTopAppBar(
|
||||
title = managerString(R.string.toolbar_installation_preferences),
|
||||
navigationIcon = {
|
||||
IconButton(
|
||||
onClick = {
|
||||
onToolbarBackButtonClick()
|
||||
viewModel.reset()
|
||||
}
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Rounded.ArrowBackIosNew,
|
||||
contentDescription = "Back"
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
},
|
||||
bottomBar = {
|
||||
ConfigurationButtons(
|
||||
modifier = Modifier
|
||||
.padding(
|
||||
horizontal = DefaultContentPaddingHorizontal,
|
||||
vertical = DefaultContentPaddingVertical
|
||||
),
|
||||
lastIndex = installationOptions.lastIndex,
|
||||
currentIndex = viewModel.currentIndex,
|
||||
onBackClick = {
|
||||
viewModel.back()
|
||||
},
|
||||
onNextClick = {
|
||||
viewModel.next()
|
||||
},
|
||||
onFinishClick = {
|
||||
onFinishClick()
|
||||
viewModel.reset()
|
||||
}
|
||||
)
|
||||
}
|
||||
) { paddingValues ->
|
||||
ConfigurationBody(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(paddingValues),
|
||||
currentIndex = viewModel.currentIndex,
|
||||
installationOptions = installationOptions
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalAnimationApi::class, ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
private fun ConfigurationBody(
|
||||
currentIndex: Int,
|
||||
installationOptions: List<InstallationOption>,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
AnimatedContent(
|
||||
modifier = modifier,
|
||||
targetState = currentIndex,
|
||||
transitionSpec = {
|
||||
slideAnimationSpec(
|
||||
if (targetState > initialState) {
|
||||
AnimatedContentScope.SlideDirection.Start
|
||||
} else {
|
||||
AnimatedContentScope.SlideDirection.End
|
||||
}
|
||||
)
|
||||
}
|
||||
) { optionIndex ->
|
||||
val installationOption = installationOptions[optionIndex]
|
||||
val categoryName = managerString(installationOption.titleId)
|
||||
LazyColumn {
|
||||
when (installationOption) {
|
||||
is InstallationOption.SingleSelect -> {
|
||||
managerCategory(
|
||||
categoryName = categoryName,
|
||||
items = installationOption.items
|
||||
) { item ->
|
||||
val preference = installationOption.getOption()
|
||||
ConfigurationItem(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth(),
|
||||
text = item.displayText(item.key),
|
||||
onClick = {
|
||||
installationOption.setOption(item.key)
|
||||
},
|
||||
trailing = {
|
||||
RadioButton(
|
||||
selected = preference == item.key,
|
||||
onClick = null
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
is InstallationOption.MultiSelect -> {
|
||||
managerCategory(
|
||||
categoryName = categoryName,
|
||||
items = installationOption.items
|
||||
) { item ->
|
||||
val preference = installationOption.getOption()
|
||||
ConfigurationItem(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth(),
|
||||
text = item.displayText(item.key),
|
||||
onClick = {
|
||||
if (preference.contains(item.key)) {
|
||||
installationOption.removeOption(item.key)
|
||||
} else {
|
||||
installationOption.addOption(item.key)
|
||||
}
|
||||
},
|
||||
trailing = {
|
||||
Checkbox(
|
||||
checked = preference.contains(item.key),
|
||||
onCheckedChange = null
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalAnimationApi::class)
|
||||
@Composable
|
||||
private fun ConfigurationButtons(
|
||||
currentIndex: Int,
|
||||
lastIndex: Int,
|
||||
onBackClick: () -> Unit,
|
||||
onNextClick: () -> Unit,
|
||||
onFinishClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Row(modifier = modifier) {
|
||||
AnimatedVisibility(
|
||||
modifier = Modifier
|
||||
.wrapContentWidth(Alignment.Start)
|
||||
.weight(1f),
|
||||
visible = currentIndex > 0) {
|
||||
TextButton(onClick = onBackClick) {
|
||||
ManagerText(text = "Back")
|
||||
}
|
||||
}
|
||||
AnimatedContent(
|
||||
modifier = Modifier
|
||||
.wrapContentWidth(Alignment.End)
|
||||
.weight(1f),
|
||||
targetState = currentIndex == lastIndex,
|
||||
transitionSpec = {
|
||||
slideAnimationSpec(
|
||||
if (initialState && !targetState) {
|
||||
AnimatedContentScope.SlideDirection.Up
|
||||
} else {
|
||||
AnimatedContentScope.SlideDirection.Down
|
||||
}
|
||||
)
|
||||
}
|
||||
) { isLastIndex ->
|
||||
if (isLastIndex) {
|
||||
ElevatedButton(onClick = onFinishClick) {
|
||||
ManagerText(text = "Finish")
|
||||
}
|
||||
} else {
|
||||
OutlinedButton(onClick = onNextClick) {
|
||||
ManagerText(text = "Next")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
@Composable
|
||||
private fun ConfigurationItem(
|
||||
text: String,
|
||||
onClick: () -> Unit,
|
||||
trailing: @Composable () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
ManagerTonalCard(
|
||||
modifier = modifier
|
||||
.padding(
|
||||
start = 6.dp,
|
||||
end = 6.dp,
|
||||
bottom = 8.dp
|
||||
),
|
||||
shape = LargeShape,
|
||||
onClick = onClick
|
||||
) {
|
||||
ListItem(
|
||||
text = {
|
||||
ManagerText(
|
||||
text = text,
|
||||
textStyle = MaterialTheme.typography.titleSmall
|
||||
)
|
||||
},
|
||||
trailing = trailing,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ExperimentalAnimationApi
|
||||
private fun <S> AnimatedContentScope<S>.slideAnimationSpec(
|
||||
slideDirection: AnimatedContentScope.SlideDirection
|
||||
) = slideIntoContainer(
|
||||
towards = slideDirection,
|
||||
animationSpec = tween(400)
|
||||
) + fadeIn(
|
||||
animationSpec = tween(400)
|
||||
) with slideOutOfContainer(
|
||||
towards = slideDirection,
|
||||
animationSpec = tween(400)
|
||||
) + fadeOut(
|
||||
animationSpec = tween(400)
|
||||
)
|
|
@ -1,225 +0,0 @@
|
|||
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 androidx.compose.ui.unit.dp
|
||||
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.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(
|
||||
contentPadding = PaddingValues(
|
||||
start = 4.dp,
|
||||
end = 4.dp,
|
||||
bottom = DefaultContentPaddingVertical
|
||||
)
|
||||
) {
|
||||
when (installationOption) {
|
||||
is InstallationOption.MultiSelect -> {
|
||||
items(installationOption.items) { item ->
|
||||
val preference = installationOption.getOption()
|
||||
CheckboxItem(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
text = item.displayText(item.key),
|
||||
checked = preference.contains(item.key),
|
||||
onCheckedChange = {
|
||||
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),
|
||||
selected = preference == item.key,
|
||||
onClick = {
|
||||
installationOption.setOption(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)
|
||||
)
|
|
@ -28,7 +28,7 @@ sealed class Screen(
|
|||
displayName = R.string.toolbar_logs,
|
||||
)
|
||||
|
||||
data class InstallPreferences(
|
||||
data class Configuration(
|
||||
val appName: String,
|
||||
val appVersions: List<String>?,
|
||||
val appInstallationOptions: List<InstallationOption>
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
package com.vanced.manager.ui.viewmodel
|
||||
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.lifecycle.ViewModel
|
||||
|
||||
class ConfigurationViewModel : ViewModel() {
|
||||
|
||||
var currentIndex by mutableStateOf(0)
|
||||
private set
|
||||
|
||||
fun next() {
|
||||
currentIndex++
|
||||
}
|
||||
|
||||
fun back() {
|
||||
currentIndex--
|
||||
}
|
||||
|
||||
fun reset() {
|
||||
currentIndex = 0
|
||||
}
|
||||
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package com.vanced.manager.ui.widget.list
|
||||
|
||||
import androidx.compose.material3.Checkbox
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
|
@ -9,6 +10,7 @@ import com.vanced.manager.ui.component.list.ManagerSelectableListItem
|
|||
import com.vanced.manager.ui.component.modifier.managerClickable
|
||||
import com.vanced.manager.ui.component.text.ManagerText
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun CheckboxItem(
|
||||
text: String,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.vanced.manager.ui.widget.list
|
||||
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.RadioButton
|
||||
import androidx.compose.runtime.Composable
|
||||
|
@ -9,6 +10,7 @@ import com.vanced.manager.ui.component.list.ManagerSelectableListItem
|
|||
import com.vanced.manager.ui.component.modifier.managerClickable
|
||||
import com.vanced.manager.ui.component.text.ManagerText
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun RadiobuttonItem(
|
||||
text: String,
|
||||
|
|
Loading…
Reference in a new issue