android: Create custom game icon loader
This commit is contained in:
		@@ -3,8 +3,6 @@
 | 
			
		||||
 | 
			
		||||
package org.yuzu.yuzu_emu.adapters
 | 
			
		||||
 | 
			
		||||
import android.graphics.Bitmap
 | 
			
		||||
import android.graphics.BitmapFactory
 | 
			
		||||
import android.net.Uri
 | 
			
		||||
import android.text.TextUtils
 | 
			
		||||
import android.view.LayoutInflater
 | 
			
		||||
@@ -15,23 +13,20 @@ import android.widget.Toast
 | 
			
		||||
import androidx.appcompat.app.AppCompatActivity
 | 
			
		||||
import androidx.documentfile.provider.DocumentFile
 | 
			
		||||
import androidx.lifecycle.ViewModelProvider
 | 
			
		||||
import androidx.lifecycle.lifecycleScope
 | 
			
		||||
import androidx.navigation.findNavController
 | 
			
		||||
import androidx.preference.PreferenceManager
 | 
			
		||||
import androidx.recyclerview.widget.AsyncDifferConfig
 | 
			
		||||
import androidx.recyclerview.widget.DiffUtil
 | 
			
		||||
import androidx.recyclerview.widget.ListAdapter
 | 
			
		||||
import androidx.recyclerview.widget.RecyclerView
 | 
			
		||||
import coil.load
 | 
			
		||||
import kotlinx.coroutines.launch
 | 
			
		||||
import org.yuzu.yuzu_emu.HomeNavigationDirections
 | 
			
		||||
import org.yuzu.yuzu_emu.NativeLibrary
 | 
			
		||||
import org.yuzu.yuzu_emu.R
 | 
			
		||||
import org.yuzu.yuzu_emu.YuzuApplication
 | 
			
		||||
import org.yuzu.yuzu_emu.adapters.GameAdapter.GameViewHolder
 | 
			
		||||
import org.yuzu.yuzu_emu.databinding.CardGameBinding
 | 
			
		||||
import org.yuzu.yuzu_emu.model.Game
 | 
			
		||||
import org.yuzu.yuzu_emu.model.GamesViewModel
 | 
			
		||||
import org.yuzu.yuzu_emu.utils.GameIconUtils
 | 
			
		||||
 | 
			
		||||
class GameAdapter(private val activity: AppCompatActivity) :
 | 
			
		||||
    ListAdapter<Game, GameViewHolder>(AsyncDifferConfig.Builder(DiffCallback()).build()),
 | 
			
		||||
@@ -98,12 +93,7 @@ class GameAdapter(private val activity: AppCompatActivity) :
 | 
			
		||||
            this.game = game
 | 
			
		||||
 | 
			
		||||
            binding.imageGameScreen.scaleType = ImageView.ScaleType.CENTER_CROP
 | 
			
		||||
            activity.lifecycleScope.launch {
 | 
			
		||||
                val bitmap = decodeGameIcon(game.path)
 | 
			
		||||
                binding.imageGameScreen.load(bitmap) {
 | 
			
		||||
                    error(R.drawable.default_icon)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            GameIconUtils.loadGameIcon(game, binding.imageGameScreen)
 | 
			
		||||
 | 
			
		||||
            binding.textGameTitle.text = game.title.replace("[\\t\\n\\r]+".toRegex(), " ")
 | 
			
		||||
 | 
			
		||||
@@ -126,14 +116,4 @@ class GameAdapter(private val activity: AppCompatActivity) :
 | 
			
		||||
            return oldItem == newItem
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun decodeGameIcon(uri: String): Bitmap? {
 | 
			
		||||
        val data = NativeLibrary.getIcon(uri)
 | 
			
		||||
        return BitmapFactory.decodeByteArray(
 | 
			
		||||
            data,
 | 
			
		||||
            0,
 | 
			
		||||
            data.size,
 | 
			
		||||
            BitmapFactory.Options()
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,77 @@
 | 
			
		||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
 | 
			
		||||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
			
		||||
 | 
			
		||||
package org.yuzu.yuzu_emu.utils
 | 
			
		||||
 | 
			
		||||
import android.graphics.Bitmap
 | 
			
		||||
import android.graphics.BitmapFactory
 | 
			
		||||
import android.widget.ImageView
 | 
			
		||||
import androidx.core.graphics.drawable.toDrawable
 | 
			
		||||
import coil.ImageLoader
 | 
			
		||||
import coil.decode.DataSource
 | 
			
		||||
import coil.fetch.DrawableResult
 | 
			
		||||
import coil.fetch.FetchResult
 | 
			
		||||
import coil.fetch.Fetcher
 | 
			
		||||
import coil.key.Keyer
 | 
			
		||||
import coil.memory.MemoryCache
 | 
			
		||||
import coil.request.ImageRequest
 | 
			
		||||
import coil.request.Options
 | 
			
		||||
import org.yuzu.yuzu_emu.NativeLibrary
 | 
			
		||||
import org.yuzu.yuzu_emu.R
 | 
			
		||||
import org.yuzu.yuzu_emu.YuzuApplication
 | 
			
		||||
import org.yuzu.yuzu_emu.model.Game
 | 
			
		||||
 | 
			
		||||
class GameIconFetcher(
 | 
			
		||||
    private val game: Game,
 | 
			
		||||
    private val options: Options
 | 
			
		||||
) : Fetcher {
 | 
			
		||||
    override suspend fun fetch(): FetchResult {
 | 
			
		||||
        return DrawableResult(
 | 
			
		||||
            drawable = decodeGameIcon(game.path)!!.toDrawable(options.context.resources),
 | 
			
		||||
            isSampled = false,
 | 
			
		||||
            dataSource = DataSource.DISK
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun decodeGameIcon(uri: String): Bitmap? {
 | 
			
		||||
        val data = NativeLibrary.getIcon(uri)
 | 
			
		||||
        return BitmapFactory.decodeByteArray(
 | 
			
		||||
            data,
 | 
			
		||||
            0,
 | 
			
		||||
            data.size,
 | 
			
		||||
            BitmapFactory.Options()
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    class Factory : Fetcher.Factory<Game> {
 | 
			
		||||
        override fun create(data: Game, options: Options, imageLoader: ImageLoader): Fetcher =
 | 
			
		||||
            GameIconFetcher(data, options)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class GameIconKeyer : Keyer<Game> {
 | 
			
		||||
    override fun key(data: Game, options: Options): String = data.path
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
object GameIconUtils {
 | 
			
		||||
    private val imageLoader = ImageLoader.Builder(YuzuApplication.appContext)
 | 
			
		||||
        .components {
 | 
			
		||||
            add(GameIconKeyer())
 | 
			
		||||
            add(GameIconFetcher.Factory())
 | 
			
		||||
        }
 | 
			
		||||
        .memoryCache {
 | 
			
		||||
            MemoryCache.Builder(YuzuApplication.appContext)
 | 
			
		||||
                .maxSizePercent(0.25)
 | 
			
		||||
                .build()
 | 
			
		||||
        }
 | 
			
		||||
        .build()
 | 
			
		||||
 | 
			
		||||
    fun loadGameIcon(game: Game, imageView: ImageView) {
 | 
			
		||||
        val request = ImageRequest.Builder(YuzuApplication.appContext)
 | 
			
		||||
            .data(game)
 | 
			
		||||
            .target(imageView)
 | 
			
		||||
            .error(R.drawable.default_icon)
 | 
			
		||||
            .build()
 | 
			
		||||
        imageLoader.enqueue(request)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user