From be176fd367d8d4836751c420d8e7f04958f04d5f Mon Sep 17 00:00:00 2001 From: BeZide93 Date: Fri, 5 Sep 2025 07:52:47 -0500 Subject: [PATCH] merged 2.0.3 Layout into 2.0.4 --- .../app/src/main/AndroidManifest.xml | 11 +- .../android/viewmodels/HomeViewModel.kt | 5 - .../org/kenjinx/android/views/HomeViews.kt | 251 ++++++++---------- .../app/src/main/res/values/styles.xml | 7 + .../app/src/main/res/values/themes.xml | 1 + 5 files changed, 129 insertions(+), 146 deletions(-) create mode 100644 src/KenjinxAndroid/app/src/main/res/values/styles.xml diff --git a/src/KenjinxAndroid/app/src/main/AndroidManifest.xml b/src/KenjinxAndroid/app/src/main/AndroidManifest.xml index 531936010..206682ed6 100644 --- a/src/KenjinxAndroid/app/src/main/AndroidManifest.xml +++ b/src/KenjinxAndroid/app/src/main/AndroidManifest.xml @@ -1,5 +1,6 @@ - + + diff --git a/src/KenjinxAndroid/app/src/main/java/org/kenjinx/android/viewmodels/HomeViewModel.kt b/src/KenjinxAndroid/app/src/main/java/org/kenjinx/android/viewmodels/HomeViewModel.kt index 25efe8412..92e9073a7 100644 --- a/src/KenjinxAndroid/app/src/main/java/org/kenjinx/android/viewmodels/HomeViewModel.kt +++ b/src/KenjinxAndroid/app/src/main/java/org/kenjinx/android/viewmodels/HomeViewModel.kt @@ -107,11 +107,6 @@ class HomeViewModel( for(game in loadedCache) { game.getGameInfo() - - if(game.isUnknown()) - { - loadedCache.remove(game); - } } } finally { isLoading.value = false diff --git a/src/KenjinxAndroid/app/src/main/java/org/kenjinx/android/views/HomeViews.kt b/src/KenjinxAndroid/app/src/main/java/org/kenjinx/android/views/HomeViews.kt index 3d010d16d..fa3c8de85 100644 --- a/src/KenjinxAndroid/app/src/main/java/org/kenjinx/android/views/HomeViews.kt +++ b/src/KenjinxAndroid/app/src/main/java/org/kenjinx/android/views/HomeViews.kt @@ -49,12 +49,12 @@ import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.material3.TextFieldDefaults import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.MutableState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue -import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip @@ -66,6 +66,7 @@ import androidx.compose.ui.input.nestedscroll.NestedScrollConnection import androidx.compose.ui.input.nestedscroll.NestedScrollSource import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview @@ -109,18 +110,16 @@ class HomeViews { val selectedModel = remember { mutableStateOf(viewModel.mainViewModel?.selected) } val query = remember { mutableStateOf("") } var refreshUser by remember { mutableStateOf(true) } - var isFabVisible by remember { mutableStateOf(true)} + var isFabVisible by remember { mutableStateOf(true) } val isNavigating = remember { mutableStateOf(false) } + val context = LocalContext.current + val nestedScrollConnection = remember { object : NestedScrollConnection { override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset { - if (available.y < -1) { - isFabVisible = false - } - if (available.y > 1) { - isFabVisible = true - } + if (available.y < -1) isFabVisible = false + if (available.y > 1) isFabVisible = true return Offset.Zero } } @@ -132,7 +131,7 @@ class HomeViews { Row( modifier = Modifier .fillMaxWidth() - .padding(horizontal = 16.dp,vertical = 8.dp) + .padding(horizontal = 16.dp, vertical = 8.dp) .background(MaterialTheme.colorScheme.surface), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically, @@ -162,7 +161,6 @@ class HomeViews { .clickable { if (!isNavigating.value) { isNavigating.value = true - val currentRoute = navController?.currentDestination?.route if (currentRoute != "user") { navController?.navigate("user") { @@ -170,7 +168,6 @@ class HomeViews { restoreState = true } } - CoroutineScope(Dispatchers.Main).launch { delay(500) isNavigating.value = false @@ -181,7 +178,6 @@ class HomeViews { ) { if (refreshUser && viewModel.mainViewModel?.userViewModel?.openedUser?.userPicture?.isNotEmpty() == true) { val pic = viewModel.mainViewModel.userViewModel.openedUser.userPicture - Image( bitmap = BitmapFactory.decodeByteArray( pic, @@ -201,11 +197,12 @@ class HomeViews { ) } } + + // Settings IconButton( onClick = { if (!isNavigating.value) { isNavigating.value = true - val currentRoute = navController?.currentDestination?.route if (currentRoute != "settings") { navController?.navigate("settings") { @@ -213,7 +210,6 @@ class HomeViews { restoreState = true } } - CoroutineScope(Dispatchers.Main).launch { delay(500) isNavigating.value = false @@ -229,33 +225,21 @@ class HomeViews { shape = RoundedCornerShape(8.dp) ) ) { - Icon( - Icons.Filled.Settings, - contentDescription = "Settings" - ) + Icon(Icons.Filled.Settings, contentDescription = "Settings") } + } OutlinedTextField( value = query.value, - onValueChange = { - query.value = it - }, + onValueChange = { query.value = it }, modifier = Modifier .weight(1f) .height(56.dp), placeholder = { - Text( - "Search...", - modifier = Modifier.padding(bottom = 4.dp) - ) - }, - leadingIcon = { - Icon( - Icons.Filled.Search, - contentDescription = "Search" - ) + Text("Search...", modifier = Modifier.padding(bottom = 4.dp)) }, + leadingIcon = { Icon(Icons.Filled.Search, contentDescription = "Search") }, singleLine = true, shape = RoundedCornerShape(8.dp), colors = TextFieldDefaults.outlinedTextFieldColors( @@ -289,11 +273,9 @@ class HomeViews { viewModel.filter(query.value) if (!isPreview) { - var settings = QuickSettings(viewModel.activity!!) - + val settings = QuickSettings(viewModel.activity!!) if (isLoading.value) { - Box(modifier = Modifier.fillMaxSize()) - { + Box(modifier = Modifier.fillMaxSize()) { CircularProgressIndicator( modifier = Modifier .width(64.dp) @@ -304,8 +286,7 @@ class HomeViews { } } else { if (settings.isGrid) { - val size = - GridImageSize / Resources.getSystem().displayMetrics.density + val size = GridImageSize / Resources.getSystem().displayMetrics.density LazyVerticalGrid( columns = GridCells.Adaptive(minSize = (size + 4).dp), modifier = Modifier @@ -318,8 +299,7 @@ class HomeViews { it.titleName?.apply { if (this.isNotEmpty() && (query.value.trim() .isEmpty() || this.lowercase(Locale.getDefault()) - .contains(query.value)) - ) + .contains(query.value))) { GridGameItem( it, viewModel, @@ -328,6 +308,7 @@ class HomeViews { selectedModel, showError ) + } } } } @@ -336,11 +317,8 @@ class HomeViews { items(list) { it.titleName?.apply { if (this.isNotEmpty() && (query.value.trim() - .isEmpty() || this.lowercase( - Locale.getDefault() - ) - .contains(query.value)) - ) + .isEmpty() || this.lowercase(Locale.getDefault()) + .contains(query.value))) { Box(modifier = Modifier.animateItemPlacement()) { ListGameItem( it, @@ -351,6 +329,7 @@ class HomeViews { showError ) } + } } } } @@ -381,27 +360,27 @@ class HomeViews { } } - if(viewModel.mainViewModel?.loadGameModel?.value != null) + if (viewModel.mainViewModel?.loadGameModel?.value != null) LaunchedEffect(viewModel.mainViewModel.loadGameModel.value) { - if (viewModel.mainViewModel.bootPath.value == "gameItem_${viewModel.mainViewModel.loadGameModel.value!!.titleName}") { + if (viewModel.mainViewModel.bootPath.value == + "gameItem_${viewModel.mainViewModel.loadGameModel.value!!.titleName}" + ) { viewModel.mainViewModel.bootPath.value = null thread { showLoading.value = true - val success = - viewModel.mainViewModel.loadGame( - viewModel.mainViewModel.loadGameModel.value!!, - true, - viewModel.mainViewModel.forceNceAndPptc.value - ) ?: false + val success = viewModel.mainViewModel.loadGame( + viewModel.mainViewModel.loadGameModel.value!!, + true, + viewModel.mainViewModel.forceNceAndPptc.value + ) ?: false if (success == 1) { launchOnUiThread { viewModel.mainViewModel.navigateToGame() } } else { if (success == -2) - showError.value = - "Error loading update. Please re-add update file" + showError.value = "Error loading update. Please re-add update file" viewModel.mainViewModel.loadGameModel.value!!.close() } showLoading.value = false @@ -421,8 +400,9 @@ class HomeViews { if (viewModel.mainViewModel?.selected != null) { thread { showLoading.value = true - val success = - viewModel.mainViewModel.loadGame(viewModel.mainViewModel.selected!!) + val success = viewModel.mainViewModel.loadGame( + viewModel.mainViewModel.selected!! + ) if (success == 1) { launchOnUiThread { viewModel.mainViewModel.navigateToGame() @@ -444,53 +424,54 @@ class HomeViews { } val showAppMenu = remember { mutableStateOf(false) } Box { - IconButton(onClick = { - showAppMenu.value = true - }) { - Icon( - Icons.Filled.Menu, - contentDescription = "Menu" - ) + 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 = "Delete All Cache") - }, onClick = { - showAppMenu.value = false - viewModel.mainViewModel?.deleteCache( - 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 - }) + 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 = "Delete All Cache") }, + onClick = { + showAppMenu.value = false + viewModel.mainViewModel?.deleteCache( + 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 + } + ) } } } @@ -513,9 +494,7 @@ class HomeViews { selectedModel: MutableState, showError: MutableState ) { - remember { - selectedModel - } + remember { selectedModel } val color = if (selectedModel.value == gameModel) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.surface @@ -530,19 +509,17 @@ class HomeViews { onClick = { if (viewModel.mainViewModel?.selected != null) { showAppActions.value = false - viewModel.mainViewModel.apply { - selected = null - } + viewModel.mainViewModel.apply { selected = null } selectedModel.value = null - } else if (gameModel.titleId.isNullOrEmpty() || gameModel.titleId != "0000000000000000" || gameModel.type == FileType.Nro) { + } else if (gameModel.titleId.isNullOrEmpty() + || gameModel.titleId != "0000000000000000" + || gameModel.type == FileType.Nro + ) { thread { showLoading.value = true - val success = - viewModel.mainViewModel?.loadGame(gameModel) ?: false + val success = viewModel.mainViewModel?.loadGame(gameModel) ?: false if (success == 1) { - launchOnUiThread { - viewModel.mainViewModel?.navigateToGame() - } + launchOnUiThread { viewModel.mainViewModel?.navigateToGame() } } else { if (success == -2) showError.value = @@ -557,7 +534,8 @@ class HomeViews { viewModel.mainViewModel?.selected = gameModel showAppActions.value = true selectedModel.value = gameModel - }) + } + ) ) { Row( modifier = Modifier @@ -566,22 +544,21 @@ class HomeViews { horizontalArrangement = Arrangement.SpaceBetween ) { Row { - if (!gameModel.titleId.isNullOrEmpty() && (gameModel.titleId != "0000000000000000" || gameModel.type == FileType.Nro)) { + if (!gameModel.titleId.isNullOrEmpty() + && (gameModel.titleId != "0000000000000000" || gameModel.type == FileType.Nro) + ) { if (gameModel.icon?.isNotEmpty() == true) { val pic = decoder.decode(gameModel.icon) - val size = - ListImageSize / Resources.getSystem().displayMetrics.density + val size = ListImageSize / Resources.getSystem().displayMetrics.density Image( - bitmap = BitmapFactory.decodeByteArray(pic, 0, pic.size) - .asImageBitmap(), + bitmap = BitmapFactory.decodeByteArray(pic, 0, pic.size).asImageBitmap(), contentDescription = gameModel.titleName + " icon", modifier = Modifier .padding(end = 8.dp) .width(size.roundToInt().dp) .height(size.roundToInt().dp) ) - } else if (gameModel.type == FileType.Nro) - NROIcon() + } else if (gameModel.type == FileType.Nro) NROIcon() else NotAvailableIcon() } else NotAvailableIcon() Column { @@ -608,9 +585,7 @@ class HomeViews { selectedModel: MutableState, showError: MutableState ) { - remember { - selectedModel - } + remember { selectedModel } val color = if (selectedModel.value == gameModel) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.surface @@ -625,19 +600,17 @@ class HomeViews { onClick = { if (viewModel.mainViewModel?.selected != null) { showAppActions.value = false - viewModel.mainViewModel.apply { - selected = null - } + viewModel.mainViewModel.apply { selected = null } selectedModel.value = null - } else if (gameModel.titleId.isNullOrEmpty() || gameModel.titleId != "0000000000000000" || gameModel.type == FileType.Nro) { + } else if (gameModel.titleId.isNullOrEmpty() + || gameModel.titleId != "0000000000000000" + || gameModel.type == FileType.Nro + ) { thread { showLoading.value = true - val success = - viewModel.mainViewModel?.loadGame(gameModel) ?: false + val success = viewModel.mainViewModel?.loadGame(gameModel) ?: false if (success == 1) { - launchOnUiThread { - viewModel.mainViewModel?.navigateToGame() - } + launchOnUiThread { viewModel.mainViewModel?.navigateToGame() } } else { if (success == -2) showError.value = @@ -652,23 +625,24 @@ class HomeViews { viewModel.mainViewModel?.selected = gameModel showAppActions.value = true selectedModel.value = gameModel - }) + } + ) ) { Column(modifier = Modifier.padding(4.dp)) { - if (!gameModel.titleId.isNullOrEmpty() && (gameModel.titleId != "0000000000000000" || gameModel.type == FileType.Nro)) { + if (!gameModel.titleId.isNullOrEmpty() + && (gameModel.titleId != "0000000000000000" || gameModel.type == FileType.Nro) + ) { if (gameModel.icon?.isNotEmpty() == true) { val pic = decoder.decode(gameModel.icon) Image( - bitmap = BitmapFactory.decodeByteArray(pic, 0, pic.size) - .asImageBitmap(), + bitmap = BitmapFactory.decodeByteArray(pic, 0, pic.size).asImageBitmap(), contentDescription = gameModel.titleName + " icon", modifier = Modifier .padding(0.dp) .clip(RoundedCornerShape(16.dp)) .align(Alignment.CenterHorizontally) ) - } else if (gameModel.type == FileType.Nro) - NROIcon() + } else if (gameModel.type == FileType.Nro) NROIcon() else NotAvailableIcon() } else NotAvailableIcon() Text( @@ -708,7 +682,6 @@ class HomeViews { .height(size.roundToInt().dp) ) } - } @Preview diff --git a/src/KenjinxAndroid/app/src/main/res/values/styles.xml b/src/KenjinxAndroid/app/src/main/res/values/styles.xml new file mode 100644 index 000000000..2d8f45e75 --- /dev/null +++ b/src/KenjinxAndroid/app/src/main/res/values/styles.xml @@ -0,0 +1,7 @@ + + + + +