mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-27 04:43:54 +01:00
[GSoC] Image Selection (#4457)
* Localisation updates from https://translatewiki.net.
* Fixes #4357 After switching to different account, contributions screen shows pictures of previous account (#4421)
* Update UploadMediaDetailFragment.java
* Update LoginActivity.java
Clear CompositeDisposable after logging in successfully. It may help solve the problem of saving the contribution to the previous account
* Revert "Update UploadMediaDetailFragment.java"
This reverts commit b1b4257f20.
Co-authored-by: Obsidian_zero <1198474846@qq.com>
* Remove unnecessary whitespace from a message (#4439)
* Merge v3.0.1 into master (#4446)
* Versioning and changelog for v3.0.0 (#4152)
* Versioning for v3.0.0
* Update changelog.md
* Handled migration 8-9-10 in BookmarksLocationDao (#4154)
* #Fixes #4141
- Handled migrations for BookmarkLocationsDao from 8-9-10
* #Fixes #4141
- Handled migrations for BookmarkLocationsDao from 8-9-10
* Fixes #4179 (#4180)
* Handled null pointer exception in MainActivity->ContributionsFragment#backButtonClicked()
* Updated >ContributionsFragment#backButtonClicked() to handle back press properly
* Fixes #4179 (#4181)
* Handled possible null check on MediaDetails in BookmarkListRootFragment#backPressed()
* Cherrypick for hotfix3.1 (#4205)
* Fixes #4159 On Explore Tab, All Available Options on toolbar in media detail view are only targeting the first media in the list.
Fixes #4159 On Explore Tab, All Available Options on toolbar in media detail view are only targeting the first media in the list.
* fixed bug: App crashes on viewing review in Review Fragment #4132 (#4146)
* fixed bug:app crashes on viewing review in Review Fragment #4135
* Fixed the issue with back button in contribution tab. (#4177)
Co-authored-by: Pratham2305 <Pratham2305@users.noreply.github.com>
* Fixed the issue with back navigation button on toolbar in explore tab. (#4175)
* Fix (#4148) Issues on theme change
* fixed themeChange crashes
* fixed comments
* Overlooked the title bar
Co-authored-by: Pratham Pahariya <54663429+Pratham2305@users.noreply.github.com>
Co-authored-by: Shabir Ahmad <56585337+shabar-shab@users.noreply.github.com>
Co-authored-by: Pratham2305 <Pratham2305@users.noreply.github.com>
Co-authored-by: Aditya-Srivastav <54016427+4D17Y4@users.noreply.github.com>
* Fixes #4173 (#4396)
* Fix #4147 Pre-fill desc in Nearby uploads with Wikidata item's label + description (#4390)
* Update query to fetch descriptions
* Make description added to NearbyResultItem
* Make string operations to display description and label in a combined way
* Fix reviews, remove long description from list and swap label and description texts
* Fix repeated information issue
* Fix double information issue
* fix style issues
* Remove douplicated information
* Changes made (#4354)
* Remove nonexistent method
* Fix #4283 IllegalStateException (#4440)
* Fix #4283 IllegalStateException
* Fix flickering issue
* Versioning for v3.0.1
* Update changelog.md
Co-authored-by: Ashish <ashishkumar468@gmail.com>
Co-authored-by: neslihanturan <tur.neslihan@gmail.com>
Co-authored-by: Pratham Pahariya <54663429+Pratham2305@users.noreply.github.com>
Co-authored-by: Shabir Ahmad <56585337+shabar-shab@users.noreply.github.com>
Co-authored-by: Pratham2305 <Pratham2305@users.noreply.github.com>
Co-authored-by: Aditya-Srivastav <54016427+4D17Y4@users.noreply.github.com>
Co-authored-by: Madhur Gupta <30932899+madhurgupta10@users.noreply.github.com>
Co-authored-by: Vinayak Aggarwal <56196007+vinayak0505@users.noreply.github.com>
* Localisation updates from https://translatewiki.net.
* Added basic Fetch
* added permission request
* Folder count rectified
* Loaded thumbnail
* disabled overlay
* Added sha1 function
* Documented the code
* Added a feature for editing coordinates (#4418)
* not
* Place Picker added
* Pick location and API call linked
* minor warnings resolved
* Code conventions followed
* issue fixed
* Wikitext edited properly
* minor modification
* Location Picker added
* Bottom sheet removed
* Location picker fully implemented
* credit added
* credit added
* issues fixed
* issues fixed
* minor issue fixed
* Some build issues occured merging release v3.0 are fixed. One paranthesis issue is solved, a method about UploadService is removed, since we don't use it anymore. (#4451)
* Localisation updates from https://translatewiki.net.
* Fixes 4344 - Duplicate Uploads (#4442)
* Fixes 4344
- Update the retention policy of the Work Manager to ExistingWorkPolicy.APPEND_OR_REPLACE- which would append the new work to the end of existing one. This helps remove the while loop in UploadWorker which was meant to handle the cases where a new worker would be created for retries. The while loop seemed to have race conditions uploading duplicate entries.
* Update states to IN_PROGRESS before uploads are processed
* Image selection added
* Forwarded activity result to upload wizard
* Initialised xmls, made folder and image item.
* xmls done
* xmls completed
* removed unwanted attribute
* Created models, adapters and view models (#4441)
* created models, adapters and view models
* Added Image Fragment
* back button linked
* Documentation and refractor
* spaces
* Butterknife annotation
* DiffUtil
* Added Examples
* Extended Custom selector From Base Activity
* made view model injectable
* Added basic Fetch
* added permission request
* Folder count rectified
* Loaded thumbnail
* disabled overlay
* Added sha1 function
* Documented the code
* Image selection added
* Forwarded activity result to upload wizard
* [GSOC] Added Image Fetch (#4449)
* Added basic Fetch
* added permission request
* Folder count rectified
* Loaded thumbnail
* disabled overlay
* Added sha1 function
* Documented the code
* fixed merge errors
* Documented the remaining function
Co-authored-by: translatewiki.net <l10n-bot@translatewiki.net>
Co-authored-by: obsidian-zero <63155026+obsidian-zero@users.noreply.github.com>
Co-authored-by: Obsidian_zero <1198474846@qq.com>
Co-authored-by: Amir E. Aharoni <amir.aharoni@mail.huji.ac.il>
Co-authored-by: Josephine Lim <josephinelim86@gmail.com>
Co-authored-by: Ashish <ashishkumar468@gmail.com>
Co-authored-by: neslihanturan <tur.neslihan@gmail.com>
Co-authored-by: Pratham Pahariya <54663429+Pratham2305@users.noreply.github.com>
Co-authored-by: Shabir Ahmad <56585337+shabar-shab@users.noreply.github.com>
Co-authored-by: Pratham2305 <Pratham2305@users.noreply.github.com>
Co-authored-by: Madhur Gupta <30932899+madhurgupta10@users.noreply.github.com>
Co-authored-by: Vinayak Aggarwal <56196007+vinayak0505@users.noreply.github.com>
Co-authored-by: Ayan Sarkar <71203077+Ayan-10@users.noreply.github.com>
This commit is contained in:
parent
a120030a44
commit
c7dae69ddf
8 changed files with 225 additions and 60 deletions
|
|
@ -8,7 +8,6 @@ import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import fr.free.nrw.commons.R;
|
import fr.free.nrw.commons.R;
|
||||||
import fr.free.nrw.commons.customselector.ui.selector.CustomSelectorActivity;
|
|
||||||
import fr.free.nrw.commons.filepicker.DefaultCallback;
|
import fr.free.nrw.commons.filepicker.DefaultCallback;
|
||||||
import fr.free.nrw.commons.filepicker.FilePicker;
|
import fr.free.nrw.commons.filepicker.FilePicker;
|
||||||
import fr.free.nrw.commons.filepicker.FilePicker.ImageSource;
|
import fr.free.nrw.commons.filepicker.FilePicker.ImageSource;
|
||||||
|
|
@ -63,16 +62,11 @@ public class ContributionController {
|
||||||
* Initiate gallery picker with permission
|
* Initiate gallery picker with permission
|
||||||
*/
|
*/
|
||||||
public void initiateCustomGalleryPickWithPermission(final Activity activity) {
|
public void initiateCustomGalleryPickWithPermission(final Activity activity) {
|
||||||
boolean useExtStorage = defaultKvStore.getBoolean("useExternalStorage", true);
|
setPickerConfiguration(activity,true);
|
||||||
Intent intent = new Intent(activity,CustomSelectorActivity.class);
|
|
||||||
if (!useExtStorage) {
|
|
||||||
activity.startActivity(intent);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PermissionUtils.checkPermissionsAndPerformAction(activity,
|
PermissionUtils.checkPermissionsAndPerformAction(activity,
|
||||||
Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
||||||
() -> activity.startActivity(intent),
|
() -> FilePicker.openCustomSelector(activity, 0),
|
||||||
R.string.storage_permission_title,
|
R.string.storage_permission_title,
|
||||||
R.string.write_storage_permission_rationale);
|
R.string.write_storage_permission_rationale);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import kotlin.collections.ArrayList
|
||||||
import kotlin.collections.LinkedHashMap
|
import kotlin.collections.LinkedHashMap
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Image Helper object, includes all the static functions required by custom selector
|
* Image Helper object, includes all the static functions required by custom selector.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
object ImageHelper {
|
object ImageHelper {
|
||||||
|
|
@ -49,6 +49,34 @@ object ImageHelper {
|
||||||
return filteredImages
|
return filteredImages
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getIndex: Returns the index of image in given list.
|
||||||
|
*/
|
||||||
|
fun getIndex(list: ArrayList<Image>, image: Image): Int {
|
||||||
|
return list.indexOf(image)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the list of indices from the master list.
|
||||||
|
*/
|
||||||
|
fun getIndexList(list: ArrayList<Image>, masterList: ArrayList<Image>): ArrayList<Int> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
* Can be optimised as masterList is sorted by time.
|
||||||
|
*/
|
||||||
|
|
||||||
|
val indexes = arrayListOf<Int>()
|
||||||
|
for(image in list) {
|
||||||
|
val index = getIndex(masterList,image)
|
||||||
|
if (index == -1) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
indexes.add(index)
|
||||||
|
}
|
||||||
|
return indexes
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates the file sha1 from file input stream.
|
* Generates the file sha1 from file input stream.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import androidx.constraintlayout.widget.Group
|
||||||
import androidx.recyclerview.widget.DiffUtil
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
|
import fr.free.nrw.commons.customselector.helper.ImageHelper
|
||||||
import fr.free.nrw.commons.customselector.listeners.ImageSelectListener
|
import fr.free.nrw.commons.customselector.listeners.ImageSelectListener
|
||||||
import fr.free.nrw.commons.customselector.model.Image
|
import fr.free.nrw.commons.customselector.model.Image
|
||||||
|
|
||||||
|
|
@ -26,6 +27,16 @@ class ImageAdapter(
|
||||||
|
|
||||||
RecyclerViewAdapter<ImageAdapter.ImageViewHolder>(context) {
|
RecyclerViewAdapter<ImageAdapter.ImageViewHolder>(context) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ImageSelectedOrUpdated payload class.
|
||||||
|
*/
|
||||||
|
class ImageSelectedOrUpdated
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ImageUnselected payload class.
|
||||||
|
*/
|
||||||
|
class ImageUnselected
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Currently selected images.
|
* Currently selected images.
|
||||||
*/
|
*/
|
||||||
|
|
@ -49,18 +60,41 @@ class ImageAdapter(
|
||||||
*/
|
*/
|
||||||
override fun onBindViewHolder(holder: ImageViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: ImageViewHolder, position: Int) {
|
||||||
val image=images[position]
|
val image=images[position]
|
||||||
// todo load image thumbnail, set selected view.
|
val selectedIndex = ImageHelper.getIndex(selectedImages,image)
|
||||||
|
val isSelected = selectedIndex != -1
|
||||||
|
if(isSelected){
|
||||||
|
holder.itemSelected(selectedIndex+1)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
holder.itemUnselected();
|
||||||
|
}
|
||||||
Glide.with(context).load(image.uri).into(holder.image)
|
Glide.with(context).load(image.uri).into(holder.image)
|
||||||
holder.itemView.setOnClickListener {
|
holder.itemView.setOnClickListener {
|
||||||
selectOrRemoveImage(image, position)
|
selectOrRemoveImage(holder, position)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle click event on an image, update counter on images.
|
* Handle click event on an image, update counter on images.
|
||||||
*/
|
*/
|
||||||
private fun selectOrRemoveImage(image:Image, position:Int){
|
private fun selectOrRemoveImage(holder:ImageViewHolder, position:Int){
|
||||||
// todo select the image if not selected and remove it if already selected
|
val clickedIndex = ImageHelper.getIndex(selectedImages,images[position])
|
||||||
|
if (clickedIndex != -1) {
|
||||||
|
selectedImages.removeAt(clickedIndex)
|
||||||
|
notifyItemChanged(position,ImageUnselected())
|
||||||
|
val indexes = ImageHelper.getIndexList(selectedImages, images)
|
||||||
|
for (index in indexes) {
|
||||||
|
notifyItemChanged(index, ImageSelectedOrUpdated())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
* Show toast on tapping an uploaded item.
|
||||||
|
*/
|
||||||
|
selectedImages.add(images[position])
|
||||||
|
notifyItemChanged(position, ImageSelectedOrUpdated())
|
||||||
|
}
|
||||||
|
imageSelectListener.onSelectedImagesChanged(selectedImages)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -90,9 +124,39 @@ class ImageAdapter(
|
||||||
*/
|
*/
|
||||||
class ImageViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) {
|
class ImageViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) {
|
||||||
val image: ImageView = itemView.findViewById(R.id.image_thumbnail)
|
val image: ImageView = itemView.findViewById(R.id.image_thumbnail)
|
||||||
val selectedNumber: TextView = itemView.findViewById(R.id.selected_count)
|
private val selectedNumber: TextView = itemView.findViewById(R.id.selected_count)
|
||||||
val uploadedGroup: Group = itemView.findViewById(R.id.uploaded_group)
|
private val uploadedGroup: Group = itemView.findViewById(R.id.uploaded_group)
|
||||||
val selectedGroup: Group = itemView.findViewById(R.id.selected_group)
|
private val selectedGroup: Group = itemView.findViewById(R.id.selected_group)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Item selected view.
|
||||||
|
*/
|
||||||
|
fun itemSelected(index: Int) {
|
||||||
|
selectedGroup.visibility = View.VISIBLE
|
||||||
|
selectedNumber.text = index.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Item Unselected view.
|
||||||
|
*/
|
||||||
|
fun itemUnselected() {
|
||||||
|
selectedGroup.visibility = View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Item Uploaded view.
|
||||||
|
*/
|
||||||
|
fun itemUploaded() {
|
||||||
|
uploadedGroup.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Item Not Uploaded view.
|
||||||
|
*/
|
||||||
|
fun itemNotUploaded() {
|
||||||
|
uploadedGroup.visibility = View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
package fr.free.nrw.commons.customselector.ui.selector
|
package fr.free.nrw.commons.customselector.ui.selector
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.widget.ImageButton
|
import android.widget.ImageButton
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
|
|
@ -10,6 +12,7 @@ import fr.free.nrw.commons.customselector.listeners.ImageSelectListener
|
||||||
import fr.free.nrw.commons.customselector.model.Folder
|
import fr.free.nrw.commons.customselector.model.Folder
|
||||||
import fr.free.nrw.commons.customselector.model.Image
|
import fr.free.nrw.commons.customselector.model.Image
|
||||||
import fr.free.nrw.commons.theme.BaseActivity
|
import fr.free.nrw.commons.theme.BaseActivity
|
||||||
|
import java.io.File
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class CustomSelectorActivity : BaseActivity(), FolderClickListener, ImageSelectListener {
|
class CustomSelectorActivity : BaseActivity(), FolderClickListener, ImageSelectListener {
|
||||||
|
|
@ -73,7 +76,8 @@ class CustomSelectorActivity : BaseActivity(), FolderClickListener, ImageSelectL
|
||||||
val back : ImageButton = findViewById(R.id.back)
|
val back : ImageButton = findViewById(R.id.back)
|
||||||
back.setOnClickListener { onBackPressed() }
|
back.setOnClickListener { onBackPressed() }
|
||||||
|
|
||||||
// todo done listener.
|
val done : ImageButton = findViewById(R.id.done)
|
||||||
|
done.setOnClickListener { onDone() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -91,9 +95,44 @@ class CustomSelectorActivity : BaseActivity(), FolderClickListener, ImageSelectL
|
||||||
* override Selected Images Change, update view model selected images.
|
* override Selected Images Change, update view model selected images.
|
||||||
*/
|
*/
|
||||||
override fun onSelectedImagesChanged(selectedImages: ArrayList<Image>) {
|
override fun onSelectedImagesChanged(selectedImages: ArrayList<Image>) {
|
||||||
|
viewModel.selectedImages.value = selectedImages
|
||||||
// todo update selected images in view model.
|
// todo update selected images in view model.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OnDone clicked.
|
||||||
|
* Get the selected images. Remove any non existent file, forward the data to finish selector.
|
||||||
|
*/
|
||||||
|
fun onDone() {
|
||||||
|
val selectedImages = viewModel.selectedImages.value
|
||||||
|
if(selectedImages.isNullOrEmpty()) {
|
||||||
|
finishPickImages(arrayListOf())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var i = 0
|
||||||
|
while (i < selectedImages.size) {
|
||||||
|
val path = selectedImages[i].path
|
||||||
|
val file = File(path)
|
||||||
|
if (!file.exists()) {
|
||||||
|
selectedImages.removeAt(i)
|
||||||
|
i--
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
finishPickImages(selectedImages)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* finishPickImages, Load the data to the intent and set result.
|
||||||
|
* Finish the activity.
|
||||||
|
*/
|
||||||
|
private fun finishPickImages(images: ArrayList<Image>) {
|
||||||
|
val data = Intent()
|
||||||
|
data.putParcelableArrayListExtra("Images", images)
|
||||||
|
setResult(Activity.RESULT_OK, data)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Back pressed.
|
* Back pressed.
|
||||||
* Change toolbar title.
|
* Change toolbar title.
|
||||||
|
|
@ -106,16 +145,4 @@ class CustomSelectorActivity : BaseActivity(), FolderClickListener, ImageSelectL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* TODO
|
|
||||||
* Permission check.
|
|
||||||
* OnDone
|
|
||||||
* Activity Result.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
package fr.free.nrw.commons.customselector.ui.selector
|
package fr.free.nrw.commons.customselector.ui.selector
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.util.Log
|
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import fr.free.nrw.commons.customselector.listeners.ImageLoaderListener
|
import fr.free.nrw.commons.customselector.listeners.ImageLoaderListener
|
||||||
|
|
@ -14,10 +13,18 @@ import kotlinx.coroutines.cancel
|
||||||
|
|
||||||
class CustomSelectorViewModel(var context: Context,var imageFileLoader: ImageFileLoader) : ViewModel() {
|
class CustomSelectorViewModel(var context: Context,var imageFileLoader: ImageFileLoader) : ViewModel() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scope for coroutine task (image fetch).
|
||||||
|
*/
|
||||||
private val scope = CoroutineScope(Dispatchers.Main)
|
private val scope = CoroutineScope(Dispatchers.Main)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Result Live Data
|
* Stores selected images.
|
||||||
|
*/
|
||||||
|
var selectedImages: MutableLiveData<ArrayList<Image>> = MutableLiveData()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Result Live Data.
|
||||||
*/
|
*/
|
||||||
val result = MutableLiveData(Result(CallbackStatus.IDLE, arrayListOf()))
|
val result = MutableLiveData(Result(CallbackStatus.IDLE, arrayListOf()))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ public interface Constants {
|
||||||
int FILE_PICKER_IMAGE_IDENTIFICATOR = 0b1101101100; //876
|
int FILE_PICKER_IMAGE_IDENTIFICATOR = 0b1101101100; //876
|
||||||
int SOURCE_CHOOSER = 1 << 15;
|
int SOURCE_CHOOSER = 1 << 15;
|
||||||
|
|
||||||
|
int PICK_PICTURE_FROM_CUSTOM_SELECTOR = FILE_PICKER_IMAGE_IDENTIFICATOR + (1 << 10);
|
||||||
int PICK_PICTURE_FROM_DOCUMENTS = FILE_PICKER_IMAGE_IDENTIFICATOR + (1 << 11);
|
int PICK_PICTURE_FROM_DOCUMENTS = FILE_PICKER_IMAGE_IDENTIFICATOR + (1 << 11);
|
||||||
int PICK_PICTURE_FROM_GALLERY = FILE_PICKER_IMAGE_IDENTIFICATOR + (1 << 12);
|
int PICK_PICTURE_FROM_GALLERY = FILE_PICKER_IMAGE_IDENTIFICATOR + (1 << 12);
|
||||||
int TAKE_PICTURE = FILE_PICKER_IMAGE_IDENTIFICATOR + (1 << 13);
|
int TAKE_PICTURE = FILE_PICKER_IMAGE_IDENTIFICATOR + (1 << 13);
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,8 @@ import android.text.TextUtils;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import fr.free.nrw.commons.customselector.model.Image;
|
||||||
|
import fr.free.nrw.commons.customselector.ui.selector.CustomSelectorActivity;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
|
|
@ -51,6 +53,11 @@ public class FilePicker implements Constants {
|
||||||
.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, configuration(context).allowsMultiplePickingInGallery());
|
.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, configuration(context).allowsMultiplePickingInGallery());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Intent createCustomSelectorIntent(@NonNull Context context, int type) {
|
||||||
|
storeType(context, type);
|
||||||
|
return new Intent(context, CustomSelectorActivity.class);
|
||||||
|
}
|
||||||
|
|
||||||
private static Intent createCameraForImageIntent(@NonNull Context context, int type) {
|
private static Intent createCameraForImageIntent(@NonNull Context context, int type) {
|
||||||
storeType(context, type);
|
storeType(context, type);
|
||||||
|
|
||||||
|
|
@ -97,6 +104,14 @@ public class FilePicker implements Constants {
|
||||||
activity.startActivityForResult(intent, RequestCodes.PICK_PICTURE_FROM_GALLERY);
|
activity.startActivityForResult(intent, RequestCodes.PICK_PICTURE_FROM_GALLERY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens Custom Selector
|
||||||
|
*/
|
||||||
|
public static void openCustomSelector(Activity activity, int type) {
|
||||||
|
Intent intent = createCustomSelectorIntent(activity, type);
|
||||||
|
activity.startActivityForResult(intent, RequestCodes.PICK_PICTURE_FROM_CUSTOM_SELECTOR);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens the camera app to pick image clicked by user
|
* Opens the camera app to pick image clicked by user
|
||||||
*/
|
*/
|
||||||
|
|
@ -135,12 +150,15 @@ public class FilePicker implements Constants {
|
||||||
if (requestCode == RequestCodes.PICK_PICTURE_FROM_GALLERY ||
|
if (requestCode == RequestCodes.PICK_PICTURE_FROM_GALLERY ||
|
||||||
requestCode == RequestCodes.TAKE_PICTURE ||
|
requestCode == RequestCodes.TAKE_PICTURE ||
|
||||||
requestCode == RequestCodes.CAPTURE_VIDEO ||
|
requestCode == RequestCodes.CAPTURE_VIDEO ||
|
||||||
requestCode == RequestCodes.PICK_PICTURE_FROM_DOCUMENTS) {
|
requestCode == RequestCodes.PICK_PICTURE_FROM_DOCUMENTS ||
|
||||||
|
requestCode == RequestCodes.PICK_PICTURE_FROM_CUSTOM_SELECTOR) {
|
||||||
if (resultCode == Activity.RESULT_OK) {
|
if (resultCode == Activity.RESULT_OK) {
|
||||||
if (requestCode == RequestCodes.PICK_PICTURE_FROM_DOCUMENTS && !isPhoto(data)) {
|
if (requestCode == RequestCodes.PICK_PICTURE_FROM_DOCUMENTS && !isPhoto(data)) {
|
||||||
onPictureReturnedFromDocuments(data, activity, callbacks);
|
onPictureReturnedFromDocuments(data, activity, callbacks);
|
||||||
} else if (requestCode == RequestCodes.PICK_PICTURE_FROM_GALLERY && !isPhoto(data)) {
|
} else if (requestCode == RequestCodes.PICK_PICTURE_FROM_GALLERY && !isPhoto(data)) {
|
||||||
onPictureReturnedFromGallery(data, activity, callbacks);
|
onPictureReturnedFromGallery(data, activity, callbacks);
|
||||||
|
} else if (requestCode == RequestCodes.PICK_PICTURE_FROM_CUSTOM_SELECTOR) {
|
||||||
|
onPictureReturnedFromCustomSelector(data, activity, callbacks);
|
||||||
} else if (requestCode == RequestCodes.TAKE_PICTURE) {
|
} else if (requestCode == RequestCodes.TAKE_PICTURE) {
|
||||||
onPictureReturnedFromCamera(activity, callbacks);
|
onPictureReturnedFromCamera(activity, callbacks);
|
||||||
} else if (requestCode == RequestCodes.CAPTURE_VIDEO) {
|
} else if (requestCode == RequestCodes.CAPTURE_VIDEO) {
|
||||||
|
|
@ -197,6 +215,32 @@ public class FilePicker implements Constants {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void onPictureReturnedFromCustomSelector(Intent data, Activity activity, @NonNull FilePicker.Callbacks callbacks) {
|
||||||
|
try {
|
||||||
|
List<UploadableFile> files = getFilesFromCustomSelector(data, activity);
|
||||||
|
callbacks.onImagesPicked(files, ImageSource.CUSTOM_SELECTOR, restoreType(activity));
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
callbacks.onImagePickerError(e, ImageSource.CUSTOM_SELECTOR, restoreType(activity));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<UploadableFile> getFilesFromCustomSelector(Intent data, Activity activity) throws IOException, SecurityException {
|
||||||
|
List<UploadableFile> files = new ArrayList<>();
|
||||||
|
ArrayList<Image> images = data.getParcelableArrayListExtra("Images");
|
||||||
|
for(Image image : images) {
|
||||||
|
Uri uri = image.getUri();
|
||||||
|
UploadableFile file = PickedFiles.pickedExistingPicture(activity, uri);
|
||||||
|
files.add(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (configuration(activity).shouldCopyPickedImagesToPublicGalleryAppFolder()) {
|
||||||
|
PickedFiles.copyFilesInSeparateThread(activity, files);
|
||||||
|
}
|
||||||
|
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
|
||||||
private static void onPictureReturnedFromGallery(Intent data, Activity activity, @NonNull FilePicker.Callbacks callbacks) {
|
private static void onPictureReturnedFromGallery(Intent data, Activity activity, @NonNull FilePicker.Callbacks callbacks) {
|
||||||
try {
|
try {
|
||||||
List<UploadableFile> files = getFilesFromGalleryPictures(data, activity);
|
List<UploadableFile> files = getFilesFromGalleryPictures(data, activity);
|
||||||
|
|
@ -301,7 +345,7 @@ public class FilePicker implements Constants {
|
||||||
|
|
||||||
|
|
||||||
public enum ImageSource {
|
public enum ImageSource {
|
||||||
GALLERY, DOCUMENTS, CAMERA_IMAGE, CAMERA_VIDEO
|
GALLERY, DOCUMENTS, CAMERA_IMAGE, CAMERA_VIDEO, CUSTOM_SELECTOR
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface Callbacks {
|
public interface Callbacks {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue