Use new result API (#5875)

* remove unused result expectancy for settings screen launch

Signed-off-by: parneet-guraya <gurayaparneet@gmail.com>

* initial refactor to new result api, wip

Signed-off-by: parneet-guraya <gurayaparneet@gmail.com>

* refactor camera launcher

Signed-off-by: parneet-guraya <gurayaparneet@gmail.com>

* revert callback for video handling

Signed-off-by: parneet-guraya <gurayaparneet@gmail.com>

* invoke callbacks when cancelled

Signed-off-by: parneet-guraya <gurayaparneet@gmail.com>

* handle gallery picker result based on preference

Signed-off-by: parneet-guraya <gurayaparneet@gmail.com>

* remove old method of refactoring for file picker

Signed-off-by: parneet-guraya <gurayaparneet@gmail.com>

* remove legacy result handling callback

Signed-off-by: parneet-guraya <gurayaparneet@gmail.com>

* request code used for handling result was never used for launching an activity, hence removed

Signed-off-by: parneet-guraya <gurayaparneet@gmail.com>

* extract voice result handling into function

Signed-off-by: parneet-guraya <gurayaparneet@gmail.com>

* refactor test

Signed-off-by: parneet-guraya <gurayaparneet@gmail.com>

* remove unused tests

Signed-off-by: parneet-guraya <gurayaparneet@gmail.com>

* cleanup

Signed-off-by: parneet-guraya <gurayaparneet@gmail.com>

* fix-docs

Signed-off-by: parneet-guraya <gurayaparneet@gmail.com>

* add space after ,

Signed-off-by: parneet-guraya <gurayaparneet@gmail.com>

---------

Signed-off-by: parneet-guraya <gurayaparneet@gmail.com>
This commit is contained in:
Parneet Singh 2024-10-23 18:28:39 +05:30 committed by GitHub
parent f1205c19be
commit 1e7aabad16
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
26 changed files with 407 additions and 487 deletions

View file

@ -107,7 +107,6 @@ public class CommonsApplication extends MultiDexApplication {
/** /**
* Constants begin * Constants begin
*/ */
public static final int OPEN_APPLICATION_DETAIL_SETTINGS = 1001;
public static final String DEFAULT_EDIT_SUMMARY = "Uploaded using [[COM:MOA|Commons Mobile App]]"; public static final String DEFAULT_EDIT_SUMMARY = "Uploaded using [[COM:MOA|Commons Mobile App]]";

View file

@ -9,6 +9,7 @@ import android.view.ViewGroup;
import androidx.activity.result.ActivityResultCallback; import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts; import androidx.activity.result.contract.ActivityResultContracts;
import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
@ -33,6 +34,23 @@ public class BookmarkLocationsFragment extends DaggerFragment {
@Inject BookmarkLocationsDao bookmarkLocationDao; @Inject BookmarkLocationsDao bookmarkLocationDao;
@Inject CommonPlaceClickActions commonPlaceClickActions; @Inject CommonPlaceClickActions commonPlaceClickActions;
private PlaceAdapter adapter; private PlaceAdapter adapter;
private final ActivityResultLauncher<Intent> cameraPickLauncherForResult =
registerForActivityResult(new StartActivityForResult(),
result -> {
contributionController.handleActivityResultWithCallback(requireActivity(), callbacks -> {
contributionController.onPictureReturnedFromCamera(result, requireActivity(), callbacks);
});
});
private final ActivityResultLauncher<Intent> galleryPickLauncherForResult =
registerForActivityResult(new StartActivityForResult(),
result -> {
contributionController.handleActivityResultWithCallback(requireActivity(), callbacks -> {
contributionController.onPictureReturnedFromGallery(result, requireActivity(), callbacks);
});
});
private ActivityResultLauncher<String[]> inAppCameraLocationPermissionLauncher = registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), new ActivityResultCallback<Map<String, Boolean>>() { private ActivityResultLauncher<String[]> inAppCameraLocationPermissionLauncher = registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), new ActivityResultCallback<Map<String, Boolean>>() {
@Override @Override
public void onActivityResult(Map<String, Boolean> result) { public void onActivityResult(Map<String, Boolean> result) {
@ -45,7 +63,7 @@ public class BookmarkLocationsFragment extends DaggerFragment {
contributionController.locationPermissionCallback.onLocationPermissionGranted(); contributionController.locationPermissionCallback.onLocationPermissionGranted();
} else { } else {
if (shouldShowRequestPermissionRationale(permission.ACCESS_FINE_LOCATION)) { if (shouldShowRequestPermissionRationale(permission.ACCESS_FINE_LOCATION)) {
contributionController.handleShowRationaleFlowCameraLocation(getActivity(), inAppCameraLocationPermissionLauncher); contributionController.handleShowRationaleFlowCameraLocation(getActivity(), inAppCameraLocationPermissionLauncher, cameraPickLauncherForResult);
} else { } else {
contributionController.locationPermissionCallback.onLocationPermissionDenied(getActivity().getString(R.string.in_app_camera_location_permission_denied)); contributionController.locationPermissionCallback.onLocationPermissionDenied(getActivity().getString(R.string.in_app_camera_location_permission_denied));
} }
@ -83,7 +101,9 @@ public class BookmarkLocationsFragment extends DaggerFragment {
return Unit.INSTANCE; return Unit.INSTANCE;
}, },
commonPlaceClickActions, commonPlaceClickActions,
inAppCameraLocationPermissionLauncher inAppCameraLocationPermissionLauncher,
galleryPickLauncherForResult,
cameraPickLauncherForResult
); );
binding.listView.setAdapter(adapter); binding.listView.setAdapter(adapter);
} }
@ -109,11 +129,6 @@ public class BookmarkLocationsFragment extends DaggerFragment {
} }
} }
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
contributionController.handleActivityResult(getActivity(), requestCode, resultCode, data);
}
@Override @Override
public void onDestroy() { public void onDestroy() {
super.onDestroy(); super.onDestroy();

View file

@ -7,6 +7,7 @@ import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.widget.Toast; import android.widget.Toast;
import androidx.activity.result.ActivityResult;
import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.ActivityResultLauncher;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.lifecycle.LiveData; import androidx.lifecycle.LiveData;
@ -64,10 +65,11 @@ public class ContributionController {
* Check for permissions and initiate camera click * Check for permissions and initiate camera click
*/ */
public void initiateCameraPick(Activity activity, public void initiateCameraPick(Activity activity,
ActivityResultLauncher<String[]> inAppCameraLocationPermissionLauncher) { ActivityResultLauncher<String[]> inAppCameraLocationPermissionLauncher,
ActivityResultLauncher<Intent> resultLauncher) {
boolean useExtStorage = defaultKvStore.getBoolean("useExternalStorage", true); boolean useExtStorage = defaultKvStore.getBoolean("useExternalStorage", true);
if (!useExtStorage) { if (!useExtStorage) {
initiateCameraUpload(activity); initiateCameraUpload(activity, resultLauncher);
return; return;
} }
@ -75,12 +77,12 @@ public class ContributionController {
() -> { () -> {
if (defaultKvStore.getBoolean("inAppCameraFirstRun")) { if (defaultKvStore.getBoolean("inAppCameraFirstRun")) {
defaultKvStore.putBoolean("inAppCameraFirstRun", false); defaultKvStore.putBoolean("inAppCameraFirstRun", false);
askUserToAllowLocationAccess(activity, inAppCameraLocationPermissionLauncher); askUserToAllowLocationAccess(activity, inAppCameraLocationPermissionLauncher, resultLauncher);
} else if (defaultKvStore.getBoolean("inAppCameraLocationPref")) { } else if (defaultKvStore.getBoolean("inAppCameraLocationPref")) {
createDialogsAndHandleLocationPermissions(activity, createDialogsAndHandleLocationPermissions(activity,
inAppCameraLocationPermissionLauncher); inAppCameraLocationPermissionLauncher, resultLauncher);
} else { } else {
initiateCameraUpload(activity); initiateCameraUpload(activity, resultLauncher);
} }
}, },
R.string.storage_permission_title, R.string.storage_permission_title,
@ -94,7 +96,8 @@ public class ContributionController {
* @param activity * @param activity
*/ */
private void createDialogsAndHandleLocationPermissions(Activity activity, private void createDialogsAndHandleLocationPermissions(Activity activity,
ActivityResultLauncher<String[]> inAppCameraLocationPermissionLauncher) { ActivityResultLauncher<String[]> inAppCameraLocationPermissionLauncher,
ActivityResultLauncher<Intent> resultLauncher) {
locationPermissionCallback = new LocationPermissionCallback() { locationPermissionCallback = new LocationPermissionCallback() {
@Override @Override
public void onLocationPermissionDenied(String toastMessage) { public void onLocationPermissionDenied(String toastMessage) {
@ -103,16 +106,16 @@ public class ContributionController {
toastMessage, toastMessage,
Toast.LENGTH_LONG Toast.LENGTH_LONG
).show(); ).show();
initiateCameraUpload(activity); initiateCameraUpload(activity, resultLauncher);
} }
@Override @Override
public void onLocationPermissionGranted() { public void onLocationPermissionGranted() {
if (!locationPermissionsHelper.isLocationAccessToAppsTurnedOn()) { if (!locationPermissionsHelper.isLocationAccessToAppsTurnedOn()) {
showLocationOffDialog(activity, R.string.in_app_camera_needs_location, showLocationOffDialog(activity, R.string.in_app_camera_needs_location,
R.string.in_app_camera_location_unavailable); R.string.in_app_camera_location_unavailable, resultLauncher);
} else { } else {
initiateCameraUpload(activity); initiateCameraUpload(activity, resultLauncher);
} }
} }
}; };
@ -135,9 +138,10 @@ public class ContributionController {
* @param activity Activity reference * @param activity Activity reference
* @param dialogTextResource Resource id of text to be shown in dialog * @param dialogTextResource Resource id of text to be shown in dialog
* @param toastTextResource Resource id of text to be shown in toast * @param toastTextResource Resource id of text to be shown in toast
* @param resultLauncher
*/ */
private void showLocationOffDialog(Activity activity, int dialogTextResource, private void showLocationOffDialog(Activity activity, int dialogTextResource,
int toastTextResource) { int toastTextResource, ActivityResultLauncher<Intent> resultLauncher) {
DialogUtil DialogUtil
.showAlertDialog(activity, .showAlertDialog(activity,
activity.getString(R.string.ask_to_turn_location_on), activity.getString(R.string.ask_to_turn_location_on),
@ -148,20 +152,21 @@ public class ContributionController {
() -> { () -> {
Toast.makeText(activity, activity.getString(toastTextResource), Toast.makeText(activity, activity.getString(toastTextResource),
Toast.LENGTH_LONG).show(); Toast.LENGTH_LONG).show();
initiateCameraUpload(activity); initiateCameraUpload(activity, resultLauncher);
} }
); );
} }
public void handleShowRationaleFlowCameraLocation(Activity activity, public void handleShowRationaleFlowCameraLocation(Activity activity,
ActivityResultLauncher<String[]> inAppCameraLocationPermissionLauncher) { ActivityResultLauncher<String[]> inAppCameraLocationPermissionLauncher,
ActivityResultLauncher<Intent> resultLauncher) {
DialogUtil.showAlertDialog(activity, activity.getString(R.string.location_permission_title), DialogUtil.showAlertDialog(activity, activity.getString(R.string.location_permission_title),
activity.getString(R.string.in_app_camera_location_permission_rationale), activity.getString(R.string.in_app_camera_location_permission_rationale),
activity.getString(android.R.string.ok), activity.getString(android.R.string.ok),
activity.getString(android.R.string.cancel), activity.getString(android.R.string.cancel),
() -> { () -> {
createDialogsAndHandleLocationPermissions(activity, createDialogsAndHandleLocationPermissions(activity,
inAppCameraLocationPermissionLauncher); inAppCameraLocationPermissionLauncher, resultLauncher);
}, },
() -> locationPermissionCallback.onLocationPermissionDenied( () -> locationPermissionCallback.onLocationPermissionDenied(
activity.getString(R.string.in_app_camera_location_permission_denied)), activity.getString(R.string.in_app_camera_location_permission_denied)),
@ -181,7 +186,8 @@ public class ContributionController {
* @param activity * @param activity
*/ */
private void askUserToAllowLocationAccess(Activity activity, private void askUserToAllowLocationAccess(Activity activity,
ActivityResultLauncher<String[]> inAppCameraLocationPermissionLauncher) { ActivityResultLauncher<String[]> inAppCameraLocationPermissionLauncher,
ActivityResultLauncher<Intent> resultLauncher) {
DialogUtil.showAlertDialog(activity, DialogUtil.showAlertDialog(activity,
activity.getString(R.string.in_app_camera_location_permission_title), activity.getString(R.string.in_app_camera_location_permission_title),
activity.getString(R.string.in_app_camera_location_access_explanation), activity.getString(R.string.in_app_camera_location_access_explanation),
@ -190,12 +196,12 @@ public class ContributionController {
() -> { () -> {
defaultKvStore.putBoolean("inAppCameraLocationPref", true); defaultKvStore.putBoolean("inAppCameraLocationPref", true);
createDialogsAndHandleLocationPermissions(activity, createDialogsAndHandleLocationPermissions(activity,
inAppCameraLocationPermissionLauncher); inAppCameraLocationPermissionLauncher, resultLauncher);
}, },
() -> { () -> {
ViewUtil.showLongToast(activity, R.string.in_app_camera_location_permission_denied); ViewUtil.showLongToast(activity, R.string.in_app_camera_location_permission_denied);
defaultKvStore.putBoolean("inAppCameraLocationPref", false); defaultKvStore.putBoolean("inAppCameraLocationPref", false);
initiateCameraUpload(activity); initiateCameraUpload(activity, resultLauncher);
}, },
null, null,
true); true);
@ -204,18 +210,18 @@ public class ContributionController {
/** /**
* Initiate gallery picker * Initiate gallery picker
*/ */
public void initiateGalleryPick(final Activity activity, final boolean allowMultipleUploads) { public void initiateGalleryPick(final Activity activity, ActivityResultLauncher<Intent> resultLauncher, final boolean allowMultipleUploads) {
initiateGalleryUpload(activity, allowMultipleUploads); initiateGalleryUpload(activity, resultLauncher, allowMultipleUploads);
} }
/** /**
* Initiate gallery picker with permission * Initiate gallery picker with permission
*/ */
public void initiateCustomGalleryPickWithPermission(final Activity activity) { public void initiateCustomGalleryPickWithPermission(final Activity activity, ActivityResultLauncher<Intent> resultLauncher) {
setPickerConfiguration(activity, true); setPickerConfiguration(activity, true);
PermissionUtils.checkPermissionsAndPerformAction(activity, PermissionUtils.checkPermissionsAndPerformAction(activity,
() -> FilePicker.openCustomSelector(activity, 0), () -> FilePicker.openCustomSelector(activity, resultLauncher, 0),
R.string.storage_permission_title, R.string.storage_permission_title,
R.string.write_storage_permission_rationale, R.string.write_storage_permission_rationale,
PermissionUtils.PERMISSIONS_STORAGE); PermissionUtils.PERMISSIONS_STORAGE);
@ -225,12 +231,10 @@ public class ContributionController {
/** /**
* Open chooser for gallery uploads * Open chooser for gallery uploads
*/ */
private void initiateGalleryUpload(final Activity activity, private void initiateGalleryUpload(final Activity activity, ActivityResultLauncher<Intent> resultLauncher,
final boolean allowMultipleUploads) { final boolean allowMultipleUploads) {
setPickerConfiguration(activity, allowMultipleUploads); setPickerConfiguration(activity, allowMultipleUploads);
boolean openDocumentIntentPreferred = defaultKvStore.getBoolean( FilePicker.openGallery(activity, resultLauncher, 0, isDocumentPhotoPickerPreferred());
"openDocumentPhotoPickerPref", true);
FilePicker.openGallery(activity, 0, openDocumentIntentPreferred);
} }
/** /**
@ -247,22 +251,43 @@ public class ContributionController {
/** /**
* Initiate camera upload by opening camera * Initiate camera upload by opening camera
*/ */
private void initiateCameraUpload(Activity activity) { private void initiateCameraUpload(Activity activity, ActivityResultLauncher<Intent> resultLauncher) {
setPickerConfiguration(activity, false); setPickerConfiguration(activity, false);
if (defaultKvStore.getBoolean("inAppCameraLocationPref", false)) { if (defaultKvStore.getBoolean("inAppCameraLocationPref", false)) {
locationBeforeImageCapture = locationManager.getLastLocation(); locationBeforeImageCapture = locationManager.getLastLocation();
} }
isInAppCameraUpload = true; isInAppCameraUpload = true;
FilePicker.openCameraForImage(activity, 0); FilePicker.openCameraForImage(activity, resultLauncher, 0);
}
private boolean isDocumentPhotoPickerPreferred(){
return defaultKvStore.getBoolean(
"openDocumentPhotoPickerPref", true);
}
public void onPictureReturnedFromGallery(ActivityResult result, Activity activity, FilePicker.Callbacks callbacks){
if(isDocumentPhotoPickerPreferred()){
FilePicker.onPictureReturnedFromDocuments(result, activity, callbacks);
} else {
FilePicker.onPictureReturnedFromGallery(result, activity, callbacks);
}
}
public void onPictureReturnedFromCustomSelector(ActivityResult result, Activity activity, @NonNull FilePicker.Callbacks callbacks) {
FilePicker.onPictureReturnedFromCustomSelector(result, activity, callbacks);
}
public void onPictureReturnedFromCamera(ActivityResult result, Activity activity, @NonNull FilePicker.Callbacks callbacks) {
FilePicker.onPictureReturnedFromCamera(result, activity, callbacks);
} }
/** /**
* Attaches callback for file picker. * Attaches callback for file picker.
*/ */
public void handleActivityResult(Activity activity, int requestCode, int resultCode, public void handleActivityResultWithCallback(Activity activity, FilePicker.HandleActivityResult handleActivityResult) {
Intent data) {
FilePicker.handleActivityResult(requestCode, resultCode, data, activity, handleActivityResult.onHandleActivityResult(new DefaultCallback() {
new DefaultCallback() {
@Override @Override
public void onCanceled(final ImageSource source, final int type) { public void onCanceled(final ImageSource source, final int type) {

View file

@ -6,6 +6,7 @@ import static fr.free.nrw.commons.di.NetworkingModule.NAMED_LANGUAGE_WIKI_PEDIA_
import android.Manifest.permission; import android.Manifest.permission;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
@ -20,6 +21,7 @@ import android.widget.LinearLayout;
import androidx.activity.result.ActivityResultCallback; import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts.RequestMultiplePermissions; import androidx.activity.result.contract.ActivityResultContracts.RequestMultiplePermissions;
import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
@ -96,6 +98,30 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment impl
private int contributionsSize; private int contributionsSize;
private String userName; private String userName;
private final ActivityResultLauncher<Intent> galleryPickLauncherForResult =
registerForActivityResult(new StartActivityForResult(),
result -> {
controller.handleActivityResultWithCallback(requireActivity(), callbacks -> {
controller.onPictureReturnedFromGallery(result, requireActivity(), callbacks);
});
});
private final ActivityResultLauncher<Intent> customSelectorLauncherForResult =
registerForActivityResult(new StartActivityForResult(),
result -> {
controller.handleActivityResultWithCallback(requireActivity(), callbacks -> {
controller.onPictureReturnedFromCustomSelector(result, requireActivity(), callbacks);
});
});
private final ActivityResultLauncher<Intent> cameraPickLauncherForResult =
registerForActivityResult(new StartActivityForResult(),
result -> {
controller.handleActivityResultWithCallback(requireActivity(), callbacks -> {
controller.onPictureReturnedFromCamera(result, requireActivity(), callbacks);
});
});
private ActivityResultLauncher<String[]> inAppCameraLocationPermissionLauncher = registerForActivityResult( private ActivityResultLauncher<String[]> inAppCameraLocationPermissionLauncher = registerForActivityResult(
new RequestMultiplePermissions(), new RequestMultiplePermissions(),
new ActivityResultCallback<Map<String, Boolean>>() { new ActivityResultCallback<Map<String, Boolean>>() {
@ -111,7 +137,7 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment impl
} else { } else {
if (shouldShowRequestPermissionRationale(permission.ACCESS_FINE_LOCATION)) { if (shouldShowRequestPermissionRationale(permission.ACCESS_FINE_LOCATION)) {
controller.handleShowRationaleFlowCameraLocation(getActivity(), controller.handleShowRationaleFlowCameraLocation(getActivity(),
inAppCameraLocationPermissionLauncher); inAppCameraLocationPermissionLauncher, cameraPickLauncherForResult);
} else { } else {
controller.locationPermissionCallback.onLocationPermissionDenied( controller.locationPermissionCallback.onLocationPermissionDenied(
getActivity().getString( getActivity().getString(
@ -322,7 +348,7 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment impl
private void setListeners() { private void setListeners() {
binding.fabPlus.setOnClickListener(view -> animateFAB(isFabOpen)); binding.fabPlus.setOnClickListener(view -> animateFAB(isFabOpen));
binding.fabCamera.setOnClickListener(view -> { binding.fabCamera.setOnClickListener(view -> {
controller.initiateCameraPick(getActivity(), inAppCameraLocationPermissionLauncher); controller.initiateCameraPick(getActivity(), inAppCameraLocationPermissionLauncher, cameraPickLauncherForResult);
animateFAB(isFabOpen); animateFAB(isFabOpen);
}); });
binding.fabCamera.setOnLongClickListener(view -> { binding.fabCamera.setOnLongClickListener(view -> {
@ -330,7 +356,7 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment impl
return true; return true;
}); });
binding.fabGallery.setOnClickListener(view -> { binding.fabGallery.setOnClickListener(view -> {
controller.initiateGalleryPick(getActivity(), true); controller.initiateGalleryPick(getActivity(), galleryPickLauncherForResult, true);
animateFAB(isFabOpen); animateFAB(isFabOpen);
}); });
binding.fabGallery.setOnLongClickListener(view -> { binding.fabGallery.setOnLongClickListener(view -> {
@ -343,7 +369,7 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment impl
* Launch Custom Selector. * Launch Custom Selector.
*/ */
protected void launchCustomSelector() { protected void launchCustomSelector() {
controller.initiateCustomGalleryPickWithPermission(getActivity()); controller.initiateCustomGalleryPickWithPermission(getActivity(), customSelectorLauncherForResult);
animateFAB(isFabOpen); animateFAB(isFabOpen);
} }

View file

@ -438,13 +438,6 @@ public class MainActivity extends BaseActivity
}); });
} }
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Timber.d(data != null ? data.toString() : "onActivityResult data is null");
super.onActivityResult(requestCode, resultCode, data);
controller.handleActivityResult(this, requestCode, resultCode, data);
}
@Override @Override
protected void onResume() { protected void onResume() {
super.onResume(); super.onResume();

View file

@ -13,6 +13,8 @@ import android.view.Window
import android.widget.Button import android.widget.Button
import android.widget.ImageButton import android.widget.ImageButton
import android.widget.TextView import android.widget.TextView
import androidx.activity.result.ActivityResult
import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult
import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
@ -146,6 +148,10 @@ class CustomSelectorActivity :
private var showPartialAccessIndicator by mutableStateOf(false) private var showPartialAccessIndicator by mutableStateOf(false)
private val startForResult = registerForActivityResult(StartActivityForResult()){ result ->
onFullScreenDataReceived(result)
}
/** /**
* onCreate Activity, sets theme, initialises the view model, setup view. * onCreate Activity, sets theme, initialises the view model, setup view.
*/ */
@ -224,17 +230,10 @@ class CustomSelectorActivity :
/** /**
* When data will be send from full screen mode, it will be passed to fragment * When data will be send from full screen mode, it will be passed to fragment
*/ */
override fun onActivityResult( private fun onFullScreenDataReceived(result: ActivityResult){
requestCode: Int, if (result.resultCode == Activity.RESULT_OK) {
resultCode: Int,
data: Intent?,
) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == Constants.RequestCodes.RECEIVE_DATA_FROM_FULL_SCREEN_MODE &&
resultCode == Activity.RESULT_OK
) {
val selectedImages: ArrayList<Image> = val selectedImages: ArrayList<Image> =
data!! result.data!!
.getParcelableArrayListExtra(CustomSelectorConstants.NEW_SELECTED_IMAGES)!! .getParcelableArrayListExtra(CustomSelectorConstants.NEW_SELECTED_IMAGES)!!
viewModel?.selectedImages?.value = selectedImages viewModel?.selectedImages?.value = selectedImages
} }
@ -509,7 +508,7 @@ class CustomSelectorActivity :
selectedImages, selectedImages,
) )
intent.putExtra(CustomSelectorConstants.BUCKET_ID, bucketId) intent.putExtra(CustomSelectorConstants.BUCKET_ID, bucketId)
startActivityForResult(intent, Constants.RequestCodes.RECEIVE_DATA_FROM_FULL_SCREEN_MODE) startForResult.launch(intent)
} }
/** /**

View file

@ -6,6 +6,8 @@ import android.os.Bundle
import android.os.Parcelable import android.os.Parcelable
import android.speech.RecognizerIntent import android.speech.RecognizerIntent
import android.view.View import android.view.View
import androidx.activity.result.ActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import fr.free.nrw.commons.CommonsApplication import fr.free.nrw.commons.CommonsApplication
@ -70,10 +72,14 @@ class DescriptionEditActivity :
private lateinit var binding: ActivityDescriptionEditBinding private lateinit var binding: ActivityDescriptionEditBinding
private val requestCodeForVoiceInput = 1213
private var descriptionAndCaptions: ArrayList<UploadMediaDetail>? = null private var descriptionAndCaptions: ArrayList<UploadMediaDetail>? = null
private val voiceInputResultLauncher = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { result: ActivityResult ->
onVoiceInput(result)
}
@Inject lateinit var descriptionEditHelper: DescriptionEditHelper @Inject lateinit var descriptionEditHelper: DescriptionEditHelper
@Inject lateinit var sessionManager: SessionManager @Inject lateinit var sessionManager: SessionManager
@ -115,6 +121,7 @@ class DescriptionEditActivity :
savedLanguageValue, savedLanguageValue,
descriptionAndCaptions, descriptionAndCaptions,
recentLanguagesDao, recentLanguagesDao,
voiceInputResultLauncher
) )
uploadMediaDetailAdapter.setCallback { titleStringID: Int, messageStringId: Int -> uploadMediaDetailAdapter.setCallback { titleStringID: Int, messageStringId: Int ->
showInfoAlert( showInfoAlert(
@ -149,6 +156,15 @@ class DescriptionEditActivity :
override fun onPrimaryCaptionTextChange(isNotEmpty: Boolean) {} override fun onPrimaryCaptionTextChange(isNotEmpty: Boolean) {}
private fun onVoiceInput(result: ActivityResult) {
if (result.resultCode == RESULT_OK && result.data != null) {
val resultData = result.data!!.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS)
uploadMediaDetailAdapter.handleSpeechResult(resultData!![0])
} else {
Timber.e("Error %s", result.resultCode)
}
}
/** /**
* Adds new language item to RecyclerView * Adds new language item to RecyclerView
*/ */
@ -292,22 +308,6 @@ class DescriptionEditActivity :
progressDialog!!.show() progressDialog!!.show()
} }
override fun onActivityResult(
requestCode: Int,
resultCode: Int,
data: Intent?,
) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == requestCodeForVoiceInput) {
if (resultCode == RESULT_OK && data != null) {
val result = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS)
uploadMediaDetailAdapter.handleSpeechResult(result!![0])
} else {
Timber.e("Error %s", resultCode)
}
}
}
override fun onSaveInstanceState(outState: Bundle) { override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState) super.onSaveInstanceState(outState)

View file

@ -4,20 +4,11 @@ public interface Constants {
String DEFAULT_FOLDER_NAME = "CommonsContributions"; String DEFAULT_FOLDER_NAME = "CommonsContributions";
/** /**
* Provides the request codes utilised by the FilePicker * Provides the request codes for permission handling
*/ */
interface RequestCodes { interface RequestCodes {
int LOCATION = 1; int LOCATION = 1;
int STORAGE = 2; int STORAGE = 2;
int FILE_PICKER_IMAGE_IDENTIFICATOR = 0b1101101100; //876
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_GALLERY = FILE_PICKER_IMAGE_IDENTIFICATOR + (1 << 12);
int TAKE_PICTURE = FILE_PICKER_IMAGE_IDENTIFICATOR + (1 << 13);
int RECEIVE_DATA_FROM_FULL_SCREEN_MODE = 1 << 9;
} }
/** /**

View file

@ -12,6 +12,8 @@ import android.content.pm.ResolveInfo;
import android.net.Uri; import android.net.Uri;
import android.provider.MediaStore; import android.provider.MediaStore;
import android.text.TextUtils; import android.text.TextUtils;
import androidx.activity.result.ActivityResult;
import androidx.activity.result.ActivityResultLauncher;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.preference.PreferenceManager; import androidx.preference.PreferenceManager;
@ -107,31 +109,25 @@ public class FilePicker implements Constants {
* *
* @param type Custom type of your choice, which will be returned with the images * @param type Custom type of your choice, which will be returned with the images
*/ */
public static void openGallery(Activity activity, int type, boolean openDocumentIntentPreferred) { public static void openGallery(Activity activity, ActivityResultLauncher<Intent> resultLauncher, int type, boolean openDocumentIntentPreferred) {
Intent intent = createGalleryIntent(activity, type, openDocumentIntentPreferred); Intent intent = createGalleryIntent(activity, type, openDocumentIntentPreferred);
int requestCode = RequestCodes.PICK_PICTURE_FROM_GALLERY; resultLauncher.launch(intent);
if(openDocumentIntentPreferred){
requestCode = RequestCodes.PICK_PICTURE_FROM_DOCUMENTS;
}
activity.startActivityForResult(intent, requestCode);
} }
/** /**
* Opens Custom Selector * Opens Custom Selector
*/ */
public static void openCustomSelector(Activity activity, int type) { public static void openCustomSelector(Activity activity, ActivityResultLauncher<Intent> resultLauncher, int type) {
Intent intent = createCustomSelectorIntent(activity, type); Intent intent = createCustomSelectorIntent(activity, type);
activity.startActivityForResult(intent, RequestCodes.PICK_PICTURE_FROM_CUSTOM_SELECTOR); resultLauncher.launch(intent);
} }
/** /**
* Opens the camera app to pick image clicked by user * Opens the camera app to pick image clicked by user
*/ */
public static void openCameraForImage(Activity activity, int type) { public static void openCameraForImage(Activity activity, ActivityResultLauncher<Intent> resultLauncher, int type) {
Intent intent = createCameraForImageIntent(activity, type); Intent intent = createCameraForImageIntent(activity, type);
activity.startActivityForResult(intent, RequestCodes.TAKE_PICTURE); resultLauncher.launch(intent);
} }
@Nullable @Nullable
@ -154,43 +150,6 @@ public class FilePicker implements Constants {
} }
} }
/**
* Any activity can use this method to attach their callback to the file picker
*/
public static void handleActivityResult(int requestCode, int resultCode, Intent data, Activity activity, @NonNull FilePicker.Callbacks callbacks) {
boolean isHandledPickedFile = (requestCode & RequestCodes.FILE_PICKER_IMAGE_IDENTIFICATOR) > 0;
if (isHandledPickedFile) {
requestCode &= ~RequestCodes.SOURCE_CHOOSER;
if (requestCode == RequestCodes.PICK_PICTURE_FROM_GALLERY ||
requestCode == RequestCodes.TAKE_PICTURE ||
requestCode == RequestCodes.PICK_PICTURE_FROM_DOCUMENTS ||
requestCode == RequestCodes.PICK_PICTURE_FROM_CUSTOM_SELECTOR) {
if (resultCode == Activity.RESULT_OK) {
if (requestCode == RequestCodes.PICK_PICTURE_FROM_DOCUMENTS && !isPhoto(data)) {
onPictureReturnedFromDocuments(data, activity, callbacks);
} else if (requestCode == RequestCodes.PICK_PICTURE_FROM_GALLERY && !isPhoto(data)) {
onPictureReturnedFromGallery(data, activity, callbacks);
} else if (requestCode == RequestCodes.PICK_PICTURE_FROM_CUSTOM_SELECTOR) {
onPictureReturnedFromCustomSelector(data, activity, callbacks);
} else if (requestCode == RequestCodes.TAKE_PICTURE) {
onPictureReturnedFromCamera(activity, callbacks);
}
} else {
if (requestCode == RequestCodes.PICK_PICTURE_FROM_DOCUMENTS) {
callbacks.onCanceled(FilePicker.ImageSource.DOCUMENTS, restoreType(activity));
} else if (requestCode == RequestCodes.PICK_PICTURE_FROM_GALLERY) {
callbacks.onCanceled(FilePicker.ImageSource.GALLERY, restoreType(activity));
} else if (requestCode == RequestCodes.PICK_PICTURE_FROM_CUSTOM_SELECTOR){
callbacks.onCanceled(ImageSource.CUSTOM_SELECTOR, restoreType(activity));
}
else {
callbacks.onCanceled(FilePicker.ImageSource.CAMERA_IMAGE, restoreType(activity));
}
}
}
}
}
public static List<UploadableFile> handleExternalImagesPicked(Intent data, Activity activity) { public static List<UploadableFile> handleExternalImagesPicked(Intent data, Activity activity) {
try { try {
return getFilesFromGalleryPictures(data, activity); return getFilesFromGalleryPictures(data, activity);
@ -243,18 +202,22 @@ public class FilePicker implements Constants {
return intent; return intent;
} }
private static void onPictureReturnedFromDocuments(Intent data, Activity activity, @NonNull FilePicker.Callbacks callbacks) { public static void onPictureReturnedFromDocuments(ActivityResult result, Activity activity, @NonNull FilePicker.Callbacks callbacks) {
try { if(result.getResultCode() == Activity.RESULT_OK && !isPhoto(result.getData())){
Uri photoPath = data.getData(); try {
UploadableFile photoFile = PickedFiles.pickedExistingPicture(activity, photoPath); Uri photoPath = result.getData().getData();
callbacks.onImagesPicked(singleFileList(photoFile), FilePicker.ImageSource.DOCUMENTS, restoreType(activity)); UploadableFile photoFile = PickedFiles.pickedExistingPicture(activity, photoPath);
callbacks.onImagesPicked(singleFileList(photoFile), FilePicker.ImageSource.DOCUMENTS, restoreType(activity));
if (configuration(activity).shouldCopyPickedImagesToPublicGalleryAppFolder()) { if (configuration(activity).shouldCopyPickedImagesToPublicGalleryAppFolder()) {
PickedFiles.copyFilesInSeparateThread(activity, singleFileList(photoFile)); PickedFiles.copyFilesInSeparateThread(activity, singleFileList(photoFile));
}
} catch (Exception e) {
e.printStackTrace();
callbacks.onImagePickerError(e, FilePicker.ImageSource.DOCUMENTS, restoreType(activity));
} }
} catch (Exception e) { } else {
e.printStackTrace(); callbacks.onCanceled(FilePicker.ImageSource.DOCUMENTS, restoreType(activity));
callbacks.onImagePickerError(e, FilePicker.ImageSource.DOCUMENTS, restoreType(activity));
} }
} }
@ -262,14 +225,18 @@ public class FilePicker implements Constants {
* onPictureReturnedFromCustomSelector. * onPictureReturnedFromCustomSelector.
* Retrieve and forward the images to upload wizard through callback. * Retrieve and forward the images to upload wizard through callback.
*/ */
private static void onPictureReturnedFromCustomSelector(Intent data, Activity activity, @NonNull FilePicker.Callbacks callbacks) { public static void onPictureReturnedFromCustomSelector(ActivityResult result, Activity activity, @NonNull FilePicker.Callbacks callbacks) {
try { if(result.getResultCode() == Activity.RESULT_OK){
List<UploadableFile> files = getFilesFromCustomSelector(data, activity); try {
callbacks.onImagesPicked(files, ImageSource.CUSTOM_SELECTOR, restoreType(activity)); List<UploadableFile> files = getFilesFromCustomSelector(result.getData(), activity);
} catch (Exception e) { callbacks.onImagesPicked(files, ImageSource.CUSTOM_SELECTOR, restoreType(activity));
e.printStackTrace(); } catch (Exception e) {
callbacks.onImagePickerError(e, ImageSource.CUSTOM_SELECTOR, restoreType(activity)); e.printStackTrace();
} callbacks.onImagePickerError(e, ImageSource.CUSTOM_SELECTOR, restoreType(activity));
}
} else {
callbacks.onCanceled(ImageSource.CUSTOM_SELECTOR, restoreType(activity));
}
} }
/** /**
@ -292,13 +259,17 @@ public class FilePicker implements Constants {
return files; return files;
} }
private static void onPictureReturnedFromGallery(Intent data, Activity activity, @NonNull FilePicker.Callbacks callbacks) { public static void onPictureReturnedFromGallery(ActivityResult result, Activity activity, @NonNull FilePicker.Callbacks callbacks) {
try { if(result.getResultCode() == Activity.RESULT_OK && !isPhoto(result.getData())){
List<UploadableFile> files = getFilesFromGalleryPictures(data, activity); try {
callbacks.onImagesPicked(files, FilePicker.ImageSource.GALLERY, restoreType(activity)); List<UploadableFile> files = getFilesFromGalleryPictures(result.getData(), activity);
} catch (Exception e) { callbacks.onImagesPicked(files, FilePicker.ImageSource.GALLERY, restoreType(activity));
e.printStackTrace(); } catch (Exception e) {
callbacks.onImagePickerError(e, FilePicker.ImageSource.GALLERY, restoreType(activity)); e.printStackTrace();
callbacks.onImagePickerError(e, FilePicker.ImageSource.GALLERY, restoreType(activity));
}
} else{
callbacks.onCanceled(FilePicker.ImageSource.GALLERY, restoreType(activity));
} }
} }
@ -324,69 +295,40 @@ public class FilePicker implements Constants {
return files; return files;
} }
private static void onPictureReturnedFromCamera(Activity activity, @NonNull FilePicker.Callbacks callbacks) { public static void onPictureReturnedFromCamera(ActivityResult activityResult, Activity activity, @NonNull FilePicker.Callbacks callbacks) {
try { if(activityResult.getResultCode() == Activity.RESULT_OK){
String lastImageUri = PreferenceManager.getDefaultSharedPreferences(activity).getString(KEY_PHOTO_URI, null); try {
if (!TextUtils.isEmpty(lastImageUri)) { String lastImageUri = PreferenceManager.getDefaultSharedPreferences(activity).getString(KEY_PHOTO_URI, null);
revokeWritePermission(activity, Uri.parse(lastImageUri)); if (!TextUtils.isEmpty(lastImageUri)) {
} revokeWritePermission(activity, Uri.parse(lastImageUri));
UploadableFile photoFile = FilePicker.takenCameraPicture(activity);
List<UploadableFile> files = new ArrayList<>();
files.add(photoFile);
if (photoFile == null) {
Exception e = new IllegalStateException("Unable to get the picture returned from camera");
callbacks.onImagePickerError(e, FilePicker.ImageSource.CAMERA_IMAGE, restoreType(activity));
} else {
if (configuration(activity).shouldCopyTakenPhotosToPublicGalleryAppFolder()) {
PickedFiles.copyFilesInSeparateThread(activity, singleFileList(photoFile));
} }
callbacks.onImagesPicked(files, FilePicker.ImageSource.CAMERA_IMAGE, restoreType(activity)); UploadableFile photoFile = FilePicker.takenCameraPicture(activity);
} List<UploadableFile> files = new ArrayList<>();
files.add(photoFile);
PreferenceManager.getDefaultSharedPreferences(activity) if (photoFile == null) {
Exception e = new IllegalStateException("Unable to get the picture returned from camera");
callbacks.onImagePickerError(e, FilePicker.ImageSource.CAMERA_IMAGE, restoreType(activity));
} else {
if (configuration(activity).shouldCopyTakenPhotosToPublicGalleryAppFolder()) {
PickedFiles.copyFilesInSeparateThread(activity, singleFileList(photoFile));
}
callbacks.onImagesPicked(files, FilePicker.ImageSource.CAMERA_IMAGE, restoreType(activity));
}
PreferenceManager.getDefaultSharedPreferences(activity)
.edit() .edit()
.remove(KEY_LAST_CAMERA_PHOTO) .remove(KEY_LAST_CAMERA_PHOTO)
.remove(KEY_PHOTO_URI) .remove(KEY_PHOTO_URI)
.apply(); .apply();
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
callbacks.onImagePickerError(e, FilePicker.ImageSource.CAMERA_IMAGE, restoreType(activity)); callbacks.onImagePickerError(e, FilePicker.ImageSource.CAMERA_IMAGE, restoreType(activity));
}
}
private static void onVideoReturnedFromCamera(Activity activity, @NonNull FilePicker.Callbacks callbacks) {
try {
String lastVideoUri = PreferenceManager.getDefaultSharedPreferences(activity).getString(KEY_VIDEO_URI, null);
if (!TextUtils.isEmpty(lastVideoUri)) {
revokeWritePermission(activity, Uri.parse(lastVideoUri));
} }
} else {
UploadableFile photoFile = FilePicker.takenCameraVideo(activity); callbacks.onCanceled(FilePicker.ImageSource.CAMERA_IMAGE, restoreType(activity));
List<UploadableFile> files = new ArrayList<>();
files.add(photoFile);
if (photoFile == null) {
Exception e = new IllegalStateException("Unable to get the video returned from camera");
callbacks.onImagePickerError(e, FilePicker.ImageSource.CAMERA_VIDEO, restoreType(activity));
} else {
if (configuration(activity).shouldCopyTakenPhotosToPublicGalleryAppFolder()) {
PickedFiles.copyFilesInSeparateThread(activity, singleFileList(photoFile));
}
callbacks.onImagesPicked(files, FilePicker.ImageSource.CAMERA_VIDEO, restoreType(activity));
}
PreferenceManager.getDefaultSharedPreferences(activity)
.edit()
.remove(KEY_LAST_CAMERA_VIDEO)
.remove(KEY_VIDEO_URI)
.apply();
} catch (Exception e) {
e.printStackTrace();
callbacks.onImagePickerError(e, FilePicker.ImageSource.CAMERA_VIDEO, restoreType(activity));
} }
} }
@ -406,4 +348,8 @@ public class FilePicker implements Constants {
void onCanceled(FilePicker.ImageSource source, int type); void onCanceled(FilePicker.ImageSource source, int type);
} }
public interface HandleActivityResult{
void onHandleActivityResult(FilePicker.Callbacks callbacks);
}
} }

View file

@ -1,13 +1,10 @@
package fr.free.nrw.commons.media; package fr.free.nrw.commons.media;
import static android.app.Activity.RESULT_CANCELED;
import static android.app.Activity.RESULT_OK;
import static android.view.View.GONE; import static android.view.View.GONE;
import static android.view.View.VISIBLE; import static android.view.View.VISIBLE;
import static fr.free.nrw.commons.category.CategoryClientKt.CATEGORY_NEEDING_CATEGORIES; import static fr.free.nrw.commons.category.CategoryClientKt.CATEGORY_NEEDING_CATEGORIES;
import static fr.free.nrw.commons.category.CategoryClientKt.CATEGORY_UNCATEGORISED; import static fr.free.nrw.commons.category.CategoryClientKt.CATEGORY_UNCATEGORISED;
import static fr.free.nrw.commons.description.EditDescriptionConstants.LIST_OF_DESCRIPTION_AND_CAPTION; import static fr.free.nrw.commons.description.EditDescriptionConstants.LIST_OF_DESCRIPTION_AND_CAPTION;
import static fr.free.nrw.commons.description.EditDescriptionConstants.UPDATED_WIKITEXT;
import static fr.free.nrw.commons.description.EditDescriptionConstants.WIKITEXT; import static fr.free.nrw.commons.description.EditDescriptionConstants.WIKITEXT;
import static fr.free.nrw.commons.upload.mediaDetails.UploadMediaDetailFragment.LAST_LOCATION; import static fr.free.nrw.commons.upload.mediaDetails.UploadMediaDetailFragment.LAST_LOCATION;
import static fr.free.nrw.commons.utils.LangCodeUtils.getLocalizedResources; import static fr.free.nrw.commons.utils.LangCodeUtils.getLocalizedResources;
@ -112,8 +109,6 @@ import timber.log.Timber;
public class MediaDetailFragment extends CommonsDaggerSupportFragment implements public class MediaDetailFragment extends CommonsDaggerSupportFragment implements
CategoryEditHelper.Callback { CategoryEditHelper.Callback {
private static final int REQUEST_CODE = 1001;
private static final int REQUEST_CODE_EDIT_DESCRIPTION = 1002;
private static final String IMAGE_BACKGROUND_COLOR = "image_background_color"; private static final String IMAGE_BACKGROUND_COLOR = "image_background_color";
static final int DEFAULT_IMAGE_BACKGROUND_COLOR = 0; static final int DEFAULT_IMAGE_BACKGROUND_COLOR = 0;
@ -1065,81 +1060,6 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment implements
return captionList; return captionList;
} }
/**
* Get the result from another activity and act accordingly.
* @param requestCode
* @param resultCode
* @param data
*/
@Override
public void onActivityResult(final int requestCode, final int resultCode,
@Nullable final Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_EDIT_DESCRIPTION && resultCode == RESULT_OK) {
final String updatedWikiText = data.getStringExtra(UPDATED_WIKITEXT);
try {
compositeDisposable.add(descriptionEditHelper.addDescription(getContext(), media,
updatedWikiText)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(s -> {
Timber.d("Descriptions are added.");
}));
} catch (Exception e) {
if (e.getLocalizedMessage().equals(CsrfTokenClient.ANONYMOUS_TOKEN_MESSAGE)) {
final String username = sessionManager.getUserName();
final CommonsApplication.BaseLogoutListener logoutListener = new CommonsApplication.BaseLogoutListener(
getActivity(),
requireActivity().getString(R.string.invalid_login_message),
username
);
CommonsApplication.getInstance().clearApplicationData(
requireActivity(), logoutListener);
}
}
final ArrayList<UploadMediaDetail> uploadMediaDetails
= data.getParcelableArrayListExtra(LIST_OF_DESCRIPTION_AND_CAPTION);
LinkedHashMap<String, String> updatedCaptions = new LinkedHashMap<>();
for (UploadMediaDetail mediaDetail:
uploadMediaDetails) {
try {
compositeDisposable.add(descriptionEditHelper.addCaption(getContext(), media,
mediaDetail.getLanguageCode(), mediaDetail.getCaptionText())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(s -> {
updateCaptions(mediaDetail, updatedCaptions);
Timber.d("Caption is added.");
}));
} catch (Exception e) {
if (e.getLocalizedMessage().equals(CsrfTokenClient.ANONYMOUS_TOKEN_MESSAGE)) {
final String username = sessionManager.getUserName();
final CommonsApplication.BaseLogoutListener logoutListener = new CommonsApplication.BaseLogoutListener(
getActivity(),
requireActivity().getString(R.string.invalid_login_message),
username
);
CommonsApplication.getInstance().clearApplicationData(
requireActivity(), logoutListener);
}
}
}
binding.progressBarEdit.setVisibility(GONE);
binding.descriptionEdit.setVisibility(VISIBLE);
} else if (requestCode == REQUEST_CODE_EDIT_DESCRIPTION && resultCode == RESULT_CANCELED) {
binding.progressBarEdit.setVisibility(GONE);
binding.descriptionEdit.setVisibility(VISIBLE);
}
}
/** /**
* Adds caption to the map and updates captions * Adds caption to the map and updates captions
* @param mediaDetail UploadMediaDetail * @param mediaDetail UploadMediaDetail

View file

@ -1,5 +1,6 @@
package fr.free.nrw.commons.nearby package fr.free.nrw.commons.nearby
import android.content.Intent
import android.view.View import android.view.View
import android.view.View.GONE import android.view.View.GONE
import android.view.View.INVISIBLE import android.view.View.INVISIBLE
@ -17,9 +18,9 @@ import fr.free.nrw.commons.databinding.ItemPlaceBinding
fun placeAdapterDelegate( fun placeAdapterDelegate(
bookmarkLocationDao: BookmarkLocationsDao, bookmarkLocationDao: BookmarkLocationsDao,
onItemClick: ((Place) -> Unit)? = null, onItemClick: ((Place) -> Unit)? = null,
onCameraClicked: (Place, ActivityResultLauncher<Array<String>>) -> Unit, onCameraClicked: (Place, ActivityResultLauncher<Array<String>>, ActivityResultLauncher<Intent>) -> Unit,
onCameraLongPressed: () -> Boolean, onCameraLongPressed: () -> Boolean,
onGalleryClicked: (Place) -> Unit, onGalleryClicked: (Place, ActivityResultLauncher<Intent>) -> Unit,
onGalleryLongPressed: () -> Boolean, onGalleryLongPressed: () -> Boolean,
onBookmarkClicked: (Place, Boolean) -> Unit, onBookmarkClicked: (Place, Boolean) -> Unit,
onBookmarkLongPressed: () -> Boolean, onBookmarkLongPressed: () -> Boolean,
@ -28,6 +29,8 @@ fun placeAdapterDelegate(
onDirectionsClicked: (Place) -> Unit, onDirectionsClicked: (Place) -> Unit,
onDirectionsLongPressed: () -> Boolean, onDirectionsLongPressed: () -> Boolean,
inAppCameraLocationPermissionLauncher: ActivityResultLauncher<Array<String>>, inAppCameraLocationPermissionLauncher: ActivityResultLauncher<Array<String>>,
cameraPickLauncherForResult: ActivityResultLauncher<Intent>,
galleryPickLauncherForResult: ActivityResultLauncher<Intent>
) = adapterDelegateViewBinding<Place, Place, ItemPlaceBinding>({ layoutInflater, parent -> ) = adapterDelegateViewBinding<Place, Place, ItemPlaceBinding>({ layoutInflater, parent ->
ItemPlaceBinding.inflate(layoutInflater, parent, false) ItemPlaceBinding.inflate(layoutInflater, parent, false)
}) { }) {
@ -44,10 +47,10 @@ fun placeAdapterDelegate(
onItemClick?.invoke(item) onItemClick?.invoke(item)
} }
} }
nearbyButtonLayout.cameraButton.setOnClickListener { onCameraClicked(item, inAppCameraLocationPermissionLauncher) } nearbyButtonLayout.cameraButton.setOnClickListener { onCameraClicked(item, inAppCameraLocationPermissionLauncher, cameraPickLauncherForResult) }
nearbyButtonLayout.cameraButton.setOnLongClickListener { onCameraLongPressed() } nearbyButtonLayout.cameraButton.setOnLongClickListener { onCameraLongPressed() }
nearbyButtonLayout.galleryButton.setOnClickListener { onGalleryClicked(item) } nearbyButtonLayout.galleryButton.setOnClickListener { onGalleryClicked(item, galleryPickLauncherForResult) }
nearbyButtonLayout.galleryButton.setOnLongClickListener { onGalleryLongPressed() } nearbyButtonLayout.galleryButton.setOnLongClickListener { onGalleryLongPressed() }
bookmarkButtonImage.setOnClickListener { bookmarkButtonImage.setOnClickListener {
val isBookmarked = bookmarkLocationDao.updateBookmarkLocation(item) val isBookmarked = bookmarkLocationDao.updateBookmarkLocation(item)

View file

@ -28,14 +28,14 @@ class CommonPlaceClickActions
private val activity: Activity, private val activity: Activity,
private val contributionController: ContributionController, private val contributionController: ContributionController,
) { ) {
fun onCameraClicked(): (Place, ActivityResultLauncher<Array<String>>) -> Unit = fun onCameraClicked(): (Place, ActivityResultLauncher<Array<String>>, ActivityResultLauncher<Intent>) -> Unit =
{ place, launcher -> { place, launcher, resultLauncher ->
if (applicationKvStore.getBoolean("login_skipped", false)) { if (applicationKvStore.getBoolean("login_skipped", false)) {
showLoginDialog() showLoginDialog()
} else { } else {
Timber.d("Camera button tapped. Image title: ${place.getName()}Image desc: ${place.longDescription}") Timber.d("Camera button tapped. Image title: ${place.getName()}Image desc: ${place.longDescription}")
storeSharedPrefs(place) storeSharedPrefs(place)
contributionController.initiateCameraPick(activity, launcher) contributionController.initiateCameraPick(activity, launcher, resultLauncher)
} }
} }
@ -72,14 +72,14 @@ class CommonPlaceClickActions
true true
} }
fun onGalleryClicked(): (Place) -> Unit = fun onGalleryClicked(): (Place, ActivityResultLauncher<Intent>) -> Unit =
{ {place, galleryPickLauncherForResult ->
if (applicationKvStore.getBoolean("login_skipped", false)) { if (applicationKvStore.getBoolean("login_skipped", false)) {
showLoginDialog() showLoginDialog()
} else { } else {
Timber.d("Gallery button tapped. Image title: ${it.getName()}Image desc: ${it.getLongDescription()}") Timber.d("Gallery button tapped. Image title: ${place.getName()}Image desc: ${place.getLongDescription()}")
storeSharedPrefs(it) storeSharedPrefs(place)
contributionController.initiateGalleryPick(activity, false) contributionController.initiateGalleryPick(activity, galleryPickLauncherForResult, false)
} }
} }

View file

@ -49,6 +49,7 @@ import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts.RequestMultiplePermissions; import androidx.activity.result.contract.ActivityResultContracts.RequestMultiplePermissions;
import androidx.activity.result.contract.ActivityResultContracts.RequestPermission; import androidx.activity.result.contract.ActivityResultContracts.RequestPermission;
import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult;
import androidx.annotation.DrawableRes; import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
@ -225,6 +226,31 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
private GridLayoutManager gridLayoutManager; private GridLayoutManager gridLayoutManager;
private List<BottomSheetItem> dataList; private List<BottomSheetItem> dataList;
private BottomSheetAdapter bottomSheetAdapter; private BottomSheetAdapter bottomSheetAdapter;
private final ActivityResultLauncher<Intent> galleryPickLauncherForResult =
registerForActivityResult(new StartActivityForResult(),
result -> {
controller.handleActivityResultWithCallback(requireActivity(), callbacks -> {
controller.onPictureReturnedFromGallery(result, requireActivity(), callbacks);
});
});
private final ActivityResultLauncher<Intent> customSelectorLauncherForResult =
registerForActivityResult(new StartActivityForResult(),
result -> {
controller.handleActivityResultWithCallback(requireActivity(), callbacks -> {
controller.onPictureReturnedFromCustomSelector(result, requireActivity(), callbacks);
});
});
private final ActivityResultLauncher<Intent> cameraPickLauncherForResult =
registerForActivityResult(new StartActivityForResult(),
result -> {
controller.handleActivityResultWithCallback(requireActivity(), callbacks -> {
controller.onPictureReturnedFromCamera(result, requireActivity(), callbacks);
});
});
private ActivityResultLauncher<String[]> inAppCameraLocationPermissionLauncher = registerForActivityResult( private ActivityResultLauncher<String[]> inAppCameraLocationPermissionLauncher = registerForActivityResult(
new RequestMultiplePermissions(), new RequestMultiplePermissions(),
new ActivityResultCallback<Map<String, Boolean>>() { new ActivityResultCallback<Map<String, Boolean>>() {
@ -240,7 +266,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
} else { } else {
if (shouldShowRequestPermissionRationale(permission.ACCESS_FINE_LOCATION)) { if (shouldShowRequestPermissionRationale(permission.ACCESS_FINE_LOCATION)) {
controller.handleShowRationaleFlowCameraLocation(getActivity(), controller.handleShowRationaleFlowCameraLocation(getActivity(),
inAppCameraLocationPermissionLauncher); inAppCameraLocationPermissionLauncher, cameraPickLauncherForResult);
} else { } else {
controller.locationPermissionCallback.onLocationPermissionDenied( controller.locationPermissionCallback.onLocationPermissionDenied(
getActivity().getString( getActivity().getString(
@ -570,7 +596,9 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
return Unit.INSTANCE; return Unit.INSTANCE;
}, },
commonPlaceClickActions, commonPlaceClickActions,
inAppCameraLocationPermissionLauncher inAppCameraLocationPermissionLauncher,
galleryPickLauncherForResult,
cameraPickLauncherForResult
); );
binding.bottomSheetNearby.rvNearbyList.setAdapter(adapter); binding.bottomSheetNearby.rvNearbyList.setAdapter(adapter);
} }
@ -2201,7 +2229,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
if (binding.fabCamera.isShown()) { if (binding.fabCamera.isShown()) {
Timber.d("Camera button tapped. Place: %s", selectedPlace.toString()); Timber.d("Camera button tapped. Place: %s", selectedPlace.toString());
storeSharedPrefs(selectedPlace); storeSharedPrefs(selectedPlace);
controller.initiateCameraPick(getActivity(), inAppCameraLocationPermissionLauncher); controller.initiateCameraPick(getActivity(), inAppCameraLocationPermissionLauncher, cameraPickLauncherForResult);
} }
}); });
@ -2210,6 +2238,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
Timber.d("Gallery button tapped. Place: %s", selectedPlace.toString()); Timber.d("Gallery button tapped. Place: %s", selectedPlace.toString());
storeSharedPrefs(selectedPlace); storeSharedPrefs(selectedPlace);
controller.initiateGalleryPick(getActivity(), controller.initiateGalleryPick(getActivity(),
galleryPickLauncherForResult,
false); false);
} }
}); });
@ -2218,7 +2247,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
if (binding.fabCustomGallery.isShown()) { if (binding.fabCustomGallery.isShown()) {
Timber.d("Gallery button tapped. Place: %s", selectedPlace.toString()); Timber.d("Gallery button tapped. Place: %s", selectedPlace.toString());
storeSharedPrefs(selectedPlace); storeSharedPrefs(selectedPlace);
controller.initiateCustomGalleryPickWithPermission(getActivity()); controller.initiateCustomGalleryPickWithPermission(getActivity(), customSelectorLauncherForResult);
} }
}); });
} }

View file

@ -1,5 +1,6 @@
package fr.free.nrw.commons.nearby.fragments package fr.free.nrw.commons.nearby.fragments
import android.content.Intent
import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.ActivityResultLauncher
import fr.free.nrw.commons.bookmarks.locations.BookmarkLocationsDao import fr.free.nrw.commons.bookmarks.locations.BookmarkLocationsDao
import fr.free.nrw.commons.nearby.Place import fr.free.nrw.commons.nearby.Place
@ -12,6 +13,8 @@ class PlaceAdapter(
onBookmarkClicked: (Place, Boolean) -> Unit, onBookmarkClicked: (Place, Boolean) -> Unit,
commonPlaceClickActions: CommonPlaceClickActions, commonPlaceClickActions: CommonPlaceClickActions,
inAppCameraLocationPermissionLauncher: ActivityResultLauncher<Array<String>>, inAppCameraLocationPermissionLauncher: ActivityResultLauncher<Array<String>>,
galleryPickLauncherForResult: ActivityResultLauncher<Intent>,
cameraPickLauncherForResult: ActivityResultLauncher<Intent>
) : BaseDelegateAdapter<Place>( ) : BaseDelegateAdapter<Place>(
placeAdapterDelegate( placeAdapterDelegate(
bookmarkLocationsDao, bookmarkLocationsDao,
@ -27,6 +30,8 @@ class PlaceAdapter(
commonPlaceClickActions.onDirectionsClicked(), commonPlaceClickActions.onDirectionsClicked(),
commonPlaceClickActions.onDirectionsLongPressed(), commonPlaceClickActions.onDirectionsLongPressed(),
inAppCameraLocationPermissionLauncher, inAppCameraLocationPermissionLauncher,
cameraPickLauncherForResult,
galleryPickLauncherForResult
), ),
areItemsTheSame = { oldItem, newItem -> oldItem.wikiDataEntityId == newItem.wikiDataEntityId }, areItemsTheSame = { oldItem, newItem -> oldItem.wikiDataEntityId == newItem.wikiDataEntityId },
) )

View file

@ -21,6 +21,7 @@ import android.widget.TextView;
import androidx.activity.result.ActivityResultCallback; import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts; import androidx.activity.result.contract.ActivityResultContracts;
import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult;
import androidx.preference.ListPreference; import androidx.preference.ListPreference;
import androidx.preference.MultiSelectListPreference; import androidx.preference.MultiSelectListPreference;
import androidx.preference.Preference; import androidx.preference.Preference;
@ -85,6 +86,15 @@ public class SettingsFragment extends PreferenceFragmentCompat {
private View separator; private View separator;
private ListView languageHistoryListView; private ListView languageHistoryListView;
private static final String GET_CONTENT_PICKER_HELP_URL = "https://commons-app.github.io/docs.html#get-content"; private static final String GET_CONTENT_PICKER_HELP_URL = "https://commons-app.github.io/docs.html#get-content";
private final ActivityResultLauncher<Intent> cameraPickLauncherForResult =
registerForActivityResult(new StartActivityForResult(),
result -> {
contributionController.handleActivityResultWithCallback(requireActivity(), callbacks -> {
contributionController.onPictureReturnedFromCamera(result, requireActivity(), callbacks);
});
});
private ActivityResultLauncher<String[]> inAppCameraLocationPermissionLauncher = registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), new ActivityResultCallback<Map<String, Boolean>>() { private ActivityResultLauncher<String[]> inAppCameraLocationPermissionLauncher = registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), new ActivityResultCallback<Map<String, Boolean>>() {
@Override @Override
public void onActivityResult(Map<String, Boolean> result) { public void onActivityResult(Map<String, Boolean> result) {
@ -93,7 +103,7 @@ public class SettingsFragment extends PreferenceFragmentCompat {
areAllGranted = areAllGranted && b; areAllGranted = areAllGranted && b;
} }
if (!areAllGranted && shouldShowRequestPermissionRationale(permission.ACCESS_FINE_LOCATION)) { if (!areAllGranted && shouldShowRequestPermissionRationale(permission.ACCESS_FINE_LOCATION)) {
contributionController.handleShowRationaleFlowCameraLocation(getActivity(), inAppCameraLocationPermissionLauncher); contributionController.handleShowRationaleFlowCameraLocation(getActivity(), inAppCameraLocationPermissionLauncher, cameraPickLauncherForResult);
} }
} }
}); });

View file

@ -441,14 +441,6 @@ public class UploadActivity extends BaseActivity implements UploadContract.View,
super.onRequestPermissionsResult(requestCode, permissions, grantResults); super.onRequestPermissionsResult(requestCode, permissions, grantResults);
} }
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CommonsApplication.OPEN_APPLICATION_DETAIL_SETTINGS) {
//TODO: Confirm if handling manual permission enabled is required
}
}
/** /**
* Sets the flag indicating whether the upload is of a specific place. * Sets the flag indicating whether the upload is of a specific place.
* *

View file

@ -20,6 +20,7 @@ import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.ListView; import android.widget.ListView;
import android.widget.TextView; import android.widget.TextView;
import androidx.activity.result.ActivityResultLauncher;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.constraintlayout.widget.ConstraintLayout; import androidx.constraintlayout.widget.ConstraintLayout;
@ -57,27 +58,29 @@ public class UploadMediaDetailAdapter extends
private int currentPosition; private int currentPosition;
private Fragment fragment; private Fragment fragment;
private Activity activity; private Activity activity;
private final ActivityResultLauncher<Intent> voiceInputResultLauncher;
private SelectedVoiceIcon selectedVoiceIcon; private SelectedVoiceIcon selectedVoiceIcon;
private static final int REQUEST_CODE_FOR_VOICE_INPUT = 1213;
private RowItemDescriptionBinding binding; private RowItemDescriptionBinding binding;
public UploadMediaDetailAdapter(Fragment fragment, String savedLanguageValue, public UploadMediaDetailAdapter(Fragment fragment, String savedLanguageValue,
RecentLanguagesDao recentLanguagesDao) { RecentLanguagesDao recentLanguagesDao, ActivityResultLauncher<Intent> voiceInputResultLauncher) {
uploadMediaDetails = new ArrayList<>(); uploadMediaDetails = new ArrayList<>();
selectedLanguages = new HashMap<>(); selectedLanguages = new HashMap<>();
this.savedLanguageValue = savedLanguageValue; this.savedLanguageValue = savedLanguageValue;
this.recentLanguagesDao = recentLanguagesDao; this.recentLanguagesDao = recentLanguagesDao;
this.fragment = fragment; this.fragment = fragment;
this.voiceInputResultLauncher = voiceInputResultLauncher;
} }
public UploadMediaDetailAdapter(Activity activity, final String savedLanguageValue, public UploadMediaDetailAdapter(Activity activity, final String savedLanguageValue,
List<UploadMediaDetail> uploadMediaDetails, RecentLanguagesDao recentLanguagesDao) { List<UploadMediaDetail> uploadMediaDetails, RecentLanguagesDao recentLanguagesDao, ActivityResultLauncher<Intent> voiceInputResultLauncher) {
this.uploadMediaDetails = uploadMediaDetails; this.uploadMediaDetails = uploadMediaDetails;
selectedLanguages = new HashMap<>(); selectedLanguages = new HashMap<>();
this.savedLanguageValue = savedLanguageValue; this.savedLanguageValue = savedLanguageValue;
this.recentLanguagesDao = recentLanguagesDao; this.recentLanguagesDao = recentLanguagesDao;
this.activity = activity; this.activity = activity;
this.voiceInputResultLauncher = voiceInputResultLauncher;
} }
public void setCallback(Callback callback) { public void setCallback(Callback callback) {
@ -150,11 +153,7 @@ public class UploadMediaDetailAdapter extends
); );
try { try {
if (activity == null) { voiceInputResultLauncher.launch(intent);
fragment.startActivityForResult(intent, REQUEST_CODE_FOR_VOICE_INPUT);
} else {
activity.startActivityForResult(intent, REQUEST_CODE_FOR_VOICE_INPUT);
}
} catch (Exception e) { } catch (Exception e) {
Timber.e(e.getMessage()); Timber.e(e.getMessage());
} }

View file

@ -18,6 +18,9 @@ import android.view.ViewGroup;
import android.widget.CheckBox; import android.widget.CheckBox;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.Toast; import android.widget.Toast;
import androidx.activity.result.ActivityResult;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.exifinterface.media.ExifInterface; import androidx.exifinterface.media.ExifInterface;
@ -58,9 +61,24 @@ import timber.log.Timber;
public class UploadMediaDetailFragment extends UploadBaseFragment implements public class UploadMediaDetailFragment extends UploadBaseFragment implements
UploadMediaDetailsContract.View, UploadMediaDetailAdapter.EventListener { UploadMediaDetailsContract.View, UploadMediaDetailAdapter.EventListener {
private static final int REQUEST_CODE = 1211; private UploadMediaDetailAdapter uploadMediaDetailAdapter;
private static final int REQUEST_CODE_FOR_EDIT_ACTIVITY = 1212;
private static final int REQUEST_CODE_FOR_VOICE_INPUT = 1213; private final ActivityResultLauncher<Intent> startForResult = registerForActivityResult(
new StartActivityForResult(), result -> {
onCameraPosition(result);
});
private final ActivityResultLauncher<Intent> startForEditActivityResult = registerForActivityResult(
new StartActivityForResult(), result -> {
onEditActivityResult(result);
}
);
private final ActivityResultLauncher<Intent> voiceInputResultLauncher = registerForActivityResult(
new StartActivityForResult(), result -> {
onVoiceInput(result);
}
);
public static Activity activity ; public static Activity activity ;
@ -84,8 +102,6 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
private boolean hasUserRemovedLocation; private boolean hasUserRemovedLocation;
private UploadMediaDetailAdapter uploadMediaDetailAdapter;
@Inject @Inject
UploadMediaDetailsContract.UserActionListener presenter; UploadMediaDetailsContract.UserActionListener presenter;
@ -279,7 +295,7 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
*/ */
private void initRecyclerView() { private void initRecyclerView() {
uploadMediaDetailAdapter = new UploadMediaDetailAdapter(this, uploadMediaDetailAdapter = new UploadMediaDetailAdapter(this,
defaultKvStore.getString(Prefs.DESCRIPTION_LANGUAGE, ""), recentLanguagesDao); defaultKvStore.getString(Prefs.DESCRIPTION_LANGUAGE, ""), recentLanguagesDao, voiceInputResultLauncher);
uploadMediaDetailAdapter.setCallback(this::showInfoAlert); uploadMediaDetailAdapter.setCallback(this::showInfoAlert);
uploadMediaDetailAdapter.setEventListener(this); uploadMediaDetailAdapter.setEventListener(this);
binding.rvDescriptions.setLayoutManager(new LinearLayoutManager(getContext())); binding.rvDescriptions.setLayoutManager(new LinearLayoutManager(getContext()));
@ -593,14 +609,14 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
* This method is called to start the image editing activity for a specific UploadItem. * This method is called to start the image editing activity for a specific UploadItem.
* It sets the UploadItem as the currently editable item, creates an intent to launch the * It sets the UploadItem as the currently editable item, creates an intent to launch the
* EditActivity, and passes the image file path as an extra in the intent. The activity * EditActivity, and passes the image file path as an extra in the intent. The activity
* is started with a request code, allowing the result to be handled in onActivityResult. * is started using resultLauncher that handles the result in respective callback.
*/ */
@Override @Override
public void showEditActivity(UploadItem uploadItem) { public void showEditActivity(UploadItem uploadItem) {
editableUploadItem = uploadItem; editableUploadItem = uploadItem;
Intent intent = new Intent(getContext(), EditActivity.class); Intent intent = new Intent(getContext(), EditActivity.class);
intent.putExtra("image", uploadableFile.getFilePath().toString()); intent.putExtra("image", uploadableFile.getFilePath().toString());
startActivityForResult(intent, REQUEST_CODE_FOR_EDIT_ACTIVITY); startForEditActivityResult.launch(intent);
} }
/** /**
@ -615,6 +631,8 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
double defaultLongitude = -122.431297; double defaultLongitude = -122.431297;
double defaultZoom = 16.0; double defaultZoom = 16.0;
final Intent locationPickerIntent;
/* Retrieve image location from EXIF if present or /* Retrieve image location from EXIF if present or
check if user has provided location while using the in-app camera. check if user has provided location while using the in-app camera.
Use location of last UploadItem if none of them is available */ Use location of last UploadItem if none of them is available */
@ -624,10 +642,11 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
.getDecLatitude(); .getDecLatitude();
defaultLongitude = uploadItem.getGpsCoords().getDecLongitude(); defaultLongitude = uploadItem.getGpsCoords().getDecLongitude();
defaultZoom = uploadItem.getGpsCoords().getZoomLevel(); defaultZoom = uploadItem.getGpsCoords().getZoomLevel();
startActivityForResult(new LocationPicker.IntentBuilder()
locationPickerIntent = new LocationPicker.IntentBuilder()
.defaultLocation(new CameraPosition(defaultLatitude,defaultLongitude,defaultZoom)) .defaultLocation(new CameraPosition(defaultLatitude,defaultLongitude,defaultZoom))
.activityKey("UploadActivity") .activityKey("UploadActivity")
.build(getActivity()), REQUEST_CODE); .build(getActivity());
} else { } else {
if (defaultKvStore.getString(LAST_LOCATION) != null) { if (defaultKvStore.getString(LAST_LOCATION) != null) {
final String[] locationLatLng final String[] locationLatLng
@ -638,27 +657,20 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
if (defaultKvStore.getString(LAST_ZOOM) != null) { if (defaultKvStore.getString(LAST_ZOOM) != null) {
defaultZoom = Double.parseDouble(defaultKvStore.getString(LAST_ZOOM)); defaultZoom = Double.parseDouble(defaultKvStore.getString(LAST_ZOOM));
} }
startActivityForResult(new LocationPicker.IntentBuilder()
locationPickerIntent = new LocationPicker.IntentBuilder()
.defaultLocation(new CameraPosition(defaultLatitude,defaultLongitude,defaultZoom)) .defaultLocation(new CameraPosition(defaultLatitude,defaultLongitude,defaultZoom))
.activityKey("NoLocationUploadActivity") .activityKey("NoLocationUploadActivity")
.build(getActivity()), REQUEST_CODE); .build(getActivity());
} }
startForResult.launch(locationPickerIntent);
} }
/** private void onCameraPosition(ActivityResult result){
* Get the coordinates and update the existing coordinates. if (result.getResultCode() == RESULT_OK) {
* @param requestCode code of request
* @param resultCode code of result
* @param data intent
*/
@Override
public void onActivityResult(final int requestCode, final int resultCode,
@Nullable final Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE && resultCode == RESULT_OK) {
assert data != null; assert result.getData() != null;
final CameraPosition cameraPosition = LocationPicker.getCameraPosition(data); final CameraPosition cameraPosition = LocationPicker.getCameraPosition(result.getData());
if (cameraPosition != null) { if (cameraPosition != null) {
@ -678,8 +690,21 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
removeLocation(); removeLocation();
} }
} }
if (requestCode == REQUEST_CODE_FOR_EDIT_ACTIVITY && resultCode == RESULT_OK) { }
String result = data.getStringExtra("editedImageFilePath");
private void onVoiceInput(ActivityResult result) {
if (result.getResultCode() == RESULT_OK && result.getData() != null) {
ArrayList<String> resultData = result.getData().getStringArrayListExtra(
RecognizerIntent.EXTRA_RESULTS);
uploadMediaDetailAdapter.handleSpeechResult(resultData.get(0));
}else {
Timber.e("Error %s", result.getResultCode());
}
}
private void onEditActivityResult(ActivityResult result){
if (result.getResultCode() == RESULT_OK) {
String path = result.getData().getStringExtra("editedImageFilePath");
if (Objects.equals(result, "Error")) { if (Objects.equals(result, "Error")) {
Timber.e("Error in rotating image"); Timber.e("Error in rotating image");
@ -687,24 +712,15 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
} }
try { try {
if (binding != null){ if (binding != null){
binding.backgroundImage.setImageURI(Uri.fromFile(new File(result))); binding.backgroundImage.setImageURI(Uri.fromFile(new File(path)));
} }
editableUploadItem.setContentUri(Uri.fromFile(new File(result))); editableUploadItem.setContentUri(Uri.fromFile(new File(path)));
callback.changeThumbnail(indexOfFragment, callback.changeThumbnail(indexOfFragment,
result); path);
} catch (Exception e) { } catch (Exception e) {
Timber.e(e); Timber.e(e);
} }
} }
else if (requestCode == REQUEST_CODE_FOR_VOICE_INPUT) {
if (resultCode == RESULT_OK && data != null) {
ArrayList<String> result = data.getStringArrayListExtra(
RecognizerIntent.EXTRA_RESULTS);
uploadMediaDetailAdapter.handleSpeechResult(result.get(0));
}else {
Timber.e("Error %s", resultCode);
}
}
} }
/** /**

View file

@ -54,8 +54,7 @@ public class PermissionUtils {
final Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); final Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
final Uri uri = Uri.fromParts("package", activity.getPackageName(), null); final Uri uri = Uri.fromParts("package", activity.getPackageName(), null);
intent.setData(uri); intent.setData(uri);
activity.startActivityForResult(intent, activity.startActivity(intent);
CommonsApplication.OPEN_APPLICATION_DETAIL_SETTINGS);
} }
/** /**

View file

@ -340,20 +340,6 @@ class MainActivityUnitTests {
method.invoke(activity, null, true) method.invoke(activity, null, true)
} }
@Test
@Throws(Exception::class)
fun testOnActivityResult() {
val method: Method =
MainActivity::class.java.getDeclaredMethod(
"onActivityResult",
Int::class.java,
Int::class.java,
Intent::class.java,
)
method.isAccessible = true
method.invoke(activity, 0, 0, null)
}
@Test @Test
@Throws(Exception::class) @Throws(Exception::class)
fun testOnResume() { fun testOnResume() {

View file

@ -1,8 +1,10 @@
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.content.Intent
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
import androidx.activity.result.ActivityResult
import fr.free.nrw.commons.OkHttpConnectionFactory import fr.free.nrw.commons.OkHttpConnectionFactory
import fr.free.nrw.commons.TestCommonsApplication import fr.free.nrw.commons.TestCommonsApplication
import fr.free.nrw.commons.contributions.ContributionDao import fr.free.nrw.commons.contributions.ContributionDao
@ -98,20 +100,20 @@ class CustomSelectorActivityTest {
} }
/** /**
* Test onActivityResult function. * Test callback when result received.
*/ */
@Test @Test
@Throws(Exception::class) @Throws(Exception::class)
fun testOnActivityResult() { fun testResultLauncher() {
val intent = Mockito.mock(Intent::class.java)
val activityResult = ActivityResult(Activity.RESULT_OK, intent)
val func = val func =
activity.javaClass.getDeclaredMethod( activity.javaClass.getDeclaredMethod(
"onActivityResult", "onFullScreenDataReceived",
Int::class.java, ActivityResult::class.java,
Int::class.java,
Intent::class.java,
) )
func.isAccessible = true func.isAccessible = true
func.invoke(activity, 512, -1, Mockito.mock(Intent::class.java)) func.invoke(activity, activityResult)
} }
/** /**

View file

@ -6,18 +6,19 @@ import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.SharedPreferences import android.content.SharedPreferences
import android.net.Uri import android.net.Uri
import android.provider.MediaStore
import androidx.activity.result.ActivityResultLauncher
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import androidx.test.core.app.ApplicationProvider import androidx.test.core.app.ApplicationProvider
import com.nhaarman.mockitokotlin2.KArgumentCaptor
import com.nhaarman.mockitokotlin2.argumentCaptor
import com.nhaarman.mockitokotlin2.verify import com.nhaarman.mockitokotlin2.verify
import fr.free.nrw.commons.TestCommonsApplication import fr.free.nrw.commons.TestCommonsApplication
import fr.free.nrw.commons.filepicker.Constants.RequestCodes import fr.free.nrw.commons.customselector.ui.selector.CustomSelectorActivity
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
import org.mockito.ArgumentMatchers
import org.mockito.Captor
import org.mockito.Mock import org.mockito.Mock
import org.mockito.Mockito.mock import org.mockito.Mockito.mock
import org.mockito.Mockito.`when` import org.mockito.Mockito.`when`
@ -48,8 +49,10 @@ class FilePickerTest {
@Mock @Mock
var unit: Unit? = null var unit: Unit? = null
@Captor @Mock
var requestCodeCaptor: ArgumentCaptor<Integer>? = null private lateinit var mockResultLauncher: ActivityResultLauncher<Intent>
private val intentCaptor: KArgumentCaptor<Intent> = argumentCaptor()
private lateinit var context: Context private lateinit var context: Context
@ -65,15 +68,17 @@ class FilePickerTest {
`when`(sharedPref.edit()).thenReturn(sharedPreferencesEditor) `when`(sharedPref.edit()).thenReturn(sharedPreferencesEditor)
`when`(sharedPref.edit().putInt("type", 0)).thenReturn(sharedPreferencesEditor) `when`(sharedPref.edit().putInt("type", 0)).thenReturn(sharedPreferencesEditor)
val openDocumentPreferred = nextBoolean() val openDocumentPreferred = nextBoolean()
FilePicker.openGallery(activity, 0, openDocumentPreferred)
verify(activity).startActivityForResult( FilePicker.openGallery(activity, mockResultLauncher, 0, openDocumentPreferred)
ArgumentMatchers.any(),
requestCodeCaptor?.capture()?.toInt()!!, verify(mockResultLauncher).launch(intentCaptor.capture())
)
if(openDocumentPreferred){ val capturedIntent = intentCaptor.firstValue
assertEquals(requestCodeCaptor?.value, RequestCodes.PICK_PICTURE_FROM_DOCUMENTS)
}else{ if (openDocumentPreferred) {
assertEquals(requestCodeCaptor?.value, RequestCodes.PICK_PICTURE_FROM_GALLERY) assertEquals(Intent.ACTION_OPEN_DOCUMENT, capturedIntent.action)
} else {
assertEquals(Intent.ACTION_GET_CONTENT, capturedIntent.action)
} }
} }
@ -84,12 +89,13 @@ class FilePickerTest {
`when`(sharedPref.edit().putInt("type", 0)).thenReturn(sharedPreferencesEditor) `when`(sharedPref.edit().putInt("type", 0)).thenReturn(sharedPreferencesEditor)
val mockApplication = mock(Application::class.java) val mockApplication = mock(Application::class.java)
`when`(activity.applicationContext).thenReturn(mockApplication) `when`(activity.applicationContext).thenReturn(mockApplication)
FilePicker.openCameraForImage(activity, 0) FilePicker.openCameraForImage(activity, mockResultLauncher, 0)
verify(activity).startActivityForResult(
ArgumentMatchers.any(), verify(mockResultLauncher).launch(intentCaptor.capture())
requestCodeCaptor?.capture()?.toInt()!!,
) val capturedIntent = intentCaptor.firstValue
assertEquals(requestCodeCaptor?.value, RequestCodes.TAKE_PICTURE)
assertEquals(MediaStore.ACTION_IMAGE_CAPTURE, capturedIntent.action)
} }
@Test @Test
@ -183,46 +189,20 @@ class FilePickerTest {
method.invoke(mockFilePicker, mockIntent) method.invoke(mockFilePicker, mockIntent)
} }
@Test
fun testHandleActivityResultCaseOne() {
val mockIntent = mock(Intent::class.java)
FilePicker.handleActivityResult(
RequestCodes.FILE_PICKER_IMAGE_IDENTIFICATOR,
Activity.RESULT_OK,
mockIntent,
activity,
object : DefaultCallback() {
override fun onCanceled(
source: FilePicker.ImageSource,
type: Int,
) {
super.onCanceled(source, type)
}
override fun onImagePickerError(
e: Exception,
source: FilePicker.ImageSource,
type: Int,
) {
}
override fun onImagesPicked(
imagesFiles: List<UploadableFile>,
source: FilePicker.ImageSource,
type: Int,
) {
}
},
)
}
@Test @Test
fun testOpenCustomSelectorRequestCode() { fun testOpenCustomSelectorRequestCode() {
`when`(PreferenceManager.getDefaultSharedPreferences(activity)).thenReturn(sharedPref) `when`(PreferenceManager.getDefaultSharedPreferences(activity)).thenReturn(sharedPref)
`when`(sharedPref.edit()).thenReturn(sharedPreferencesEditor) `when`(sharedPref.edit()).thenReturn(sharedPreferencesEditor)
`when`(sharedPref.edit().putInt("type", 0)).thenReturn(sharedPreferencesEditor) `when`(sharedPref.edit().putInt("type", 0)).thenReturn(sharedPreferencesEditor)
FilePicker.openCustomSelector(activity, 0) FilePicker.openCustomSelector(activity, mockResultLauncher, 0)
verify(activity).startActivityForResult(ArgumentMatchers.any(), requestCodeCaptor?.capture()?.toInt()!!)
assertEquals(requestCodeCaptor?.value, RequestCodes.PICK_PICTURE_FROM_CUSTOM_SELECTOR) verify(mockResultLauncher).launch(intentCaptor.capture())
val capturedIntent = intentCaptor.firstValue
assertEquals(
CustomSelectorActivity.Companion::class.java.declaringClass.name,
capturedIntent.component?.className
)
} }
} }

View file

@ -19,6 +19,7 @@ import android.widget.ProgressBar
import android.widget.ScrollView import android.widget.ScrollView
import android.widget.Spinner import android.widget.Spinner
import android.widget.TextView import android.widget.TextView
import androidx.activity.result.ActivityResult
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentTransaction import androidx.fragment.app.FragmentTransaction
import androidx.test.core.app.ApplicationProvider import androidx.test.core.app.ApplicationProvider
@ -76,7 +77,6 @@ import java.util.Locale
@Config(sdk = [21], application = TestCommonsApplication::class) @Config(sdk = [21], application = TestCommonsApplication::class)
@LooperMode(LooperMode.Mode.PAUSED) @LooperMode(LooperMode.Mode.PAUSED)
class MediaDetailFragmentUnitTests { class MediaDetailFragmentUnitTests {
private val requestCode = 1001
private val lastLocation = "last_location_while_uploading" private val lastLocation = "last_location_while_uploading"
private lateinit var fragment: MediaDetailFragment private lateinit var fragment: MediaDetailFragment
private lateinit var fragmentManager: FragmentManager private lateinit var fragmentManager: FragmentManager
@ -231,24 +231,6 @@ class MediaDetailFragmentUnitTests {
fragment.onCreateView(layoutInflater, null, savedInstanceState) fragment.onCreateView(layoutInflater, null, savedInstanceState)
} }
@Test
@Throws(Exception::class)
fun testOnActivityResultLocationPickerActivity() {
fragment.onActivityResult(requestCode, Activity.RESULT_CANCELED, intent)
}
@Test
@Throws(Exception::class)
fun `test OnActivity Result Cancelled LocationPickerActivity`() {
fragment.onActivityResult(requestCode, Activity.RESULT_CANCELED, intent)
}
@Test
@Throws(Exception::class)
fun `test OnActivity Result Cancelled DescriptionEditActivity`() {
fragment.onActivityResult(requestCode, Activity.RESULT_OK, intent)
}
@Test @Test
@Throws(Exception::class) @Throws(Exception::class)
fun testOnSaveInstanceState() { fun testOnSaveInstanceState() {

View file

@ -167,20 +167,6 @@ class UploadActivityUnitTests {
activity.makeUploadRequest() activity.makeUploadRequest()
} }
@Test
@Throws(Exception::class)
fun testOnActivityResult() {
val method: Method =
UploadActivity::class.java.getDeclaredMethod(
"onActivityResult",
Int::class.java,
Int::class.java,
Intent::class.java,
)
method.isAccessible = true
method.invoke(activity, CommonsApplication.OPEN_APPLICATION_DETAIL_SETTINGS, 0, Intent())
}
@Test @Test
@Throws(Exception::class) @Throws(Exception::class)
fun testReceiveSharedItems() { fun testReceiveSharedItems() {

View file

@ -2,11 +2,13 @@ package fr.free.nrw.commons.upload
import android.app.Dialog import android.app.Dialog
import android.content.Context import android.content.Context
import android.content.Intent
import android.view.View import android.view.View
import android.widget.AdapterView import android.widget.AdapterView
import android.widget.GridLayout import android.widget.GridLayout
import android.widget.ListView import android.widget.ListView
import android.widget.TextView import android.widget.TextView
import androidx.activity.result.ActivityResultLauncher
import androidx.test.core.app.ApplicationProvider import androidx.test.core.app.ApplicationProvider
import com.nhaarman.mockitokotlin2.any import com.nhaarman.mockitokotlin2.any
import com.nhaarman.mockitokotlin2.times import com.nhaarman.mockitokotlin2.times
@ -67,13 +69,16 @@ class UploadMediaDetailAdapterUnitTest {
@Mock @Mock
private lateinit var adapterView: AdapterView<RecentLanguagesAdapter> private lateinit var adapterView: AdapterView<RecentLanguagesAdapter>
@Mock
private lateinit var mockResultLauncher: ActivityResultLauncher<Intent>
@Before @Before
fun setUp() { fun setUp() {
MockitoAnnotations.openMocks(this) MockitoAnnotations.openMocks(this)
uploadMediaDetails = mutableListOf(uploadMediaDetail, uploadMediaDetail) uploadMediaDetails = mutableListOf(uploadMediaDetail, uploadMediaDetail)
activity = Robolectric.buildActivity(UploadActivity::class.java).get() activity = Robolectric.buildActivity(UploadActivity::class.java).get()
fragment = mock(UploadMediaDetailFragment::class.java) fragment = mock(UploadMediaDetailFragment::class.java)
adapter = UploadMediaDetailAdapter(fragment, "", recentLanguagesDao) adapter = UploadMediaDetailAdapter(fragment, "", recentLanguagesDao, mockResultLauncher)
context = ApplicationProvider.getApplicationContext() context = ApplicationProvider.getApplicationContext()
Whitebox.setInternalState(adapter, "uploadMediaDetails", uploadMediaDetails) Whitebox.setInternalState(adapter, "uploadMediaDetails", uploadMediaDetails)
Whitebox.setInternalState(adapter, "eventListener", eventListener) Whitebox.setInternalState(adapter, "eventListener", eventListener)

View file

@ -11,6 +11,7 @@ import android.view.View
import android.widget.ImageView import android.widget.ImageView
import android.widget.LinearLayout import android.widget.LinearLayout
import android.widget.TextView import android.widget.TextView
import androidx.activity.result.ActivityResult
import androidx.appcompat.widget.AppCompatButton import androidx.appcompat.widget.AppCompatButton
import androidx.appcompat.widget.AppCompatImageButton import androidx.appcompat.widget.AppCompatImageButton
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
@ -348,7 +349,7 @@ class UploadMediaDetailFragmentUnitTest {
@Test @Test
@Throws(Exception::class) @Throws(Exception::class)
fun testOnActivityResultOnMapIconClicked() { fun testOnCameraPositionCallbackOnMapIconClicked() {
shadowOf(Looper.getMainLooper()).idle() shadowOf(Looper.getMainLooper()).idle()
Mockito.mock(LocationPicker::class.java) Mockito.mock(LocationPicker::class.java)
val intent = Mockito.mock(Intent::class.java) val intent = Mockito.mock(Intent::class.java)
@ -363,13 +364,18 @@ class UploadMediaDetailFragmentUnitTest {
`when`(latLng.latitude).thenReturn(0.0) `when`(latLng.latitude).thenReturn(0.0)
`when`(latLng.longitude).thenReturn(0.0) `when`(latLng.longitude).thenReturn(0.0)
`when`(uploadItem.gpsCoords).thenReturn(imageCoordinates) `when`(uploadItem.gpsCoords).thenReturn(imageCoordinates)
fragment.onActivityResult(1211, Activity.RESULT_OK, intent) val activityResult = ActivityResult(Activity.RESULT_OK, intent)
val handleResultMethod = UploadMediaDetailFragment::class.java.getDeclaredMethod("onCameraPosition", ActivityResult::class.java)
handleResultMethod.isAccessible = true
handleResultMethod.invoke(fragment, activityResult)
Mockito.verify(presenter, Mockito.times(0)).getImageQuality(0, location, activity) Mockito.verify(presenter, Mockito.times(0)).getImageQuality(0, location, activity)
} }
@Test @Test
@Throws(Exception::class) @Throws(Exception::class)
fun testOnActivityResultAddLocationDialog() { fun testOnCameraPositionCallbackAddLocationDialog() {
shadowOf(Looper.getMainLooper()).idle() shadowOf(Looper.getMainLooper()).idle()
Mockito.mock(LocationPicker::class.java) Mockito.mock(LocationPicker::class.java)
val intent = Mockito.mock(Intent::class.java) val intent = Mockito.mock(Intent::class.java)
@ -387,7 +393,13 @@ class UploadMediaDetailFragmentUnitTest {
`when`(latLng.latitude).thenReturn(0.0) `when`(latLng.latitude).thenReturn(0.0)
`when`(latLng.longitude).thenReturn(0.0) `when`(latLng.longitude).thenReturn(0.0)
`when`(uploadItem.gpsCoords).thenReturn(imageCoordinates) `when`(uploadItem.gpsCoords).thenReturn(imageCoordinates)
fragment.onActivityResult(1211, Activity.RESULT_OK, intent)
val activityResult = ActivityResult(Activity.RESULT_OK,intent)
val handleResultMethod = UploadMediaDetailFragment::class.java.getDeclaredMethod("onCameraPosition", ActivityResult::class.java)
handleResultMethod.isAccessible = true
handleResultMethod.invoke(fragment, activityResult)
Mockito.verify(presenter, Mockito.times(1)).displayLocDialog(0, null, false) Mockito.verify(presenter, Mockito.times(1)).displayLocDialog(0, null, false)
} }