From 5028673968eed0a105889a8197eada42a5651c79 Mon Sep 17 00:00:00 2001
From: Emmanuel Hansen <emmausssss@gmail.com>
Date: Sun, 3 Dec 2023 14:03:25 +0000
Subject: [PATCH] android - reload list if game folder changed, fix game
 updates scanning

---
 .../main/java/org/ryujinx/android/Helpers.kt  | 25 ++++++-----
 .../android/viewmodels/HomeViewModel.kt       | 45 ++++++++-----------
 .../viewmodels/TitleUpdateViewModel.kt        |  2 +-
 .../org/ryujinx/android/views/HomeViews.kt    |  2 +
 .../org/ryujinx/android/views/SettingViews.kt |  2 +-
 5 files changed, 35 insertions(+), 41 deletions(-)

diff --git a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/Helpers.kt b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/Helpers.kt
index 7cda8a3ac..77dab8240 100644
--- a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/Helpers.kt
+++ b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/Helpers.kt
@@ -72,6 +72,7 @@ class Helpers {
             }
             return null
         }
+
         fun copyToData(
             file: DocumentFile, path: String, storageHelper: SimpleStorageHelper,
             isCopying: MutableState<Boolean>,
@@ -79,17 +80,18 @@ class Helpers {
             currentProgressName: MutableState<String>,
             finish: () -> Unit
         ) {
+            var fPath = path + "/${file.name}";
             var callback: FileCallback? = object : FileCallback() {
                 override fun onFailed(errorCode: FileCallback.ErrorCode) {
                     super.onFailed(errorCode)
-                    File(path).delete()
+                    File(fPath).delete()
                     finish()
                 }
 
                 override fun onStart(file: Any, workerThread: Thread): Long {
                     copyProgress.value = 0f
 
-                    (file as DocumentFile)?.apply {
+                    (file as DocumentFile).apply {
                         currentProgressName.value = "Copying ${file.name}"
                     }
                     return super.onStart(file, workerThread)
@@ -98,7 +100,7 @@ class Helpers {
                 override fun onReport(report: Report) {
                     super.onReport(report)
 
-                    if(!isCopying.value) {
+                    if (!isCopying.value) {
                         Thread.currentThread().interrupt()
                     }
 
@@ -113,17 +115,16 @@ class Helpers {
             }
             val ioScope = CoroutineScope(Dispatchers.IO)
             isCopying.value = true
+            File(fPath).delete()
             file.apply {
-                if (!File(path + "/${file.name}").exists()) {
-                    val f = this
-                    ioScope.launch {
-                        f.copyFileTo(
-                            storageHelper.storage.context,
-                            File(path),
-                            callback = callback!!
-                        )
+                val f = this
+                ioScope.launch {
+                    f.copyFileTo(
+                        storageHelper.storage.context,
+                        File(path),
+                        callback = callback!!
+                    )
 
-                    }
                 }
             }
         }
diff --git a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/viewmodels/HomeViewModel.kt b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/viewmodels/HomeViewModel.kt
index 8b13f903f..d1182611f 100644
--- a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/viewmodels/HomeViewModel.kt
+++ b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/viewmodels/HomeViewModel.kt
@@ -9,15 +9,17 @@ import com.anggrayudi.storage.file.DocumentFileType
 import com.anggrayudi.storage.file.extension
 import com.anggrayudi.storage.file.search
 import org.ryujinx.android.MainActivity
+import java.util.Locale
 import kotlin.concurrent.thread
 
 class HomeViewModel(
     val activity: MainActivity? = null,
     val mainViewModel: MainViewModel? = null
 ) {
+    private var shouldReload: Boolean = false
     private var savedFolder: String = ""
     private var isLoading: Boolean = false
-    private var loadedCache: List<GameModel> = listOf()
+    private var loadedCache: MutableList<GameModel> = mutableListOf()
     private var gameFolderPath: DocumentFile? = null
     private var sharedPref: SharedPreferences? = null
     val gameList: SnapshotStateList<GameModel> = SnapshotStateList()
@@ -25,31 +27,14 @@ class HomeViewModel(
     init {
         if (activity != null) {
             sharedPref = PreferenceManager.getDefaultSharedPreferences(activity)
-
-            savedFolder = sharedPref?.getString("gameFolder", "") ?: ""
-
-            if (savedFolder.isNotEmpty()) {
-                try {
-                    gameFolderPath = DocumentFileCompat.fromFullPath(
-                        activity,
-                        savedFolder,
-                        documentType = DocumentFileType.FOLDER,
-                        requiresWriteAccess = true
-                    )
-
-                    reloadGameList()
-                } catch (e: Exception) {
-
-                }
-            }
         }
     }
 
     fun ensureReloadIfNecessary() {
         val oldFolder = savedFolder
-        val savedFolder = sharedPref?.getString("gameFolder", "") ?: ""
+        savedFolder = sharedPref?.getString("gameFolder", "") ?: ""
 
-        if(savedFolder.isNotEmpty() && savedFolder != oldFolder) {
+        if (savedFolder.isNotEmpty() && (shouldReload || savedFolder != oldFolder)) {
             gameFolderPath = DocumentFileCompat.fromFullPath(
                 mainViewModel?.activity!!,
                 savedFolder,
@@ -61,6 +46,17 @@ class HomeViewModel(
         }
     }
 
+    fun filter(query : String){
+        gameList.clear()
+        gameList.addAll(loadedCache.filter { it.titleName != null && it.titleName!!.isNotEmpty() && (query.trim()
+            .isEmpty() || it.titleName!!.lowercase(Locale.getDefault())
+            .contains(query)) })
+    }
+
+    fun requestReload(){
+        shouldReload = true
+    }
+
     fun reloadGameList() {
         var storage = activity?.storageHelper ?: return
         
@@ -73,6 +69,7 @@ class HomeViewModel(
         isLoading = true
         thread {
             try {
+                loadedCache.clear()
                 val files = mutableListOf<GameModel>()
                 for (file in folder.search(false, DocumentFileType.FILE)) {
                     if (file.extension == "xci" || file.extension == "nsp")
@@ -80,22 +77,16 @@ class HomeViewModel(
                             val item = GameModel(file, it)
 
                             if(item.titleId?.isNotEmpty() == true && item.titleName?.isNotEmpty() == true) {
-                                files.add(item)
+                                loadedCache.add(item)
                                 gameList.add(item)
                             }
                         }
                 }
 
-                loadedCache = files.toList()
-
                 isLoading = false
             } finally {
                 isLoading = false
             }
         }
     }
-
-    fun clearLoadedCache(){
-        loadedCache = listOf()
-    }
 }
diff --git a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/viewmodels/TitleUpdateViewModel.kt b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/viewmodels/TitleUpdateViewModel.kt
index e42108220..6a515f404 100644
--- a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/viewmodels/TitleUpdateViewModel.kt
+++ b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/viewmodels/TitleUpdateViewModel.kt
@@ -137,8 +137,8 @@ class TitleUpdateViewModel(val titleId: String) {
             val gson = Gson()
             data = gson.fromJson(File(jsonPath).readText(), TitleUpdateMetadata::class.java)
 
-            refreshPaths()
         }
+        refreshPaths()
 
         storageHelper = MainActivity.StorageHelper!!
     }
diff --git a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/views/HomeViews.kt b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/views/HomeViews.kt
index e8a39b0ce..dd6993b3b 100644
--- a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/views/HomeViews.kt
+++ b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/views/HomeViews.kt
@@ -81,6 +81,7 @@ class HomeViews {
             viewModel: HomeViewModel = HomeViewModel(),
             navController: NavHostController? = null
         ) {
+            viewModel.ensureReloadIfNecessary()
             val showAppActions = remember { mutableStateOf(false) }
             val showLoading = remember { mutableStateOf(false) }
             val openTitleUpdateDialog = remember { mutableStateOf(false) }
@@ -169,6 +170,7 @@ class HomeViews {
                     val list = remember {
                         viewModel.gameList
                     }
+                    viewModel.filter(query.value)
                     var settings = QuickSettings(viewModel.activity!!)
 
                     if (settings.isGrid) {
diff --git a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/views/SettingViews.kt b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/views/SettingViews.kt
index 629d75886..d6be07e01 100644
--- a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/views/SettingViews.kt
+++ b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/views/SettingViews.kt
@@ -371,7 +371,7 @@ class SettingViews {
                                     showImportCompletion.value = false
                                     importFile.value = null
                                     mainViewModel.userViewModel.refreshUsers()
-                                    mainViewModel.homeViewModel.clearLoadedCache()
+                                    mainViewModel.homeViewModel.requestReload()
                                 }) {
                                     Card(
                                         modifier = Modifier,