initial refactor to new result api, wip

Signed-off-by: parneet-guraya <gurayaparneet@gmail.com>
This commit is contained in:
parneet-guraya 2024-10-14 06:37:27 +05:30
parent fb9c88026b
commit 6a98923a83
No known key found for this signature in database
GPG key ID: 63B807C4B2A9064B
16 changed files with 357 additions and 176 deletions

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,19 @@ public class BookmarkLocationsFragment extends DaggerFragment {
@Inject BookmarkLocationsDao bookmarkLocationDao; @Inject BookmarkLocationsDao bookmarkLocationDao;
@Inject CommonPlaceClickActions commonPlaceClickActions; @Inject CommonPlaceClickActions commonPlaceClickActions;
private PlaceAdapter adapter; private PlaceAdapter adapter;
private ActivityResultLauncher<Intent> cameraPickLauncherForResult = registerForActivityResult(new StartActivityForResult(),
result -> {
// TODO handle result from controller
});
private 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 +59,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 +97,11 @@ public class BookmarkLocationsFragment extends DaggerFragment {
return Unit.INSTANCE; return Unit.INSTANCE;
}, },
commonPlaceClickActions, commonPlaceClickActions,
inAppCameraLocationPermissionLauncher inAppCameraLocationPermissionLauncher,
galleryPickLauncherForResult,
//TODO[Parry] just a stub, make sure if this is actually the launcher we need!!
cameraPickLauncherForResult
); );
binding.listView.setAdapter(adapter); binding.listView.setAdapter(adapter);
} }
@ -109,9 +127,10 @@ public class BookmarkLocationsFragment extends DaggerFragment {
} }
} }
//TODO[Parr]: doubtful if it even used, check while testing
@Override @Override
public void onActivityResult(int requestCode, int resultCode, Intent data) { public void onActivityResult(int requestCode, int resultCode, Intent data) {
contributionController.handleActivityResult(getActivity(), requestCode, resultCode, data); // contributionController.handleActivityResult(getActivity(), resultCode, data);
} }
@Override @Override

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,7 +106,7 @@ public class ContributionController {
toastMessage, toastMessage,
Toast.LENGTH_LONG Toast.LENGTH_LONG
).show(); ).show();
initiateCameraUpload(activity); initiateCameraUpload(activity, resultLauncher);
} }
@Override @Override
@ -112,7 +115,7 @@ public class ContributionController {
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);
} else { } else {
initiateCameraUpload(activity); initiateCameraUpload(activity, resultLauncher);
} }
} }
}; };
@ -148,20 +151,22 @@ 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); //TODO [Parry] why do we need this call???
// initiateCameraUpload(activity);
} }
); );
} }
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,12 @@ 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( boolean openDocumentIntentPreferred = defaultKvStore.getBoolean(
"openDocumentPhotoPickerPref", true); "openDocumentPhotoPickerPref", true);
FilePicker.openGallery(activity, 0, openDocumentIntentPreferred); FilePicker.openGallery(activity, resultLauncher,0, openDocumentIntentPreferred);
} }
/** /**
@ -247,42 +253,72 @@ 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);
}
public void onPictureReturnedFromGallery(ActivityResult result, Activity activity, FilePicker.Callbacks callbacks){
FilePicker.onPictureReturnedFromGallery(result,activity,callbacks);
}
public void onPictureReturnedFromCustomSelector(ActivityResult result, Activity activity, @NonNull FilePicker.Callbacks callbacks) {
FilePicker.onPictureReturnedFromCustomSelector(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,
new DefaultCallback() {
@Override handleActivityResult.onHandleActivityResult(new DefaultCallback() {
public void onCanceled(final ImageSource source, final int type) {
super.onCanceled(source, type);
defaultKvStore.remove(PLACE_OBJECT);
}
@Override @Override
public void onImagePickerError(Exception e, FilePicker.ImageSource source, public void onCanceled(final ImageSource source, final int type) {
int type) { super.onCanceled(source, type);
ViewUtil.showShortToast(activity, R.string.error_occurred_in_picking_images); defaultKvStore.remove(PLACE_OBJECT);
} }
@Override @Override
public void onImagesPicked(@NonNull List<UploadableFile> imagesFiles, public void onImagePickerError(Exception e, FilePicker.ImageSource source,
FilePicker.ImageSource source, int type) { int type) {
Intent intent = handleImagesPicked(activity, imagesFiles); ViewUtil.showShortToast(activity, R.string.error_occurred_in_picking_images);
activity.startActivity(intent); }
}
}); @Override
public void onImagesPicked(@NonNull List<UploadableFile> imagesFiles,
FilePicker.ImageSource source, int type) {
Intent intent = handleImagesPicked(activity, imagesFiles);
activity.startActivity(intent);
}
});
// FilePicker.handleActivityResult(requestCode, resultCode, data, activity,
// new DefaultCallback() {
//
// @Override
// public void onCanceled(final ImageSource source, final int type) {
// super.onCanceled(source, type);
// defaultKvStore.remove(PLACE_OBJECT);
// }
//
// @Override
// public void onImagePickerError(Exception e, FilePicker.ImageSource source,
// int type) {
// ViewUtil.showShortToast(activity, R.string.error_occurred_in_picking_images);
// }
//
// @Override
// public void onImagesPicked(@NonNull List<UploadableFile> imagesFiles,
// FilePicker.ImageSource source, int type) {
// Intent intent = handleImagesPicked(activity, imagesFiles);
// activity.startActivity(intent);
// }
// });
} }
public List<UploadableFile> handleExternalImagesPicked(Activity activity, public List<UploadableFile> handleExternalImagesPicked(Activity activity,

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,25 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment impl
private int contributionsSize; private int contributionsSize;
private String userName; private String userName;
private ActivityResultLauncher<Intent> galleryPickLauncherForResult = registerForActivityResult(new StartActivityForResult(),
result -> {
controller.handleActivityResultWithCallback(requireActivity(),callbacks -> {
controller.onPictureReturnedFromGallery(result,requireActivity(),callbacks);
});
});
private ActivityResultLauncher<Intent> customSelectorLauncherForResult = registerForActivityResult(new StartActivityForResult(),
result -> {
controller.handleActivityResultWithCallback(requireActivity(),callbacks -> {
controller.onPictureReturnedFromCustomSelector(result,requireActivity(),callbacks);
});
});
private ActivityResultLauncher<Intent> cameraPickLauncherForResult = registerForActivityResult(new StartActivityForResult(),
result -> {
// TODO handle result from controller
});
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 +132,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 +343,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 +351,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 +364,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

@ -1,13 +1,10 @@
package fr.free.nrw.commons.contributions; package fr.free.nrw.commons.contributions;
import android.Manifest.permission;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.os.Bundle; import android.os.Bundle;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
@ -16,10 +13,8 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import androidx.viewpager.widget.ViewPager;
import androidx.work.ExistingWorkPolicy; import androidx.work.ExistingWorkPolicy;
import fr.free.nrw.commons.databinding.MainBinding; import fr.free.nrw.commons.databinding.MainBinding;
import fr.free.nrw.commons.CommonsApplication;
import fr.free.nrw.commons.R; import fr.free.nrw.commons.R;
import fr.free.nrw.commons.WelcomeActivity; import fr.free.nrw.commons.WelcomeActivity;
import fr.free.nrw.commons.auth.SessionManager; import fr.free.nrw.commons.auth.SessionManager;
@ -41,10 +36,8 @@ import fr.free.nrw.commons.notification.NotificationController;
import fr.free.nrw.commons.quiz.QuizChecker; import fr.free.nrw.commons.quiz.QuizChecker;
import fr.free.nrw.commons.settings.SettingsFragment; import fr.free.nrw.commons.settings.SettingsFragment;
import fr.free.nrw.commons.theme.BaseActivity; import fr.free.nrw.commons.theme.BaseActivity;
import fr.free.nrw.commons.upload.UploadActivity;
import fr.free.nrw.commons.upload.UploadProgressActivity; import fr.free.nrw.commons.upload.UploadProgressActivity;
import fr.free.nrw.commons.upload.worker.WorkRequestHelper; import fr.free.nrw.commons.upload.worker.WorkRequestHelper;
import fr.free.nrw.commons.utils.PermissionUtils;
import fr.free.nrw.commons.utils.ViewUtilWrapper; import fr.free.nrw.commons.utils.ViewUtilWrapper;
import io.reactivex.Completable; import io.reactivex.Completable;
import io.reactivex.schedulers.Schedulers; import io.reactivex.schedulers.Schedulers;
@ -442,7 +435,9 @@ public class MainActivity extends BaseActivity
protected void onActivityResult(int requestCode, int resultCode, Intent data) { protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Timber.d(data != null ? data.toString() : "onActivityResult data is null"); Timber.d(data != null ? data.toString() : "onActivityResult data is null");
super.onActivityResult(requestCode, resultCode, data); super.onActivityResult(requestCode, resultCode, data);
controller.handleActivityResult(this, requestCode, resultCode, data); //TODO [parr] This can be removed. since any screen that expects a result from launched activity
// handles that in it's own respective place.
// controller.handleActivityResult(this, resultCode, data);
} }
@Override @Override

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( 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
@ -74,6 +76,17 @@ class DescriptionEditActivity :
private var descriptionAndCaptions: ArrayList<UploadMediaDetail>? = null private var descriptionAndCaptions: ArrayList<UploadMediaDetail>? = null
private val voiceInputResultLauncher = registerForActivityResult<Intent, ActivityResult>(
ActivityResultContracts.StartActivityForResult()
) { 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)
}
}
@Inject lateinit var descriptionEditHelper: DescriptionEditHelper @Inject lateinit var descriptionEditHelper: DescriptionEditHelper
@Inject lateinit var sessionManager: SessionManager @Inject lateinit var sessionManager: SessionManager
@ -115,6 +128,7 @@ class DescriptionEditActivity :
savedLanguageValue, savedLanguageValue,
descriptionAndCaptions, descriptionAndCaptions,
recentLanguagesDao, recentLanguagesDao,
voiceInputResultLauncher
) )
uploadMediaDetailAdapter.setCallback { titleStringID: Int, messageStringId: Int -> uploadMediaDetailAdapter.setCallback { titleStringID: Int, messageStringId: Int ->
showInfoAlert( showInfoAlert(
@ -292,21 +306,21 @@ class DescriptionEditActivity :
progressDialog!!.show() progressDialog!!.show()
} }
override fun onActivityResult( // override fun onActivityResult(
requestCode: Int, // requestCode: Int,
resultCode: Int, // resultCode: Int,
data: Intent?, // data: Intent?,
) { // ) {
super.onActivityResult(requestCode, resultCode, data) // super.onActivityResult(requestCode, resultCode, data)
if (requestCode == requestCodeForVoiceInput) { // if (requestCode == requestCodeForVoiceInput) {
if (resultCode == RESULT_OK && data != null) { // if (resultCode == RESULT_OK && data != null) {
val result = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS) // val result = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS)
uploadMediaDetailAdapter.handleSpeechResult(result!![0]) // uploadMediaDetailAdapter.handleSpeechResult(result!![0])
} else { // } else {
Timber.e("Error %s", resultCode) // Timber.e("Error %s", resultCode)
} // }
} // }
} // }
override fun onSaveInstanceState(outState: Bundle) { override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState) super.onSaveInstanceState(outState)

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,35 @@ 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; // int requestCode = RequestCodes.PICK_PICTURE_FROM_GALLERY;
//
if(openDocumentIntentPreferred){ // if(openDocumentIntentPreferred){
requestCode = RequestCodes.PICK_PICTURE_FROM_DOCUMENTS; // requestCode = RequestCodes.PICK_PICTURE_FROM_DOCUMENTS;
} // }
//
activity.startActivityForResult(intent, requestCode); // activity.startActivityForResult(intent, requestCode);
resultLauncher.launch(intent);
} }
/** /**
* 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); // 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); //TODO[Parry] we're not using the result anyways.
// activity.startActivityForResult(intent, RequestCodes.TAKE_PICTURE);
resultLauncher.launch(intent);
} }
@Nullable @Nullable
@ -169,10 +175,11 @@ public class FilePicker implements Constants {
if (requestCode == RequestCodes.PICK_PICTURE_FROM_DOCUMENTS && !isPhoto(data)) { if (requestCode == RequestCodes.PICK_PICTURE_FROM_DOCUMENTS && !isPhoto(data)) {
onPictureReturnedFromDocuments(data, activity, callbacks); onPictureReturnedFromDocuments(data, activity, callbacks);
} else if (requestCode == RequestCodes.PICK_PICTURE_FROM_GALLERY && !isPhoto(data)) { } else if (requestCode == RequestCodes.PICK_PICTURE_FROM_GALLERY && !isPhoto(data)) {
onPictureReturnedFromGallery(data, activity, callbacks); // onPictureReturnedFromGallery(data, activity, callbacks);
} else if (requestCode == RequestCodes.PICK_PICTURE_FROM_CUSTOM_SELECTOR) { } else if (requestCode == RequestCodes.PICK_PICTURE_FROM_CUSTOM_SELECTOR) {
onPictureReturnedFromCustomSelector(data, activity, callbacks); // onPictureReturnedFromCustomSelector(data, activity, callbacks);
} else if (requestCode == RequestCodes.TAKE_PICTURE) { } else if (requestCode == RequestCodes.TAKE_PICTURE) {
//TODO[Parry] why handle the result , when not using it in the first place???
onPictureReturnedFromCamera(activity, callbacks); onPictureReturnedFromCamera(activity, callbacks);
} }
} else { } else {
@ -262,14 +269,16 @@ 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));
}
}
} }
/** /**
@ -292,13 +301,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){
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));
} }
} }
@ -406,4 +419,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

@ -1065,6 +1065,8 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment implements
return captionList; return captionList;
} }
// TODO[Parry]: Request code is never used to start an activity, so the result will never
// be used, safely remove this.
/** /**
* Get the result from another activity and act accordingly. * Get the result from another activity and act accordingly.
* @param requestCode * @param requestCode

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>>,
resultLauncher: 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, resultLauncher) }
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,26 @@ 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 ActivityResultLauncher<Intent> galleryPickLauncherForResult = registerForActivityResult(new StartActivityForResult(),
result -> {
controller.handleActivityResultWithCallback(requireActivity(),callbacks -> {
controller.onPictureReturnedFromGallery(result,requireActivity(),callbacks);
});
});
private ActivityResultLauncher<Intent> customSelectorLauncherForResult = registerForActivityResult(new StartActivityForResult(),
result -> {
controller.handleActivityResultWithCallback(requireActivity(),callbacks -> {
controller.onPictureReturnedFromCustomSelector(result,requireActivity(),callbacks);
});
});
private ActivityResultLauncher<Intent> cameraPickLauncherForResult = registerForActivityResult(new StartActivityForResult(),
result -> {
// TODO handle result from controller
});
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 +261,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 +591,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 +2224,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 +2233,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 +2242,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>,
resultLauncherStub: 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,
resultLauncherStub,
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,12 @@ 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 ActivityResultLauncher<Intent> cameraPickLauncherForResult = registerForActivityResult(new StartActivityForResult(),
result -> {
// TODO handle result from controller
});
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 +100,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

@ -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,30 @@ public class UploadMediaDetailAdapter extends
private int currentPosition; private int currentPosition;
private Fragment fragment; private Fragment fragment;
private Activity activity; private Activity activity;
private ActivityResultLauncher<Intent> voiceInputResultLauncher;
private SelectedVoiceIcon selectedVoiceIcon; private SelectedVoiceIcon selectedVoiceIcon;
private static final int REQUEST_CODE_FOR_VOICE_INPUT = 1213; 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 +154,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,33 @@ 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 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 -> {
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());
}
}
);
public static Activity activity ; public static Activity activity ;
@ -84,8 +111,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 +304,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()));
@ -600,7 +625,7 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
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 +640,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 +651,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 +666,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 +699,12 @@ 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 onEditActivityResult(ActivityResult result){
//TODO[Parry] Doubtful how it works, understand it....
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,26 +712,39 @@ 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);
}
}
} }
/**
* Get the coordinates and update the existing coordinates.
* @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_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);
// }
// }
// }
/** /**
* Removes the location data from the image, by setting them to null * Removes the location data from the image, by setting them to null
*/ */

View file

@ -73,7 +73,8 @@ class UploadMediaDetailAdapterUnitTest {
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) //TODO[Parry] Adapt tests to new result api
// adapter = UploadMediaDetailAdapter(fragment, "", recentLanguagesDao)
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)