From 19037fb35d64c400f68bb121f6c4d2971596328a Mon Sep 17 00:00:00 2001 From: SolsticeSpectrum Date: Sun, 30 Nov 2025 20:44:11 +0100 Subject: [PATCH] Add SEND_MULTIPLE support for saving multiple files --- app/src/main/AndroidManifest.xml | 1 + .../files/util/IntentPathExtensions.kt | 13 ++++++++ .../files/viewer/saveas/SaveAsActivity.kt | 30 ++++++++++++++----- 3 files changed, 37 insertions(+), 7 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index f4b7b77d5..19de40640 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -310,6 +310,7 @@ + diff --git a/app/src/main/java/me/zhanghai/android/files/util/IntentPathExtensions.kt b/app/src/main/java/me/zhanghai/android/files/util/IntentPathExtensions.kt index 62074bfca..7e3fa2b57 100644 --- a/app/src/main/java/me/zhanghai/android/files/util/IntentPathExtensions.kt +++ b/app/src/main/java/me/zhanghai/android/files/util/IntentPathExtensions.kt @@ -48,6 +48,19 @@ val Intent.saveAsPath: Path? return uri?.toPathOrNull() } +val Intent.saveAsPaths: List + get() = + when (action) { + Intent.ACTION_VIEW -> listOfNotNull(data?.toPathOrNull()) + Intent.ACTION_SEND -> + listOfNotNull((getParcelableExtraSafe(Intent.EXTRA_STREAM) as? Uri)?.toPathOrNull()) + Intent.ACTION_SEND_MULTIPLE -> + getParcelableArrayListExtraSafe(Intent.EXTRA_STREAM) + ?.mapNotNull { it.toPathOrNull() } + ?: emptyList() + else -> emptyList() + } + private fun Uri.toPathOrNull(): Path? = when (scheme) { ContentResolver.SCHEME_FILE, null -> path?.takeIfNotEmpty()?.let { Paths.get(it) } diff --git a/app/src/main/java/me/zhanghai/android/files/viewer/saveas/SaveAsActivity.kt b/app/src/main/java/me/zhanghai/android/files/viewer/saveas/SaveAsActivity.kt index a550f34c4..78a935fd2 100644 --- a/app/src/main/java/me/zhanghai/android/files/viewer/saveas/SaveAsActivity.kt +++ b/app/src/main/java/me/zhanghai/android/files/viewer/saveas/SaveAsActivity.kt @@ -15,30 +15,37 @@ import me.zhanghai.android.files.file.MimeType import me.zhanghai.android.files.file.asMimeTypeOrNull import me.zhanghai.android.files.filejob.FileJobService import me.zhanghai.android.files.filelist.FileListActivity -import me.zhanghai.android.files.util.saveAsPath +import me.zhanghai.android.files.util.saveAsPaths import me.zhanghai.android.files.util.showToast class SaveAsActivity : AppActivity() { private val createFileLauncher = registerForActivityResult(FileListActivity.CreateFileContract(), ::onCreateFileResult) + private val openDirectoryLauncher = + registerForActivityResult(FileListActivity.OpenDirectoryContract(), ::onOpenDirectoryResult) + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val intent = intent - val mimeType = intent.type?.asMimeTypeOrNull() ?: MimeType.ANY - val path = intent.saveAsPath - if (path == null) { + val paths = intent.saveAsPaths + if (paths.isEmpty()) { showToast(R.string.save_as_error) finish() return } - val title = path.fileName.toString() val initialPath = Paths.get( Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).path ) - createFileLauncher.launch(Triple(mimeType, title, initialPath)) + if (paths.size == 1) { + val mimeType = intent.type?.asMimeTypeOrNull() ?: MimeType.ANY + val title = paths.first().fileName.toString() + createFileLauncher.launch(Triple(mimeType, title, initialPath)) + } else { + openDirectoryLauncher.launch(initialPath) + } } private fun onCreateFileResult(result: Path?) { @@ -46,7 +53,16 @@ class SaveAsActivity : AppActivity() { finish() return } - FileJobService.save(intent.saveAsPath!!, result, this) + FileJobService.save(intent.saveAsPaths.first(), result, this) + finish() + } + + private fun onOpenDirectoryResult(result: Path?) { + if (result == null) { + finish() + return + } + FileJobService.copy(intent.saveAsPaths, result, this) finish() } }