Skip to content

Implement single selection logic in custom image picker #6341

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -253,13 +253,14 @@ class ContributionController @Inject constructor(@param:Named("default_preferenc
*/
fun initiateCustomGalleryPickWithPermission(
activity: Activity,
resultLauncher: ActivityResultLauncher<Intent>
resultLauncher: ActivityResultLauncher<Intent>,
singleSelection: Boolean = false
) {
setPickerConfiguration(activity, true)

checkPermissionsAndPerformAction(
activity,
{ openCustomSelector(activity, resultLauncher, 0) },
{ FilePicker.openCustomSelector(activity, resultLauncher, 0, singleSelection) },
R.string.storage_permission_title,
R.string.write_storage_permission_rationale,
*PERMISSIONS_STORAGE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -327,12 +327,17 @@ class ImageAdapter(

// Getting clicked index from all images index when show_already_actioned_images
// 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 =
if (showAlreadyActionedImages) {
ImageHelper.getIndex(selectedImages, images[position])

// Getting clicked index from actionable images when show_already_actioned_images
// switch is off
} else {
ImageHelper.getIndex(selectedImages, ArrayList(actionableImagesMap.values)[position])
}
Expand Down Expand Up @@ -618,4 +623,13 @@ class ImageAdapter(
* Returns the text for showing inside the bubble during bubble scroll.
*/
override fun getSectionName(position: Int): String = images[position].date

private var singleSelection: Boolean = false

/**
* Set single selection mode
*/
fun setSingleSelection(single: Boolean) {
singleSelection = single
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ class CustomSelectorActivity :
/**
* 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
Expand Down Expand Up @@ -207,6 +207,9 @@ class CustomSelectorActivity :
CustomSelectorViewModel::class.java,
)

// Check for single selection extra
uploadLimit = if (intent.getBooleanExtra(EXTRA_SINGLE_SELECTION, false)) 1 else 20

setupViews()

if (prefs.getBoolean("customSelectorFirstLaunch", true)) {
Expand Down Expand Up @@ -728,6 +731,7 @@ class CustomSelectorActivity :
const val FOLDER_ID: String = "FolderId"
const val FOLDER_NAME: String = "FolderName"
const val ITEM_ID: String = "ItemId"
const val EXTRA_SINGLE_SELECTION: String = "EXTRA_SINGLE_SELECTION"
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,9 @@ class ImageFragment :
_binding = FragmentCustomSelectorBinding.inflate(inflater, container, false)
imageAdapter =
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())
with(binding?.selectorRv) {
this?.layoutManager = gridLayoutManager
Expand Down
17 changes: 13 additions & 4 deletions app/src/main/java/fr/free/nrw/commons/filepicker/FilePicker.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ object FilePicker : Constants {
private const val KEY_LAST_CAMERA_VIDEO = "last_video"
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
*/
Expand Down Expand Up @@ -73,12 +76,17 @@ object FilePicker : Constants {
* CreateCustomSectorIntent, creates intent for custom selector activity.
* @param context
* @param type
* @param singleSelection If true, restricts to single image selection
* @return Custom selector intent
*/
@JvmStatic
private fun createCustomSelectorIntent(context: Context, type: Int): Intent {
private fun createCustomSelectorIntent(context: Context, type: Int, singleSelection: Boolean = false): Intent {
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
Expand Down Expand Up @@ -153,9 +161,10 @@ object FilePicker : Constants {
fun openCustomSelector(
activity: Activity,
resultLauncher: ActivityResultLauncher<Intent>,
type: Int
type: Int,
singleSelection: Boolean = false
) {
val intent = createCustomSelectorIntent(activity, type)
val intent = createCustomSelectorIntent(activity, type, singleSelection)
resultLauncher.launch(intent)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -974,7 +974,7 @@ class NearbyParentFragment : CommonsDaggerSupportFragment(),
} else if (bottomSheetDetailsBehavior!!.state
== BottomSheetBehavior.STATE_EXPANDED
) {
bottomSheetDetailsBehavior!!.state = BottomSheetBehavior.STATE_COLLAPSED
bottomSheetDetailsBehavior!!.setState(BottomSheetBehavior.STATE_COLLAPSED)
}
}

Expand Down Expand Up @@ -2457,9 +2457,11 @@ class NearbyParentFragment : CommonsDaggerSupportFragment(),
Timber.d("Gallery button tapped. Place: %s", selectedPlace.toString())
storeSharedPrefs(selectedPlace!!)
activity?.let {
// Pass singleSelection = true for Nearby flow
controller!!.initiateCustomGalleryPickWithPermission(
it,
customSelectorLauncherForResult
customSelectorLauncherForResult,
singleSelection = true
)
}
}
Expand Down
10 changes: 0 additions & 10 deletions app/src/main/res/values-x-invalidLanguageCode/error.xml

This file was deleted.