refractoring (#4541)

This commit is contained in:
Aditya-Srivastav 2021-08-10 17:59:33 +05:30 committed by GitHub
parent a055f3baec
commit dfabaf8b42
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 158 additions and 12 deletions

View file

@ -265,6 +265,9 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment impl
});
}
/**
* Launch Custom Selector.
*/
@OnClick(R.id.fab_custom_gallery)
void launchCustomSelector(){
controller.initiateCustomGalleryPickWithPermission(getActivity());

View file

@ -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) {

View file

@ -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)
}

View file

@ -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)
}

View file

@ -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>)
}

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -1,5 +1,8 @@
package fr.free.nrw.commons.customselector.model
/**
* Custom selector data class Result.
*/
data class Result(
/**
* CallbackStatus : stores the result status

View file

@ -13,6 +13,9 @@ import fr.free.nrw.commons.customselector.listeners.FolderClickListener
import fr.free.nrw.commons.customselector.model.Folder
import fr.free.nrw.commons.customselector.model.Image
/**
* Custom selector FolderAdapter.
*/
class FolderAdapter(
/**
* Application context.
@ -91,7 +94,6 @@ class FolderAdapter(
diffResult.dispatchUpdatesTo(this)
}
/**
* returns item count.
*/

View file

@ -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.

View file

@ -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 {
/**

View file

@ -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() {
/**

View file

@ -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() {
/**

View file

@ -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).

View file

@ -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";

View file

@ -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);

View file

@ -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");

View file

@ -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";

View file

@ -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) {