summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/AddonAdapter.kt36
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/FolderAdapter.kt36
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt192
3 files changed, 92 insertions, 172 deletions
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/AddonAdapter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/AddonAdapter.kt
index 15c7ca3c9..94c151325 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/AddonAdapter.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/AddonAdapter.kt
@@ -5,48 +5,28 @@ package org.yuzu.yuzu_emu.adapters
5 5
6import android.view.LayoutInflater 6import android.view.LayoutInflater
7import android.view.ViewGroup 7import android.view.ViewGroup
8import androidx.recyclerview.widget.AsyncDifferConfig
9import androidx.recyclerview.widget.DiffUtil
10import androidx.recyclerview.widget.ListAdapter
11import androidx.recyclerview.widget.RecyclerView
12import org.yuzu.yuzu_emu.databinding.ListItemAddonBinding 8import org.yuzu.yuzu_emu.databinding.ListItemAddonBinding
13import org.yuzu.yuzu_emu.model.Addon 9import org.yuzu.yuzu_emu.model.Addon
10import org.yuzu.yuzu_emu.viewholder.AbstractViewHolder
14 11
15class AddonAdapter : ListAdapter<Addon, AddonAdapter.AddonViewHolder>( 12class AddonAdapter : AbstractDiffAdapter<Addon, AddonAdapter.AddonViewHolder>() {
16 AsyncDifferConfig.Builder(DiffCallback()).build()
17) {
18 override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AddonViewHolder { 13 override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AddonViewHolder {
19 ListItemAddonBinding.inflate(LayoutInflater.from(parent.context), parent, false) 14 ListItemAddonBinding.inflate(LayoutInflater.from(parent.context), parent, false)
20 .also { return AddonViewHolder(it) } 15 .also { return AddonViewHolder(it) }
21 } 16 }
22 17
23 override fun getItemCount(): Int = currentList.size
24
25 override fun onBindViewHolder(holder: AddonViewHolder, position: Int) =
26 holder.bind(currentList[position])
27
28 inner class AddonViewHolder(val binding: ListItemAddonBinding) : 18 inner class AddonViewHolder(val binding: ListItemAddonBinding) :
29 RecyclerView.ViewHolder(binding.root) { 19 AbstractViewHolder<Addon>(binding) {
30 fun bind(addon: Addon) { 20 override fun bind(model: Addon) {
31 binding.root.setOnClickListener { 21 binding.root.setOnClickListener {
32 binding.addonSwitch.isChecked = !binding.addonSwitch.isChecked 22 binding.addonSwitch.isChecked = !binding.addonSwitch.isChecked
33 } 23 }
34 binding.title.text = addon.title 24 binding.title.text = model.title
35 binding.version.text = addon.version 25 binding.version.text = model.version
36 binding.addonSwitch.setOnCheckedChangeListener { _, checked -> 26 binding.addonSwitch.setOnCheckedChangeListener { _, checked ->
37 addon.enabled = checked 27 model.enabled = checked
38 } 28 }
39 binding.addonSwitch.isChecked = addon.enabled 29 binding.addonSwitch.isChecked = model.enabled
40 }
41 }
42
43 private class DiffCallback : DiffUtil.ItemCallback<Addon>() {
44 override fun areItemsTheSame(oldItem: Addon, newItem: Addon): Boolean {
45 return oldItem == newItem
46 }
47
48 override fun areContentsTheSame(oldItem: Addon, newItem: Addon): Boolean {
49 return oldItem == newItem
50 } 30 }
51 } 31 }
52} 32}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/FolderAdapter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/FolderAdapter.kt
index ab657a7b9..3d8f0bda8 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/FolderAdapter.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/FolderAdapter.kt
@@ -8,19 +8,14 @@ import android.text.TextUtils
8import android.view.LayoutInflater 8import android.view.LayoutInflater
9import android.view.ViewGroup 9import android.view.ViewGroup
10import androidx.fragment.app.FragmentActivity 10import androidx.fragment.app.FragmentActivity
11import androidx.recyclerview.widget.AsyncDifferConfig
12import androidx.recyclerview.widget.DiffUtil
13import androidx.recyclerview.widget.ListAdapter
14import androidx.recyclerview.widget.RecyclerView
15import org.yuzu.yuzu_emu.databinding.CardFolderBinding 11import org.yuzu.yuzu_emu.databinding.CardFolderBinding
16import org.yuzu.yuzu_emu.fragments.GameFolderPropertiesDialogFragment 12import org.yuzu.yuzu_emu.fragments.GameFolderPropertiesDialogFragment
17import org.yuzu.yuzu_emu.model.GameDir 13import org.yuzu.yuzu_emu.model.GameDir
18import org.yuzu.yuzu_emu.model.GamesViewModel 14import org.yuzu.yuzu_emu.model.GamesViewModel
15import org.yuzu.yuzu_emu.viewholder.AbstractViewHolder
19 16
20class FolderAdapter(val activity: FragmentActivity, val gamesViewModel: GamesViewModel) : 17class FolderAdapter(val activity: FragmentActivity, val gamesViewModel: GamesViewModel) :
21 ListAdapter<GameDir, FolderAdapter.FolderViewHolder>( 18 AbstractDiffAdapter<GameDir, FolderAdapter.FolderViewHolder>() {
22 AsyncDifferConfig.Builder(DiffCallback()).build()
23 ) {
24 override fun onCreateViewHolder( 19 override fun onCreateViewHolder(
25 parent: ViewGroup, 20 parent: ViewGroup,
26 viewType: Int 21 viewType: Int
@@ -29,18 +24,11 @@ class FolderAdapter(val activity: FragmentActivity, val gamesViewModel: GamesVie
29 .also { return FolderViewHolder(it) } 24 .also { return FolderViewHolder(it) }
30 } 25 }
31 26
32 override fun onBindViewHolder(holder: FolderAdapter.FolderViewHolder, position: Int) =
33 holder.bind(currentList[position])
34
35 inner class FolderViewHolder(val binding: CardFolderBinding) : 27 inner class FolderViewHolder(val binding: CardFolderBinding) :
36 RecyclerView.ViewHolder(binding.root) { 28 AbstractViewHolder<GameDir>(binding) {
37 private lateinit var gameDir: GameDir 29 override fun bind(model: GameDir) {
38
39 fun bind(gameDir: GameDir) {
40 this.gameDir = gameDir
41
42 binding.apply { 30 binding.apply {
43 path.text = Uri.parse(gameDir.uriString).path 31 path.text = Uri.parse(model.uriString).path
44 path.postDelayed( 32 path.postDelayed(
45 { 33 {
46 path.isSelected = true 34 path.isSelected = true
@@ -50,7 +38,7 @@ class FolderAdapter(val activity: FragmentActivity, val gamesViewModel: GamesVie
50 ) 38 )
51 39
52 buttonEdit.setOnClickListener { 40 buttonEdit.setOnClickListener {
53 GameFolderPropertiesDialogFragment.newInstance(this@FolderViewHolder.gameDir) 41 GameFolderPropertiesDialogFragment.newInstance(model)
54 .show( 42 .show(
55 activity.supportFragmentManager, 43 activity.supportFragmentManager,
56 GameFolderPropertiesDialogFragment.TAG 44 GameFolderPropertiesDialogFragment.TAG
@@ -58,19 +46,9 @@ class FolderAdapter(val activity: FragmentActivity, val gamesViewModel: GamesVie
58 } 46 }
59 47
60 buttonDelete.setOnClickListener { 48 buttonDelete.setOnClickListener {
61 gamesViewModel.removeFolder(this@FolderViewHolder.gameDir) 49 gamesViewModel.removeFolder(model)
62 } 50 }
63 } 51 }
64 } 52 }
65 } 53 }
66
67 private class DiffCallback : DiffUtil.ItemCallback<GameDir>() {
68 override fun areItemsTheSame(oldItem: GameDir, newItem: GameDir): Boolean {
69 return oldItem == newItem
70 }
71
72 override fun areContentsTheSame(oldItem: GameDir, newItem: GameDir): Boolean {
73 return oldItem == newItem
74 }
75 }
76} 54}
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 a578f0de8..e26c2e0ab 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
@@ -9,7 +9,6 @@ import android.graphics.drawable.LayerDrawable
9import android.net.Uri 9import android.net.Uri
10import android.text.TextUtils 10import android.text.TextUtils
11import android.view.LayoutInflater 11import android.view.LayoutInflater
12import android.view.View
13import android.view.ViewGroup 12import android.view.ViewGroup
14import android.widget.ImageView 13import android.widget.ImageView
15import android.widget.Toast 14import android.widget.Toast
@@ -25,10 +24,6 @@ import androidx.lifecycle.ViewModelProvider
25import androidx.lifecycle.lifecycleScope 24import androidx.lifecycle.lifecycleScope
26import androidx.navigation.findNavController 25import androidx.navigation.findNavController
27import androidx.preference.PreferenceManager 26import androidx.preference.PreferenceManager
28import androidx.recyclerview.widget.AsyncDifferConfig
29import androidx.recyclerview.widget.DiffUtil
30import androidx.recyclerview.widget.ListAdapter
31import androidx.recyclerview.widget.RecyclerView
32import kotlinx.coroutines.Dispatchers 27import kotlinx.coroutines.Dispatchers
33import kotlinx.coroutines.launch 28import kotlinx.coroutines.launch
34import kotlinx.coroutines.withContext 29import kotlinx.coroutines.withContext
@@ -36,122 +31,26 @@ import org.yuzu.yuzu_emu.HomeNavigationDirections
36import org.yuzu.yuzu_emu.R 31import org.yuzu.yuzu_emu.R
37import org.yuzu.yuzu_emu.YuzuApplication 32import org.yuzu.yuzu_emu.YuzuApplication
38import org.yuzu.yuzu_emu.activities.EmulationActivity 33import org.yuzu.yuzu_emu.activities.EmulationActivity
39import org.yuzu.yuzu_emu.adapters.GameAdapter.GameViewHolder
40import org.yuzu.yuzu_emu.databinding.CardGameBinding 34import org.yuzu.yuzu_emu.databinding.CardGameBinding
41import org.yuzu.yuzu_emu.model.Game 35import org.yuzu.yuzu_emu.model.Game
42import org.yuzu.yuzu_emu.model.GamesViewModel 36import org.yuzu.yuzu_emu.model.GamesViewModel
43import org.yuzu.yuzu_emu.utils.GameIconUtils 37import org.yuzu.yuzu_emu.utils.GameIconUtils
38import org.yuzu.yuzu_emu.viewholder.AbstractViewHolder
44 39
45class GameAdapter(private val activity: AppCompatActivity) : 40class GameAdapter(private val activity: AppCompatActivity) :
46 ListAdapter<Game, GameViewHolder>(AsyncDifferConfig.Builder(DiffCallback()).build()), 41 AbstractDiffAdapter<Game, GameAdapter.GameViewHolder>() {
47 View.OnClickListener,
48 View.OnLongClickListener {
49 override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GameViewHolder { 42 override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GameViewHolder {
50 // Create a new view. 43 CardGameBinding.inflate(LayoutInflater.from(parent.context), parent, false)
51 val binding = CardGameBinding.inflate(LayoutInflater.from(parent.context), parent, false) 44 .also { return GameViewHolder(it) }
52 binding.cardGame.setOnClickListener(this)
53 binding.cardGame.setOnLongClickListener(this)
54
55 // Use that view to create a ViewHolder.
56 return GameViewHolder(binding)
57 }
58
59 override fun onBindViewHolder(holder: GameViewHolder, position: Int) =
60 holder.bind(currentList[position])
61
62 override fun getItemCount(): Int = currentList.size
63
64 /**
65 * Launches the game that was clicked on.
66 *
67 * @param view The card representing the game the user wants to play.
68 */
69 override fun onClick(view: View) {
70 val holder = view.tag as GameViewHolder
71
72 val gameExists = DocumentFile.fromSingleUri(
73 YuzuApplication.appContext,
74 Uri.parse(holder.game.path)
75 )?.exists() == true
76 if (!gameExists) {
77 Toast.makeText(
78 YuzuApplication.appContext,
79 R.string.loader_error_file_not_found,
80 Toast.LENGTH_LONG
81 ).show()
82
83 ViewModelProvider(activity)[GamesViewModel::class.java].reloadGames(true)
84 return
85 }
86
87 val preferences = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext)
88 preferences.edit()
89 .putLong(
90 holder.game.keyLastPlayedTime,
91 System.currentTimeMillis()
92 )
93 .apply()
94
95 val openIntent = Intent(YuzuApplication.appContext, EmulationActivity::class.java).apply {
96 action = Intent.ACTION_VIEW
97 data = Uri.parse(holder.game.path)
98 }
99
100 activity.lifecycleScope.launch {
101 withContext(Dispatchers.IO) {
102 val layerDrawable = ResourcesCompat.getDrawable(
103 YuzuApplication.appContext.resources,
104 R.drawable.shortcut,
105 null
106 ) as LayerDrawable
107 layerDrawable.setDrawableByLayerId(
108 R.id.shortcut_foreground,
109 GameIconUtils.getGameIcon(activity, holder.game)
110 .toDrawable(YuzuApplication.appContext.resources)
111 )
112 val inset = YuzuApplication.appContext.resources
113 .getDimensionPixelSize(R.dimen.icon_inset)
114 layerDrawable.setLayerInset(1, inset, inset, inset, inset)
115 val shortcut =
116 ShortcutInfoCompat.Builder(YuzuApplication.appContext, holder.game.path)
117 .setShortLabel(holder.game.title)
118 .setIcon(
119 IconCompat.createWithAdaptiveBitmap(
120 layerDrawable.toBitmap(config = Bitmap.Config.ARGB_8888)
121 )
122 )
123 .setIntent(openIntent)
124 .build()
125 ShortcutManagerCompat.pushDynamicShortcut(YuzuApplication.appContext, shortcut)
126 }
127 }
128
129 val action = HomeNavigationDirections.actionGlobalEmulationActivity(holder.game, true)
130 view.findNavController().navigate(action)
131 }
132
133 override fun onLongClick(view: View): Boolean {
134 val holder = view.tag as GameViewHolder
135 val action = HomeNavigationDirections.actionGlobalPerGamePropertiesFragment(holder.game)
136 view.findNavController().navigate(action)
137 return true
138 } 45 }
139 46
140 inner class GameViewHolder(val binding: CardGameBinding) : 47 inner class GameViewHolder(val binding: CardGameBinding) :
141 RecyclerView.ViewHolder(binding.root) { 48 AbstractViewHolder<Game>(binding) {
142 lateinit var game: Game 49 override fun bind(model: Game) {
143
144 init {
145 binding.cardGame.tag = this
146 }
147
148 fun bind(game: Game) {
149 this.game = game
150
151 binding.imageGameScreen.scaleType = ImageView.ScaleType.CENTER_CROP 50 binding.imageGameScreen.scaleType = ImageView.ScaleType.CENTER_CROP
152 GameIconUtils.loadGameIcon(game, binding.imageGameScreen) 51 GameIconUtils.loadGameIcon(model, binding.imageGameScreen)
153 52
154 binding.textGameTitle.text = game.title.replace("[\\t\\n\\r]+".toRegex(), " ") 53 binding.textGameTitle.text = model.title.replace("[\\t\\n\\r]+".toRegex(), " ")
155 54
156 binding.textGameTitle.postDelayed( 55 binding.textGameTitle.postDelayed(
157 { 56 {
@@ -160,16 +59,79 @@ class GameAdapter(private val activity: AppCompatActivity) :
160 }, 59 },
161 3000 60 3000
162 ) 61 )
62
63 binding.cardGame.setOnClickListener { onClick(model) }
64 binding.cardGame.setOnLongClickListener { onLongClick(model) }
163 } 65 }
164 }
165 66
166 private class DiffCallback : DiffUtil.ItemCallback<Game>() { 67 fun onClick(game: Game) {
167 override fun areItemsTheSame(oldItem: Game, newItem: Game): Boolean { 68 val gameExists = DocumentFile.fromSingleUri(
168 return oldItem == newItem 69 YuzuApplication.appContext,
70 Uri.parse(game.path)
71 )?.exists() == true
72 if (!gameExists) {
73 Toast.makeText(
74 YuzuApplication.appContext,
75 R.string.loader_error_file_not_found,
76 Toast.LENGTH_LONG
77 ).show()
78
79 ViewModelProvider(activity)[GamesViewModel::class.java].reloadGames(true)
80 return
81 }
82
83 val preferences =
84 PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext)
85 preferences.edit()
86 .putLong(
87 game.keyLastPlayedTime,
88 System.currentTimeMillis()
89 )
90 .apply()
91
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 {
99 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 =
114 ShortcutInfoCompat.Builder(YuzuApplication.appContext, game.path)
115 .setShortLabel(game.title)
116 .setIcon(
117 IconCompat.createWithAdaptiveBitmap(
118 layerDrawable.toBitmap(config = Bitmap.Config.ARGB_8888)
119 )
120 )
121 .setIntent(openIntent)
122 .build()
123 ShortcutManagerCompat.pushDynamicShortcut(YuzuApplication.appContext, shortcut)
124 }
125 }
126
127 val action = HomeNavigationDirections.actionGlobalEmulationActivity(game, true)
128 binding.root.findNavController().navigate(action)
169 } 129 }
170 130
171 override fun areContentsTheSame(oldItem: Game, newItem: Game): Boolean { 131 fun onLongClick(game: Game): Boolean {
172 return oldItem == newItem 132 val action = HomeNavigationDirections.actionGlobalPerGamePropertiesFragment(game)
133 binding.root.findNavController().navigate(action)
134 return true
173 } 135 }
174 } 136 }
175} 137}