Skip to content

Commit

Permalink
icerockdev#34 Add base PickerDelegate class
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexey Nesterov committed May 7, 2024
1 parent 3a81ec6 commit 6ae0752
Show file tree
Hide file tree
Showing 7 changed files with 272 additions and 259 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* Copyright 2024 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license.
*/

package dev.icerock.moko.media.picker

import android.content.Context
import android.net.Uri
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.ActivityResultRegistry
import androidx.activity.result.contract.ActivityResultContracts

internal class CameraPickerDelegate :
ImagePickerDelegate<CameraPickerDelegate.CallbackData, Uri>() {

override fun registerActivityResult(
context: Context,
activityResultRegistry: ActivityResultRegistry
): ActivityResultLauncher<Uri> = activityResultRegistry.register(
PICK_CAMERA_IMAGE_KEY,
ActivityResultContracts.TakePicture(),
) { result ->
val callbackData = callback ?: return@register
callback = null

if (!result) {
callbackData.callback.invoke(Result.failure(CanceledException()))
return@register
}

processResult(
context = context,
callback = callbackData.callback,
uri = callbackData.outputUri,
maxImageWidth = callbackData.maxWidth,
maxImageHeight = callbackData.maxHeight,
)
}

fun pick(
maxWidth: Int,
maxHeight: Int,
callback: (Result<android.graphics.Bitmap>) -> Unit,
outputUri: Uri,
) {
this.callback?.let {
it.callback.invoke(Result.failure(IllegalStateException("Callback should be null")))
this.callback = null
}
this.callback = CallbackData(
callback,
outputUri,
maxWidth,
maxHeight,
)

pickerLauncherHolder.value?.launch(
outputUri
)
}

class CallbackData(
val callback: (Result<android.graphics.Bitmap>) -> Unit,
val outputUri: Uri,
val maxWidth: Int,
val maxHeight: Int,
)

companion object {
private const val PICK_CAMERA_IMAGE_KEY = "PickCameraImageKey"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,76 +6,69 @@ package dev.icerock.moko.media.picker

import android.annotation.SuppressLint
import android.content.ContentResolver
import android.content.Context
import android.provider.OpenableColumns
import androidx.activity.ComponentActivity
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.ActivityResultRegistryOwner
import androidx.activity.result.ActivityResultRegistry
import androidx.activity.result.contract.ActivityResultContracts
import dev.icerock.moko.media.FileMedia
import kotlinx.coroutines.flow.MutableStateFlow
import java.io.File

internal class FilePickerDelegate {
internal class FilePickerDelegate :
PickerDelegate<FilePickerDelegate.CallbackData, Array<String>>() {

private var callback: CallbackData? = null
override fun registerActivityResult(
context: Context,
activityResultRegistry: ActivityResultRegistry
): ActivityResultLauncher<Array<String>> = activityResultRegistry.register(
PICK_FILE_KEY,
ActivityResultContracts.OpenDocument(),
) { uri ->
val callbackData = callback ?: return@register
callback = null

private val filePickerLauncherHolder =
MutableStateFlow<ActivityResultLauncher<Array<String>>?>(null)
val callback = callbackData.callback

fun bind(activity: ComponentActivity) {
val activityResultRegistryOwner = activity as ActivityResultRegistryOwner
val activityResultRegistry = activityResultRegistryOwner.activityResultRegistry

filePickerLauncherHolder.value = activityResultRegistry.register(
PICK_FILE_KEY,
ActivityResultContracts.OpenDocument(),
) { uri ->
val callbackData = callback ?: return@register
callback = null

val callback = callbackData.callback
if (uri == null) {
callback.invoke(Result.failure(CanceledException()))
return@register
}

if (uri == null) {
callback.invoke(Result.failure(CanceledException()))
return@register
}
val path = uri.path
if (path == null) {
callback.invoke(Result.failure(java.lang.IllegalStateException("File is null")))
return@register
}

val path = uri.path
if (path == null) {
callback.invoke(Result.failure(java.lang.IllegalStateException("File is null")))
return@register
@SuppressLint("Range")
val fileNameWithExtension = if (uri.scheme == ContentResolver.SCHEME_CONTENT) {
val cursor = context.contentResolver.query(uri, null, null, null, null)
cursor?.use {
if (!it.moveToFirst()) null
else it.getString(it.getColumnIndex(OpenableColumns.DISPLAY_NAME))
}

@SuppressLint("Range")
val fileNameWithExtension = if (uri.scheme == ContentResolver.SCHEME_CONTENT) {
val cursor = activity.contentResolver.query(uri, null, null, null, null)
cursor?.use {
if (!it.moveToFirst()) null
else it.getString(it.getColumnIndex(OpenableColumns.DISPLAY_NAME))
}
} else null

val file = File(path)
val name = file.name
val result = Result.success(
FileMedia(
fileNameWithExtension ?: name,
uri.toString(),
)
} else null

val file = File(path)
val name = file.name
val result = Result.success(
FileMedia(
fileNameWithExtension ?: name,
uri.toString(),
)
callback.invoke(result)
}
)
callback.invoke(result)
}

fun pickFile(callback: (Result<FileMedia>) -> Unit) {
fun pick(callback: (Result<FileMedia>) -> Unit) {
this.callback?.let {
it.callback.invoke(Result.failure(IllegalStateException("Callback should be null")))
this.callback = null
}

this.callback = CallbackData(callback)

filePickerLauncherHolder.value?.launch(
pickerLauncherHolder.value?.launch(
arrayOf(
"*/*",
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Copyright 2024 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license.
*/

package dev.icerock.moko.media.picker

import android.content.Context
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.ActivityResultRegistry
import androidx.activity.result.PickVisualMediaRequest
import androidx.activity.result.contract.ActivityResultContracts

internal class GalleryPickerDelegate :
ImagePickerDelegate<GalleryPickerDelegate.CallbackData, PickVisualMediaRequest>() {

override fun registerActivityResult(
context: Context,
activityResultRegistry: ActivityResultRegistry
): ActivityResultLauncher<PickVisualMediaRequest> = activityResultRegistry.register(
PICK_GALLERY_IMAGE_KEY,
ActivityResultContracts.PickVisualMedia(),
) { uri ->
val callbackData = callback ?: return@register
callback = null

if (uri == null) {
callbackData.callback.invoke(Result.failure(CanceledException()))
return@register
}

processResult(
context = context,
callback = callbackData.callback,
uri = uri,
maxImageWidth = callbackData.maxWidth,
maxImageHeight = callbackData.maxHeight,
)
}

fun pick(
maxWidth: Int,
maxHeight: Int,
callback: (Result<android.graphics.Bitmap>) -> Unit,
) {
this.callback?.let {
it.callback.invoke(Result.failure(IllegalStateException("Callback should be null")))
this.callback = null
}

this.callback = CallbackData(
callback,
maxWidth,
maxHeight,
)

pickerLauncherHolder.value?.launch(
PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly)
)
}

class CallbackData(
val callback: (Result<android.graphics.Bitmap>) -> Unit,
val maxWidth: Int,
val maxHeight: Int,
)

companion object {
private const val PICK_GALLERY_IMAGE_KEY = "PickGalleryImageKey"
}
}
Loading

0 comments on commit 6ae0752

Please sign in to comment.