From 19674ec78d0c8b831083de3e7cf2fa29aacf9d4d Mon Sep 17 00:00:00 2001
From: PabloG02
Date: Sat, 3 Jun 2023 14:13:20 +0200
Subject: android: move unzip function to FileUtil and use SecurityException
---
.../fragments/ImportExportSavesFragment.kt | 34 ++--------------------
.../main/java/org/yuzu/yuzu_emu/utils/FileUtil.kt | 32 ++++++++++++++++++++
2 files changed, 34 insertions(+), 32 deletions(-)
(limited to 'src/android')
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/ImportExportSavesFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/ImportExportSavesFragment.kt
index 5f107b37d..36e63bb9e 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/ImportExportSavesFragment.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/ImportExportSavesFragment.kt
@@ -23,17 +23,14 @@ import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.YuzuApplication
import org.yuzu.yuzu_emu.features.DocumentProvider
import org.yuzu.yuzu_emu.getPublicFilesDir
-import java.io.BufferedInputStream
+import org.yuzu.yuzu_emu.utils.FileUtil
import java.io.BufferedOutputStream
import java.io.File
import java.io.FileOutputStream
import java.io.FilenameFilter
-import java.io.IOException
-import java.io.InputStream
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
import java.util.zip.ZipEntry
-import java.util.zip.ZipInputStream
import java.util.zip.ZipOutputStream
class ImportExportSavesFragment : DialogFragment() {
@@ -124,33 +121,6 @@ class ImportExportSavesFragment : DialogFragment() {
return true
}
- /**
- * Extracts the save files located in the given zip file and copies them to the saves folder.
- * @exception IOException if the file was being created outside of the target directory
- */
- private fun unzip(zipStream: InputStream, destDir: File): Boolean {
- val zis = ZipInputStream(BufferedInputStream(zipStream))
- var entry: ZipEntry? = zis.nextEntry
- while (entry != null) {
- val entryName = entry.name
- val entryFile = File(destDir, entryName)
- if (!entryFile.canonicalPath.startsWith(destDir.canonicalPath + File.separator)) {
- zis.close()
- throw IOException("Entry is outside of the target dir: " + entryFile.name)
- }
- if (entry.isDirectory) {
- entryFile.mkdirs()
- } else {
- entryFile.parentFile?.mkdirs()
- entryFile.createNewFile()
- entryFile.outputStream().use { fos -> zis.copyTo(fos) }
- }
- entry = zis.nextEntry
- }
- zis.close()
- return true
- }
-
/**
* Exports the save file located in the given folder path by creating a zip file and sharing it via intent.
*/
@@ -204,7 +174,7 @@ class ImportExportSavesFragment : DialogFragment() {
try {
CoroutineScope(Dispatchers.IO).launch {
- unzip(inputZip, cacheSaveDir)
+ FileUtil.unzip(inputZip, cacheSaveDir)
cacheSaveDir.list(filterTitleId)?.forEach { savePath ->
File(savesFolder, savePath).deleteRecursively()
File(cacheSaveDir, savePath).copyRecursively(File(savesFolder, savePath), true)
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/FileUtil.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/FileUtil.kt
index 0a7b323b1..593dad8d3 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/FileUtil.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/FileUtil.kt
@@ -9,10 +9,14 @@ import android.net.Uri
import android.provider.DocumentsContract
import androidx.documentfile.provider.DocumentFile
import org.yuzu.yuzu_emu.model.MinimalDocumentFile
+import java.io.BufferedInputStream
+import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.io.InputStream
import java.net.URLDecoder
+import java.util.zip.ZipEntry
+import java.util.zip.ZipInputStream
object FileUtil {
const val PATH_TREE = "tree"
@@ -276,6 +280,34 @@ object FileUtil {
return false
}
+ /**
+ * Extracts the given zip file into the given directory.
+ * @exception IOException if the file was being created outside of the target directory
+ */
+ @Throws(SecurityException::class)
+ fun unzip(zipStream: InputStream, destDir: File): Boolean {
+ ZipInputStream(BufferedInputStream(zipStream)).use { zis ->
+ var entry: ZipEntry? = zis.nextEntry
+ while (entry != null) {
+ val entryName = entry.name
+ val entryFile = File(destDir, entryName)
+ if (!entryFile.canonicalPath.startsWith(destDir.canonicalPath + File.separator)) {
+ throw SecurityException("Entry is outside of the target dir: " + entryFile.name)
+ }
+ if (entry.isDirectory) {
+ entryFile.mkdirs()
+ } else {
+ entryFile.parentFile?.mkdirs()
+ entryFile.createNewFile()
+ entryFile.outputStream().use { fos -> zis.copyTo(fos) }
+ }
+ entry = zis.nextEntry
+ }
+ }
+
+ return true
+ }
+
fun isRootTreeUri(uri: Uri): Boolean {
val paths = uri.pathSegments
return paths.size == 2 && PATH_TREE == paths[0]
--
cgit v1.2.3
From 5435f0be5e4d81da5140cea79904252403f108c2 Mon Sep 17 00:00:00 2001
From: PabloG02
Date: Sat, 3 Jun 2023 14:14:05 +0200
Subject: android: add option to install firmware
---
.../yuzu_emu/fragments/HomeSettingsFragment.kt | 8 ++-
.../IndeterminateProgressDialogFragment.kt | 36 ++++++++++++
.../java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt | 65 ++++++++++++++++++++++
.../app/src/main/res/drawable/ic_firmware.xml | 10 ++++
src/android/app/src/main/res/values/strings.xml | 6 ++
5 files changed, 124 insertions(+), 1 deletion(-)
create mode 100644 src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/IndeterminateProgressDialogFragment.kt
create mode 100644 src/android/app/src/main/res/drawable/ic_firmware.xml
(limited to 'src/android')
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/HomeSettingsFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/HomeSettingsFragment.kt
index 67bcf8491..cc4b0157b 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/HomeSettingsFragment.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/HomeSettingsFragment.kt
@@ -19,10 +19,10 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
-import androidx.core.content.ContextCompat
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding
+import androidx.documentfile.provider.DocumentFile
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.navigation.fragment.findNavController
@@ -40,6 +40,7 @@ import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile
import org.yuzu.yuzu_emu.model.HomeSetting
import org.yuzu.yuzu_emu.model.HomeViewModel
import org.yuzu.yuzu_emu.ui.main.MainActivity
+import org.yuzu.yuzu_emu.utils.FileUtil
import org.yuzu.yuzu_emu.utils.GpuDriverHelper
class HomeSettingsFragment : Fragment() {
@@ -108,6 +109,11 @@ class HomeSettingsFragment : Fragment() {
R.string.install_prod_keys_description,
R.drawable.ic_unlock
) { mainActivity.getProdKey.launch(arrayOf("*/*")) },
+ HomeSetting(
+ R.string.install_firmware,
+ R.string.install_firmware_description,
+ R.drawable.ic_firmware
+ ) { mainActivity.getFirmware.launch(arrayOf("application/zip")) },
HomeSetting(
R.string.about,
R.string.about_description,
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/IndeterminateProgressDialogFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/IndeterminateProgressDialogFragment.kt
new file mode 100644
index 000000000..edf7b8a3c
--- /dev/null
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/IndeterminateProgressDialogFragment.kt
@@ -0,0 +1,36 @@
+package org.yuzu.yuzu_emu.fragments
+
+import android.app.Dialog
+import android.os.Bundle
+import androidx.fragment.app.DialogFragment
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import org.yuzu.yuzu_emu.databinding.DialogProgressBarBinding
+
+class IndeterminateProgressDialogFragment : DialogFragment() {
+ override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
+ val titleId = requireArguments().getInt(TITLE)
+
+ val progressBinding = DialogProgressBarBinding.inflate(layoutInflater)
+ progressBinding.progressBar.isIndeterminate = true
+ return MaterialAlertDialogBuilder(requireContext())
+ .setTitle(titleId)
+ .setView(progressBinding.root)
+ .show()
+ }
+
+ companion object {
+ const val TAG = "IndeterminateProgressDialogFragment"
+
+ private const val TITLE = "Title"
+
+ fun newInstance(
+ titleId: Int,
+ ): IndeterminateProgressDialogFragment {
+ val dialog = IndeterminateProgressDialogFragment()
+ val args = Bundle()
+ args.putInt(TITLE, titleId)
+ dialog.arguments = args
+ return dialog
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt
index f8bca11bb..bb8311023 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt
@@ -26,6 +26,7 @@ import androidx.preference.PreferenceManager
import com.google.android.material.color.MaterialColors
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.navigation.NavigationBarView
+import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@@ -37,10 +38,13 @@ import org.yuzu.yuzu_emu.databinding.DialogProgressBarBinding
import org.yuzu.yuzu_emu.features.settings.model.Settings
import org.yuzu.yuzu_emu.features.settings.ui.SettingsActivity
import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile
+import org.yuzu.yuzu_emu.fragments.IndeterminateProgressDialogFragment
import org.yuzu.yuzu_emu.fragments.MessageDialogFragment
import org.yuzu.yuzu_emu.model.GamesViewModel
import org.yuzu.yuzu_emu.model.HomeViewModel
import org.yuzu.yuzu_emu.utils.*
+import java.io.File
+import java.io.FilenameFilter
import java.io.IOException
class MainActivity : AppCompatActivity(), ThemeProvider {
@@ -315,6 +319,67 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
}
}
+ val getFirmware =
+ registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
+ if (result == null)
+ return@registerForActivityResult
+
+ val inputZip = contentResolver.openInputStream(result)
+ if (inputZip == null) {
+ Toast.makeText(
+ applicationContext,
+ getString(R.string.fatal_error),
+ Toast.LENGTH_LONG
+ ).show()
+ return@registerForActivityResult
+ }
+
+ val filterNCA = FilenameFilter { _, dirName -> dirName.endsWith(".nca") }
+
+ val firmwarePath =
+ File(DirectoryInitialization.userDirectory + "/nand/system/Contents/registered/")
+ val cacheFirmwareDir = File("${cacheDir.path}/registered/")
+
+ val installingFirmwareDialog = IndeterminateProgressDialogFragment.newInstance(
+ R.string.firmware_installing
+ )
+ installingFirmwareDialog.isCancelable = false
+ installingFirmwareDialog.show(supportFragmentManager, IndeterminateProgressDialogFragment.TAG)
+
+ lifecycleScope.launch(Dispatchers.IO) {
+ try {
+ FileUtil.unzip(inputZip, cacheFirmwareDir)
+ val unfilteredNumOfFiles = cacheFirmwareDir.list()?.size ?: -1
+ val filteredNumOfFiles = cacheFirmwareDir.list(filterNCA)?.size ?: -2
+ if (unfilteredNumOfFiles != filteredNumOfFiles) {
+ withContext(Dispatchers.Main) {
+ installingFirmwareDialog.dismiss()
+ MessageDialogFragment.newInstance(
+ R.string.firmware_installed_failure,
+ R.string.firmware_installed_failure_description
+ ).show(supportFragmentManager, MessageDialogFragment.TAG)
+ }
+ } else {
+ firmwarePath.deleteRecursively()
+ cacheFirmwareDir.copyRecursively(firmwarePath, true)
+ withContext(Dispatchers.Main) {
+ installingFirmwareDialog.dismiss()
+ Toast.makeText(
+ applicationContext,
+ getString(R.string.save_file_imported_success),
+ Toast.LENGTH_LONG
+ ).show()
+ }
+ }
+ } catch (e: Exception) {
+ Toast.makeText(applicationContext, getString(R.string.fatal_error), Toast.LENGTH_LONG)
+ .show()
+ } finally {
+ cacheFirmwareDir.deleteRecursively()
+ }
+ }
+ }
+
val getAmiiboKey =
registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
if (result == null)
diff --git a/src/android/app/src/main/res/drawable/ic_firmware.xml b/src/android/app/src/main/res/drawable/ic_firmware.xml
new file mode 100644
index 000000000..61f3485e4
--- /dev/null
+++ b/src/android/app/src/main/res/drawable/ic_firmware.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml
index fc24e27f5..4b3bfcf9d 100644
--- a/src/android/app/src/main/res/values/strings.xml
+++ b/src/android/app/src/main/res/values/strings.xml
@@ -96,6 +96,12 @@
The first subfolder name must be the title ID of the game.
Import
Export
+ Install firmware
+ Required to boot some games
+ Installing firmware
+ Firmware installed successfully
+ Firmware installation failed.
+ Check that the ZIP contains a firmware.
Gaia isn\'t real
--
cgit v1.2.3
From 8713c442e9e5408f8d8a4e937e2c8e5c9c335430 Mon Sep 17 00:00:00 2001
From: PabloG02
Date: Sat, 3 Jun 2023 14:15:15 +0200
Subject: android: add option to share log
---
.../yuzu_emu/fragments/HomeSettingsFragment.kt | 23 ++++++++++++++++++++++
src/android/app/src/main/res/drawable/ic_log.xml | 10 ++++++++++
src/android/app/src/main/res/values/strings.xml | 3 +++
3 files changed, 36 insertions(+)
create mode 100644 src/android/app/src/main/res/drawable/ic_log.xml
(limited to 'src/android')
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/HomeSettingsFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/HomeSettingsFragment.kt
index cc4b0157b..0bdbabe79 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/HomeSettingsFragment.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/HomeSettingsFragment.kt
@@ -114,6 +114,11 @@ class HomeSettingsFragment : Fragment() {
R.string.install_firmware_description,
R.drawable.ic_firmware
) { mainActivity.getFirmware.launch(arrayOf("application/zip")) },
+ HomeSetting(
+ R.string.share_log,
+ R.string.share_log_description,
+ R.drawable.ic_log
+ ) { shareLog() },
HomeSetting(
R.string.about,
R.string.about_description,
@@ -268,6 +273,24 @@ class HomeSettingsFragment : Fragment() {
.show()
}
+ private fun shareLog() {
+ val file = DocumentFile.fromSingleUri(
+ mainActivity, DocumentsContract.buildDocumentUri(
+ DocumentProvider.AUTHORITY,
+ "${DocumentProvider.ROOT_ID}/log/yuzu_log.txt"
+ )
+ )!!
+ if (file.exists()) {
+ val intent = Intent(Intent.ACTION_SEND)
+ .setDataAndType(file.uri, FileUtil.TEXT_PLAIN)
+ .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
+ .putExtra(Intent.EXTRA_STREAM, file.uri)
+ startActivity(Intent.createChooser(intent, "Share log"))
+ } else {
+ Toast.makeText(requireContext(), getText(R.string.share_log_missing), Toast.LENGTH_SHORT).show()
+ }
+ }
+
private fun setInsets() =
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { view: View, windowInsets: WindowInsetsCompat ->
val barInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
diff --git a/src/android/app/src/main/res/drawable/ic_log.xml b/src/android/app/src/main/res/drawable/ic_log.xml
new file mode 100644
index 000000000..f55b9ad85
--- /dev/null
+++ b/src/android/app/src/main/res/drawable/ic_log.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml
index 4b3bfcf9d..5d42be5e6 100644
--- a/src/android/app/src/main/res/values/strings.xml
+++ b/src/android/app/src/main/res/values/strings.xml
@@ -102,6 +102,9 @@
Firmware installed successfully
Firmware installation failed.
Check that the ZIP contains a firmware.
+ Share log
+ Share the log file
+ No log file found
Gaia isn\'t real
--
cgit v1.2.3
From 72597b8ffea24de329366b2beda6b1cad0620fa0 Mon Sep 17 00:00:00 2001
From: PabloG02
Date: Sat, 3 Jun 2023 14:16:07 +0200
Subject: android: update strings
---
src/android/app/src/main/res/values/strings.xml | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
(limited to 'src/android')
diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml
index 5d42be5e6..1646b90eb 100644
--- a/src/android/app/src/main/res/values/strings.xml
+++ b/src/android/app/src/main/res/values/strings.xml
@@ -97,13 +97,13 @@
Import
Export
Install firmware
- Required to boot some games
+ Firmware must be in a ZIP archive and is needed to boot some games
Installing firmware
Firmware installed successfully
- Firmware installation failed.
- Check that the ZIP contains a firmware.
- Share log
- Share the log file
+ Firmware installation failed
+ Verify that the ZIP contains valid firmware and try again.
+ Share debug logs
+ Share yuzu\'s log file to debug issues
No log file found
--
cgit v1.2.3
From 3733187c147149c995df97d7ac72ab5e4aafd137 Mon Sep 17 00:00:00 2001
From: PabloG02
Date: Sun, 4 Jun 2023 02:24:14 +0200
Subject: Attempt to move the unzip coroutine to a ViewModel
---
.../IndeterminateProgressDialogFragment.kt | 40 +++++++++++++++++++--
.../java/org/yuzu/yuzu_emu/model/TaskViewModel.kt | 42 ++++++++++++++++++++++
.../java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt | 39 ++++++++------------
3 files changed, 94 insertions(+), 27 deletions(-)
create mode 100644 src/android/app/src/main/java/org/yuzu/yuzu_emu/model/TaskViewModel.kt
(limited to 'src/android')
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/IndeterminateProgressDialogFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/IndeterminateProgressDialogFragment.kt
index edf7b8a3c..10a897392 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/IndeterminateProgressDialogFragment.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/IndeterminateProgressDialogFragment.kt
@@ -2,33 +2,69 @@ package org.yuzu.yuzu_emu.fragments
import android.app.Dialog
import android.os.Bundle
+import android.widget.Toast
import androidx.fragment.app.DialogFragment
+import androidx.lifecycle.ViewModelProvider
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.yuzu.yuzu_emu.databinding.DialogProgressBarBinding
+import org.yuzu.yuzu_emu.model.TaskViewModel
+import java.io.Serializable
+
class IndeterminateProgressDialogFragment : DialogFragment() {
+ private lateinit var taskViewModel: TaskViewModel
+
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
+ taskViewModel = ViewModelProvider(requireActivity())[TaskViewModel::class.java]
+
val titleId = requireArguments().getInt(TITLE)
val progressBinding = DialogProgressBarBinding.inflate(layoutInflater)
progressBinding.progressBar.isIndeterminate = true
- return MaterialAlertDialogBuilder(requireContext())
+ val dialog = MaterialAlertDialogBuilder(requireContext())
.setTitle(titleId)
.setView(progressBinding.root)
- .show()
+ .create()
+ dialog.setCanceledOnTouchOutside(false)
+
+ taskViewModel.isComplete.observe(this) { complete ->
+ if (complete) {
+ dialog.dismiss()
+ when (val result = taskViewModel.result.value) {
+ is String -> Toast.makeText(requireContext(), result, Toast.LENGTH_LONG).show()
+ is MessageDialogFragment -> result.show(
+ parentFragmentManager,
+ MessageDialogFragment.TAG
+ )
+ }
+ taskViewModel.clear()
+ }
+ }
+
+ if (taskViewModel.isRunning.value == false) {
+ val task = requireArguments().getSerializable(TASK) as? () -> Any
+ if (task != null) {
+ taskViewModel.task = task
+ taskViewModel.runTask()
+ }
+ }
+ return dialog
}
companion object {
const val TAG = "IndeterminateProgressDialogFragment"
private const val TITLE = "Title"
+ private const val TASK = "Task"
fun newInstance(
titleId: Int,
+ task: () -> Any
): IndeterminateProgressDialogFragment {
val dialog = IndeterminateProgressDialogFragment()
val args = Bundle()
args.putInt(TITLE, titleId)
+ args.putSerializable(TASK, task as Serializable)
dialog.arguments = args
return dialog
}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/TaskViewModel.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/TaskViewModel.kt
new file mode 100644
index 000000000..23723bceb
--- /dev/null
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/TaskViewModel.kt
@@ -0,0 +1,42 @@
+package org.yuzu.yuzu_emu.model
+
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+
+class TaskViewModel : ViewModel() {
+ private val _result = MutableLiveData()
+ val result: LiveData = _result
+
+ private val _isComplete = MutableLiveData()
+ val isComplete: LiveData = _isComplete
+
+ private val _isRunning = MutableLiveData()
+ val isRunning: LiveData = _isRunning
+
+ lateinit var task: () -> Any
+
+ init {
+ clear()
+ }
+
+ fun clear() {
+ _result.value = Any()
+ _isComplete.value = false
+ _isRunning.value = false
+ }
+
+ fun runTask() {
+ if (_isRunning.value == true) return
+ _isRunning.value = true
+
+ viewModelScope.launch(Dispatchers.IO) {
+ val res = task()
+ _result.postValue(res)
+ _isComplete.postValue(true)
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt
index bb8311023..2001ad704 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt
@@ -26,7 +26,6 @@ import androidx.preference.PreferenceManager
import com.google.android.material.color.MaterialColors
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.navigation.NavigationBarView
-import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@@ -340,44 +339,34 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
File(DirectoryInitialization.userDirectory + "/nand/system/Contents/registered/")
val cacheFirmwareDir = File("${cacheDir.path}/registered/")
- val installingFirmwareDialog = IndeterminateProgressDialogFragment.newInstance(
- R.string.firmware_installing
- )
- installingFirmwareDialog.isCancelable = false
- installingFirmwareDialog.show(supportFragmentManager, IndeterminateProgressDialogFragment.TAG)
-
- lifecycleScope.launch(Dispatchers.IO) {
+ val task: () -> Any = {
+ var messageToShow: Any
try {
FileUtil.unzip(inputZip, cacheFirmwareDir)
val unfilteredNumOfFiles = cacheFirmwareDir.list()?.size ?: -1
val filteredNumOfFiles = cacheFirmwareDir.list(filterNCA)?.size ?: -2
if (unfilteredNumOfFiles != filteredNumOfFiles) {
- withContext(Dispatchers.Main) {
- installingFirmwareDialog.dismiss()
- MessageDialogFragment.newInstance(
- R.string.firmware_installed_failure,
- R.string.firmware_installed_failure_description
- ).show(supportFragmentManager, MessageDialogFragment.TAG)
- }
+ messageToShow = MessageDialogFragment.newInstance(
+ R.string.firmware_installed_failure,
+ R.string.firmware_installed_failure_description
+ )
} else {
firmwarePath.deleteRecursively()
cacheFirmwareDir.copyRecursively(firmwarePath, true)
- withContext(Dispatchers.Main) {
- installingFirmwareDialog.dismiss()
- Toast.makeText(
- applicationContext,
- getString(R.string.save_file_imported_success),
- Toast.LENGTH_LONG
- ).show()
- }
+ messageToShow = getString(R.string.save_file_imported_success)
}
} catch (e: Exception) {
- Toast.makeText(applicationContext, getString(R.string.fatal_error), Toast.LENGTH_LONG)
- .show()
+ messageToShow = getString(R.string.fatal_error)
} finally {
cacheFirmwareDir.deleteRecursively()
}
+ messageToShow
}
+
+ IndeterminateProgressDialogFragment.newInstance(
+ R.string.firmware_installing,
+ task
+ ).show(supportFragmentManager, IndeterminateProgressDialogFragment.TAG)
}
val getAmiiboKey =
--
cgit v1.2.3
From 409ff26f029861235b3f7b12400eea82c843244d Mon Sep 17 00:00:00 2001
From: PabloG02
Date: Mon, 5 Jun 2023 08:39:49 +0200
Subject: Address feedback
---
.../yuzu_emu/fragments/HomeSettingsFragment.kt | 9 +++++++--
.../IndeterminateProgressDialogFragment.kt | 22 ++++++++++------------
.../java/org/yuzu/yuzu_emu/model/TaskViewModel.kt | 9 +++++++--
.../java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt | 7 ++++---
4 files changed, 28 insertions(+), 19 deletions(-)
(limited to 'src/android')
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/HomeSettingsFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/HomeSettingsFragment.kt
index 0bdbabe79..d2fa46323 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/HomeSettingsFragment.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/HomeSettingsFragment.kt
@@ -275,7 +275,8 @@ class HomeSettingsFragment : Fragment() {
private fun shareLog() {
val file = DocumentFile.fromSingleUri(
- mainActivity, DocumentsContract.buildDocumentUri(
+ mainActivity,
+ DocumentsContract.buildDocumentUri(
DocumentProvider.AUTHORITY,
"${DocumentProvider.ROOT_ID}/log/yuzu_log.txt"
)
@@ -287,7 +288,11 @@ class HomeSettingsFragment : Fragment() {
.putExtra(Intent.EXTRA_STREAM, file.uri)
startActivity(Intent.createChooser(intent, "Share log"))
} else {
- Toast.makeText(requireContext(), getText(R.string.share_log_missing), Toast.LENGTH_SHORT).show()
+ Toast.makeText(
+ requireContext(),
+ getText(R.string.share_log_missing),
+ Toast.LENGTH_SHORT
+ ).show()
}
}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/IndeterminateProgressDialogFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/IndeterminateProgressDialogFragment.kt
index 10a897392..c7880d8cc 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/IndeterminateProgressDialogFragment.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/IndeterminateProgressDialogFragment.kt
@@ -1,22 +1,24 @@
+// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
package org.yuzu.yuzu_emu.fragments
import android.app.Dialog
import android.os.Bundle
import android.widget.Toast
+import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.DialogFragment
+import androidx.fragment.app.activityViewModels
import androidx.lifecycle.ViewModelProvider
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.yuzu.yuzu_emu.databinding.DialogProgressBarBinding
import org.yuzu.yuzu_emu.model.TaskViewModel
-import java.io.Serializable
class IndeterminateProgressDialogFragment : DialogFragment() {
- private lateinit var taskViewModel: TaskViewModel
+ private val taskViewModel: TaskViewModel by activityViewModels()
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
- taskViewModel = ViewModelProvider(requireActivity())[TaskViewModel::class.java]
-
val titleId = requireArguments().getInt(TITLE)
val progressBinding = DialogProgressBarBinding.inflate(layoutInflater)
@@ -42,11 +44,7 @@ class IndeterminateProgressDialogFragment : DialogFragment() {
}
if (taskViewModel.isRunning.value == false) {
- val task = requireArguments().getSerializable(TASK) as? () -> Any
- if (task != null) {
- taskViewModel.task = task
- taskViewModel.runTask()
- }
+ taskViewModel.runTask()
}
return dialog
}
@@ -55,18 +53,18 @@ class IndeterminateProgressDialogFragment : DialogFragment() {
const val TAG = "IndeterminateProgressDialogFragment"
private const val TITLE = "Title"
- private const val TASK = "Task"
fun newInstance(
+ activity: AppCompatActivity,
titleId: Int,
task: () -> Any
): IndeterminateProgressDialogFragment {
val dialog = IndeterminateProgressDialogFragment()
val args = Bundle()
+ ViewModelProvider(activity)[TaskViewModel::class.java].task = task
args.putInt(TITLE, titleId)
- args.putSerializable(TASK, task as Serializable)
dialog.arguments = args
return dialog
}
}
-}
\ No newline at end of file
+}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/TaskViewModel.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/TaskViewModel.kt
index 23723bceb..27ea725a5 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/TaskViewModel.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/TaskViewModel.kt
@@ -1,3 +1,6 @@
+// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
package org.yuzu.yuzu_emu.model
import androidx.lifecycle.LiveData
@@ -30,7 +33,9 @@ class TaskViewModel : ViewModel() {
}
fun runTask() {
- if (_isRunning.value == true) return
+ if (_isRunning.value == true) {
+ return
+ }
_isRunning.value = true
viewModelScope.launch(Dispatchers.IO) {
@@ -39,4 +44,4 @@ class TaskViewModel : ViewModel() {
_isComplete.postValue(true)
}
}
-}
\ No newline at end of file
+}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt
index 2001ad704..6805efb55 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt
@@ -345,15 +345,15 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
FileUtil.unzip(inputZip, cacheFirmwareDir)
val unfilteredNumOfFiles = cacheFirmwareDir.list()?.size ?: -1
val filteredNumOfFiles = cacheFirmwareDir.list(filterNCA)?.size ?: -2
- if (unfilteredNumOfFiles != filteredNumOfFiles) {
- messageToShow = MessageDialogFragment.newInstance(
+ messageToShow = if (unfilteredNumOfFiles != filteredNumOfFiles) {
+ MessageDialogFragment.newInstance(
R.string.firmware_installed_failure,
R.string.firmware_installed_failure_description
)
} else {
firmwarePath.deleteRecursively()
cacheFirmwareDir.copyRecursively(firmwarePath, true)
- messageToShow = getString(R.string.save_file_imported_success)
+ getString(R.string.save_file_imported_success)
}
} catch (e: Exception) {
messageToShow = getString(R.string.fatal_error)
@@ -364,6 +364,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
}
IndeterminateProgressDialogFragment.newInstance(
+ this,
R.string.firmware_installing,
task
).show(supportFragmentManager, IndeterminateProgressDialogFragment.TAG)
--
cgit v1.2.3
From e1078ec0f48186ea6947271fff0da881d91b7d1c Mon Sep 17 00:00:00 2001
From: bunnei
Date: Mon, 5 Jun 2023 17:40:43 -0700
Subject: android: HomeSettingsFragment: Use string resource for "Share log".
---
.../src/main/java/org/yuzu/yuzu_emu/fragments/HomeSettingsFragment.kt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'src/android')
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/HomeSettingsFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/HomeSettingsFragment.kt
index d2fa46323..bdc337501 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/HomeSettingsFragment.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/HomeSettingsFragment.kt
@@ -286,7 +286,7 @@ class HomeSettingsFragment : Fragment() {
.setDataAndType(file.uri, FileUtil.TEXT_PLAIN)
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
.putExtra(Intent.EXTRA_STREAM, file.uri)
- startActivity(Intent.createChooser(intent, "Share log"))
+ startActivity(Intent.createChooser(intent, getText(R.string.share_log)))
} else {
Toast.makeText(
requireContext(),
--
cgit v1.2.3