Skip to content
Open
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 @@ -10,4 +10,5 @@ object CustomSelectorConstants {
const val NEW_SELECTED_IMAGES = "new_selected_images"
const val SHOULD_REFRESH = "should_refresh"
const val FULL_SCREEN_MODE_FIRST_LUNCH = "full_screen_mode_first_launch"
const val MAX_IMAGE_COUNT = 20
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import fr.free.nrw.commons.contributions.Contribution
import fr.free.nrw.commons.customselector.helper.ImageHelper
import fr.free.nrw.commons.customselector.helper.ImageHelper.CUSTOM_SELECTOR_PREFERENCE_KEY
import fr.free.nrw.commons.customselector.helper.ImageHelper.SHOW_ALREADY_ACTIONED_IMAGES_PREFERENCE_KEY
import fr.free.nrw.commons.customselector.helper.CustomSelectorConstants.MAX_IMAGE_COUNT
import fr.free.nrw.commons.customselector.listeners.ImageSelectListener
import fr.free.nrw.commons.customselector.model.Image
import fr.free.nrw.commons.customselector.ui.selector.ImageLoader
Expand Down Expand Up @@ -188,55 +189,38 @@ class ImageAdapter(
defaultDispatcher,
uploadingContributionList,
)
scope.launch {
val sharedPreferences: SharedPreferences =
context.getSharedPreferences(CUSTOM_SELECTOR_PREFERENCE_KEY, 0)
val showAlreadyActionedImages =
sharedPreferences.getBoolean(SHOW_ALREADY_ACTIONED_IMAGES_PREFERENCE_KEY, true)
if (!showAlreadyActionedImages) {
// If the position is not already visited, that means the position is new then
// finds the next actionable image position from all images
if (!alreadyAddedPositions.contains(position)) {
processThumbnailForActionedImage(
holder,
position,
uploadingContributionList
)
_isLoadingImages.value = false
// If the position is already visited, that means the image is already present
// inside map, so it will fetch the image from the map and load in the holder
holder.itemView.setOnClickListener {
if (!holder.isItemUploaded() && !holder.isItemNotForUpload()) {
if (selectedImages.size >= MAX_IMAGE_COUNT && !isSelected) { //enforce the 20-image limit
Toast.makeText(context, "Cannot select more than 20 images", Toast.LENGTH_SHORT).show()
return@setOnClickListener
}
if (isSelected) {
selectedImages.removeAt(selectedIndex)
holder.itemUnselected()
notifyItemChanged(position, ImageUnselected())
imageSelectListener.onSelectedImagesChanged(selectedImages, selectedImages.size)
} else {
val actionableImages: List<Image> = ArrayList(actionableImagesMap.values)
if (actionableImages.size > position) {
image = actionableImages[position]
Glide
.with(holder.image)
.load(image.uri)
.thumbnail(0.3f)
.into(holder.image)
}
selectedImages.add(image)
holder.itemSelected()
notifyItemChanged(position, ImageSelectedOrUpdated())
imageSelectListener.onSelectedImagesChanged(selectedImages, selectedImages.size)
}

// If switch is turned off, it just fetches the image from all images without any
// further operations
} else {
Glide
.with(holder.image)
.load(image.uri)
.thumbnail(0.3f)
.into(holder.image)
}
}

holder.itemView.setOnClickListener {
onThumbnailClicked(position, holder)
}

// launch media preview on long click.
holder.itemView.setOnLongClickListener {
imageSelectListener.onLongPress(images.indexOf(image), images, selectedImages)
imageSelectListener.onLongPress(position, images, ArrayList(selectedImages))
true
}
//handle close button click for deselection
holder.closeButton.setOnClickListener {
if (isSelected) {
selectedImages.removeAt(selectedIndex)
holder.itemUnselected()
notifyItemChanged(position, ImageUnselected())
imageSelectListener.onSelectedImagesChanged(selectedImages, selectedImages.size)
}
}
}
}

Expand Down Expand Up @@ -417,7 +401,7 @@ class ImageAdapter(
* Set new selected images
*/
fun setSelectedImages(newSelectedImages: ArrayList<Image>) {
selectedImages = ArrayList(newSelectedImages)
selectedImages = ArrayList(newSelectedImages.take(MAX_IMAGE_COUNT)) // enforce 20-image limit
imageSelectListener.onSelectedImagesChanged(selectedImages, 0)
}

Expand All @@ -431,7 +415,7 @@ class ImageAdapter(
) {
numberOfSelectedImagesMarkedAsNotForUpload = 0
images.clear()
selectedImages = arrayListOf()
selectedImages = ArrayList(selectedImages.take(5)) // enforce the 5-image limit
init(newImages, fixedImages, TreeMap(), uploadingImages)
notifyDataSetChanged()
}
Expand Down Expand Up @@ -523,19 +507,22 @@ class ImageAdapter(
private val uploadingGroup: Group = itemView.findViewById(R.id.uploading_group)
private val notForUploadGroup: Group = itemView.findViewById(R.id.not_for_upload_group)
private val selectedGroup: Group = itemView.findViewById(R.id.selected_group)
val closeButton: ImageView = itemView.findViewById(R.id.close_button) // Added for close button

/**
* Item selected view.
*/
fun itemSelected() {
selectedGroup.visibility = View.VISIBLE
closeButton.visibility = View.VISIBLE // Show close button when selected
}

/**
* Item Unselected view.
*/
fun itemUnselected() {
selectedGroup.visibility = View.GONE
closeButton.visibility = View.GONE // Hide close button when unselected
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import fr.free.nrw.commons.customselector.database.NotForUploadStatus
import fr.free.nrw.commons.customselector.database.NotForUploadStatusDao
import fr.free.nrw.commons.customselector.helper.CustomSelectorConstants
import fr.free.nrw.commons.customselector.helper.FolderDeletionHelper
import fr.free.nrw.commons.customselector.helper.CustomSelectorConstants.MAX_IMAGE_COUNT
import fr.free.nrw.commons.customselector.listeners.FolderClickListener
import fr.free.nrw.commons.customselector.listeners.ImageSelectListener
import fr.free.nrw.commons.customselector.model.Image
Expand Down Expand Up @@ -107,7 +108,7 @@ class CustomSelectorActivity :
/**
* Maximum number of images that can be selected.
*/
private var uploadLimit: Int = 20
private var uploadLimit: Int = MAX_IMAGE_COUNT // changed to 20 asper the issue #3101

/**
* Flag that is marked true when the amount
Expand Down Expand Up @@ -214,7 +215,7 @@ class CustomSelectorActivity :
)

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

setupViews()

Expand Down Expand Up @@ -650,8 +651,12 @@ class CustomSelectorActivity :
finishPickImages(arrayListOf())
return
}
if (selectedImages.size > uploadLimit) {
displayUploadLimitWarning() // shows the warning dialog if >20 images
return
}
scope.launch(ioDispatcher) {
val uniqueImages = selectedImages.distinctBy { image ->
val uniqueImages = selectedImages.take(uploadLimit).distinctBy { image -> //enforce limit
CustomSelectorUtils.getImageSHA1(
image.uri,
ioDispatcher,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import com.facebook.drawee.view.SimpleDraweeView
import fr.free.nrw.commons.R
import fr.free.nrw.commons.customselector.helper.CustomSelectorConstants.MAX_IMAGE_COUNT
import fr.free.nrw.commons.databinding.ItemUploadThumbnailBinding
import fr.free.nrw.commons.filepicker.UploadableFile
import java.io.File
Expand All @@ -23,7 +24,7 @@ internal class ThumbnailsAdapter(private val callback: Callback) :
var onThumbnailDeletedListener: OnThumbnailDeletedListener? = null
var uploadableFiles: List<UploadableFile> = emptyList()
set(value) {
field = value
field = value.take(MAX_IMAGE_COUNT) //enforce 20-image limit
notifyDataSetChanged()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import fr.free.nrw.commons.R
import fr.free.nrw.commons.auth.LoginActivity
import fr.free.nrw.commons.auth.SessionManager
import fr.free.nrw.commons.contributions.ContributionController
import fr.free.nrw.commons.customselector.helper.CustomSelectorConstants.MAX_IMAGE_COUNT
import fr.free.nrw.commons.databinding.ActivityUploadBinding
import fr.free.nrw.commons.filepicker.Constants.RequestCodes
import fr.free.nrw.commons.filepicker.UploadableFile
Expand Down Expand Up @@ -743,8 +744,8 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
intent.getParcelableArrayListExtra<UploadableFile>(EXTRA_FILES)
}

// Convert to mutable list or return empty list if null
files?.toMutableList() ?: run {
// Convert to mutable list,takes up to 20 files, or return empty list if null
files?.toMutableList()?.take(MAX_IMAGE_COUNT)?.toMutableList() ?: run { //enforce 20-image limit
Timber.w("Files array was null")
mutableListOf()
}
Expand All @@ -761,6 +762,9 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
Timber.d("File $index path: ${file.getFilePath()}")
}

//update thumbnails adapter with limited files
thumbnailsAdapter?.uploadableFiles = uploadableFiles

// Handle other extras with null safety
place = try {
if (VERSION.SDK_INT >= VERSION_CODES.TIRAMISU) {
Expand Down
15 changes: 12 additions & 3 deletions app/src/main/res/layout/item_custom_selector_image.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
Expand Down Expand Up @@ -45,14 +44,24 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>

<ImageView
android:id="@+id/close_button"
android:layout_width="@dimen/dimen_20"
android:layout_height="@dimen/dimen_20"
app:layout_constraintDimensionRatio="H,1:1"
android:src="@drawable/ic_cancel_white"
android:layout_margin="@dimen/dimen_6"
android:background="@drawable/circle_shape"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:visibility="gone"/>

<androidx.constraintlayout.widget.Group
android:id="@+id/selected_group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
app:constraint_referenced_ids="selected_overlay,selected_image"/>

app:constraint_referenced_ids="selected_overlay,selected_image,close_button"/>

<View
android:id="@+id/uploaded_overlay"
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -887,4 +887,6 @@ Upload your first media by tapping on the add button.</string>
<string name="image_tag_line_created_and_uploaded_by">Created and uploaded by: %1$s</string>
<string name="image_tag_line_created_by_and_uploaded_by">Created by %1$s and uploaded by %2$s</string>
<string name="nominated_for_deletion_btn">Nominated for Deletion</string>

<string name="custom_selector_limit_warning_message">You can only select up to 20 images.</string>
</resources>