Implement single selection logic in custom image picker (#6341)
Some checks are pending
Android CI / Run tests and generate APK (push) Waiting to run

* build failure cause

* Fix image selector logic in custom picker
This commit is contained in:
Sonal Yadav 2025-06-07 19:39:47 +05:30 committed by GitHub
parent 06a613e855
commit f45f26e602
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 45 additions and 22 deletions

View file

@ -253,13 +253,14 @@ class ContributionController @Inject constructor(@param:Named("default_preferenc
*/ */
fun initiateCustomGalleryPickWithPermission( fun initiateCustomGalleryPickWithPermission(
activity: Activity, activity: Activity,
resultLauncher: ActivityResultLauncher<Intent> resultLauncher: ActivityResultLauncher<Intent>,
singleSelection: Boolean = false
) { ) {
setPickerConfiguration(activity, true) setPickerConfiguration(activity, true)
checkPermissionsAndPerformAction( checkPermissionsAndPerformAction(
activity, activity,
{ openCustomSelector(activity, resultLauncher, 0) }, { FilePicker.openCustomSelector(activity, resultLauncher, 0, singleSelection) },
R.string.storage_permission_title, R.string.storage_permission_title,
R.string.write_storage_permission_rationale, R.string.write_storage_permission_rationale,
*PERMISSIONS_STORAGE *PERMISSIONS_STORAGE

View file

@ -327,12 +327,17 @@ class ImageAdapter(
// Getting clicked index from all images index when show_already_actioned_images // Getting clicked index from all images index when show_already_actioned_images
// switch is on // switch is on
if (singleSelection) {
// If single selection mode, clear previous selection and select only the new one
if (selectedImages.isNotEmpty() && (selectedImages[0] != images[position])) {
val prevIndex = images.indexOf(selectedImages[0])
selectedImages.clear()
notifyItemChanged(prevIndex, ImageUnselected())
}
}
val clickedIndex: Int = val clickedIndex: Int =
if (showAlreadyActionedImages) { if (showAlreadyActionedImages) {
ImageHelper.getIndex(selectedImages, images[position]) ImageHelper.getIndex(selectedImages, images[position])
// Getting clicked index from actionable images when show_already_actioned_images
// switch is off
} else { } else {
ImageHelper.getIndex(selectedImages, ArrayList(actionableImagesMap.values)[position]) ImageHelper.getIndex(selectedImages, ArrayList(actionableImagesMap.values)[position])
} }
@ -618,4 +623,13 @@ class ImageAdapter(
* Returns the text for showing inside the bubble during bubble scroll. * Returns the text for showing inside the bubble during bubble scroll.
*/ */
override fun getSectionName(position: Int): String = images[position].date override fun getSectionName(position: Int): String = images[position].date
private var singleSelection: Boolean = false
/**
* Set single selection mode
*/
fun setSingleSelection(single: Boolean) {
singleSelection = single
}
} }

View file

@ -104,7 +104,7 @@ class CustomSelectorActivity :
/** /**
* Maximum number of images that can be selected. * Maximum number of images that can be selected.
*/ */
private val uploadLimit: Int = 20 private var uploadLimit: Int = 20
/** /**
* Flag that is marked true when the amount * Flag that is marked true when the amount
@ -207,6 +207,9 @@ class CustomSelectorActivity :
CustomSelectorViewModel::class.java, CustomSelectorViewModel::class.java,
) )
// Check for single selection extra
uploadLimit = if (intent.getBooleanExtra(EXTRA_SINGLE_SELECTION, false)) 1 else 20
setupViews() setupViews()
if (prefs.getBoolean("customSelectorFirstLaunch", true)) { if (prefs.getBoolean("customSelectorFirstLaunch", true)) {
@ -728,6 +731,7 @@ class CustomSelectorActivity :
const val FOLDER_ID: String = "FolderId" const val FOLDER_ID: String = "FolderId"
const val FOLDER_NAME: String = "FolderName" const val FOLDER_NAME: String = "FolderName"
const val ITEM_ID: String = "ItemId" const val ITEM_ID: String = "ItemId"
const val EXTRA_SINGLE_SELECTION: String = "EXTRA_SINGLE_SELECTION"
} }
} }

View file

@ -212,6 +212,9 @@ class ImageFragment :
_binding = FragmentCustomSelectorBinding.inflate(inflater, container, false) _binding = FragmentCustomSelectorBinding.inflate(inflater, container, false)
imageAdapter = imageAdapter =
ImageAdapter(requireActivity(), activity as ImageSelectListener, imageLoader!!) ImageAdapter(requireActivity(), activity as ImageSelectListener, imageLoader!!)
// Set single selection mode if needed
val singleSelection = (activity as? CustomSelectorActivity)?.intent?.getBooleanExtra(CustomSelectorActivity.EXTRA_SINGLE_SELECTION, false) == true
imageAdapter.setSingleSelection(singleSelection)
gridLayoutManager = GridLayoutManager(context, getSpanCount()) gridLayoutManager = GridLayoutManager(context, getSpanCount())
with(binding?.selectorRv) { with(binding?.selectorRv) {
this?.layoutManager = gridLayoutManager this?.layoutManager = gridLayoutManager

View file

@ -25,6 +25,9 @@ object FilePicker : Constants {
private const val KEY_LAST_CAMERA_VIDEO = "last_video" private const val KEY_LAST_CAMERA_VIDEO = "last_video"
private const val KEY_TYPE = "type" private const val KEY_TYPE = "type"
// Add extra for single selection
private const val EXTRA_SINGLE_SELECTION = "EXTRA_SINGLE_SELECTION"
/** /**
* Returns the uri of the clicked image so that it can be put in MediaStore * Returns the uri of the clicked image so that it can be put in MediaStore
*/ */
@ -73,12 +76,17 @@ object FilePicker : Constants {
* CreateCustomSectorIntent, creates intent for custom selector activity. * CreateCustomSectorIntent, creates intent for custom selector activity.
* @param context * @param context
* @param type * @param type
* @param singleSelection If true, restricts to single image selection
* @return Custom selector intent * @return Custom selector intent
*/ */
@JvmStatic @JvmStatic
private fun createCustomSelectorIntent(context: Context, type: Int): Intent { private fun createCustomSelectorIntent(context: Context, type: Int, singleSelection: Boolean = false): Intent {
storeType(context, type) storeType(context, type)
return Intent(context, CustomSelectorActivity::class.java) val intent = Intent(context, CustomSelectorActivity::class.java)
if (singleSelection) {
intent.putExtra(EXTRA_SINGLE_SELECTION, true)
}
return intent
} }
@JvmStatic @JvmStatic
@ -153,9 +161,10 @@ object FilePicker : Constants {
fun openCustomSelector( fun openCustomSelector(
activity: Activity, activity: Activity,
resultLauncher: ActivityResultLauncher<Intent>, resultLauncher: ActivityResultLauncher<Intent>,
type: Int type: Int,
singleSelection: Boolean = false
) { ) {
val intent = createCustomSelectorIntent(activity, type) val intent = createCustomSelectorIntent(activity, type, singleSelection)
resultLauncher.launch(intent) resultLauncher.launch(intent)
} }

View file

@ -974,7 +974,7 @@ class NearbyParentFragment : CommonsDaggerSupportFragment(),
} else if (bottomSheetDetailsBehavior!!.state } else if (bottomSheetDetailsBehavior!!.state
== BottomSheetBehavior.STATE_EXPANDED == BottomSheetBehavior.STATE_EXPANDED
) { ) {
bottomSheetDetailsBehavior!!.state = BottomSheetBehavior.STATE_COLLAPSED bottomSheetDetailsBehavior!!.setState(BottomSheetBehavior.STATE_COLLAPSED)
} }
} }
@ -2457,9 +2457,11 @@ class NearbyParentFragment : CommonsDaggerSupportFragment(),
Timber.d("Gallery button tapped. Place: %s", selectedPlace.toString()) Timber.d("Gallery button tapped. Place: %s", selectedPlace.toString())
storeSharedPrefs(selectedPlace!!) storeSharedPrefs(selectedPlace!!)
activity?.let { activity?.let {
// Pass singleSelection = true for Nearby flow
controller!!.initiateCustomGalleryPickWithPermission( controller!!.initiateCustomGalleryPickWithPermission(
it, it,
customSelectorLauncherForResult customSelectorLauncherForResult,
singleSelection = true
) )
} }
} }

View file

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Vlad5250
-->
<resources>
<string name="crash_dialog_title">کامَنٕز گوو رُکِتھ</string>
<string name="crash_dialog_text">Oops. کیہہ تام گوو غلط!</string>
<string name="crash_dialog_comment_prompt">ؤنِیوٚ اَسہِ توٚہہِ کیاہ ٲسِیوٚ کران، تہٕ کٕریٚو تہِ اَسہِ سٕتی شیر بذریعہِ برقی خط. یُس مَدَتھ کَرِ اَسہِ اَتھ شہَرنَس منٛز!</string>
<string name="crash_dialog_ok_toast">شُکریہ!</string>
</resources>