summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt35
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/GamePropertiesFragment.kt20
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Game.kt8
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameIconUtils.kt21
-rw-r--r--src/android/app/src/main/res/drawable/ic_shortcut.xml9
-rw-r--r--src/android/app/src/main/res/layout-w600dp/fragment_game_properties.xml35
-rw-r--r--src/android/app/src/main/res/layout/fragment_game_properties.xml40
7 files changed, 116 insertions, 52 deletions
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt
index e26c2e0ab..b4f4d950f 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt
@@ -3,9 +3,6 @@
3 3
4package org.yuzu.yuzu_emu.adapters 4package org.yuzu.yuzu_emu.adapters
5 5
6import android.content.Intent
7import android.graphics.Bitmap
8import android.graphics.drawable.LayerDrawable
9import android.net.Uri 6import android.net.Uri
10import android.text.TextUtils 7import android.text.TextUtils
11import android.view.LayoutInflater 8import android.view.LayoutInflater
@@ -15,10 +12,6 @@ import android.widget.Toast
15import androidx.appcompat.app.AppCompatActivity 12import androidx.appcompat.app.AppCompatActivity
16import androidx.core.content.pm.ShortcutInfoCompat 13import androidx.core.content.pm.ShortcutInfoCompat
17import androidx.core.content.pm.ShortcutManagerCompat 14import androidx.core.content.pm.ShortcutManagerCompat
18import androidx.core.content.res.ResourcesCompat
19import androidx.core.graphics.drawable.IconCompat
20import androidx.core.graphics.drawable.toBitmap
21import androidx.core.graphics.drawable.toDrawable
22import androidx.documentfile.provider.DocumentFile 15import androidx.documentfile.provider.DocumentFile
23import androidx.lifecycle.ViewModelProvider 16import androidx.lifecycle.ViewModelProvider
24import androidx.lifecycle.lifecycleScope 17import androidx.lifecycle.lifecycleScope
@@ -30,7 +23,6 @@ import kotlinx.coroutines.withContext
30import org.yuzu.yuzu_emu.HomeNavigationDirections 23import org.yuzu.yuzu_emu.HomeNavigationDirections
31import org.yuzu.yuzu_emu.R 24import org.yuzu.yuzu_emu.R
32import org.yuzu.yuzu_emu.YuzuApplication 25import org.yuzu.yuzu_emu.YuzuApplication
33import org.yuzu.yuzu_emu.activities.EmulationActivity
34import org.yuzu.yuzu_emu.databinding.CardGameBinding 26import org.yuzu.yuzu_emu.databinding.CardGameBinding
35import org.yuzu.yuzu_emu.model.Game 27import org.yuzu.yuzu_emu.model.Game
36import org.yuzu.yuzu_emu.model.GamesViewModel 28import org.yuzu.yuzu_emu.model.GamesViewModel
@@ -89,36 +81,13 @@ class GameAdapter(private val activity: AppCompatActivity) :
89 ) 81 )
90 .apply() 82 .apply()
91 83
92 val openIntent =
93 Intent(YuzuApplication.appContext, EmulationActivity::class.java).apply {
94 action = Intent.ACTION_VIEW
95 data = Uri.parse(game.path)
96 }
97
98 activity.lifecycleScope.launch { 84 activity.lifecycleScope.launch {
99 withContext(Dispatchers.IO) { 85 withContext(Dispatchers.IO) {
100 val layerDrawable = ResourcesCompat.getDrawable(
101 YuzuApplication.appContext.resources,
102 R.drawable.shortcut,
103 null
104 ) as LayerDrawable
105 layerDrawable.setDrawableByLayerId(
106 R.id.shortcut_foreground,
107 GameIconUtils.getGameIcon(activity, game)
108 .toDrawable(YuzuApplication.appContext.resources)
109 )
110 val inset = YuzuApplication.appContext.resources
111 .getDimensionPixelSize(R.dimen.icon_inset)
112 layerDrawable.setLayerInset(1, inset, inset, inset, inset)
113 val shortcut = 86 val shortcut =
114 ShortcutInfoCompat.Builder(YuzuApplication.appContext, game.path) 87 ShortcutInfoCompat.Builder(YuzuApplication.appContext, game.path)
115 .setShortLabel(game.title) 88 .setShortLabel(game.title)
116 .setIcon( 89 .setIcon(GameIconUtils.getShortcutIcon(activity, game))
117 IconCompat.createWithAdaptiveBitmap( 90 .setIntent(game.launchIntent)
118 layerDrawable.toBitmap(config = Bitmap.Config.ARGB_8888)
119 )
120 )
121 .setIntent(openIntent)
122 .build() 91 .build()
123 ShortcutManagerCompat.pushDynamicShortcut(YuzuApplication.appContext, shortcut) 92 ShortcutManagerCompat.pushDynamicShortcut(YuzuApplication.appContext, shortcut)
124 } 93 }
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/GamePropertiesFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/GamePropertiesFragment.kt
index 83a845434..582df0133 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/GamePropertiesFragment.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/GamePropertiesFragment.kt
@@ -4,6 +4,8 @@
4package org.yuzu.yuzu_emu.fragments 4package org.yuzu.yuzu_emu.fragments
5 5
6import android.annotation.SuppressLint 6import android.annotation.SuppressLint
7import android.content.pm.ShortcutInfo
8import android.content.pm.ShortcutManager
7import android.os.Bundle 9import android.os.Bundle
8import android.text.TextUtils 10import android.text.TextUtils
9import android.view.LayoutInflater 11import android.view.LayoutInflater
@@ -84,6 +86,24 @@ class GamePropertiesFragment : Fragment() {
84 view.findNavController().popBackStack() 86 view.findNavController().popBackStack()
85 } 87 }
86 88
89 val shortcutManager = requireActivity().getSystemService(ShortcutManager::class.java)
90 binding.buttonShortcut.isEnabled = shortcutManager.isRequestPinShortcutSupported
91 binding.buttonShortcut.setOnClickListener {
92 viewLifecycleOwner.lifecycleScope.launch {
93 withContext(Dispatchers.IO) {
94 val shortcut = ShortcutInfo.Builder(requireContext(), args.game.title)
95 .setShortLabel(args.game.title)
96 .setIcon(
97 GameIconUtils.getShortcutIcon(requireActivity(), args.game)
98 .toIcon(requireContext())
99 )
100 .setIntent(args.game.launchIntent)
101 .build()
102 shortcutManager.requestPinShortcut(shortcut, null)
103 }
104 }
105 }
106
87 GameIconUtils.loadGameIcon(args.game, binding.imageGameScreen) 107 GameIconUtils.loadGameIcon(args.game, binding.imageGameScreen)
88 binding.title.text = args.game.title 108 binding.title.text = args.game.title
89 binding.title.postDelayed( 109 binding.title.postDelayed(
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Game.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Game.kt
index f1ea1e20f..c8a4a2d17 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Game.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Game.kt
@@ -3,6 +3,7 @@
3 3
4package org.yuzu.yuzu_emu.model 4package org.yuzu.yuzu_emu.model
5 5
6import android.content.Intent
6import android.net.Uri 7import android.net.Uri
7import android.os.Parcelable 8import android.os.Parcelable
8import java.util.HashSet 9import java.util.HashSet
@@ -11,6 +12,7 @@ import kotlinx.serialization.Serializable
11import org.yuzu.yuzu_emu.NativeLibrary 12import org.yuzu.yuzu_emu.NativeLibrary
12import org.yuzu.yuzu_emu.R 13import org.yuzu.yuzu_emu.R
13import org.yuzu.yuzu_emu.YuzuApplication 14import org.yuzu.yuzu_emu.YuzuApplication
15import org.yuzu.yuzu_emu.activities.EmulationActivity
14import org.yuzu.yuzu_emu.utils.DirectoryInitialization 16import org.yuzu.yuzu_emu.utils.DirectoryInitialization
15import org.yuzu.yuzu_emu.utils.FileUtil 17import org.yuzu.yuzu_emu.utils.FileUtil
16import java.time.LocalDateTime 18import java.time.LocalDateTime
@@ -61,6 +63,12 @@ class Game(
61 val addonDir: String 63 val addonDir: String
62 get() = DirectoryInitialization.userDirectory + "/load/" + programIdHex + "/" 64 get() = DirectoryInitialization.userDirectory + "/load/" + programIdHex + "/"
63 65
66 val launchIntent: Intent
67 get() = Intent(YuzuApplication.appContext, EmulationActivity::class.java).apply {
68 action = Intent.ACTION_VIEW
69 data = Uri.parse(path)
70 }
71
64 override fun equals(other: Any?): Boolean { 72 override fun equals(other: Any?): Boolean {
65 if (other !is Game) { 73 if (other !is Game) {
66 return false 74 return false
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameIconUtils.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameIconUtils.kt
index 2e9b0beb8..d05020560 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameIconUtils.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameIconUtils.kt
@@ -5,7 +5,10 @@ package org.yuzu.yuzu_emu.utils
5 5
6import android.graphics.Bitmap 6import android.graphics.Bitmap
7import android.graphics.BitmapFactory 7import android.graphics.BitmapFactory
8import android.graphics.drawable.LayerDrawable
8import android.widget.ImageView 9import android.widget.ImageView
10import androidx.core.content.res.ResourcesCompat
11import androidx.core.graphics.drawable.IconCompat
9import androidx.core.graphics.drawable.toBitmap 12import androidx.core.graphics.drawable.toBitmap
10import androidx.core.graphics.drawable.toDrawable 13import androidx.core.graphics.drawable.toDrawable
11import androidx.lifecycle.LifecycleOwner 14import androidx.lifecycle.LifecycleOwner
@@ -85,4 +88,22 @@ object GameIconUtils {
85 return imageLoader.execute(request) 88 return imageLoader.execute(request)
86 .drawable!!.toBitmap(config = Bitmap.Config.ARGB_8888) 89 .drawable!!.toBitmap(config = Bitmap.Config.ARGB_8888)
87 } 90 }
91
92 suspend fun getShortcutIcon(lifecycleOwner: LifecycleOwner, game: Game): IconCompat {
93 val layerDrawable = ResourcesCompat.getDrawable(
94 YuzuApplication.appContext.resources,
95 R.drawable.shortcut,
96 null
97 ) as LayerDrawable
98 layerDrawable.setDrawableByLayerId(
99 R.id.shortcut_foreground,
100 getGameIcon(lifecycleOwner, game).toDrawable(YuzuApplication.appContext.resources)
101 )
102 val inset = YuzuApplication.appContext.resources
103 .getDimensionPixelSize(R.dimen.icon_inset)
104 layerDrawable.setLayerInset(1, inset, inset, inset, inset)
105 return IconCompat.createWithAdaptiveBitmap(
106 layerDrawable.toBitmap(config = Bitmap.Config.ARGB_8888)
107 )
108 }
88} 109}
diff --git a/src/android/app/src/main/res/drawable/ic_shortcut.xml b/src/android/app/src/main/res/drawable/ic_shortcut.xml
new file mode 100644
index 000000000..06e1983b2
--- /dev/null
+++ b/src/android/app/src/main/res/drawable/ic_shortcut.xml
@@ -0,0 +1,9 @@
1<vector xmlns:android="http://schemas.android.com/apk/res/android"
2 android:width="24dp"
3 android:height="24dp"
4 android:viewportWidth="960"
5 android:viewportHeight="960">
6 <path
7 android:fillColor="?attr/colorControlNormal"
8 android:pathData="M280,920q-33,0 -56.5,-23.5T200,840v-720q0,-33 23.5,-56.5T280,40h400q33,0 56.5,23.5T760,120v160h-80v-40L280,240v480h400v-40h80v160q0,33 -23.5,56.5T680,920L280,920ZM686,520L480,520v120h-80v-120q0,-33 23.5,-56.5T480,440h206l-62,-64 56,-56 160,160 -160,160 -56,-56 62,-64Z" />
9</vector>
diff --git a/src/android/app/src/main/res/layout-w600dp/fragment_game_properties.xml b/src/android/app/src/main/res/layout-w600dp/fragment_game_properties.xml
index 0b9633855..551f255c0 100644
--- a/src/android/app/src/main/res/layout-w600dp/fragment_game_properties.xml
+++ b/src/android/app/src/main/res/layout-w600dp/fragment_game_properties.xml
@@ -43,16 +43,35 @@
43 app:layout_constraintStart_toStartOf="parent" 43 app:layout_constraintStart_toStartOf="parent"
44 app:layout_constraintTop_toTopOf="parent"> 44 app:layout_constraintTop_toTopOf="parent">
45 45
46 <Button 46 <androidx.constraintlayout.widget.ConstraintLayout
47 android:id="@+id/button_back" 47 android:layout_width="match_parent"
48 style="?attr/materialIconButtonStyle"
49 android:layout_width="wrap_content"
50 android:layout_height="wrap_content" 48 android:layout_height="wrap_content"
51 android:layout_gravity="start"
52 android:layout_margin="8dp" 49 android:layout_margin="8dp"
53 app:icon="@drawable/ic_back" 50 android:orientation="horizontal">
54 app:iconSize="24dp" 51
55 app:iconTint="?attr/colorOnSurface" /> 52 <Button
53 android:id="@+id/button_back"
54 style="?attr/materialIconButtonStyle"
55 android:layout_width="wrap_content"
56 android:layout_height="wrap_content"
57 app:icon="@drawable/ic_back"
58 app:iconSize="24dp"
59 app:iconTint="?attr/colorOnSurface"
60 app:layout_constraintStart_toStartOf="parent"
61 app:layout_constraintTop_toTopOf="parent" />
62
63 <Button
64 android:id="@+id/button_shortcut"
65 style="?attr/materialIconButtonStyle"
66 android:layout_width="wrap_content"
67 android:layout_height="wrap_content"
68 app:icon="@drawable/ic_shortcut"
69 app:iconSize="24dp"
70 app:iconTint="?attr/colorOnSurface"
71 app:layout_constraintTop_toTopOf="parent"
72 app:layout_constraintEnd_toEndOf="parent" />
73
74 </androidx.constraintlayout.widget.ConstraintLayout>
56 75
57 <com.google.android.material.card.MaterialCardView 76 <com.google.android.material.card.MaterialCardView
58 style="?attr/materialCardViewElevatedStyle" 77 style="?attr/materialCardViewElevatedStyle"
diff --git a/src/android/app/src/main/res/layout/fragment_game_properties.xml b/src/android/app/src/main/res/layout/fragment_game_properties.xml
index 72ecbde30..cadd0bc4a 100644
--- a/src/android/app/src/main/res/layout/fragment_game_properties.xml
+++ b/src/android/app/src/main/res/layout/fragment_game_properties.xml
@@ -1,6 +1,5 @@
1<?xml version="1.0" encoding="utf-8"?> 1<?xml version="1.0" encoding="utf-8"?>
2<androidx.constraintlayout.widget.ConstraintLayout 2<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 xmlns:android="http://schemas.android.com/apk/res/android"
4 xmlns:app="http://schemas.android.com/apk/res-auto" 3 xmlns:app="http://schemas.android.com/apk/res-auto"
5 xmlns:tools="http://schemas.android.com/tools" 4 xmlns:tools="http://schemas.android.com/tools"
6 android:layout_width="match_parent" 5 android:layout_width="match_parent"
@@ -22,16 +21,35 @@
22 android:orientation="vertical" 21 android:orientation="vertical"
23 android:gravity="center_horizontal"> 22 android:gravity="center_horizontal">
24 23
25 <Button 24 <androidx.constraintlayout.widget.ConstraintLayout
26 android:id="@+id/button_back" 25 android:layout_width="match_parent"
27 style="?attr/materialIconButtonStyle"
28 android:layout_width="wrap_content"
29 android:layout_height="wrap_content" 26 android:layout_height="wrap_content"
30 android:layout_margin="8dp" 27 android:layout_margin="8dp"
31 android:layout_gravity="start" 28 android:orientation="horizontal">
32 app:icon="@drawable/ic_back" 29
33 app:iconSize="24dp" 30 <Button
34 app:iconTint="?attr/colorOnSurface" /> 31 android:id="@+id/button_back"
32 style="?attr/materialIconButtonStyle"
33 android:layout_width="wrap_content"
34 android:layout_height="wrap_content"
35 app:icon="@drawable/ic_back"
36 app:iconSize="24dp"
37 app:iconTint="?attr/colorOnSurface"
38 app:layout_constraintStart_toStartOf="parent"
39 app:layout_constraintTop_toTopOf="parent" />
40
41 <Button
42 android:id="@+id/button_shortcut"
43 style="?attr/materialIconButtonStyle"
44 android:layout_width="wrap_content"
45 android:layout_height="wrap_content"
46 app:icon="@drawable/ic_shortcut"
47 app:iconSize="24dp"
48 app:iconTint="?attr/colorOnSurface"
49 app:layout_constraintEnd_toEndOf="parent"
50 app:layout_constraintTop_toTopOf="parent" />
51
52 </androidx.constraintlayout.widget.ConstraintLayout>
35 53
36 <com.google.android.material.card.MaterialCardView 54 <com.google.android.material.card.MaterialCardView
37 style="?attr/materialCardViewElevatedStyle" 55 style="?attr/materialCardViewElevatedStyle"
@@ -45,7 +63,7 @@
45 android:id="@+id/image_game_screen" 63 android:id="@+id/image_game_screen"
46 android:layout_width="175dp" 64 android:layout_width="175dp"
47 android:layout_height="175dp" 65 android:layout_height="175dp"
48 tools:src="@drawable/default_icon"/> 66 tools:src="@drawable/default_icon" />
49 67
50 </com.google.android.material.card.MaterialCardView> 68 </com.google.android.material.card.MaterialCardView>
51 69