mirror of
https://github.com/sudosylabs/vnidrop.git
synced 2026-08-05 18:39:55 +02:00
feat(send): multi-file shares and receivers polish
Allow selecting multiple files on Android, desktop, and iOS and share them as one transfer through the core multi-source path. Update the composer UI for multi-file review, hide unfinished iOS receive methods, and surface refusal reasons on the receivers list.
This commit is contained in:
@@ -16,18 +16,22 @@ import androidx.compose.ui.platform.LocalContext
|
||||
|
||||
@Composable
|
||||
actual fun rememberShareFilePicker(
|
||||
onFilePicked: (PickedShareFile) -> Unit,
|
||||
onFilesPicked: (List<PickedShareFile>) -> Unit,
|
||||
onError: (String) -> Unit,
|
||||
): ShareFilePicker {
|
||||
val context = LocalContext.current
|
||||
val launcher = rememberLauncherForActivityResult(ActivityResultContracts.OpenDocument()) { uri ->
|
||||
if (uri != null) {
|
||||
onFilePicked(context.pickedShareFile(uri))
|
||||
}
|
||||
val launcher = rememberLauncherForActivityResult(ActivityResultContracts.OpenMultipleDocuments()) { uris ->
|
||||
if (uris.isEmpty()) return@rememberLauncherForActivityResult
|
||||
runCatching {
|
||||
uris.map { uri -> context.pickedShareFile(uri) }
|
||||
}.fold(
|
||||
onSuccess = onFilesPicked,
|
||||
onFailure = { onError(it.message ?: "Could not open the selected files") },
|
||||
)
|
||||
}
|
||||
return remember(launcher) {
|
||||
object : ShareFilePicker {
|
||||
override fun pickFile() {
|
||||
override fun pickFiles() {
|
||||
launcher.launch(arrayOf("*/*"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,22 +63,30 @@ private class AndroidFileSystemService(
|
||||
ReceiveFolderKind.IosSecurityScopedUrl -> null
|
||||
}
|
||||
|
||||
override suspend fun sharePickedFile(
|
||||
override suspend fun sharePickedFiles(
|
||||
repository: CoreGateway,
|
||||
file: PickedShareFile,
|
||||
files: List<PickedShareFile>,
|
||||
transferName: String,
|
||||
senderName: String,
|
||||
accessPolicy: ShareAccessPolicy,
|
||||
): Result<Share> = runCatching {
|
||||
context.contentResolver.openFileDescriptor(Uri.parse(file.value), "r").use { descriptor ->
|
||||
checkNotNull(descriptor) { "Could not open selected file descriptor" }
|
||||
repository.shareFileDescriptor(
|
||||
fd = descriptor.fd,
|
||||
displayName = file.displayName,
|
||||
transferName = transferName,
|
||||
senderName = senderName,
|
||||
accessPolicy = accessPolicy,
|
||||
).getOrThrow()
|
||||
require(files.isNotEmpty()) { "Select at least one file to share" }
|
||||
val descriptors = files.map { file ->
|
||||
context.contentResolver.openFileDescriptor(Uri.parse(file.value), "r")
|
||||
?: error("Could not open selected file descriptor for ${file.displayName}")
|
||||
}
|
||||
try {
|
||||
val sources = files.zip(descriptors) { file, descriptor ->
|
||||
uniffi.vnidrop.ShareSource(
|
||||
kind = uniffi.vnidrop.SourceKind.FILE_DESCRIPTOR,
|
||||
value = descriptor.fd.toString(),
|
||||
displayName = file.displayName,
|
||||
isDirectory = false,
|
||||
)
|
||||
}
|
||||
repository.shareSources(sources, transferName, senderName, accessPolicy).getOrThrow()
|
||||
} finally {
|
||||
descriptors.forEach { it.close() }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user