From 5971c9fef851d76799904ad612870e5778a3185f Mon Sep 17 00:00:00 2001 From: phobos665 Date: Wed, 26 Nov 2025 23:07:58 +0000 Subject: [PATCH] initial commit to show controller support and filter via it. --- .../java/app/gamenative/data/LibraryItem.kt | 2 ++ .../app/gamenative/ui/data/GameDisplayInfo.kt | 3 ++ .../java/app/gamenative/ui/enums/AppFilter.kt | 6 ++++ .../gamenative/ui/model/LibraryViewModel.kt | 8 ++++++ .../ui/screen/library/LibraryAppScreen.kt | 24 ++++++++++++++++ .../library/appscreen/SteamAppScreen.kt | 1 + .../library/components/LibraryAppItem.kt | 28 +++++++++++++++++-- 7 files changed, 70 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/app/gamenative/data/LibraryItem.kt b/app/src/main/java/app/gamenative/data/LibraryItem.kt index b7271ccca..f204563ae 100644 --- a/app/src/main/java/app/gamenative/data/LibraryItem.kt +++ b/app/src/main/java/app/gamenative/data/LibraryItem.kt @@ -1,6 +1,7 @@ package app.gamenative.data import app.gamenative.Constants +import app.gamenative.enums.ControllerSupport import app.gamenative.utils.CustomGameScanner enum class GameSource { @@ -19,6 +20,7 @@ data class LibraryItem( val iconHash: String = "", val isShared: Boolean = false, val gameSource: GameSource = GameSource.STEAM, + val controllerSupport: ControllerSupport = ControllerSupport.none, ) { val clientIconUrl: String get() = when (gameSource) { diff --git a/app/src/main/java/app/gamenative/ui/data/GameDisplayInfo.kt b/app/src/main/java/app/gamenative/ui/data/GameDisplayInfo.kt index 6d9654045..e955a3b15 100644 --- a/app/src/main/java/app/gamenative/ui/data/GameDisplayInfo.kt +++ b/app/src/main/java/app/gamenative/ui/data/GameDisplayInfo.kt @@ -1,5 +1,7 @@ package app.gamenative.ui.data +import app.gamenative.enums.ControllerSupport + /** * Common data structure for displaying game information in the UI. * This allows both Steam and Custom Games to use the same UI layout. @@ -20,5 +22,6 @@ data class GameDisplayInfo( val logoUrl: String? = null, // Logo image URL (for SteamGridDB) val capsuleUrl: String? = null, // Capsule/grid image URL (for SteamGridDB) val headerUrl: String? = null, // Header image URL (for SteamGridDB, can use grid as header) + val controllerSupport: ControllerSupport = ControllerSupport.none, ) diff --git a/app/src/main/java/app/gamenative/ui/enums/AppFilter.kt b/app/src/main/java/app/gamenative/ui/enums/AppFilter.kt index e891f2acf..246bfa773 100644 --- a/app/src/main/java/app/gamenative/ui/enums/AppFilter.kt +++ b/app/src/main/java/app/gamenative/ui/enums/AppFilter.kt @@ -6,6 +6,7 @@ import androidx.compose.material.icons.filled.Build import androidx.compose.material.icons.filled.Computer import androidx.compose.material.icons.filled.Diversity3 import androidx.compose.material.icons.filled.InstallMobile +import androidx.compose.material.icons.filled.SportsEsports import androidx.compose.material.icons.filled.VideogameAsset import androidx.compose.ui.graphics.vector.ImageVector import app.gamenative.enums.AppType @@ -46,6 +47,11 @@ enum class AppFilter( displayText = "Family", icon = Icons.Default.Diversity3, ), + CONTROLLER_SUPPORT( + code = 0x40, + displayText = "Controller Support", + icon = Icons.Default.SportsEsports, + ), // ALPHABETIC( // code = 0x20, // displayText = "Alphabetic", diff --git a/app/src/main/java/app/gamenative/ui/model/LibraryViewModel.kt b/app/src/main/java/app/gamenative/ui/model/LibraryViewModel.kt index d5599edae..d02552026 100644 --- a/app/src/main/java/app/gamenative/ui/model/LibraryViewModel.kt +++ b/app/src/main/java/app/gamenative/ui/model/LibraryViewModel.kt @@ -222,6 +222,13 @@ class LibraryViewModel @Inject constructor( true } } + .filter { item -> + if (currentState.appInfoSortType.contains(AppFilter.CONTROLLER_SUPPORT)) { + item.controllerSupport != app.gamenative.enums.ControllerSupport.none || !gameSource + } else { + true + } + } .sortedWith( compareByDescending { downloadDirectorySet.contains(SteamService.getAppDirName(it)) @@ -240,6 +247,7 @@ class LibraryViewModel @Inject constructor( name = item.name, iconHash = item.clientIconHash, isShared = (PrefManager.steamUserAccountId != 0 && !item.ownerAccountId.contains(PrefManager.steamUserAccountId)), + controllerSupport = item.controllerSupport, ), isInstalled = isInstalled, ) diff --git a/app/src/main/java/app/gamenative/ui/screen/library/LibraryAppScreen.kt b/app/src/main/java/app/gamenative/ui/screen/library/LibraryAppScreen.kt index 39e687cef..2d4a21b78 100644 --- a/app/src/main/java/app/gamenative/ui/screen/library/LibraryAppScreen.kt +++ b/app/src/main/java/app/gamenative/ui/screen/library/LibraryAppScreen.kt @@ -28,6 +28,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.MoreVert +import androidx.compose.material.icons.filled.SportsEsports import androidx.compose.material3.AlertDialog import androidx.compose.material3.Button import androidx.compose.material3.ButtonDefaults @@ -297,6 +298,28 @@ internal fun AppScreenContent( BackButton(onClick = onBack) } + // Controller support icon (top right, next to settings) + if (displayInfo.controllerSupport != app.gamenative.enums.ControllerSupport.none) { + Box( + modifier = Modifier + .align(Alignment.BottomEnd) + .padding(top = 20.dp, end = 76.dp) + .size(28.dp) + .background( + color = Color.Black.copy(alpha = 0.6f), + shape = RoundedCornerShape(8.dp) + ) + .padding(4.dp) + ) { + Icon( + imageVector = Icons.Filled.SportsEsports, + contentDescription = "Controller Support", + tint = Color.White, + modifier = Modifier.fillMaxSize() + ) + } + } + // Settings/options button (top right) Box( modifier = Modifier @@ -854,6 +877,7 @@ private fun Preview_AppScreen() { sizeFromStore = null, lastPlayedText = null, playtimeText = null, + controllerSupport = fakeApp.controllerSupport, ) PluviaTheme { Surface { diff --git a/app/src/main/java/app/gamenative/ui/screen/library/appscreen/SteamAppScreen.kt b/app/src/main/java/app/gamenative/ui/screen/library/appscreen/SteamAppScreen.kt index 9c054b9d8..33ee03934 100644 --- a/app/src/main/java/app/gamenative/ui/screen/library/appscreen/SteamAppScreen.kt +++ b/app/src/main/java/app/gamenative/ui/screen/library/appscreen/SteamAppScreen.kt @@ -261,6 +261,7 @@ class SteamAppScreen : BaseAppScreen() { sizeFromStore = sizeFromStore, lastPlayedText = lastPlayedText, playtimeText = playtimeText, + controllerSupport = appInfo.controllerSupport, ) } diff --git a/app/src/main/java/app/gamenative/ui/screen/library/components/LibraryAppItem.kt b/app/src/main/java/app/gamenative/ui/screen/library/components/LibraryAppItem.kt index 4f0273a62..09cad7c6a 100644 --- a/app/src/main/java/app/gamenative/ui/screen/library/components/LibraryAppItem.kt +++ b/app/src/main/java/app/gamenative/ui/screen/library/components/LibraryAppItem.kt @@ -11,6 +11,7 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.aspectRatio +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding @@ -25,6 +26,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Check import androidx.compose.material.icons.filled.Face4 +import androidx.compose.material.icons.filled.SportsEsports import androidx.compose.material3.Button import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.Card @@ -83,7 +85,7 @@ internal fun AppItem( hideText = true alpha = 1f } - + // Reset alpha and hideText when image URL changes (e.g., when new images are fetched) LaunchedEffect(imageRefreshCounter) { if (paneType != PaneType.LIST) { @@ -230,7 +232,7 @@ internal fun AppItem( } } } - + // Reset alpha and hideText when image URL changes (e.g., when new images are fetched) LaunchedEffect(imageUrl) { if (paneType != PaneType.LIST) { @@ -249,6 +251,28 @@ internal fun AppItem( } ) + // Controller support icon (top-right corner) + if (hideText && appInfo.controllerSupport != app.gamenative.enums.ControllerSupport.none) { + Box( + modifier = Modifier + .align(Alignment.TopEnd) + .padding(6.dp) + .size(20.dp) + .background( + color = Color.Black.copy(alpha = 0.7f), + shape = RoundedCornerShape(4.dp) + ) + .padding(2.dp) + ) { + Icon( + imageVector = Icons.Filled.SportsEsports, + contentDescription = "Controller Support", + tint = Color.White, + modifier = Modifier.fillMaxSize() + ) + } + } + // Only display text if the image loading has failed if (! hideText) { GameInfoBlock(