android - adjust grid view design, remove bottom app bar

This commit is contained in:
Emmanuel Hansen 2023-11-12 19:36:10 +00:00
parent bc6e5de507
commit 9765f7a388
5 changed files with 161 additions and 161 deletions

View File

@ -11,8 +11,8 @@ android {
applicationId "org.ryujinx.android"
minSdk 30
targetSdk 33
versionCode 10004
versionName '1.0.4'
versionCode 10006
versionName '1.0.6'
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {

View File

@ -6,9 +6,7 @@ import androidx.documentfile.provider.DocumentFile
import androidx.preference.PreferenceManager
import com.anggrayudi.storage.file.DocumentFileCompat
import com.anggrayudi.storage.file.DocumentFileType
import com.anggrayudi.storage.file.FileFullPath
import com.anggrayudi.storage.file.extension
import com.anggrayudi.storage.file.getAbsolutePath
import com.anggrayudi.storage.file.search
import org.ryujinx.android.MainActivity
import kotlin.concurrent.thread
@ -17,6 +15,7 @@ class HomeViewModel(
val activity: MainActivity? = null,
val mainViewModel: MainViewModel? = null
) {
private var savedFolder: String = ""
private var isLoading: Boolean = false
private var loadedCache: List<GameModel> = listOf()
private var gameFolderPath: DocumentFile? = null
@ -26,18 +25,8 @@ class HomeViewModel(
init {
if (activity != null) {
sharedPref = PreferenceManager.getDefaultSharedPreferences(activity)
activity.storageHelper!!.onFolderSelected = { requestCode, folder ->
run {
gameFolderPath = folder
val p = folder.getAbsolutePath(activity!!)
val editor = sharedPref?.edit()
editor?.putString("gameFolder", p)
editor?.apply()
reloadGameList()
}
}
val savedFolder = sharedPref?.getString("gameFolder", "") ?: ""
savedFolder = sharedPref?.getString("gameFolder", "") ?: ""
if (savedFolder.isNotEmpty()) {
try {
@ -56,16 +45,20 @@ class HomeViewModel(
}
}
fun openGameFolder() {
val path = sharedPref?.getString("gameFolder", "") ?: ""
fun ensureReloadIfNecessary() {
val oldFolder = savedFolder
val savedFolder = sharedPref?.getString("gameFolder", "") ?: ""
if (path.isEmpty())
activity?.storageHelper?.storage?.openFolderPicker()
else
activity?.storageHelper?.storage?.openFolderPicker(
activity.storageHelper!!.storage.requestCodeFolderPicker,
FileFullPath(activity, path)
if(savedFolder.isNotEmpty() && savedFolder != oldFolder) {
gameFolderPath = DocumentFileCompat.fromFullPath(
mainViewModel?.activity!!,
savedFolder,
documentType = DocumentFileType.FOLDER,
requiresWriteAccess = true
)
reloadGameList()
}
}
fun reloadGameList() {

View File

@ -2,15 +2,28 @@ package org.ryujinx.android.viewmodels
import android.content.SharedPreferences
import androidx.compose.runtime.MutableState
import androidx.documentfile.provider.DocumentFile
import androidx.navigation.NavHostController
import androidx.preference.PreferenceManager
import com.anggrayudi.storage.file.FileFullPath
import com.anggrayudi.storage.file.getAbsolutePath
import org.ryujinx.android.MainActivity
class SettingsViewModel(var navController: NavHostController, val activity: MainActivity) {
private var previousCallback: ((requestCode: Int, folder: DocumentFile) -> Unit)?
private var sharedPref: SharedPreferences
init {
sharedPref = getPreferences()
previousCallback = activity.storageHelper!!.onFolderSelected
activity.storageHelper!!.onFolderSelected = { requestCode, folder ->
run {
val p = folder.getAbsolutePath(activity!!)
val editor = sharedPref?.edit()
editor?.putString("gameFolder", p)
editor?.apply()
}
}
}
private fun getPreferences() : SharedPreferences {
@ -73,5 +86,20 @@ class SettingsViewModel(var navController: NavHostController, val activity: Main
editor.putBoolean("isGrid", isGrid.value)
editor.apply()
activity.storageHelper!!.onFolderSelected = previousCallback
}
fun openGameFolder() {
val path = sharedPref?.getString("gameFolder", "") ?: ""
if (path.isEmpty())
activity?.storageHelper?.storage?.openFolderPicker()
else
activity?.storageHelper?.storage?.openFolderPicker(
activity.storageHelper!!.storage.requestCodeFolderPicker,
FileFullPath(activity, path)
)
}
}

View File

@ -33,18 +33,15 @@ import androidx.compose.material.icons.filled.Search
import androidx.compose.material.icons.filled.Settings
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.AlertDialogDefaults
import androidx.compose.material3.BottomAppBar
import androidx.compose.material3.BottomAppBarDefaults
import androidx.compose.material3.Card
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.FloatingActionButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SearchBar
import androidx.compose.material3.SearchBarDefaults
@ -55,6 +52,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.asImageBitmap
@ -75,7 +73,7 @@ import kotlin.math.roundToInt
class HomeViews {
companion object {
const val ListImageSize = 150
const val GridImageSize = 256
const val GridImageSize = 300
@OptIn(ExperimentalMaterial3Api::class)
@Composable
@ -88,6 +86,9 @@ class HomeViews {
val openTitleUpdateDialog = remember { mutableStateOf(false) }
val canClose = remember { mutableStateOf(true) }
val openDlcDialog = remember { mutableStateOf(false) }
val selectedModel = remember {
mutableStateOf(viewModel.mainViewModel?.selected)
}
val query = remember {
mutableStateOf("")
}
@ -161,138 +162,13 @@ class HomeViews {
}
}
)
},
bottomBar = {
BottomAppBar(
actions = {
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 = {
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(
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(
onClick = {
viewModel.openGameFolder()
},
containerColor = BottomAppBarDefaults.bottomAppBarFabColor,
elevation = FloatingActionButtonDefaults.bottomAppBarFabElevation()
) {
Icon(
org.ryujinx.android.Icons.folderOpen(MaterialTheme.colorScheme.onSurface),
contentDescription = "Open Folder"
)
}
}
)
}
) { contentPadding ->
Box(modifier = Modifier.padding(contentPadding)) {
val list = remember {
viewModel.gameList
}
val selectedModel = remember {
mutableStateOf(viewModel.mainViewModel?.selected)
}
var settings = QuickSettings(viewModel.activity!!)
if (settings.isGrid) {
@ -301,13 +177,13 @@ class HomeViews {
columns = GridCells.Adaptive(minSize = (size + 4).dp),
modifier = Modifier
.fillMaxSize()
.padding(4.dp),
horizontalArrangement = Arrangement.SpaceEvenly
) {
items(list) {
it.titleName?.apply {
if (this.isNotEmpty() && (query.value.trim()
.isEmpty() || this.lowercase(
Locale.getDefault()
)
.isEmpty() || this.lowercase(Locale.getDefault())
.contains(query.value))
)
GridGameItem(
@ -335,7 +211,7 @@ class HomeViews {
viewModel,
showAppActions,
showLoading,
selectedModel
selectedModel,
)
}
}
@ -405,6 +281,89 @@ class HomeViews {
}
}
}
if (showAppActions.value)
ModalBottomSheet(
content = {
Row(
modifier = Modifier.padding(8.dp),
horizontalArrangement = Arrangement.SpaceEvenly
) {
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 = {
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
})
}
}
}
}
},
onDismissRequest = {
showAppActions.value = false
selectedModel.value = null
}
)
}
@OptIn(ExperimentalFoundationApi::class)
@ -548,7 +507,7 @@ class HomeViews {
selectedModel.value = gameModel
})
) {
Column {
Column(modifier = Modifier.padding(4.dp)) {
if (!gameModel.titleId.isNullOrEmpty() && gameModel.titleId != "0000000000000000") {
if (gameModel.icon?.isNotEmpty() == true) {
val pic = decoder.decode(gameModel.icon)
@ -560,6 +519,7 @@ class HomeViews {
modifier = Modifier
.padding(0.dp)
.clip(RoundedCornerShape(16.dp))
.align(Alignment.CenterHorizontally)
)
} else NotAvailableIcon()
} else NotAvailableIcon()
@ -567,13 +527,15 @@ class HomeViews {
text = gameModel.titleName ?: "N/A",
maxLines = 1,
overflow = TextOverflow.Ellipsis,
modifier = Modifier.basicMarquee()
modifier = Modifier.padding(vertical = 4.dp)
.basicMarquee()
)
Text(
text = gameModel.developer ?: "N/A",
maxLines = 1,
overflow = TextOverflow.Ellipsis,
modifier = Modifier.basicMarquee()
modifier = Modifier.padding(vertical = 4.dp)
.basicMarquee()
)
}
}
@ -584,7 +546,7 @@ class HomeViews {
val size = ListImageSize / Resources.getSystem().displayMetrics.density
Icon(
Icons.Filled.Add,
contentDescription = "Options",
contentDescription = "N/A",
modifier = Modifier
.padding(end = 8.dp)
.width(size.roundToInt().dp)

View File

@ -167,6 +167,23 @@ class SettingViews {
isGrid.value = !isGrid.value
})
}
Row(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = "Game Folder",
modifier = Modifier.align(Alignment.CenterVertically)
)
Button(onClick = {
settingsViewModel.openGameFolder()
}) {
Text(text = "Choose Folder")
}
}
}
}
ExpandableView(onCardArrowClick = { }, title = "System") {