mirror of
https://github.com/rafaelvcaetano/melonDS-android.git
synced 2024-11-23 13:49:43 +00:00
Move all preference composables to a separate package for better reusability
This commit is contained in:
parent
b538a8498f
commit
4bca90ee42
@ -0,0 +1,50 @@
|
||||
package me.magnum.melonds.ui.common.preference
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.focusable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.ContentAlpha
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Composable
|
||||
fun ActionLauncherItem(
|
||||
name: String,
|
||||
value: String,
|
||||
enabled: Boolean = true,
|
||||
onLaunchAction: () -> Unit,
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.run {
|
||||
if (enabled) {
|
||||
clickable { onLaunchAction() }.focusable()
|
||||
} else {
|
||||
this
|
||||
}
|
||||
}
|
||||
.heightIn(min = 64.dp)
|
||||
.padding(start = 16.dp, end = 16.dp, top = 8.dp, bottom = 8.dp),
|
||||
verticalArrangement = Arrangement.Center,
|
||||
) {
|
||||
Text(
|
||||
text = name,
|
||||
style = MaterialTheme.typography.body1,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
color = MaterialTheme.typography.body1.color.copy(alpha = if (enabled) ContentAlpha.high else ContentAlpha.disabled)
|
||||
)
|
||||
Text(
|
||||
text = value,
|
||||
style = MaterialTheme.typography.caption,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
color = MaterialTheme.typography.caption.color.copy(alpha = if (enabled) ContentAlpha.medium else ContentAlpha.disabled)
|
||||
)
|
||||
}
|
||||
}
|
@ -0,0 +1,138 @@
|
||||
package me.magnum.melonds.ui.common.preference
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.focusable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.Dialog
|
||||
import me.magnum.melonds.R
|
||||
|
||||
@Composable
|
||||
fun SingleChoiceItem(
|
||||
name: String,
|
||||
value: String,
|
||||
items: List<String>,
|
||||
selectedItemIndex: Int,
|
||||
onItemSelected: (Int) -> Unit,
|
||||
) {
|
||||
var isDialogShown by remember {
|
||||
mutableStateOf(false)
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable { isDialogShown = true }
|
||||
.focusable()
|
||||
.heightIn(min = 64.dp)
|
||||
.padding(start = 16.dp, end = 16.dp, top = 8.dp, bottom = 8.dp),
|
||||
verticalArrangement = Arrangement.Center
|
||||
) {
|
||||
Text(
|
||||
text = name,
|
||||
style = MaterialTheme.typography.body1,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
Text(
|
||||
text = value,
|
||||
style = MaterialTheme.typography.caption,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
}
|
||||
|
||||
if (isDialogShown) {
|
||||
SingleChoiceDialog(
|
||||
title = name,
|
||||
items = items,
|
||||
selectedItemIndex = selectedItemIndex,
|
||||
onOptionSelected = onItemSelected,
|
||||
onDismissRequest = { isDialogShown = false },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SingleChoiceDialog(
|
||||
title: String,
|
||||
items: List<String>,
|
||||
selectedItemIndex: Int,
|
||||
onOptionSelected: (index: Int) -> Unit,
|
||||
onDismissRequest: () -> Unit,
|
||||
) {
|
||||
Dialog(
|
||||
onDismissRequest = onDismissRequest,
|
||||
) {
|
||||
Card(
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
Column(Modifier.fillMaxWidth()) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.heightIn(min = 64.dp)
|
||||
.padding(start = 24.dp, end = 24.dp),
|
||||
contentAlignment = Alignment.CenterStart,
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier,
|
||||
text = title,
|
||||
style = MaterialTheme.typography.h6,
|
||||
fontWeight = FontWeight.Bold,
|
||||
maxLines = 2,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
}
|
||||
|
||||
LazyColumn {
|
||||
itemsIndexed(items) { index, item ->
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable {
|
||||
onOptionSelected(index)
|
||||
onDismissRequest()
|
||||
}
|
||||
.heightIn(min = 48.dp)
|
||||
.padding(start = 24.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
RadioButton(
|
||||
selected = index == selectedItemIndex,
|
||||
onClick = null,
|
||||
)
|
||||
Spacer(Modifier.width(32.dp))
|
||||
Text(text = item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(52.dp)
|
||||
.padding(8.dp),
|
||||
horizontalArrangement = Arrangement.End,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
TextButton(onClick = { onDismissRequest() }) {
|
||||
Text(
|
||||
text = stringResource(id = R.string.cancel).uppercase(),
|
||||
style = MaterialTheme.typography.button,
|
||||
color = MaterialTheme.colors.secondary,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
package me.magnum.melonds.ui.common.preference
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.focusable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Switch
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import me.magnum.melonds.ui.common.melonSwitchColors
|
||||
|
||||
@Composable
|
||||
fun SwitchItem(
|
||||
name: String,
|
||||
isOn: Boolean,
|
||||
onToggle: (Boolean) -> Unit,
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable { onToggle(!isOn) }
|
||||
.focusable()
|
||||
.heightIn(min = 48.dp)
|
||||
.padding(start = 16.dp, end = 16.dp, top = 8.dp, bottom = 8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.weight(1f),
|
||||
text = name,
|
||||
style = MaterialTheme.typography.body1,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
Spacer(Modifier.width(16.dp))
|
||||
Switch(
|
||||
checked = isOn,
|
||||
onCheckedChange = null,
|
||||
colors = melonSwitchColors(),
|
||||
)
|
||||
}
|
||||
}
|
@ -32,10 +32,8 @@ import coil.request.ImageRequest
|
||||
import me.magnum.melonds.R
|
||||
import me.magnum.melonds.domain.model.retroachievements.RAUserAchievement
|
||||
import me.magnum.melonds.ui.common.MelonPreviewSet
|
||||
import me.magnum.melonds.ui.romdetails.ui.preview.mockRAAchievementPreview
|
||||
import me.magnum.melonds.ui.theme.MelonTheme
|
||||
import me.magnum.rcheevosapi.model.RAAchievement
|
||||
import me.magnum.rcheevosapi.model.RAGameId
|
||||
import java.net.URL
|
||||
|
||||
@Composable
|
||||
fun RomAchievementUi(
|
||||
@ -191,20 +189,7 @@ fun PreviewRomAchievementUi() {
|
||||
RomAchievementUi(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
userAchievement = RAUserAchievement(
|
||||
achievement = RAAchievement(
|
||||
id = 123,
|
||||
gameId = RAGameId(123),
|
||||
totalAwardsCasual = 5435,
|
||||
totalAwardsHardcore = 4532,
|
||||
title = "Amazing Achievement [m]",
|
||||
description = "Do the definitely amazing stuff while back-flipping on top of a turtle.",
|
||||
points = 10,
|
||||
displayOrder = 0,
|
||||
badgeUrlUnlocked = URL("http://localhost:80"),
|
||||
badgeUrlLocked = URL("http://localhost:80"),
|
||||
memoryAddress = "",
|
||||
type = RAAchievement.Type.CORE,
|
||||
),
|
||||
achievement = mockRAAchievementPreview(),
|
||||
isUnlocked = true,
|
||||
),
|
||||
onViewAchievement = {},
|
||||
|
@ -4,31 +4,25 @@ import android.app.Activity
|
||||
import android.content.Intent
|
||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.focusable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringArrayResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.Dialog
|
||||
import me.magnum.melonds.R
|
||||
import me.magnum.melonds.common.Permission
|
||||
import me.magnum.melonds.common.contracts.FilePickerContract
|
||||
import me.magnum.melonds.domain.model.RuntimeConsoleType
|
||||
import me.magnum.melonds.domain.model.RuntimeMicSource
|
||||
import me.magnum.melonds.ui.common.MelonPreviewSet
|
||||
import me.magnum.melonds.ui.common.melonSwitchColors
|
||||
import me.magnum.melonds.ui.common.preference.ActionLauncherItem
|
||||
import me.magnum.melonds.ui.common.preference.SingleChoiceItem
|
||||
import me.magnum.melonds.ui.common.preference.SwitchItem
|
||||
import me.magnum.melonds.ui.layouts.LayoutSelectorActivity
|
||||
import me.magnum.melonds.ui.romdetails.model.RomConfigUiModel
|
||||
import me.magnum.melonds.ui.romdetails.model.RomConfigUiState
|
||||
@ -149,196 +143,6 @@ private fun Content(
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SingleChoiceItem(
|
||||
name: String,
|
||||
value: String,
|
||||
items: List<String>,
|
||||
selectedItemIndex: Int,
|
||||
onItemSelected: (Int) -> Unit,
|
||||
) {
|
||||
var isDialogShown by remember {
|
||||
mutableStateOf(false)
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable { isDialogShown = true }
|
||||
.focusable()
|
||||
.heightIn(min = 64.dp)
|
||||
.padding(start = 16.dp, end = 16.dp, top = 8.dp, bottom = 8.dp),
|
||||
verticalArrangement = Arrangement.Center
|
||||
) {
|
||||
Text(
|
||||
text = name,
|
||||
style = MaterialTheme.typography.body1,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
Text(
|
||||
text = value,
|
||||
style = MaterialTheme.typography.caption,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
}
|
||||
|
||||
if (isDialogShown) {
|
||||
SingleChoiceDialog(
|
||||
title = name,
|
||||
items = items,
|
||||
selectedItemIndex = selectedItemIndex,
|
||||
onOptionSelected = onItemSelected,
|
||||
onDismissRequest = { isDialogShown = false },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SingleChoiceDialog(
|
||||
title: String,
|
||||
items: List<String>,
|
||||
selectedItemIndex: Int,
|
||||
onOptionSelected: (index: Int) -> Unit,
|
||||
onDismissRequest: () -> Unit,
|
||||
) {
|
||||
Dialog(
|
||||
onDismissRequest = onDismissRequest,
|
||||
) {
|
||||
Card(
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
Column(Modifier.fillMaxWidth()) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.heightIn(min = 64.dp)
|
||||
.padding(start = 24.dp, end = 24.dp),
|
||||
contentAlignment = Alignment.CenterStart,
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier,
|
||||
text = title,
|
||||
style = MaterialTheme.typography.h6,
|
||||
fontWeight = FontWeight.Bold,
|
||||
maxLines = 2,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
}
|
||||
|
||||
LazyColumn {
|
||||
itemsIndexed(items) { index, item ->
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable {
|
||||
onOptionSelected(index)
|
||||
onDismissRequest()
|
||||
}
|
||||
.heightIn(min = 48.dp)
|
||||
.padding(start = 24.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
RadioButton(
|
||||
selected = index == selectedItemIndex,
|
||||
onClick = null,
|
||||
)
|
||||
Spacer(Modifier.width(32.dp))
|
||||
Text(text = item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(52.dp)
|
||||
.padding(8.dp),
|
||||
horizontalArrangement = Arrangement.End,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
TextButton(onClick = { onDismissRequest() }) {
|
||||
Text(
|
||||
text = stringResource(id = R.string.cancel).uppercase(),
|
||||
style = MaterialTheme.typography.button,
|
||||
color = MaterialTheme.colors.secondary,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ActionLauncherItem(
|
||||
name: String,
|
||||
value: String,
|
||||
enabled: Boolean = true,
|
||||
onLaunchAction: () -> Unit,
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.run {
|
||||
if (enabled) {
|
||||
clickable { onLaunchAction() }.focusable()
|
||||
} else {
|
||||
this
|
||||
}
|
||||
}
|
||||
.heightIn(min = 64.dp)
|
||||
.padding(start = 16.dp, end = 16.dp, top = 8.dp, bottom = 8.dp),
|
||||
verticalArrangement = Arrangement.Center,
|
||||
) {
|
||||
Text(
|
||||
text = name,
|
||||
style = MaterialTheme.typography.body1,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
color = MaterialTheme.typography.body1.color.copy(alpha = if (enabled) ContentAlpha.high else ContentAlpha.disabled)
|
||||
)
|
||||
Text(
|
||||
text = value,
|
||||
style = MaterialTheme.typography.caption,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
color = MaterialTheme.typography.caption.color.copy(alpha = if (enabled) ContentAlpha.medium else ContentAlpha.disabled)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SwitchItem(
|
||||
name: String,
|
||||
isOn: Boolean,
|
||||
onToggle: (Boolean) -> Unit,
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable { onToggle(!isOn) }
|
||||
.focusable()
|
||||
.heightIn(min = 48.dp)
|
||||
.padding(start = 16.dp, end = 16.dp, top = 8.dp, bottom = 8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.weight(1f),
|
||||
text = name,
|
||||
style = MaterialTheme.typography.body1,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
Spacer(Modifier.width(16.dp))
|
||||
Switch(
|
||||
checked = isOn,
|
||||
onCheckedChange = null,
|
||||
colors = melonSwitchColors(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@MelonPreviewSet
|
||||
@Composable
|
||||
private fun PreviewRomConfigUi() {
|
||||
|
@ -19,10 +19,12 @@ import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import me.magnum.melonds.R
|
||||
import me.magnum.melonds.domain.model.retroachievements.RAUserAchievement
|
||||
import me.magnum.melonds.ui.common.MelonPreviewSet
|
||||
import me.magnum.melonds.ui.common.melonButtonColors
|
||||
import me.magnum.melonds.ui.romdetails.model.RomAchievementsSummary
|
||||
import me.magnum.melonds.ui.romdetails.model.RomRetroAchievementsUiState
|
||||
import me.magnum.melonds.ui.romdetails.ui.preview.mockRAAchievementPreview
|
||||
import me.magnum.melonds.ui.theme.MelonTheme
|
||||
import me.magnum.rcheevosapi.model.RAAchievement
|
||||
|
||||
@ -283,6 +285,24 @@ private fun LoadError(
|
||||
}
|
||||
}
|
||||
|
||||
@MelonPreviewSet
|
||||
@Composable
|
||||
private fun PreviewContent() {
|
||||
MelonTheme {
|
||||
Ready(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
content = RomRetroAchievementsUiState.Ready(
|
||||
listOf(
|
||||
RAUserAchievement(mockRAAchievementPreview(id = 1), false),
|
||||
RAUserAchievement(mockRAAchievementPreview(id = 2, title = "This is another amazing achievement", description = "But this one cannot be missed."), false),
|
||||
),
|
||||
RomAchievementsSummary(50, 20, 85),
|
||||
),
|
||||
onViewAchievement = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@MelonPreviewSet
|
||||
@Composable
|
||||
private fun PreviewLoggedOut() {
|
||||
|
@ -0,0 +1,35 @@
|
||||
package me.magnum.melonds.ui.romdetails.ui.preview
|
||||
|
||||
import me.magnum.rcheevosapi.model.RAAchievement
|
||||
import me.magnum.rcheevosapi.model.RAGameId
|
||||
import java.net.URL
|
||||
|
||||
fun mockRAAchievementPreview(
|
||||
id: Long = 1,
|
||||
gameId: Long = 123,
|
||||
totalAwardsCasual: Int = 5435,
|
||||
totalAwardsHardcore: Int = 4532,
|
||||
title: String = "Amazing Achievement [m]",
|
||||
description: String = "Do the definitely amazing stuff while back-flipping on top of a turtle.",
|
||||
points: Int = 10,
|
||||
displayOrder: Int = 0,
|
||||
badgeUrlUnlocked: String = "http://localhost:80",
|
||||
badgeUrlLocked: String = "http://localhost:80",
|
||||
memoryAddress: String = "",
|
||||
type: RAAchievement.Type = RAAchievement.Type.CORE,
|
||||
): RAAchievement {
|
||||
return RAAchievement(
|
||||
id = id,
|
||||
gameId = RAGameId(gameId),
|
||||
totalAwardsCasual = totalAwardsCasual,
|
||||
totalAwardsHardcore = totalAwardsHardcore,
|
||||
title = title,
|
||||
description = description,
|
||||
points = points,
|
||||
displayOrder = displayOrder,
|
||||
badgeUrlUnlocked = URL(badgeUrlUnlocked),
|
||||
badgeUrlLocked = URL(badgeUrlLocked),
|
||||
memoryAddress = memoryAddress,
|
||||
type = type,
|
||||
)
|
||||
}
|
Loading…
Reference in New Issue
Block a user