Refactored gamelist & emulation gui code

This commit is contained in:
SSimco
2025-03-10 17:15:53 +02:00
parent f73b921349
commit e919c23ea5
4 changed files with 59 additions and 51 deletions
@@ -189,7 +189,7 @@ class EmulationFragment(private val launchPath: String) : Fragment() {
}
private fun LayoutSideMenuTextItemBinding.setEnabled(isEnabled: Boolean) {
textItem.isClickable = isEnabled
textItem.isEnabled = isEnabled
textItem.alpha = if (isEnabled) 1f else 0.7f
}
@@ -37,11 +37,13 @@ class GameListViewModel : ViewModel() {
)
init {
NativeGameTitles.setGameTitleLoadedCallback(NativeGameTitles.GameTitleLoadedCallback { game: Game? ->
if (game == null || !isGameValid(game))
NativeGameTitles.setGameTitleLoadedCallback(NativeGameTitles.GameTitleLoadedCallback { game: Game ->
if (!game.isValid())
return@GameTitleLoadedCallback
if (_games.value.any { it.titleId == game.titleId })
return@GameTitleLoadedCallback
_games.value += game
})
refreshGames()
@@ -63,10 +65,6 @@ class GameListViewModel : ViewModel() {
_gameToRemoveShaders.value = null
}
private fun isGameValid(game: Game): Boolean {
return !game.path.isNullOrEmpty() && !game.name.isNullOrEmpty()
}
fun setGameTitleFavorite(game: Game, isFavorite: Boolean) {
if (!_games.value.contains(game)) {
return
@@ -82,7 +80,7 @@ class GameListViewModel : ViewModel() {
NativeGameTitles.setGameTitleLoadedCallback(null)
}
fun checkIfGamePathsHaveChanged(): Boolean {
fun gamePathsHaveChanged(): Boolean {
val newGamePaths = NativeSettings.getGamesPaths().toSet()
if (newGamePaths != gamePaths) {
gamePaths = newGamePaths
@@ -40,6 +40,7 @@ import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
@@ -56,6 +57,7 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.compose.LocalLifecycleOwner
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel
@@ -74,7 +76,6 @@ data class GamesListScreenActions(
val startGame: (Game) -> Unit,
)
@Composable
fun GamesListScreen(
selectedGameViewModel: GameViewModel,
@@ -83,27 +84,21 @@ fun GamesListScreen(
toolbarActions: @Composable RowScope.() -> Unit,
) {
val context = LocalContext.current
val lifecycleOwner = LocalLifecycleOwner.current
val lifecycleState by lifecycleOwner.lifecycle.currentStateFlow.collectAsState()
val coroutineScope = rememberCoroutineScope()
var refreshing by remember { mutableStateOf(false) }
val gameToRemoveShaders by gameListViewModel.gameToRemoveShaders.collectAsStateWithLifecycle()
val snackbarHostState = remember { SnackbarHostState() }
fun onRefresh() = coroutineScope.launch {
refreshing = true
gameListViewModel.refreshGames()
delay(1500)
refreshing = false
}
val state = rememberPullToRefreshState()
LaunchedEffect(Unit) {
if (gameListViewModel.checkIfGamePathsHaveChanged()) {
LaunchedEffect(lifecycleState) {
if (lifecycleState == Lifecycle.State.RESUMED && gameListViewModel.gamePathsHaveChanged())
gameListViewModel.refreshGames()
}
}
DisposableEffect(LocalLifecycleOwner.current) {
DisposableEffect(lifecycleOwner) {
onDispose {
gameListViewModel.setFilterText("")
}
@@ -125,7 +120,14 @@ fun GamesListScreen(
.pullToRefresh(
isRefreshing = refreshing,
state = state,
onRefresh = ::onRefresh,
onRefresh = {
coroutineScope.launch {
refreshing = true
gameListViewModel.refreshGames()
delay(1500)
refreshing = false
}
},
),
) {
GameList(
@@ -367,35 +369,39 @@ private fun createShortcutForGame(
game: Game,
onFailedToCreateShortCut: () -> Unit,
) {
val shortcutManager = context.getSystemService(
ShortcutManager::class.java
)
if (!shortcutManager.isRequestPinShortcutSupported) {
try {
val shortcutManager = context.getSystemService(
ShortcutManager::class.java
)
if (!shortcutManager.isRequestPinShortcutSupported) {
onFailedToCreateShortCut()
return
}
val icon = game.icon?.asAndroidBitmap().let {
if (it != null) ShortcutIcon.createWithBitmap(it)
else ShortcutIcon.createWithResource(context, R.mipmap.ic_launcher)
}
val intent = Intent(
context,
EmulationActivity::class.java
)
intent.setAction(Intent.ACTION_VIEW)
intent.putExtra(EmulationActivity.EXTRA_LAUNCH_PATH, game.path)
val pinShortcutInfo = ShortcutInfo.Builder(context, game.titleId.toString())
.setShortLabel(game.name!!)
.setIntent(intent)
.setIcon(icon)
.build()
val pinnedShortcutCallbackIntent =
shortcutManager.createShortcutResultIntent(pinShortcutInfo)
val successCallback = PendingIntent.getBroadcast(
context,
0,
pinnedShortcutCallbackIntent,
PendingIntent.FLAG_IMMUTABLE
)
shortcutManager.requestPinShortcut(pinShortcutInfo, successCallback.intentSender)
} catch (_: Exception) {
onFailedToCreateShortCut()
return
}
val icon = game.icon?.asAndroidBitmap().let {
if (it != null) ShortcutIcon.createWithBitmap(it)
else ShortcutIcon.createWithResource(context, R.mipmap.ic_launcher)
}
val intent = Intent(
context,
EmulationActivity::class.java
)
intent.setAction(Intent.ACTION_VIEW)
intent.putExtra(EmulationActivity.EXTRA_LAUNCH_PATH, game.path)
val pinShortcutInfo = ShortcutInfo.Builder(context, game.titleId.toString())
.setShortLabel(game.name!!)
.setIntent(intent)
.setIcon(icon)
.build()
val pinnedShortcutCallbackIntent =
shortcutManager.createShortcutResultIntent(pinShortcutInfo)
val successCallback = PendingIntent.getBroadcast(
context,
0,
pinnedShortcutCallbackIntent,
PendingIntent.FLAG_IMMUTABLE
)
shortcutManager.requestPinShortcut(pinShortcutInfo, successCallback.intentSender)
}
@@ -102,11 +102,15 @@ object NativeGameTitles {
}
val icon: ImageBitmap? = _icon?.asImageBitmap()
fun isValid(): Boolean {
return !path.isNullOrEmpty() && !name.isNullOrEmpty()
}
}
@Keep
fun interface GameTitleLoadedCallback {
fun onGameTitleLoaded(game: Game?)
fun onGameTitleLoaded(game: Game)
}
@Keep