0
0
mirror of https://github.com/Ishan09811/pine.git synced 2025-04-24 08:55:10 +00:00

Fix save export (#71)

This commit is contained in:
Ishan09811 2025-03-02 15:06:00 +05:30 committed by GitHub
parent 630e84d635
commit 85e33f94a7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 48 additions and 40 deletions

View File

@ -80,7 +80,7 @@ class AppDialog : BottomSheetDialogFragment() {
* Used to manage save files
*/
private lateinit var documentPicker : ActivityResultLauncher<Array<String>>
private lateinit var startForResultExportSave : ActivityResultLauncher<Intent>
private lateinit var startForResultExportSave : ActivityResultLauncher<String>
private val contents by lazy { ContentsHelper(requireContext()) }
@ -96,28 +96,9 @@ class AppDialog : BottomSheetDialogFragment() {
val isSaveFileOfThisGame = SaveManagementUtils.saveFolderGameExists(item.titleId)
binding.deleteSave.isEnabled = isSaveFileOfThisGame
binding.exportSave.isEnabled = isSaveFileOfThisGame
}
}
startForResultExportSave = SaveManagementUtils.registerStartForResultExportSave(requireActivity())
startForResultExportSave = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == Activity.RESULT_OK) {
result.data?.data?.let { uri ->
val pickedDir = DocumentFile.fromTreeUri(requireContext(), uri) ?: return@let
CoroutineScope(Dispatchers.IO).launch {
val zipFilePath = "${SkylineApplication.instance.getPublicFilesDir().canonicalPath}/temp/${SaveManagementUtils.saveZipName}"
val zipFile = File(zipFilePath)
val inputStream: InputStream = zipFile.inputStream()
val outputStream: OutputStream? = requireContext().contentResolver.openOutputStream(pickedDir.createFile("application/zip", zipFile.name)?.uri!!)
inputStream.use { input ->
outputStream?.use { output ->
input.copyTo(output)
}
}
}
}
}
}
contentPickerLauncher = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { result ->
@ -246,7 +227,7 @@ class AppDialog : BottomSheetDialogFragment() {
binding.exportSave.isEnabled = saveExists
binding.exportSave.setOnClickListener {
SaveManagementUtils.exportSave(requireContext(), startForResultExportSave, item.titleId, "${item.title} (v${binding.gameVersion.text}) [${item.titleId}]")
SaveManagementUtils.exportSave(startForResultExportSave, item.titleId, "${item.title} (v${binding.gameVersion.text}) [${item.titleId}]")
}
binding.importUpdate.setOnClickListener {

View File

@ -29,7 +29,7 @@ class ImportExportSavesPreference @JvmOverloads constructor(context : Context, a
if (saveDataExists) {
dialog.setMessage(R.string.save_data_found)
.setNegativeButton(R.string.export_save) { _, _ ->
SaveManagementUtils.exportSave(context, startForResultExportSave, "", context.getString(R.string.global_save_data_zip_name))
SaveManagementUtils.exportSave(startForResultExportSave, "", context.getString(R.string.global_save_data_zip_name))
}
} else {
dialog.setMessage(R.string.save_data_not_found)

View File

@ -33,12 +33,15 @@ import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream
import java.io.FileInputStream
interface SaveManagementUtils {
companion object {
val savesFolderRoot = "${SkylineApplication.instance.getPublicFilesDir().canonicalPath}/switch/nand/user/save/0000000000000000/00000000000000000000000000000001"
lateinit var saveZipName: String
private var exportZipName: String = "export"
private var exportZipTitleId: String = ""
fun registerDocumentPicker(context : Context) : ActivityResultLauncher<Array<String>> {
return (context as ComponentActivity).registerForActivityResult(ActivityResultContracts.OpenDocument()) {
@ -55,21 +58,29 @@ interface SaveManagementUtils {
}
}
fun registerStartForResultExportSave(context : Context) : ActivityResultLauncher<Intent> {
return (context as ComponentActivity).registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
File(context.getPublicFilesDir().canonicalPath, "temp").deleteRecursively()
fun registerStartForResultExportSave(context : Context) : ActivityResultLauncher<String> {
File(context.getPublicFilesDir().canonicalPath, "temp").deleteRecursively()
return (context as ComponentActivity).registerForActivityResult(ActivityResultContracts.CreateDocument("application/zip")) { uri ->
uri?.let {
exportSave(context, it)
}
}
}
fun registerStartForResultExportSave(fragmentAct : FragmentActivity) : ActivityResultLauncher<Intent> {
fun registerStartForResultExportSave(fragmentAct : FragmentActivity) : ActivityResultLauncher<String> {
val activity = fragmentAct as AppCompatActivity
val activityResultRegistry = fragmentAct.activityResultRegistry
return activityResultRegistry.register("startForResultExportSaveKey", ActivityResultContracts.StartActivityForResult()) {
File(activity.getPublicFilesDir().canonicalPath, "temp").deleteRecursively()
File(activity.getPublicFilesDir().canonicalPath, "temp").deleteRecursively()
return activityResultRegistry.register("saveExportFolderPickerKey", ActivityResultContracts.CreateDocument("application/zip")) { uri ->
uri?.let {
activity.contentResolver.takePersistableUriPermission(
it, Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
)
exportSave(fragmentAct as Context, it)
}
}
}
/**
* Checks if the saves folder exists.
*/
@ -126,11 +137,11 @@ interface SaveManagementUtils {
* @param titleId The title ID of the game to export the save file of. If empty, export all save files.
* @param outputZipName The initial part of the name of the zip file to create.
*/
fun exportSave(context : Context, startForResultExportSave : ActivityResultLauncher<Intent>, titleId : String?, outputZipName : String) {
if (titleId == null) return
fun exportSave(context : Context, uri: Uri) {
if (exportZipTitleId == null) return
CoroutineScope(Dispatchers.IO).launch {
val saveFolderPath = "$savesFolderRoot/$titleId"
val zipCreated = zipSave(saveFolderPath, outputZipName)
val saveFolderPath = "$savesFolderRoot/$exportZipTitleId"
val zipCreated = zipSave(saveFolderPath, exportZipName)
if (zipCreated == null) {
withContext(Dispatchers.Main) {
Toast.makeText(context, R.string.error, Toast.LENGTH_LONG).show()
@ -138,14 +149,29 @@ interface SaveManagementUtils {
return@launch
}
try {
context.contentResolver.openOutputStream(uri)?.use { output ->
FileInputStream(zipCreated).use { it.copyTo(output) }
}
} catch (e: Exception) {
withContext(Dispatchers.Main) {
Toast.makeText(context, "Error: ${e.message}", Toast.LENGTH_LONG).show()
}
return@launch
}
withContext(Dispatchers.Main) {
saveZipName = "${zipCreated.name}"
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
startForResultExportSave.launch(intent)
Toast.makeText(context, R.string.save_exported_successfully, Toast.LENGTH_LONG).show()
}
}
}
fun exportSave(startForResultExportSave : ActivityResultLauncher<String>, titleId: String?, outputZipName : String) {
exportZipTitleId = titleId ?: ""
exportZipName = outputZipName
startForResultExportSave.launch("$exportZipName - ${LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))}")
}
/**
* Launches the document picker to import a save file.
*/

View File

@ -29,6 +29,7 @@
<string name="delete_save">Delete save</string>
<string name="import_save">Import</string>
<string name="export_save">Export</string>
<string name="save_exported_successfully">Successfully exported save file</string>
<string name="manage_contents">Contents</string>
<string name="import_update">Update</string>
<string name="import_dlcs">DLCs</string>