From 488303b06127d427555b4134c20c2e56f0c69b7c Mon Sep 17 00:00:00 2001 From: Akshay Ashok <63944420+AkshayAshokCode@users.noreply.github.com> Date: Thu, 28 May 2026 02:52:12 +0530 Subject: [PATCH 1/9] Refactor ImagePickerBuilder API entrypoint consistency --- .../imagepicker/builder/ImagePickerBuilder.kt | 43 ++++++++++++------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/imagepicker/src/main/java/com/akshayashokcode/imagepicker/builder/ImagePickerBuilder.kt b/imagepicker/src/main/java/com/akshayashokcode/imagepicker/builder/ImagePickerBuilder.kt index b6e9002..128dedf 100644 --- a/imagepicker/src/main/java/com/akshayashokcode/imagepicker/builder/ImagePickerBuilder.kt +++ b/imagepicker/src/main/java/com/akshayashokcode/imagepicker/builder/ImagePickerBuilder.kt @@ -1,19 +1,27 @@ package com.akshayashokcode.imagepicker.builder import android.content.Context -import android.net.Uri import androidx.activity.result.ActivityResultCaller import com.akshayashokcode.imagepicker.coordinator.ImagePickerCoordinator import com.akshayashokcode.imagepicker.model.ImagePickerException import com.akshayashokcode.imagepicker.model.ImagePickerResult import com.akshayashokcode.imagepicker.model.MediaSource -class ImagePickerBuilder( +/** + * Fluent builder used to configure and launch the MediaKit image picker flow. + * + * Consumers should create instances through [with] to keep the public API + * consistent and future-proof. + */ +class ImagePickerBuilder private constructor( private val context: Context, private val caller: ActivityResultCaller ) { private var source: MediaSource = MediaSource.Gallery - private var crop: Boolean = false // Reserved for future integration + + // Reserved for future cropper module integration. + private var crop: Boolean = false + private var onResult: ((ImagePickerResult) -> Unit)? = null private var onError: ((ImagePickerException) -> Unit)? = null @@ -21,58 +29,61 @@ class ImagePickerBuilder( /** * Entry point to start building an image picker flow. * - * @param context Application or activity context - * @param caller ActivityResultCaller (Activity or Fragment) + * @param context Application or activity context. + * @param caller ActivityResultCaller (Activity or Fragment). */ - fun with(context: Context, caller: ActivityResultCaller): ImagePickerBuilder { + fun with( + context: Context, + caller: ActivityResultCaller + ): ImagePickerBuilder { return ImagePickerBuilder(context, caller) } } /** - * Set the image source (GALLERY, CAMERA, or BOTH). + * Configure the media source. */ fun source(source: MediaSource): ImagePickerBuilder = apply { this.source = source } /** - * Enable cropping after selection (optional feature, not yet active). + * Enables optional cropping support. + * + * Cropper integration is planned for a future MediaKit release. */ fun crop(enable: Boolean): ImagePickerBuilder = apply { this.crop = enable } /** - * Callback to receive the picker result. + * Callback invoked with picker results. */ fun onResult(callback: (ImagePickerResult) -> Unit): ImagePickerBuilder = apply { this.onResult = callback } /** - * Optional error callback to receive specific error cases. + * Optional callback invoked for picker failures. */ fun onError(callback: (ImagePickerException) -> Unit): ImagePickerBuilder = apply { this.onError = callback } /** - * Launch the image picker with the current configuration. + * Launches the picker flow with the current configuration. */ fun launch() { requireNotNull(onResult) { "You must provide a result callback using onResult()" } - val coordinator = ImagePickerCoordinator( + ImagePickerCoordinator( context = context, caller = caller, source = source, onResult = onResult!!, onError = onError - ) - - coordinator.launch() + ).launch() } -} \ No newline at end of file +} From c6efd8d2baedfb537707c554326d019fc60c2a7d Mon Sep 17 00:00:00 2001 From: Akshay Ashok <63944420+AkshayAshokCode@users.noreply.github.com> Date: Thu, 28 May 2026 02:52:24 +0530 Subject: [PATCH 2/9] Improve ImagePickerResult API documentation --- .../imagepicker/model/ImagePickerResult.kt | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/imagepicker/src/main/java/com/akshayashokcode/imagepicker/model/ImagePickerResult.kt b/imagepicker/src/main/java/com/akshayashokcode/imagepicker/model/ImagePickerResult.kt index 299f79b..cd7d7c7 100644 --- a/imagepicker/src/main/java/com/akshayashokcode/imagepicker/model/ImagePickerResult.kt +++ b/imagepicker/src/main/java/com/akshayashokcode/imagepicker/model/ImagePickerResult.kt @@ -3,9 +3,35 @@ package com.akshayashokcode.imagepicker.model import android.graphics.Bitmap import android.net.Uri +/** + * Represents the final state returned from the MediaKit image picker flow. + */ sealed class ImagePickerResult { + + /** + * Successful image selection with resulting Uri. + */ data class Success(val uri: Uri) : ImagePickerResult() - data class SuccessWithBitmap(val uri: Uri, val bitmap: Bitmap) : ImagePickerResult() + + /** + * Successful image selection with decoded bitmap. + * + * Intended for advanced consumers that require immediate bitmap access. + */ + data class SuccessWithBitmap( + val uri: Uri, + val bitmap: Bitmap + ) : ImagePickerResult() + + /** + * User cancelled the picker flow. + */ data object Cancelled : ImagePickerResult() + + /** + * Generic picker error. + * + * This will later migrate to a sealed error model for stronger typing. + */ data class Error(val message: String) : ImagePickerResult() -} \ No newline at end of file +} From 15baede469747355d180d20687ed738656dc06b6 Mon Sep 17 00:00:00 2001 From: Akshay Ashok <63944420+AkshayAshokCode@users.noreply.github.com> Date: Thu, 28 May 2026 02:53:13 +0530 Subject: [PATCH 3/9] Refine ImagePickerException documentation and consistency --- .../imagepicker/model/ImagePickerException.kt | 78 ++++++++++++++----- 1 file changed, 58 insertions(+), 20 deletions(-) diff --git a/imagepicker/src/main/java/com/akshayashokcode/imagepicker/model/ImagePickerException.kt b/imagepicker/src/main/java/com/akshayashokcode/imagepicker/model/ImagePickerException.kt index 491609b..ba2a730 100644 --- a/imagepicker/src/main/java/com/akshayashokcode/imagepicker/model/ImagePickerException.kt +++ b/imagepicker/src/main/java/com/akshayashokcode/imagepicker/model/ImagePickerException.kt @@ -1,38 +1,76 @@ package com.akshayashokcode.imagepicker.model /** - * Represents various error states that can occur during image picking. + * Represents strongly-typed error states that can occur during the MediaKit + * image picker flow. */ sealed class ImagePickerException(message: String) : Exception(message) { - /** Required permission was denied by the user */ - object PermissionDenied : ImagePickerException("Required permission was denied.") + /** + * Required runtime permission was denied. + */ + data object PermissionDenied : ImagePickerException( + "Required permission was denied." + ) - /** No app available to handle the requested action (e.g., no gallery/camera app) */ - object AppNotFound : ImagePickerException("Required app (camera or gallery) is not available.") + /** + * No compatible application is available to handle the requested action. + */ + data object AppNotFound : ImagePickerException( + "Required app (camera or gallery) is not available." + ) - /** Could not create temporary file for captured image */ - object FileCreationFailed : ImagePickerException("Could not create temporary file.") + /** + * Temporary file creation failed before launching camera capture. + */ + data object FileCreationFailed : ImagePickerException( + "Could not create temporary file." + ) - /** The image URI returned was null or invalid */ - object InvalidUri : ImagePickerException("Invalid or null URI received.") + /** + * The returned image Uri was invalid or null. + */ + data object InvalidUri : ImagePickerException( + "Invalid or null URI received." + ) - /** Failed to decode or rotate the image properly */ - object RotationFailed : ImagePickerException("Failed to decode or rotate the image.") + /** + * Bitmap decoding or orientation correction failed. + */ + data object RotationFailed : ImagePickerException( + "Failed to decode or rotate the image." + ) - /** Error deleting temporary file after cancel or failure */ - object FileDeletionFailed : ImagePickerException("Failed to delete temporary image file.") + /** + * Cleanup of temporary files failed. + */ + data object FileDeletionFailed : ImagePickerException( + "Failed to delete temporary image file." + ) - /** Raised when decoding the image or applying orientation corrections fails. */ - object DecodingFailed : ImagePickerException("Failed to decode or rotate image.") + /** + * Image decoding pipeline failed. + */ + data object DecodingFailed : ImagePickerException( + "Failed to decode or rotate image." + ) - object IntentFailed : ImagePickerException("Failed to launch intent for image capture or selection.") + /** + * Intent launch failed unexpectedly. + */ + data object IntentFailed : ImagePickerException( + "Failed to launch intent for image capture or selection." + ) - - /** Generic catch-all error */ - class Unknown(message: String, cause: Throwable? = null) : ImagePickerException(message) { + /** + * Generic fallback error. + */ + class Unknown( + message: String, + cause: Throwable? = null + ) : ImagePickerException(message) { init { cause?.let { initCause(it) } } } -} \ No newline at end of file +} From f06d50b699dfb3d7c8b23677fd148d2a396d9407 Mon Sep 17 00:00:00 2001 From: Akshay Ashok <63944420+AkshayAshokCode@users.noreply.github.com> Date: Thu, 28 May 2026 02:53:25 +0530 Subject: [PATCH 4/9] Clean up ImagePickerCoordinator flow --- .../coordinator/ImagePickerCoordinator.kt | 32 ++++++++++++++++--- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/imagepicker/src/main/java/com/akshayashokcode/imagepicker/coordinator/ImagePickerCoordinator.kt b/imagepicker/src/main/java/com/akshayashokcode/imagepicker/coordinator/ImagePickerCoordinator.kt index 8a4e430..8be35d8 100644 --- a/imagepicker/src/main/java/com/akshayashokcode/imagepicker/coordinator/ImagePickerCoordinator.kt +++ b/imagepicker/src/main/java/com/akshayashokcode/imagepicker/coordinator/ImagePickerCoordinator.kt @@ -8,6 +8,10 @@ import com.akshayashokcode.imagepicker.model.MediaSource import com.akshayashokcode.imagepicker.picker.CameraImagePicker import com.akshayashokcode.imagepicker.picker.GalleryImagePicker +/** + * Coordinates the image picker flow and delegates execution to the appropriate + * picker implementation. + */ internal class ImagePickerCoordinator( private val context: Context, private val caller: ActivityResultCaller, @@ -15,17 +19,37 @@ internal class ImagePickerCoordinator( private val onResult: (ImagePickerResult) -> Unit, private val onError: ((ImagePickerException) -> Unit)? = null ) { - private val galleryPicker = GalleryImagePicker(context, caller, onResult, onError) - private val cameraPicker = CameraImagePicker(context, caller, onResult, onError) + private val galleryPicker by lazy { + GalleryImagePicker( + context = context, + caller = caller, + callback = onResult, + onError = onError + ) + } + + private val cameraPicker by lazy { + CameraImagePicker( + context = context, + caller = caller, + callback = onResult, + onError = onError + ) + } + + /** + * Starts the configured picker flow. + */ fun launch() { when (source) { is MediaSource.Gallery -> galleryPicker.launch() is MediaSource.Camera -> cameraPicker.launch() is MediaSource.Both -> { - // 🚧 Future enhancement: show source selection UI + // Future enhancement: + // Provide a source chooser bottom sheet/dialog. galleryPicker.launch() } } } -} \ No newline at end of file +} From e571948db0006617d0adf1855667e6837c2a23fb Mon Sep 17 00:00:00 2001 From: Akshay Ashok <63944420+AkshayAshokCode@users.noreply.github.com> Date: Thu, 28 May 2026 02:53:40 +0530 Subject: [PATCH 5/9] Improve CameraImagePicker documentation --- .../imagepicker/picker/CameraImagePicker.kt | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/imagepicker/src/main/java/com/akshayashokcode/imagepicker/picker/CameraImagePicker.kt b/imagepicker/src/main/java/com/akshayashokcode/imagepicker/picker/CameraImagePicker.kt index 94b0bf5..2bd4773 100644 --- a/imagepicker/src/main/java/com/akshayashokcode/imagepicker/picker/CameraImagePicker.kt +++ b/imagepicker/src/main/java/com/akshayashokcode/imagepicker/picker/CameraImagePicker.kt @@ -6,15 +6,26 @@ import com.akshayashokcode.imagepicker.launcher.CameraImageLauncher import com.akshayashokcode.imagepicker.model.ImagePickerException import com.akshayashokcode.imagepicker.model.ImagePickerResult +/** + * Camera-backed picker implementation. + */ internal class CameraImagePicker( private val context: Context, private val caller: ActivityResultCaller, private val callback: (ImagePickerResult) -> Unit, private val onError: ((ImagePickerException) -> Unit)? = null ) { - private val launcher = CameraImageLauncher(context, caller, callback, onError) + + private val launcher by lazy { + CameraImageLauncher( + context = context, + caller = caller, + callback = callback, + onError = onError + ) + } fun launch() { launcher.launch() } -} \ No newline at end of file +} From 883810063b8e22c82a89e72c346a974234900d13 Mon Sep 17 00:00:00 2001 From: Akshay Ashok <63944420+AkshayAshokCode@users.noreply.github.com> Date: Thu, 28 May 2026 02:53:51 +0530 Subject: [PATCH 6/9] Improve GalleryImagePicker documentation --- .../imagepicker/picker/GalleryImagePicker.kt | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/imagepicker/src/main/java/com/akshayashokcode/imagepicker/picker/GalleryImagePicker.kt b/imagepicker/src/main/java/com/akshayashokcode/imagepicker/picker/GalleryImagePicker.kt index 99c7115..ac8d1f1 100644 --- a/imagepicker/src/main/java/com/akshayashokcode/imagepicker/picker/GalleryImagePicker.kt +++ b/imagepicker/src/main/java/com/akshayashokcode/imagepicker/picker/GalleryImagePicker.kt @@ -6,15 +6,26 @@ import com.akshayashokcode.imagepicker.launcher.GalleryImageLauncher import com.akshayashokcode.imagepicker.model.ImagePickerException import com.akshayashokcode.imagepicker.model.ImagePickerResult +/** + * Gallery-backed picker implementation. + */ internal class GalleryImagePicker( private val context: Context, private val caller: ActivityResultCaller, private val callback: (ImagePickerResult) -> Unit, private val onError: ((ImagePickerException) -> Unit)? = null ) { - private val launcher = GalleryImageLauncher(context, caller, callback, onError) + + private val launcher by lazy { + GalleryImageLauncher( + context = context, + caller = caller, + callback = callback, + onError = onError + ) + } fun launch() { launcher.launch() } -} \ No newline at end of file +} From e12e8d7dc75c25454765139941e069ebceeda8d1 Mon Sep 17 00:00:00 2001 From: Akshay Ashok <63944420+AkshayAshokCode@users.noreply.github.com> Date: Thu, 28 May 2026 02:59:40 +0530 Subject: [PATCH 7/9] Fix imagecropper module reference casing --- sample-app/build.gradle.kts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sample-app/build.gradle.kts b/sample-app/build.gradle.kts index ff3ca76..5f085d4 100644 --- a/sample-app/build.gradle.kts +++ b/sample-app/build.gradle.kts @@ -56,6 +56,7 @@ dependencies { androidTestImplementation(libs.androidx.ui.test.junit4) debugImplementation(libs.androidx.ui.tooling) debugImplementation(libs.androidx.ui.test.manifest) - implementation(project(":ImageCropper")) + + implementation(project(":imagecropper")) implementation(project(":imagepicker")) -} \ No newline at end of file +} From 0241b067fd2bca0b36c94b065db85c6b654cb362 Mon Sep 17 00:00:00 2001 From: Akshay Ashok <63944420+AkshayAshokCode@users.noreply.github.com> Date: Thu, 28 May 2026 03:04:00 +0530 Subject: [PATCH 8/9] Fix ImagePickerBuilder private constructor usage --- .../imagepicker/entrypoint/ImagePicker.kt | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/imagepicker/src/main/java/com/akshayashokcode/imagepicker/entrypoint/ImagePicker.kt b/imagepicker/src/main/java/com/akshayashokcode/imagepicker/entrypoint/ImagePicker.kt index 157d3ce..20c4046 100644 --- a/imagepicker/src/main/java/com/akshayashokcode/imagepicker/entrypoint/ImagePicker.kt +++ b/imagepicker/src/main/java/com/akshayashokcode/imagepicker/entrypoint/ImagePicker.kt @@ -4,8 +4,15 @@ import android.content.Context import androidx.activity.result.ActivityResultCaller import com.akshayashokcode.imagepicker.builder.ImagePickerBuilder +/** + * Public entry point for launching MediaKit image picker flows. + */ object ImagePicker { - fun with(context: Context, caller: ActivityResultCaller): ImagePickerBuilder { - return ImagePickerBuilder(context, caller) + + fun with( + context: Context, + caller: ActivityResultCaller + ): ImagePickerBuilder { + return ImagePickerBuilder.with(context, caller) } -} \ No newline at end of file +} From 687e5b3097094b66587d7233ef58ca1718b3653e Mon Sep 17 00:00:00 2001 From: Akshay Ashok <63944420+AkshayAshokCode@users.noreply.github.com> Date: Thu, 28 May 2026 03:09:52 +0530 Subject: [PATCH 9/9] Fix lint suspicious indentation warning in CropperScreen --- .../sample_app/ui/CropperScreen.kt | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/sample-app/src/main/java/com/akshayashokcode/sample_app/ui/CropperScreen.kt b/sample-app/src/main/java/com/akshayashokcode/sample_app/ui/CropperScreen.kt index 9487c96..23be21f 100644 --- a/sample-app/src/main/java/com/akshayashokcode/sample_app/ui/CropperScreen.kt +++ b/sample-app/src/main/java/com/akshayashokcode/sample_app/ui/CropperScreen.kt @@ -42,13 +42,16 @@ fun CropperScreen() { val inflater = LayoutInflater.from(ctx) val view = inflater.inflate(R.layout.cropper_view_layout, null) val cropperView = view.findViewById(R.id.cropperView) - cropperViewState.value = cropperView // 🔐 Save for use in Button click - // Load a sample image - val bitmap = BitmapFactory.decodeResource(ctx.resources, R.drawable.image) - // cropperView.post { - cropperView.setImageBitmap(bitmap) - // } + cropperViewState.value = cropperView + + // Load sample image into cropper. + val bitmap = BitmapFactory.decodeResource( + ctx.resources, + R.drawable.image + ) + + cropperView.setImageBitmap(bitmap) view },