Skip to content

Commit

Permalink
Merge pull request #129 from MohamedRejeb/0.5.x
Browse files Browse the repository at this point in the history
Refactor rememberImageVideoPickerLauncher
  • Loading branch information
MohamedRejeb authored Jul 25, 2024
2 parents 10e2a4e + 20460ab commit 088e018
Showing 1 changed file with 42 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ import com.mohamedrejeb.calf.core.InternalCalfApi
import com.mohamedrejeb.calf.io.KmpFile
import kotlinx.cinterop.BetaInteropApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withContext
import platform.Foundation.NSItemProvider
import platform.Foundation.NSURL
import platform.Photos.PHPhotoLibrary
import platform.PhotosUI.PHPickerConfiguration
Expand All @@ -30,6 +32,7 @@ import platform.UniformTypeIdentifiers.UTTypeImage
import platform.UniformTypeIdentifiers.UTTypeText
import platform.UniformTypeIdentifiers.UTTypeVideo
import platform.darwin.NSObject
import kotlin.coroutines.resume

@BetaInteropApi
@Composable
Expand All @@ -51,15 +54,16 @@ private fun rememberDocumentPickerLauncher(
selectionMode: FilePickerSelectionMode,
onResult: (List<KmpFile>) -> Unit,
): FilePickerLauncher {
val coroutineScope = rememberCoroutineScope()
val scope = rememberCoroutineScope()

val delegate =
remember {
object : NSObject(), UIDocumentPickerDelegateProtocol {
override fun documentPicker(
controller: UIDocumentPickerViewController,
didPickDocumentAtURL: NSURL,
) {
coroutineScope.launch(Dispatchers.Main) {
scope.launch(Dispatchers.Main) {
val result =
if (type == FilePickerFileType.Folder)
listOf(KmpFile(didPickDocumentAtURL))
Expand Down Expand Up @@ -95,13 +99,13 @@ private fun rememberDocumentPickerLauncher(
}
}

coroutineScope.launch(Dispatchers.Main) {
scope.launch(Dispatchers.Main) {
onResult(dataList)
}
}

override fun documentPickerWasCancelled(controller: UIDocumentPickerViewController) {
coroutineScope.launch(Dispatchers.Main) {
scope.launch(Dispatchers.Main) {
onResult(emptyList())
}
}
Expand Down Expand Up @@ -130,51 +134,32 @@ private fun rememberDocumentPickerLauncher(
}
}

@OptIn(InternalCalfApi::class)
@Composable
private fun rememberImageVideoPickerLauncher(
type: FilePickerFileType,
selectionMode: FilePickerSelectionMode,
onResult: (List<KmpFile>) -> Unit,
): FilePickerLauncher {
val scope = rememberCoroutineScope()

val pickerDelegate = remember {
object : NSObject(), PHPickerViewControllerDelegateProtocol {
override fun picker(
picker: PHPickerViewController,
didFinishPicking: List<*>,
) {
var pendingOperations = didFinishPicking.size
val results = mutableListOf<KmpFile>()

didFinishPicking.forEach {
val result = it as? PHPickerResult ?: return@forEach


println(result.itemProvider.registeredTypeIdentifiers.size)
result.itemProvider.loadFileRepresentationForTypeIdentifier(
typeIdentifier = result.itemProvider.registeredTypeIdentifiers.firstOrNull() as? String ?: UTTypeImage.identifier) { url, error ->
if (error != null) {
return@loadFileRepresentationForTypeIdentifier
}
scope.launch {
val results = didFinishPicking.mapNotNull {
val result = it as? PHPickerResult ?: return@mapNotNull null

url?.createTempFile()?.let { tempUrl ->
results.add(
KmpFile(
url = url,
tempUrl = tempUrl,
)
)
}

pendingOperations--
result.itemProvider.loadFileRepresentationForTypeIdentifierSuspend()
}

if(pendingOperations == 0){
//only call one onResult, in file picker it isnt called twice
onResult(results)
}
withContext(Dispatchers.Main) {
onResult(results)
}
}

picker.dismissViewControllerAnimated(true, null)
}
}
Expand Down Expand Up @@ -202,6 +187,30 @@ private fun rememberImageVideoPickerLauncher(
}
}

@OptIn(InternalCalfApi::class)
private suspend fun NSItemProvider.loadFileRepresentationForTypeIdentifierSuspend(): KmpFile? = suspendCancellableCoroutine { continuation ->
val progress = loadFileRepresentationForTypeIdentifier(
typeIdentifier = registeredTypeIdentifiers.firstOrNull() as? String ?: UTTypeImage.identifier
) { url, error ->
if (error != null) {
continuation.resume(null)
return@loadFileRepresentationForTypeIdentifier
}

continuation.resume(
url?.createTempFile()?.let { tempUrl ->
KmpFile(
url = url,
tempUrl = tempUrl,
)
}
)
}

continuation.invokeOnCancellation {
progress.cancel()
}
}

private fun createUIDocumentPickerViewController(
delegate: UIDocumentPickerDelegateProtocol,
Expand Down

0 comments on commit 088e018

Please sign in to comment.