1
0
forked from MeloNX/MeloNX

improve homeview extra options

update gradle deps
cleanup search bar
This commit is contained in:
Emmanuel Hansen 2024-05-08 15:20:31 +00:00
parent d19b391ca6
commit 8888edde5c
6 changed files with 472 additions and 128 deletions

View File

@ -11,8 +11,8 @@ android {
applicationId "org.ryujinx.android"
minSdk 30
targetSdk 34
versionCode 10026
versionName '1.0.26t'
versionCode 10030
versionName '1.0.30t'
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
@ -52,7 +52,7 @@ android {
buildConfig true
}
composeOptions {
kotlinCompilerExtensionVersion '1.5.2'
kotlinCompilerExtensionVersion '1.5.13'
}
packagingOptions {
jniLibs {
@ -77,18 +77,18 @@ tasks.named("preBuild") {
dependencies {
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.11.0'
implementation platform('androidx.compose:compose-bom:2023.03.00')
implementation platform('androidx.compose:compose-bom:2023.03.00')
androidTestImplementation platform('androidx.compose:compose-bom:2023.03.00')
androidTestImplementation platform('androidx.compose:compose-bom:2023.03.00')
implementation 'com.google.android.material:material:1.12.0'
implementation platform('androidx.compose:compose-bom:2024.05.00')
implementation platform('androidx.compose:compose-bom:2024.05.00')
androidTestImplementation platform('androidx.compose:compose-bom:2024.05.00')
androidTestImplementation platform('androidx.compose:compose-bom:2024.05.00')
runtimeOnly project(":libryujinx")
implementation 'androidx.core:core-ktx:1.12.0'
implementation platform('org.jetbrains.kotlin:kotlin-bom:1.8.0')
implementation 'androidx.core:core-ktx:1.13.1'
implementation platform('org.jetbrains.kotlin:kotlin-bom:1.9.24')
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.7.0'
implementation "androidx.navigation:navigation-compose:2.7.6"
implementation 'androidx.activity:activity-compose:1.8.2'
implementation platform('androidx.compose:compose-bom:2023.06.00')
implementation "androidx.navigation:navigation-compose:2.7.7"
implementation 'androidx.activity:activity-compose:1.9.0'
implementation platform('androidx.compose:compose-bom:2024.05.00')
implementation 'androidx.compose.ui:ui'
implementation 'androidx.compose.ui:ui-graphics'
implementation 'androidx.compose.ui:ui-tooling-preview'
@ -97,20 +97,20 @@ dependencies {
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation "com.anggrayudi:storage:1.5.5"
implementation "androidx.preference:preference-ktx:1.2.1"
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.2'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.0'
implementation 'com.google.code.gson:gson:2.10.1'
implementation 'net.lingala.zip4j:zip4j:2.11.5'
implementation("br.com.devsrsouza.compose.icons:css-gg:1.1.0")
implementation "io.coil-kt:coil-compose:2.4.0"
implementation 'io.coil-kt:coil-compose:2.6.0'
implementation("com.halilibo.compose-richtext:richtext-ui:0.20.0")
implementation("com.halilibo.compose-richtext:richtext-commonmark:0.20.0")
implementation("com.halilibo.compose-richtext:richtext-ui-material3:0.20.0")
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
androidTestImplementation platform('androidx.compose:compose-bom:2023.06.00')
androidTestImplementation platform('androidx.compose:compose-bom:2024.05.00')
androidTestImplementation 'androidx.compose.ui:ui-test-junit4'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.2'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0'
debugImplementation 'androidx.compose.ui:ui-tooling'
debugImplementation 'androidx.compose.ui:ui-test-manifest'
}

View File

@ -23,6 +23,200 @@ class Icons {
companion object{
/// Icons exported from https://www.composables.com/icons
@Composable
fun listView(color: Color): ImageVector {
return remember {
ImageVector.Builder(
name = "list",
defaultWidth = 40.0.dp,
defaultHeight = 40.0.dp,
viewportWidth = 40.0f,
viewportHeight = 40.0f
).apply {
path(
fill = SolidColor(color),
fillAlpha = 1f,
stroke = null,
strokeAlpha = 1f,
strokeLineWidth = 1.0f,
strokeLineCap = StrokeCap.Butt,
strokeLineJoin = StrokeJoin.Miter,
strokeLineMiter = 1f,
pathFillType = PathFillType.NonZero
) {
moveTo(13.375f, 14.458f)
quadToRelative(-0.583f, 0f, -0.958f, -0.395f)
quadToRelative(-0.375f, -0.396f, -0.375f, -0.938f)
quadToRelative(0f, -0.542f, 0.375f, -0.937f)
quadToRelative(0.375f, -0.396f, 0.958f, -0.396f)
horizontalLineToRelative(20.083f)
quadToRelative(0.584f, 0f, 0.959f, 0.396f)
quadToRelative(0.375f, 0.395f, 0.375f, 0.937f)
reflectiveQuadToRelative(-0.375f, 0.938f)
quadToRelative(-0.375f, 0.395f, -0.959f, 0.395f)
close()
moveToRelative(0f, 6.834f)
quadToRelative(-0.583f, 0f, -0.958f, -0.375f)
reflectiveQuadTo(12.042f, 20f)
quadToRelative(0f, -0.583f, 0.375f, -0.958f)
reflectiveQuadToRelative(0.958f, -0.375f)
horizontalLineToRelative(20.083f)
quadToRelative(0.584f, 0f, 0.959f, 0.395f)
quadToRelative(0.375f, 0.396f, 0.375f, 0.938f)
quadToRelative(0f, 0.542f, -0.375f, 0.917f)
reflectiveQuadToRelative(-0.959f, 0.375f)
close()
moveToRelative(0f, 6.916f)
quadToRelative(-0.583f, 0f, -0.958f, -0.396f)
quadToRelative(-0.375f, -0.395f, -0.375f, -0.937f)
reflectiveQuadToRelative(0.375f, -0.937f)
quadToRelative(0.375f, -0.396f, 0.958f, -0.396f)
horizontalLineToRelative(20.083f)
quadToRelative(0.584f, 0f, 0.959f, 0.396f)
quadToRelative(0.375f, 0.395f, 0.375f, 0.937f)
reflectiveQuadToRelative(-0.375f, 0.937f)
quadToRelative(-0.375f, 0.396f, -0.959f, 0.396f)
close()
moveToRelative(-6.833f, -13.75f)
quadToRelative(-0.584f, 0f, -0.959f, -0.395f)
quadToRelative(-0.375f, -0.396f, -0.375f, -0.938f)
quadToRelative(0f, -0.583f, 0.375f, -0.958f)
reflectiveQuadToRelative(0.959f, -0.375f)
quadToRelative(0.583f, 0f, 0.958f, 0.375f)
reflectiveQuadToRelative(0.375f, 0.958f)
quadToRelative(0f, 0.542f, -0.375f, 0.938f)
quadToRelative(-0.375f, 0.395f, -0.958f, 0.395f)
close()
moveToRelative(0f, 6.875f)
quadToRelative(-0.584f, 0f, -0.959f, -0.375f)
reflectiveQuadTo(5.208f, 20f)
quadToRelative(0f, -0.583f, 0.375f, -0.958f)
reflectiveQuadToRelative(0.959f, -0.375f)
quadToRelative(0.583f, 0f, 0.958f, 0.375f)
reflectiveQuadToRelative(0.375f, 0.958f)
quadToRelative(0f, 0.583f, -0.375f, 0.958f)
reflectiveQuadToRelative(-0.958f, 0.375f)
close()
moveToRelative(0f, 6.875f)
quadToRelative(-0.584f, 0f, -0.959f, -0.375f)
reflectiveQuadToRelative(-0.375f, -0.958f)
quadToRelative(0f, -0.542f, 0.375f, -0.937f)
quadToRelative(0.375f, -0.396f, 0.959f, -0.396f)
quadToRelative(0.583f, 0f, 0.958f, 0.396f)
quadToRelative(0.375f, 0.395f, 0.375f, 0.937f)
quadToRelative(0f, 0.583f, -0.375f, 0.958f)
reflectiveQuadToRelative(-0.958f, 0.375f)
close()
}
}.build()
}
}
@Composable
fun gridView(color: Color): ImageVector {
return remember {
ImageVector.Builder(
name = "grid_view",
defaultWidth = 40.0.dp,
defaultHeight = 40.0.dp,
viewportWidth = 40.0f,
viewportHeight = 40.0f
).apply {
path(
fill = SolidColor(color),
fillAlpha = 1f,
stroke = null,
strokeAlpha = 1f,
strokeLineWidth = 1.0f,
strokeLineCap = StrokeCap.Butt,
strokeLineJoin = StrokeJoin.Miter,
strokeLineMiter = 1f,
pathFillType = PathFillType.NonZero
) {
moveTo(7.875f, 18.667f)
quadToRelative(-1.083f, 0f, -1.854f, -0.771f)
quadToRelative(-0.771f, -0.771f, -0.771f, -1.854f)
verticalLineTo(7.875f)
quadToRelative(0f, -1.083f, 0.771f, -1.854f)
quadToRelative(0.771f, -0.771f, 1.854f, -0.771f)
horizontalLineToRelative(8.167f)
quadToRelative(1.083f, 0f, 1.875f, 0.771f)
quadToRelative(0.791f, 0.771f, 0.791f, 1.854f)
verticalLineToRelative(8.167f)
quadToRelative(0f, 1.083f, -0.791f, 1.854f)
quadToRelative(-0.792f, 0.771f, -1.875f, 0.771f)
close()
moveToRelative(0f, 16.083f)
quadToRelative(-1.083f, 0f, -1.854f, -0.771f)
quadToRelative(-0.771f, -0.771f, -0.771f, -1.854f)
verticalLineToRelative(-8.167f)
quadToRelative(0f, -1.083f, 0.771f, -1.875f)
quadToRelative(0.771f, -0.791f, 1.854f, -0.791f)
horizontalLineToRelative(8.167f)
quadToRelative(1.083f, 0f, 1.875f, 0.791f)
quadToRelative(0.791f, 0.792f, 0.791f, 1.875f)
verticalLineToRelative(8.167f)
quadToRelative(0f, 1.083f, -0.791f, 1.854f)
quadToRelative(-0.792f, 0.771f, -1.875f, 0.771f)
close()
moveToRelative(16.083f, -16.083f)
quadToRelative(-1.083f, 0f, -1.854f, -0.771f)
quadToRelative(-0.771f, -0.771f, -0.771f, -1.854f)
verticalLineTo(7.875f)
quadToRelative(0f, -1.083f, 0.771f, -1.854f)
quadToRelative(0.771f, -0.771f, 1.854f, -0.771f)
horizontalLineToRelative(8.167f)
quadToRelative(1.083f, 0f, 1.854f, 0.771f)
quadToRelative(0.771f, 0.771f, 0.771f, 1.854f)
verticalLineToRelative(8.167f)
quadToRelative(0f, 1.083f, -0.771f, 1.854f)
quadToRelative(-0.771f, 0.771f, -1.854f, 0.771f)
close()
moveToRelative(0f, 16.083f)
quadToRelative(-1.083f, 0f, -1.854f, -0.771f)
quadToRelative(-0.771f, -0.771f, -0.771f, -1.854f)
verticalLineToRelative(-8.167f)
quadToRelative(0f, -1.083f, 0.771f, -1.875f)
quadToRelative(0.771f, -0.791f, 1.854f, -0.791f)
horizontalLineToRelative(8.167f)
quadToRelative(1.083f, 0f, 1.854f, 0.791f)
quadToRelative(0.771f, 0.792f, 0.771f, 1.875f)
verticalLineToRelative(8.167f)
quadToRelative(0f, 1.083f, -0.771f, 1.854f)
quadToRelative(-0.771f, 0.771f, -1.854f, 0.771f)
close()
moveTo(7.875f, 16.042f)
horizontalLineToRelative(8.167f)
verticalLineTo(7.875f)
horizontalLineTo(7.875f)
close()
moveToRelative(16.083f, 0f)
horizontalLineToRelative(8.167f)
verticalLineTo(7.875f)
horizontalLineToRelative(-8.167f)
close()
moveToRelative(0f, 16.083f)
horizontalLineToRelative(8.167f)
verticalLineToRelative(-8.167f)
horizontalLineToRelative(-8.167f)
close()
moveToRelative(-16.083f, 0f)
horizontalLineToRelative(8.167f)
verticalLineToRelative(-8.167f)
horizontalLineTo(7.875f)
close()
moveToRelative(16.083f, -16.083f)
close()
moveToRelative(0f, 7.916f)
close()
moveToRelative(-7.916f, 0f)
close()
moveToRelative(0f, -7.916f)
close()
}
}.build()
}
}
@Composable
fun applets(color: Color): ImageVector {
return remember {
ImageVector.Builder(

View File

@ -174,10 +174,9 @@ class MainActivity : BaseActivity() {
}
}
@SuppressLint("RestrictedApi")
override fun dispatchKeyEvent(event: KeyEvent?): Boolean {
event?.apply {
override fun dispatchKeyEvent(event: KeyEvent): Boolean {
event.apply {
if (physicalControllerManager.onKeyEvent(this))
return true
}

View File

@ -178,9 +178,9 @@ class GameViews {
modifier = Modifier.padding(16.dp),
shape = MaterialTheme.shapes.medium
) {
Column {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Row(
modifier = Modifier,
modifier = Modifier.padding(horizontal = 16.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {

View File

@ -2,9 +2,13 @@ package org.ryujinx.android.views
import android.content.res.Resources
import android.graphics.BitmapFactory
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.expandVertically
import androidx.compose.animation.shrinkVertically
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.basicMarquee
import androidx.compose.foundation.border
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
@ -19,6 +23,7 @@ import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.items
@ -34,33 +39,44 @@ import androidx.compose.material.icons.filled.Settings
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.AlertDialogDefaults
import androidx.compose.material3.Card
import androidx.compose.material3.CardElevation
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.ExperimentalMaterial3Api
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.OutlinedCard
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SearchBar
import androidx.compose.material3.SearchBarDefaults
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
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.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.layout.HorizontalAlignmentLine
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Popup
import androidx.navigation.NavHostController
import com.anggrayudi.storage.extension.launchOnUiThread
import org.ryujinx.android.R
@ -78,11 +94,12 @@ class HomeViews {
const val ListImageSize = 150
const val GridImageSize = 300
@OptIn(ExperimentalMaterial3Api::class)
@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
@Composable
fun Home(
viewModel: HomeViewModel = HomeViewModel(),
navController: NavHostController? = null
navController: NavHostController? = null,
isPreview: Boolean = false
) {
viewModel.ensureReloadIfNecessary()
val showAppActions = remember { mutableStateOf(false) }
@ -90,23 +107,25 @@ class HomeViews {
val openTitleUpdateDialog = remember { mutableStateOf(false) }
val canClose = remember { mutableStateOf(true) }
val openDlcDialog = remember { mutableStateOf(false) }
var openAppBarExtra by remember { mutableStateOf(false) }
val selectedModel = remember {
mutableStateOf(viewModel.mainViewModel?.selected)
}
val query = remember {
mutableStateOf("")
}
var refreshUser by remember {
mutableStateOf(true)
}
Scaffold(
modifier = Modifier.fillMaxSize(),
topBar = {
TopAppBar(
SearchBar(
modifier = Modifier
.fillMaxWidth()
.padding(top = 8.dp),
title = {
SearchBar(
modifier = Modifier.fillMaxWidth(),
.padding(8.dp),
shape = SearchBarDefaults.inputFieldShape,
query = query.value,
onQueryChange = {
@ -123,13 +142,15 @@ class HomeViews {
},
placeholder = {
Text(text = "Ryujinx")
}
) { }
},
actions = {
trailingIcon = {
IconButton(onClick = {
navController?.navigate("user")
openAppBarExtra = !openAppBarExtra
}) {
if (!refreshUser) {
refreshUser = true
}
if (refreshUser)
if (viewModel.mainViewModel?.userViewModel?.openedUser?.userPicture?.isNotEmpty() == true) {
val pic =
viewModel.mainViewModel.userViewModel.openedUser.userPicture
@ -154,30 +175,157 @@ class HomeViews {
)
}
}
}
) {
}
}
) { contentPadding ->
Column(modifier = Modifier.padding(contentPadding)) {
val iconSize = 52.dp
AnimatedVisibility(
visible = openAppBarExtra,
)
{
Card(
modifier = Modifier
.padding(vertical = 8.dp, horizontal = 16.dp)
.fillMaxWidth(),
shape = MaterialTheme.shapes.medium
) {
Column(modifier = Modifier.padding(8.dp)) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(12.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween
) {
if (refreshUser) {
Box(
modifier = Modifier
.border(
width = 2.dp,
color = Color(0xFF14bf00),
shape = CircleShape
)
.size(iconSize)
.padding(2.dp),
contentAlignment = Alignment.Center
) {
if (viewModel.mainViewModel?.userViewModel?.openedUser?.userPicture?.isNotEmpty() == true) {
val pic =
viewModel.mainViewModel.userViewModel.openedUser.userPicture
Image(
bitmap = BitmapFactory.decodeByteArray(
pic,
0,
pic?.size ?: 0
)
.asImageBitmap(),
contentDescription = "user image",
contentScale = ContentScale.Crop,
modifier = Modifier
.padding(4.dp)
.size(iconSize)
.clip(CircleShape)
)
} else {
Icon(
Icons.Filled.Person,
contentDescription = "user"
)
}
}
Card(
modifier = Modifier
.padding(horizontal = 4.dp)
.fillMaxWidth(0.7f),
shape = MaterialTheme.shapes.small,
) {
LazyRow {
if (viewModel.mainViewModel?.userViewModel?.userList?.isNotEmpty() == true) {
items(viewModel.mainViewModel.userViewModel.userList) { user ->
if (user.id != viewModel.mainViewModel.userViewModel.openedUser.id) {
Image(
bitmap = BitmapFactory.decodeByteArray(
user.userPicture,
0,
user.userPicture?.size ?: 0
)
.asImageBitmap(),
contentDescription = "selected image",
contentScale = ContentScale.Crop,
modifier = Modifier
.padding(4.dp)
.size(iconSize)
.clip(CircleShape)
.combinedClickable(
onClick = {
viewModel.mainViewModel.userViewModel.openUser(
user
)
refreshUser =
false
})
)
}
}
}
}
}
Box(
modifier = Modifier
.size(iconSize)
) {
IconButton(
modifier = Modifier.fillMaxSize(),
onClick = {
openAppBarExtra = false
navController?.navigate("user")
}) {
Icon(
Icons.Filled.Add,
contentDescription = "N/A"
)
}
}
}
}
TextButton(modifier = Modifier.fillMaxWidth(),
onClick = {
navController?.navigate("settings")
}
) {
Row(modifier = Modifier.fillMaxWidth()) {
Icon(
Icons.Filled.Settings,
contentDescription = "Settings"
)
}
}
Text(
text = "Settings",
modifier = Modifier
.align(Alignment.CenterVertically)
.padding(start = 8.dp)
)
}
) { contentPadding ->
Box(modifier = Modifier.padding(contentPadding)) {
}
}
}
}
Box {
val list = remember {
viewModel.gameList
}
viewModel.filter(query.value)
if (!isPreview) {
var settings = QuickSettings(viewModel.activity!!)
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
@ -211,6 +359,7 @@ class HomeViews {
)
.contains(query.value))
)
Box(modifier = Modifier.animateItemPlacement()) {
ListGameItem(
it,
viewModel,
@ -223,6 +372,9 @@ class HomeViews {
}
}
}
}
}
}
if (showLoading.value) {
AlertDialog(onDismissRequest = { }) {
@ -248,7 +400,6 @@ class HomeViews {
}
}
}
if (openTitleUpdateDialog.value) {
AlertDialog(onDismissRequest = {
openTitleUpdateDialog.value = false
@ -575,6 +726,6 @@ class HomeViews {
@Preview
@Composable
fun HomePreview() {
Home()
Home(isPreview = true)
}
}

View File

@ -2,5 +2,5 @@
plugins {
id 'com.android.application' version '8.2.1' apply false
id 'com.android.library' version '8.2.1' apply false
id 'org.jetbrains.kotlin.android' version '1.9.0' apply false
id 'org.jetbrains.kotlin.android' version '1.9.23' apply false
}