mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 20:33:53 +01:00
refractoring (#4541)
This commit is contained in:
parent
a055f3baec
commit
dfabaf8b42
20 changed files with 158 additions and 12 deletions
|
|
@ -265,6 +265,9 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment impl
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch Custom Selector.
|
||||
*/
|
||||
@OnClick(R.id.fab_custom_gallery)
|
||||
void launchCustomSelector(){
|
||||
controller.initiateCustomGalleryPickWithPermission(getActivity());
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import fr.free.nrw.commons.customselector.model.Image
|
|||
/**
|
||||
* Image Helper object, includes all the static functions required by custom selector.
|
||||
*/
|
||||
|
||||
object ImageHelper {
|
||||
|
||||
/**
|
||||
|
|
@ -65,10 +64,7 @@ object ImageHelper {
|
|||
*/
|
||||
fun getIndexList(list: ArrayList<Image>, masterList: ArrayList<Image>): ArrayList<Int> {
|
||||
|
||||
/**
|
||||
* TODO
|
||||
* Can be optimised as masterList is sorted by time.
|
||||
*/
|
||||
// Can be optimised as masterList is sorted by time.
|
||||
|
||||
val indexes = arrayListOf<Int>()
|
||||
for(image in list) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,15 @@
|
|||
package fr.free.nrw.commons.customselector.listeners
|
||||
|
||||
/**
|
||||
* Custom Selector Folder Click Listener
|
||||
*/
|
||||
interface FolderClickListener {
|
||||
|
||||
/**
|
||||
* onFolderClick
|
||||
* @param folderId : folder id of the folder.
|
||||
* @param folderName : folder name of the folder.
|
||||
* @param lastItemId : last scroll position in the folder.
|
||||
*/
|
||||
fun onFolderClick(folderId: Long, folderName: String, lastItemId: Long)
|
||||
}
|
||||
|
|
@ -2,7 +2,21 @@ package fr.free.nrw.commons.customselector.listeners
|
|||
|
||||
import fr.free.nrw.commons.customselector.model.Image
|
||||
|
||||
/**
|
||||
* Custom Selector Image Loader Listener
|
||||
* responds to the device image query.
|
||||
*/
|
||||
interface ImageLoaderListener {
|
||||
|
||||
/**
|
||||
* On image loaded
|
||||
* @param images : queried device images.
|
||||
*/
|
||||
fun onImageLoaded(images: ArrayList<Image>)
|
||||
|
||||
/**
|
||||
* On failed
|
||||
* @param throwable : throwable exception on failure.
|
||||
*/
|
||||
fun onFailed(throwable: Throwable)
|
||||
}
|
||||
|
|
@ -2,6 +2,14 @@ package fr.free.nrw.commons.customselector.listeners
|
|||
|
||||
import fr.free.nrw.commons.customselector.model.Image
|
||||
|
||||
/**
|
||||
* Custom selector Image select listener
|
||||
*/
|
||||
interface ImageSelectListener {
|
||||
|
||||
/**
|
||||
* onSelectedImagesChanged
|
||||
* @param selectedImages : new selected images.
|
||||
*/
|
||||
fun onSelectedImagesChanged(selectedImages: ArrayList<Image>)
|
||||
}
|
||||
|
|
@ -1,5 +1,9 @@
|
|||
package fr.free.nrw.commons.customselector.model
|
||||
|
||||
/**
|
||||
* sealed class Callback Status.
|
||||
* Current status of the device image query.
|
||||
*/
|
||||
sealed class CallbackStatus {
|
||||
/**
|
||||
IDLE : The callback is idle , doing nothing.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
package fr.free.nrw.commons.customselector.model
|
||||
|
||||
/**
|
||||
* Custom selector data class Folder.
|
||||
*/
|
||||
data class Folder(
|
||||
/**
|
||||
bucketId : Unique directory id, eg 540528482
|
||||
|
|
|
|||
|
|
@ -4,6 +4,9 @@ import android.net.Uri
|
|||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
/**
|
||||
* Custom selector data class Image.
|
||||
*/
|
||||
data class Image(
|
||||
/**
|
||||
id : Unique image id, primary key of image in device, eg 104950
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
package fr.free.nrw.commons.customselector.model
|
||||
|
||||
/**
|
||||
* Custom selector data class Result.
|
||||
*/
|
||||
data class Result(
|
||||
/**
|
||||
* CallbackStatus : stores the result status
|
||||
|
|
|
|||
|
|
@ -13,7 +13,10 @@ import fr.free.nrw.commons.customselector.listeners.FolderClickListener
|
|||
import fr.free.nrw.commons.customselector.model.Folder
|
||||
import fr.free.nrw.commons.customselector.model.Image
|
||||
|
||||
class FolderAdapter(
|
||||
/**
|
||||
* Custom selector FolderAdapter.
|
||||
*/
|
||||
class FolderAdapter(
|
||||
/**
|
||||
* Application context.
|
||||
*/
|
||||
|
|
@ -91,7 +94,6 @@ class FolderAdapter(
|
|||
diffResult.dispatchUpdatesTo(this)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* returns item count.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -16,6 +16,9 @@ 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
|
||||
|
||||
/**
|
||||
* Custom selector ImageAdapter.
|
||||
*/
|
||||
class ImageAdapter(
|
||||
/**
|
||||
* Application Context.
|
||||
|
|
|
|||
|
|
@ -16,6 +16,9 @@ import fr.free.nrw.commons.theme.BaseActivity
|
|||
import java.io.File
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* Custom Selector Activity.
|
||||
*/
|
||||
class CustomSelectorActivity: BaseActivity(), FolderClickListener, ImageSelectListener {
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -11,6 +11,9 @@ import kotlinx.coroutines.CoroutineScope
|
|||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.cancel
|
||||
|
||||
/**
|
||||
* Custom Selector view model.
|
||||
*/
|
||||
class CustomSelectorViewModel(var context: Context,var imageFileLoader: ImageFileLoader) : ViewModel() {
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -22,6 +22,9 @@ import fr.free.nrw.commons.upload.FileProcessor
|
|||
import kotlinx.android.synthetic.main.fragment_custom_selector.view.*
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* Custom selector folder fragment.
|
||||
*/
|
||||
class FolderFragment : CommonsDaggerSupportFragment() {
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -9,6 +9,10 @@ import kotlinx.coroutines.*
|
|||
import java.io.File
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
/**
|
||||
* Custom Selector Image File Loader.
|
||||
* Loads device images.
|
||||
*/
|
||||
class ImageFileLoader(val context: Context) : CoroutineScope{
|
||||
|
||||
/**
|
||||
|
|
@ -39,7 +43,7 @@ class ImageFileLoader(val context: Context) : CoroutineScope{
|
|||
|
||||
|
||||
/**
|
||||
* Load the device images using cursor
|
||||
* Load Device images using cursor
|
||||
*/
|
||||
private fun getImages(listener:ImageLoaderListener) {
|
||||
val cursor = context.contentResolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection, null, null, MediaStore.Images.Media.DATE_ADDED + " DESC")
|
||||
|
|
@ -99,7 +103,7 @@ class ImageFileLoader(val context: Context) : CoroutineScope{
|
|||
//todo Abort loading images.
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
*
|
||||
* TODO
|
||||
* Sha1 for image (original image).
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import fr.free.nrw.commons.explore.recentsearches.RecentSearchesDao;
|
|||
public class DBOpenHelper extends SQLiteOpenHelper {
|
||||
|
||||
private static final String DATABASE_NAME = "commons.db";
|
||||
private static final int DATABASE_VERSION = 14;
|
||||
private static final int DATABASE_VERSION = 16;
|
||||
public static final String CONTRIBUTIONS_TABLE = "contributions";
|
||||
private final String DROP_TABLE_STATEMENT="DROP TABLE IF EXISTS %s";
|
||||
|
||||
|
|
|
|||
|
|
@ -68,6 +68,11 @@ public class CommonsApplicationModule {
|
|||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides ImageFileLoader used to fetch device images.
|
||||
* @param context
|
||||
* @return
|
||||
*/
|
||||
@Provides
|
||||
public ImageFileLoader providesImageFileLoader(Context context) {
|
||||
return new ImageFileLoader(context);
|
||||
|
|
|
|||
|
|
@ -53,6 +53,12 @@ public class FilePicker implements Constants {
|
|||
.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, configuration(context).allowsMultiplePickingInGallery());
|
||||
}
|
||||
|
||||
/**
|
||||
* CreateCustomSectorIntent, creates intent for custom selector activity.
|
||||
* @param context
|
||||
* @param type
|
||||
* @return Custom selector intent
|
||||
*/
|
||||
private static Intent createCustomSelectorIntent(@NonNull Context context, int type) {
|
||||
storeType(context, type);
|
||||
return new Intent(context, CustomSelectorActivity.class);
|
||||
|
|
@ -215,6 +221,10 @@ public class FilePicker implements Constants {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* onPictureReturnedFromCustomSelector.
|
||||
* Retrieve and forward the images to upload wizard through callback.
|
||||
*/
|
||||
private static void onPictureReturnedFromCustomSelector(Intent data, Activity activity, @NonNull FilePicker.Callbacks callbacks) {
|
||||
try {
|
||||
List<UploadableFile> files = getFilesFromCustomSelector(data, activity);
|
||||
|
|
@ -225,6 +235,10 @@ public class FilePicker implements Constants {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get files from custom selector
|
||||
* Retrieve and process the selected images from the custom selector.
|
||||
*/
|
||||
private static List<UploadableFile> getFilesFromCustomSelector(Intent data, Activity activity) throws IOException, SecurityException {
|
||||
List<UploadableFile> files = new ArrayList<>();
|
||||
ArrayList<Image> images = data.getParcelableArrayListExtra("Images");
|
||||
|
|
|
|||
|
|
@ -24,19 +24,38 @@ import java.util.UUID;
|
|||
|
||||
import timber.log.Timber;
|
||||
|
||||
|
||||
/**
|
||||
* PickedFiles.
|
||||
* Process the upload items.
|
||||
*/
|
||||
public class PickedFiles implements Constants {
|
||||
|
||||
/**
|
||||
* Get Folder Name
|
||||
* @param context
|
||||
* @return default application folder name.
|
||||
*/
|
||||
private static String getFolderName(@NonNull Context context) {
|
||||
return FilePicker.configuration(context).getFolderName();
|
||||
}
|
||||
|
||||
/**
|
||||
* tempImageDirectory
|
||||
* @param context
|
||||
* @return temporary image directory to copy and perform exif changes.
|
||||
*/
|
||||
private static File tempImageDirectory(@NonNull Context context) {
|
||||
File privateTempDir = new File(context.getCacheDir(), DEFAULT_FOLDER_NAME);
|
||||
if (!privateTempDir.exists()) privateTempDir.mkdirs();
|
||||
return privateTempDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* writeToFile
|
||||
* writes inputStream data to the destination file.
|
||||
* @param in input stream of source file.
|
||||
* @param file destination file
|
||||
*/
|
||||
private static void writeToFile(InputStream in, File file) {
|
||||
try {
|
||||
OutputStream out = new FileOutputStream(file);
|
||||
|
|
@ -52,11 +71,24 @@ public class PickedFiles implements Constants {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy file function.
|
||||
* Copies source file to destination file.
|
||||
* @param src source file
|
||||
* @param dst destination file
|
||||
* @throws IOException (File input stream exception)
|
||||
*/
|
||||
private static void copyFile(File src, File dst) throws IOException {
|
||||
InputStream in = new FileInputStream(src);
|
||||
writeToFile(in, dst);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy files in separate thread.
|
||||
* Copies all the uploadable files to the temp image folder on background thread.
|
||||
* @param context
|
||||
* @param filesToCopy uploadable file list to be copied.
|
||||
*/
|
||||
static void copyFilesInSeparateThread(final Context context, final List<UploadableFile> filesToCopy) {
|
||||
new Thread(() -> {
|
||||
List<File> copiedFiles = new ArrayList<>();
|
||||
|
|
@ -64,7 +96,9 @@ public class PickedFiles implements Constants {
|
|||
for (UploadableFile uploadableFile : filesToCopy) {
|
||||
File fileToCopy = uploadableFile.getFile();
|
||||
File dstDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), getFolderName(context));
|
||||
if (!dstDir.exists()) dstDir.mkdirs();
|
||||
if (!dstDir.exists()) {
|
||||
dstDir.mkdirs();
|
||||
}
|
||||
|
||||
String[] filenameSplit = fileToCopy.getName().split("\\.");
|
||||
String extension = "." + filenameSplit[filenameSplit.length - 1];
|
||||
|
|
@ -84,12 +118,24 @@ public class PickedFiles implements Constants {
|
|||
}).run();
|
||||
}
|
||||
|
||||
/**
|
||||
* singleFileList.
|
||||
* converts a single uploadableFile to list of uploadableFile.
|
||||
* @param file uploadable file
|
||||
* @return
|
||||
*/
|
||||
static List<UploadableFile> singleFileList(UploadableFile file) {
|
||||
List<UploadableFile> list = new ArrayList<>();
|
||||
list.add(file);
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* ScanCopiedImages
|
||||
* Scan copied images metadata using media scanner.
|
||||
* @param context
|
||||
* @param copiedImages copied images list.
|
||||
*/
|
||||
static void scanCopiedImages(Context context, List<File> copiedImages) {
|
||||
String[] paths = new String[copiedImages.size()];
|
||||
for (int i = 0; i < copiedImages.size(); i++) {
|
||||
|
|
@ -104,6 +150,12 @@ public class PickedFiles implements Constants {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* pickedExistingPicture
|
||||
* convert the image into uploadable file.
|
||||
* @param photoUri Uri of the image.
|
||||
* @return Uploadable file ready for tag redaction.
|
||||
*/
|
||||
public static UploadableFile pickedExistingPicture(@NonNull Context context, Uri photoUri) throws IOException, SecurityException {// SecurityException for those file providers who share URI but forget to grant necessary permissions
|
||||
InputStream pictureInputStream = context.getContentResolver().openInputStream(photoUri);
|
||||
File directory = tempImageDirectory(context);
|
||||
|
|
@ -116,6 +168,9 @@ public class PickedFiles implements Constants {
|
|||
return new UploadableFile(photoUri, photoFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* getCameraPictureLocation
|
||||
*/
|
||||
static File getCameraPicturesLocation(@NonNull Context context) throws IOException {
|
||||
File dir = tempImageDirectory(context);
|
||||
return File.createTempFile(UUID.randomUUID().toString(), ".jpg", dir);
|
||||
|
|
@ -142,6 +197,11 @@ public class PickedFiles implements Constants {
|
|||
return extension;
|
||||
}
|
||||
|
||||
/**
|
||||
* GetUriToFile
|
||||
* @param file get uri of file
|
||||
* @return uri of requested file.
|
||||
*/
|
||||
static Uri getUriToFile(@NonNull Context context, @NonNull File file) {
|
||||
String packageName = context.getApplicationContext().getPackageName();
|
||||
String authority = packageName + ".provider";
|
||||
|
|
|
|||
|
|
@ -69,6 +69,11 @@ public class UploadItem {
|
|||
return imageQuality.getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* getContentUri.
|
||||
* @return Uri of uploadItem
|
||||
* Uri points to image location or name, eg content://media/external/images/camera/10495 (Android 10)
|
||||
*/
|
||||
public Uri getContentUri() { return contentUri; }
|
||||
|
||||
public void setImageQuality(final int imageQuality) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue