forked from MeloNX/MeloNX
android - add grid list option
This commit is contained in:
parent
e5d54d5374
commit
bc6e5de507
@ -85,8 +85,11 @@ class HomeViewModel(
|
|||||||
if (file.extension == "xci" || file.extension == "nsp")
|
if (file.extension == "xci" || file.extension == "nsp")
|
||||||
activity.let {
|
activity.let {
|
||||||
val item = GameModel(file, it)
|
val item = GameModel(file, it)
|
||||||
files.add(item)
|
|
||||||
gameList.add(item)
|
if(item.titleId?.isNotEmpty() == true && item.titleName?.isNotEmpty() == true) {
|
||||||
|
files.add(item)
|
||||||
|
gameList.add(item)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ class QuickSettings(val activity: Activity) {
|
|||||||
var enableShaderCache: Boolean
|
var enableShaderCache: Boolean
|
||||||
var enableTextureRecompression: Boolean
|
var enableTextureRecompression: Boolean
|
||||||
var resScale : Float
|
var resScale : Float
|
||||||
|
var isGrid : Boolean
|
||||||
|
|
||||||
private var sharedPref: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(activity)
|
private var sharedPref: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(activity)
|
||||||
|
|
||||||
@ -29,5 +30,6 @@ class QuickSettings(val activity: Activity) {
|
|||||||
enableTextureRecompression = sharedPref.getBoolean("enableTextureRecompression", false)
|
enableTextureRecompression = sharedPref.getBoolean("enableTextureRecompression", false)
|
||||||
resScale = sharedPref.getFloat("resScale", 1f)
|
resScale = sharedPref.getFloat("resScale", 1f)
|
||||||
useVirtualController = sharedPref.getBoolean("useVirtualController", true)
|
useVirtualController = sharedPref.getBoolean("useVirtualController", true)
|
||||||
|
isGrid = sharedPref.getBoolean("isGrid", true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,8 @@ class SettingsViewModel(var navController: NavHostController, val activity: Main
|
|||||||
enableShaderCache: MutableState<Boolean>,
|
enableShaderCache: MutableState<Boolean>,
|
||||||
enableTextureRecompression: MutableState<Boolean>,
|
enableTextureRecompression: MutableState<Boolean>,
|
||||||
resScale: MutableState<Float>,
|
resScale: MutableState<Float>,
|
||||||
useVirtualController: MutableState<Boolean>
|
useVirtualController: MutableState<Boolean>,
|
||||||
|
isGrid: MutableState<Boolean>,
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -41,6 +42,7 @@ class SettingsViewModel(var navController: NavHostController, val activity: Main
|
|||||||
enableTextureRecompression.value = sharedPref.getBoolean("enableTextureRecompression", false)
|
enableTextureRecompression.value = sharedPref.getBoolean("enableTextureRecompression", false)
|
||||||
resScale.value = sharedPref.getFloat("resScale", 1f)
|
resScale.value = sharedPref.getFloat("resScale", 1f)
|
||||||
useVirtualController.value = sharedPref.getBoolean("useVirtualController", true)
|
useVirtualController.value = sharedPref.getBoolean("useVirtualController", true)
|
||||||
|
isGrid.value = sharedPref.getBoolean("isGrid", true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun save(
|
fun save(
|
||||||
@ -53,7 +55,8 @@ class SettingsViewModel(var navController: NavHostController, val activity: Main
|
|||||||
enableShaderCache: MutableState<Boolean>,
|
enableShaderCache: MutableState<Boolean>,
|
||||||
enableTextureRecompression: MutableState<Boolean>,
|
enableTextureRecompression: MutableState<Boolean>,
|
||||||
resScale: MutableState<Float>,
|
resScale: MutableState<Float>,
|
||||||
useVirtualController: MutableState<Boolean>
|
useVirtualController: MutableState<Boolean>,
|
||||||
|
isGrid: MutableState<Boolean>
|
||||||
){
|
){
|
||||||
val editor = sharedPref.edit()
|
val editor = sharedPref.edit()
|
||||||
|
|
||||||
@ -67,7 +70,8 @@ class SettingsViewModel(var navController: NavHostController, val activity: Main
|
|||||||
editor.putBoolean("enableTextureRecompression", enableTextureRecompression.value)
|
editor.putBoolean("enableTextureRecompression", enableTextureRecompression.value)
|
||||||
editor.putFloat("resScale", resScale.value)
|
editor.putFloat("resScale", resScale.value)
|
||||||
editor.putBoolean("useVirtualController", useVirtualController.value)
|
editor.putBoolean("useVirtualController", useVirtualController.value)
|
||||||
|
editor.putBoolean("isGrid", isGrid.value)
|
||||||
|
|
||||||
editor.apply()
|
editor.apply()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import android.content.res.Resources
|
|||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
|
import androidx.compose.foundation.basicMarquee
|
||||||
import androidx.compose.foundation.combinedClickable
|
import androidx.compose.foundation.combinedClickable
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
@ -18,8 +19,12 @@ import androidx.compose.foundation.layout.width
|
|||||||
import androidx.compose.foundation.layout.wrapContentHeight
|
import androidx.compose.foundation.layout.wrapContentHeight
|
||||||
import androidx.compose.foundation.layout.wrapContentWidth
|
import androidx.compose.foundation.layout.wrapContentWidth
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.lazy.grid.GridCells
|
||||||
|
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
||||||
|
import androidx.compose.foundation.lazy.grid.items
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
import androidx.compose.foundation.shape.CircleShape
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.Add
|
import androidx.compose.material.icons.filled.Add
|
||||||
import androidx.compose.material.icons.filled.Menu
|
import androidx.compose.material.icons.filled.Menu
|
||||||
@ -54,12 +59,14 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.graphics.asImageBitmap
|
import androidx.compose.ui.graphics.asImageBitmap
|
||||||
import androidx.compose.ui.layout.ContentScale
|
import androidx.compose.ui.layout.ContentScale
|
||||||
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.navigation.NavHostController
|
import androidx.navigation.NavHostController
|
||||||
import com.anggrayudi.storage.extension.launchOnUiThread
|
import com.anggrayudi.storage.extension.launchOnUiThread
|
||||||
import org.ryujinx.android.viewmodels.GameModel
|
import org.ryujinx.android.viewmodels.GameModel
|
||||||
import org.ryujinx.android.viewmodels.HomeViewModel
|
import org.ryujinx.android.viewmodels.HomeViewModel
|
||||||
|
import org.ryujinx.android.viewmodels.QuickSettings
|
||||||
import java.util.Base64
|
import java.util.Base64
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import kotlin.concurrent.thread
|
import kotlin.concurrent.thread
|
||||||
@ -67,7 +74,8 @@ import kotlin.math.roundToInt
|
|||||||
|
|
||||||
class HomeViews {
|
class HomeViews {
|
||||||
companion object {
|
companion object {
|
||||||
const val ImageSize = 150
|
const val ListImageSize = 150
|
||||||
|
const val GridImageSize = 256
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
@ -157,108 +165,108 @@ class HomeViews {
|
|||||||
bottomBar = {
|
bottomBar = {
|
||||||
BottomAppBar(
|
BottomAppBar(
|
||||||
actions = {
|
actions = {
|
||||||
if (showAppActions.value) {
|
if (showAppActions.value) {
|
||||||
IconButton(onClick = {
|
|
||||||
if(viewModel.mainViewModel?.selected != null) {
|
|
||||||
thread {
|
|
||||||
showLoading.value = true
|
|
||||||
val success =
|
|
||||||
viewModel.mainViewModel?.loadGame(viewModel.mainViewModel.selected!!)
|
|
||||||
?: false
|
|
||||||
if (success) {
|
|
||||||
launchOnUiThread {
|
|
||||||
viewModel.mainViewModel?.navigateToGame()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
viewModel.mainViewModel?.selected!!.close()
|
|
||||||
}
|
|
||||||
showLoading.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}) {
|
|
||||||
Icon(
|
|
||||||
org.ryujinx.android.Icons.playArrow(MaterialTheme.colorScheme.onSurface),
|
|
||||||
contentDescription = "Run"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
val showAppMenu = remember { mutableStateOf(false) }
|
|
||||||
Box {
|
|
||||||
IconButton(onClick = {
|
IconButton(onClick = {
|
||||||
showAppMenu.value = true
|
if (viewModel.mainViewModel?.selected != null) {
|
||||||
|
thread {
|
||||||
|
showLoading.value = true
|
||||||
|
val success =
|
||||||
|
viewModel.mainViewModel?.loadGame(viewModel.mainViewModel.selected!!)
|
||||||
|
?: false
|
||||||
|
if (success) {
|
||||||
|
launchOnUiThread {
|
||||||
|
viewModel.mainViewModel?.navigateToGame()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
viewModel.mainViewModel?.selected!!.close()
|
||||||
|
}
|
||||||
|
showLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
}) {
|
}) {
|
||||||
Icon(
|
Icon(
|
||||||
Icons.Filled.Menu,
|
org.ryujinx.android.Icons.playArrow(MaterialTheme.colorScheme.onSurface),
|
||||||
contentDescription = "Menu"
|
contentDescription = "Run"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
val showAppMenu = remember { mutableStateOf(false) }
|
||||||
|
Box {
|
||||||
|
IconButton(onClick = {
|
||||||
|
showAppMenu.value = true
|
||||||
|
}) {
|
||||||
|
Icon(
|
||||||
|
Icons.Filled.Menu,
|
||||||
|
contentDescription = "Menu"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
DropdownMenu(
|
||||||
|
expanded = showAppMenu.value,
|
||||||
|
onDismissRequest = { showAppMenu.value = false }) {
|
||||||
|
DropdownMenuItem(text = {
|
||||||
|
Text(text = "Clear PPTC Cache")
|
||||||
|
}, onClick = {
|
||||||
|
showAppMenu.value = false
|
||||||
|
viewModel.mainViewModel?.clearPptcCache(
|
||||||
|
viewModel.mainViewModel?.selected?.titleId ?: ""
|
||||||
|
)
|
||||||
|
})
|
||||||
|
DropdownMenuItem(text = {
|
||||||
|
Text(text = "Purge Shader Cache")
|
||||||
|
}, onClick = {
|
||||||
|
showAppMenu.value = false
|
||||||
|
viewModel.mainViewModel?.purgeShaderCache(
|
||||||
|
viewModel.mainViewModel?.selected?.titleId ?: ""
|
||||||
|
)
|
||||||
|
})
|
||||||
|
DropdownMenuItem(text = {
|
||||||
|
Text(text = "Manage Updates")
|
||||||
|
}, onClick = {
|
||||||
|
showAppMenu.value = false
|
||||||
|
openTitleUpdateDialog.value = true
|
||||||
|
})
|
||||||
|
DropdownMenuItem(text = {
|
||||||
|
Text(text = "Manage DLC")
|
||||||
|
}, onClick = {
|
||||||
|
showAppMenu.value = false
|
||||||
|
openDlcDialog.value = true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*\val showAppletMenu = remember { mutableStateOf(false) }
|
||||||
|
Box {
|
||||||
|
IconButton(onClick = {
|
||||||
|
showAppletMenu.value = true
|
||||||
|
}) {
|
||||||
|
Icon(
|
||||||
|
org.ryujinx.android.Icons.applets(MaterialTheme.colorScheme.onSurface),
|
||||||
|
contentDescription = "Applets"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
DropdownMenu(
|
DropdownMenu(
|
||||||
expanded = showAppMenu.value,
|
expanded = showAppletMenu.value,
|
||||||
onDismissRequest = { showAppMenu.value = false }) {
|
onDismissRequest = { showAppletMenu.value = false }) {
|
||||||
DropdownMenuItem(text = {
|
DropdownMenuItem(text = {
|
||||||
Text(text = "Clear PPTC Cache")
|
Text(text = "Launch Mii Editor")
|
||||||
}, onClick = {
|
}, onClick = {
|
||||||
showAppMenu.value = false
|
showAppletMenu.value = false
|
||||||
viewModel.mainViewModel?.clearPptcCache(
|
showLoading.value = true
|
||||||
viewModel.mainViewModel?.selected?.titleId ?: ""
|
thread {
|
||||||
)
|
val success =
|
||||||
})
|
viewModel.mainViewModel?.loadMiiEditor() ?: false
|
||||||
DropdownMenuItem(text = {
|
if (success) {
|
||||||
Text(text = "Purge Shader Cache")
|
launchOnUiThread {
|
||||||
}, onClick = {
|
viewModel.mainViewModel?.navigateToGame()
|
||||||
showAppMenu.value = false
|
}
|
||||||
viewModel.mainViewModel?.purgeShaderCache(
|
} else
|
||||||
viewModel.mainViewModel?.selected?.titleId ?: ""
|
viewModel.mainViewModel!!.isMiiEditorLaunched = false
|
||||||
)
|
showLoading.value = false
|
||||||
})
|
}
|
||||||
DropdownMenuItem(text = {
|
|
||||||
Text(text = "Manage Updates")
|
|
||||||
}, onClick = {
|
|
||||||
showAppMenu.value = false
|
|
||||||
openTitleUpdateDialog.value = true
|
|
||||||
})
|
|
||||||
DropdownMenuItem(text = {
|
|
||||||
Text(text = "Manage DLC")
|
|
||||||
}, onClick = {
|
|
||||||
showAppMenu.value = false
|
|
||||||
openDlcDialog.value = true
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
}
|
},
|
||||||
|
|
||||||
/*\val showAppletMenu = remember { mutableStateOf(false) }
|
|
||||||
Box {
|
|
||||||
IconButton(onClick = {
|
|
||||||
showAppletMenu.value = true
|
|
||||||
}) {
|
|
||||||
Icon(
|
|
||||||
org.ryujinx.android.Icons.applets(MaterialTheme.colorScheme.onSurface),
|
|
||||||
contentDescription = "Applets"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
DropdownMenu(
|
|
||||||
expanded = showAppletMenu.value,
|
|
||||||
onDismissRequest = { showAppletMenu.value = false }) {
|
|
||||||
DropdownMenuItem(text = {
|
|
||||||
Text(text = "Launch Mii Editor")
|
|
||||||
}, onClick = {
|
|
||||||
showAppletMenu.value = false
|
|
||||||
showLoading.value = true
|
|
||||||
thread {
|
|
||||||
val success =
|
|
||||||
viewModel.mainViewModel?.loadMiiEditor() ?: false
|
|
||||||
if (success) {
|
|
||||||
launchOnUiThread {
|
|
||||||
viewModel.mainViewModel?.navigateToGame()
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
viewModel.mainViewModel!!.isMiiEditorLaunched = false
|
|
||||||
showLoading.value = false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
},
|
|
||||||
floatingActionButton = {
|
floatingActionButton = {
|
||||||
FloatingActionButton(
|
FloatingActionButton(
|
||||||
onClick = {
|
onClick = {
|
||||||
@ -285,22 +293,51 @@ class HomeViews {
|
|||||||
val selectedModel = remember {
|
val selectedModel = remember {
|
||||||
mutableStateOf(viewModel.mainViewModel?.selected)
|
mutableStateOf(viewModel.mainViewModel?.selected)
|
||||||
}
|
}
|
||||||
LazyColumn(Modifier.fillMaxSize()) {
|
var settings = QuickSettings(viewModel.activity!!)
|
||||||
items(list) {
|
|
||||||
it.titleName?.apply {
|
if (settings.isGrid) {
|
||||||
if (this.isNotEmpty() && (query.value.trim()
|
val size = GridImageSize / Resources.getSystem().displayMetrics.density
|
||||||
.isEmpty() || this.lowercase(
|
LazyVerticalGrid(
|
||||||
Locale.getDefault()
|
columns = GridCells.Adaptive(minSize = (size + 4).dp),
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
) {
|
||||||
|
items(list) {
|
||||||
|
it.titleName?.apply {
|
||||||
|
if (this.isNotEmpty() && (query.value.trim()
|
||||||
|
.isEmpty() || this.lowercase(
|
||||||
|
Locale.getDefault()
|
||||||
|
)
|
||||||
|
.contains(query.value))
|
||||||
)
|
)
|
||||||
.contains(query.value))
|
GridGameItem(
|
||||||
)
|
it,
|
||||||
GameItem(
|
viewModel,
|
||||||
it,
|
showAppActions,
|
||||||
viewModel,
|
showLoading,
|
||||||
showAppActions,
|
selectedModel
|
||||||
showLoading,
|
)
|
||||||
selectedModel
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LazyColumn(Modifier.fillMaxSize()) {
|
||||||
|
items(list) {
|
||||||
|
it.titleName?.apply {
|
||||||
|
if (this.isNotEmpty() && (query.value.trim()
|
||||||
|
.isEmpty() || this.lowercase(
|
||||||
|
Locale.getDefault()
|
||||||
|
)
|
||||||
|
.contains(query.value))
|
||||||
)
|
)
|
||||||
|
ListGameItem(
|
||||||
|
it,
|
||||||
|
viewModel,
|
||||||
|
showAppActions,
|
||||||
|
showLoading,
|
||||||
|
selectedModel
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -372,7 +409,7 @@ class HomeViews {
|
|||||||
|
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun GameItem(
|
fun ListGameItem(
|
||||||
gameModel: GameModel,
|
gameModel: GameModel,
|
||||||
viewModel: HomeViewModel,
|
viewModel: HomeViewModel,
|
||||||
showAppActions: MutableState<Boolean>,
|
showAppActions: MutableState<Boolean>,
|
||||||
@ -432,7 +469,8 @@ class HomeViews {
|
|||||||
if (!gameModel.titleId.isNullOrEmpty() && gameModel.titleId != "0000000000000000") {
|
if (!gameModel.titleId.isNullOrEmpty() && gameModel.titleId != "0000000000000000") {
|
||||||
if (gameModel.icon?.isNotEmpty() == true) {
|
if (gameModel.icon?.isNotEmpty() == true) {
|
||||||
val pic = decoder.decode(gameModel.icon)
|
val pic = decoder.decode(gameModel.icon)
|
||||||
val size = ImageSize / Resources.getSystem().displayMetrics.density
|
val size =
|
||||||
|
ListImageSize / Resources.getSystem().displayMetrics.density
|
||||||
Image(
|
Image(
|
||||||
bitmap = BitmapFactory.decodeByteArray(pic, 0, pic.size)
|
bitmap = BitmapFactory.decodeByteArray(pic, 0, pic.size)
|
||||||
.asImageBitmap(),
|
.asImageBitmap(),
|
||||||
@ -458,9 +496,92 @@ class HomeViews {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
|
@Composable
|
||||||
|
fun GridGameItem(
|
||||||
|
gameModel: GameModel,
|
||||||
|
viewModel: HomeViewModel,
|
||||||
|
showAppActions: MutableState<Boolean>,
|
||||||
|
showLoading: MutableState<Boolean>,
|
||||||
|
selectedModel: MutableState<GameModel?>
|
||||||
|
) {
|
||||||
|
remember {
|
||||||
|
selectedModel
|
||||||
|
}
|
||||||
|
val color =
|
||||||
|
if (selectedModel.value == gameModel) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.surface
|
||||||
|
|
||||||
|
val decoder = Base64.getDecoder()
|
||||||
|
Surface(
|
||||||
|
shape = MaterialTheme.shapes.medium,
|
||||||
|
color = color,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(8.dp)
|
||||||
|
.combinedClickable(
|
||||||
|
onClick = {
|
||||||
|
if (viewModel.mainViewModel?.selected != null) {
|
||||||
|
showAppActions.value = false
|
||||||
|
viewModel.mainViewModel?.apply {
|
||||||
|
selected = null
|
||||||
|
}
|
||||||
|
selectedModel.value = null
|
||||||
|
} else if (gameModel.titleId.isNullOrEmpty() || gameModel.titleId != "0000000000000000") {
|
||||||
|
thread {
|
||||||
|
showLoading.value = true
|
||||||
|
val success =
|
||||||
|
viewModel.mainViewModel?.loadGame(gameModel) ?: false
|
||||||
|
if (success) {
|
||||||
|
launchOnUiThread {
|
||||||
|
viewModel.mainViewModel?.navigateToGame()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
gameModel.close()
|
||||||
|
}
|
||||||
|
showLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLongClick = {
|
||||||
|
viewModel.mainViewModel?.selected = gameModel
|
||||||
|
showAppActions.value = true
|
||||||
|
selectedModel.value = gameModel
|
||||||
|
})
|
||||||
|
) {
|
||||||
|
Column {
|
||||||
|
if (!gameModel.titleId.isNullOrEmpty() && gameModel.titleId != "0000000000000000") {
|
||||||
|
if (gameModel.icon?.isNotEmpty() == true) {
|
||||||
|
val pic = decoder.decode(gameModel.icon)
|
||||||
|
val size = GridImageSize / Resources.getSystem().displayMetrics.density
|
||||||
|
Image(
|
||||||
|
bitmap = BitmapFactory.decodeByteArray(pic, 0, pic.size)
|
||||||
|
.asImageBitmap(),
|
||||||
|
contentDescription = gameModel.titleName + " icon",
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(0.dp)
|
||||||
|
.clip(RoundedCornerShape(16.dp))
|
||||||
|
)
|
||||||
|
} else NotAvailableIcon()
|
||||||
|
} else NotAvailableIcon()
|
||||||
|
Text(
|
||||||
|
text = gameModel.titleName ?: "N/A",
|
||||||
|
maxLines = 1,
|
||||||
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
modifier = Modifier.basicMarquee()
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = gameModel.developer ?: "N/A",
|
||||||
|
maxLines = 1,
|
||||||
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
modifier = Modifier.basicMarquee()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun NotAvailableIcon() {
|
fun NotAvailableIcon() {
|
||||||
val size = ImageSize / Resources.getSystem().displayMetrics.density
|
val size = ListImageSize / Resources.getSystem().displayMetrics.density
|
||||||
Icon(
|
Icon(
|
||||||
Icons.Filled.Add,
|
Icons.Filled.Add,
|
||||||
contentDescription = "Options",
|
contentDescription = "Options",
|
||||||
|
@ -103,6 +103,9 @@ class SettingViews {
|
|||||||
val useVirtualController = remember {
|
val useVirtualController = remember {
|
||||||
mutableStateOf(true)
|
mutableStateOf(true)
|
||||||
}
|
}
|
||||||
|
val isGrid = remember {
|
||||||
|
mutableStateOf(true)
|
||||||
|
}
|
||||||
|
|
||||||
if (!loaded.value) {
|
if (!loaded.value) {
|
||||||
settingsViewModel.initializeState(
|
settingsViewModel.initializeState(
|
||||||
@ -112,7 +115,8 @@ class SettingViews {
|
|||||||
enableShaderCache,
|
enableShaderCache,
|
||||||
enableTextureRecompression,
|
enableTextureRecompression,
|
||||||
resScale,
|
resScale,
|
||||||
useVirtualController
|
useVirtualController,
|
||||||
|
isGrid
|
||||||
)
|
)
|
||||||
loaded.value = true
|
loaded.value = true
|
||||||
}
|
}
|
||||||
@ -134,7 +138,8 @@ class SettingViews {
|
|||||||
enableShaderCache,
|
enableShaderCache,
|
||||||
enableTextureRecompression,
|
enableTextureRecompression,
|
||||||
resScale,
|
resScale,
|
||||||
useVirtualController
|
useVirtualController,
|
||||||
|
isGrid
|
||||||
)
|
)
|
||||||
settingsViewModel.navController.popBackStack()
|
settingsViewModel.navController.popBackStack()
|
||||||
}) {
|
}) {
|
||||||
@ -145,6 +150,25 @@ class SettingViews {
|
|||||||
Column(modifier = Modifier
|
Column(modifier = Modifier
|
||||||
.padding(contentPadding)
|
.padding(contentPadding)
|
||||||
.verticalScroll(rememberScrollState())) {
|
.verticalScroll(rememberScrollState())) {
|
||||||
|
ExpandableView(onCardArrowClick = { }, title = "App") {
|
||||||
|
Column(modifier = Modifier.fillMaxWidth()) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(8.dp),
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Use Grid",
|
||||||
|
modifier = Modifier.align(Alignment.CenterVertically)
|
||||||
|
)
|
||||||
|
Switch(checked = isGrid.value, onCheckedChange = {
|
||||||
|
isGrid.value = !isGrid.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
ExpandableView(onCardArrowClick = { }, title = "System") {
|
ExpandableView(onCardArrowClick = { }, title = "System") {
|
||||||
Column(modifier = Modifier.fillMaxWidth()) {
|
Column(modifier = Modifier.fillMaxWidth()) {
|
||||||
Row(
|
Row(
|
||||||
@ -602,7 +626,8 @@ class SettingViews {
|
|||||||
enableShaderCache,
|
enableShaderCache,
|
||||||
enableTextureRecompression,
|
enableTextureRecompression,
|
||||||
resScale,
|
resScale,
|
||||||
useVirtualController
|
useVirtualController,
|
||||||
|
isGrid
|
||||||
)
|
)
|
||||||
settingsViewModel.navController.popBackStack()
|
settingsViewModel.navController.popBackStack()
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user