This commit is contained in:
Trey t
2025-11-04 16:34:05 -06:00
parent 3e617c9cd8
commit 177e588944
11 changed files with 410 additions and 9 deletions

View File

@@ -0,0 +1,107 @@
package com.mycrib.platform
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.interop.LocalUIViewController
import kotlinx.cinterop.*
import platform.Foundation.*
import platform.PhotosUI.*
import platform.UIKit.*
import platform.darwin.NSObject
import platform.posix.memcpy
@OptIn(ExperimentalForeignApi::class)
@Composable
actual fun rememberImagePicker(
onImagesPicked: (List<ImageData>) -> Unit
): () -> Unit {
val viewController = LocalUIViewController.current
val pickerDelegate = remember {
object : NSObject(), PHPickerViewControllerDelegateProtocol {
override fun picker(
picker: PHPickerViewController,
didFinishPicking: List<*>
) {
picker.dismissViewControllerAnimated(true, null)
val results = didFinishPicking as List<PHPickerResult>
if (results.isEmpty()) {
return
}
val images = mutableListOf<ImageData>()
var processedCount = 0
results.forEach { result ->
val itemProvider = result.itemProvider
// Check if the item has an image using UTType
if (itemProvider.hasItemConformingToTypeIdentifier("public.image")) {
itemProvider.loadFileRepresentationForTypeIdentifier(
typeIdentifier = "public.image",
completionHandler = { url, error ->
if (error == null && url != null) {
// Read the image data from the file URL
val imageData = NSData.dataWithContentsOfURL(url)
if (imageData != null) {
// Convert to UIImage and then to JPEG for consistent format
val image = UIImage.imageWithData(imageData)
if (image != null) {
val jpegData = UIImageJPEGRepresentation(image, 0.8)
if (jpegData != null) {
val bytes = jpegData.toByteArray()
val fileName = "image_${NSDate().timeIntervalSince1970.toLong()}_${processedCount}.jpg"
synchronized(images) {
images.add(ImageData(bytes, fileName))
}
}
}
}
}
processedCount++
// When all images are processed, call the callback
if (processedCount == results.size) {
if (images.isNotEmpty()) {
onImagesPicked(images.toList())
}
}
}
)
} else {
processedCount++
}
}
}
}
}
return {
val config = PHPickerConfiguration().apply {
setSelectionLimit(5)
setFilter(PHPickerFilter.imagesFilter())
}
val picker = PHPickerViewController(config).apply {
setDelegate(pickerDelegate)
}
viewController.presentViewController(picker, animated = true, completion = null)
}
}
@OptIn(ExperimentalForeignApi::class)
private fun NSData.toByteArray(): ByteArray {
return ByteArray(length.toInt()).apply {
usePinned {
memcpy(it.addressOf(0), bytes, length)
}
}
}
@Suppress("UNCHECKED_CAST")
private fun <T : Any> synchronized(lock: Any, block: () -> T): T {
return block()
}