diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 5ba49201a..02f31185a 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,262 +1,266 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ xmlns:tools="http://schemas.android.com/tools">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
+
-
+
-
+
-
+
-
+
-
-
-
+
-
-
+
+
+
-
+
+
-
-
+
-
-
-
+
+
-
+
+
+
-
-
-
-
-
+
-
+
+
+
+
+
-
-
-
-
-
-
-
+
-
+
+
+
+
+
+
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
-
-
-
-
+
-
+
+
+
+
+
+
-
-
-
+
-
+
+
+
-
+
-
+
-
+
-
+
-
+
-
-
-
-
+
-
-
+
+
+
+
-
+
+
-
+
-
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/fr/free/nrw/commons/actions/PageEditClient.kt b/app/src/main/java/fr/free/nrw/commons/actions/PageEditClient.kt
index cb153b7cb..93e833c15 100644
--- a/app/src/main/java/fr/free/nrw/commons/actions/PageEditClient.kt
+++ b/app/src/main/java/fr/free/nrw/commons/actions/PageEditClient.kt
@@ -4,6 +4,7 @@ import fr.free.nrw.commons.auth.csrf.InvalidLoginTokenException
import io.reactivex.Observable
import io.reactivex.Single
import fr.free.nrw.commons.auth.csrf.CsrfTokenClient
+import timber.log.Timber
/**
* This class acts as a Client to facilitate wiki page editing
@@ -27,7 +28,41 @@ class PageEditClient(
fun edit(pageTitle: String, text: String, summary: String): Observable {
return try {
pageEditInterface.postEdit(pageTitle, summary, text, csrfTokenClient.getTokenBlocking())
- .map { editResponse -> editResponse.edit()!!.editSucceeded() }
+ .map { editResponse ->
+ editResponse.edit()!!.editSucceeded()
+ }
+ } catch (throwable: Throwable) {
+ if (throwable is InvalidLoginTokenException) {
+ throw throwable
+ } else {
+ Observable.just(false)
+ }
+ }
+ }
+
+ /**
+ * Creates a new page with the given title, text, and summary.
+ *
+ * @param pageTitle The title of the page to be created.
+ * @param text The content of the page in wikitext format.
+ * @param summary The edit summary for the page creation.
+ * @return An observable that emits true if the page creation succeeded, false otherwise.
+ * @throws InvalidLoginTokenException If an invalid login token is encountered during the process.
+ */
+ fun postCreate(pageTitle: String, text: String, summary: String): Observable {
+ return try {
+ pageEditInterface.postCreate(
+ pageTitle,
+ summary,
+ text,
+ "text/x-wiki",
+ "wikitext",
+ true,
+ true,
+ csrfTokenClient.getTokenBlocking()
+ ).map { editResponse ->
+ editResponse.edit()!!.editSucceeded()
+ }
} catch (throwable: Throwable) {
if (throwable is InvalidLoginTokenException) {
throw throwable
diff --git a/app/src/main/java/fr/free/nrw/commons/actions/PageEditInterface.kt b/app/src/main/java/fr/free/nrw/commons/actions/PageEditInterface.kt
index 070aaaa64..1aa0bbfce 100644
--- a/app/src/main/java/fr/free/nrw/commons/actions/PageEditInterface.kt
+++ b/app/src/main/java/fr/free/nrw/commons/actions/PageEditInterface.kt
@@ -36,6 +36,33 @@ interface PageEditInterface {
@Field("token") token: String
): Observable
+ /**
+ * This method creates or edits a page for nearby items.
+ *
+ * @param title Title of the page to edit. Cannot be used together with pageid.
+ * @param summary Edit summary. Also used as the section title when section=new and sectiontitle is not set.
+ * @param text Text of the page.
+ * @param contentformat Format of the content (e.g., "text/x-wiki").
+ * @param contentmodel Model of the content (e.g., "wikitext").
+ * @param minor Whether the edit is a minor edit.
+ * @param recreate Whether to recreate the page if it does not exist.
+ * @param token A "csrf" token. This should always be sent as the last field of form data.
+ */
+ @FormUrlEncoded
+ @Headers("Cache-Control: no-cache")
+ @POST(MW_API_PREFIX + "action=edit")
+ fun postCreate(
+ @Field("title") title: String,
+ @Field("summary") summary: String,
+ @Field("text") text: String,
+ @Field("contentformat") contentformat: String,
+ @Field("contentmodel") contentmodel: String,
+ @Field("minor") minor: Boolean,
+ @Field("recreate") recreate: Boolean,
+ // NOTE: This csrf shold always be sent as the last field of form data
+ @Field("token") token: String
+ ): Observable
+
/**
* This method posts such that the Content which the page
* has will be appended with the value being passed to the
diff --git a/app/src/main/java/fr/free/nrw/commons/di/ActivityBuilderModule.java b/app/src/main/java/fr/free/nrw/commons/di/ActivityBuilderModule.java
index 6a9277906..0df9685c1 100644
--- a/app/src/main/java/fr/free/nrw/commons/di/ActivityBuilderModule.java
+++ b/app/src/main/java/fr/free/nrw/commons/di/ActivityBuilderModule.java
@@ -14,6 +14,7 @@ import fr.free.nrw.commons.description.DescriptionEditActivity;
import fr.free.nrw.commons.explore.depictions.WikidataItemDetailsActivity;
import fr.free.nrw.commons.explore.SearchActivity;
import fr.free.nrw.commons.media.ZoomableActivity;
+import fr.free.nrw.commons.nearby.WikidataFeedback;
import fr.free.nrw.commons.notification.NotificationActivity;
import fr.free.nrw.commons.profile.ProfileActivity;
import fr.free.nrw.commons.review.ReviewActivity;
@@ -79,4 +80,7 @@ public abstract class ActivityBuilderModule {
@ContributesAndroidInjector
abstract ZoomableActivity bindZoomableActivity();
+
+ @ContributesAndroidInjector
+ abstract WikidataFeedback bindWikiFeedback();
}
diff --git a/app/src/main/java/fr/free/nrw/commons/di/CommonsApplicationComponent.java b/app/src/main/java/fr/free/nrw/commons/di/CommonsApplicationComponent.java
index cbbf1f0c5..1390bd8ef 100644
--- a/app/src/main/java/fr/free/nrw/commons/di/CommonsApplicationComponent.java
+++ b/app/src/main/java/fr/free/nrw/commons/di/CommonsApplicationComponent.java
@@ -2,9 +2,11 @@ package fr.free.nrw.commons.di;
import com.google.gson.Gson;
+import fr.free.nrw.commons.actions.PageEditClient;
import fr.free.nrw.commons.explore.categories.CategoriesModule;
import fr.free.nrw.commons.navtab.MoreBottomSheetFragment;
import fr.free.nrw.commons.navtab.MoreBottomSheetLoggedOutFragment;
+import fr.free.nrw.commons.nearby.NearbyController;
import fr.free.nrw.commons.upload.worker.UploadWorker;
import javax.inject.Singleton;
@@ -68,6 +70,9 @@ public interface CommonsApplicationComponent extends AndroidInjector"
+ "\n";
- List placeBindings = runQuery(leftLatLng,rightLatLng);
+ List placeBindings = runQuery(leftLatLng, rightLatLng);
if (placeBindings != null) {
for (PlaceBindings item : placeBindings) {
if (item.getItem() != null && item.getLabel() != null && item.getClas() != null) {
diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/BottomSheetAdapter.kt b/app/src/main/java/fr/free/nrw/commons/nearby/BottomSheetAdapter.kt
new file mode 100644
index 000000000..ca21f25ad
--- /dev/null
+++ b/app/src/main/java/fr/free/nrw/commons/nearby/BottomSheetAdapter.kt
@@ -0,0 +1,108 @@
+package fr.free.nrw.commons.nearby
+
+import android.content.Context
+import android.view.LayoutInflater
+import android.view.View
+import android.view.View.OnLongClickListener
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.TextView
+import androidx.annotation.NonNull
+import androidx.core.content.ContextCompat
+import androidx.recyclerview.widget.RecyclerView
+import fr.free.nrw.commons.R
+import fr.free.nrw.commons.nearby.model.BottomSheetItem
+
+/**
+ * RecyclerView Adapter for displaying items in a bottom sheet.
+ *
+ * @property context The context used for inflating layout resources.
+ * @property itemList The list of BottomSheetItem objects to display.
+ * @constructor Creates an instance of BottomSheetAdapter.
+ */
+class BottomSheetAdapter(context: Context?, private val itemList: List) :
+ RecyclerView.Adapter() {
+ private val layoutInflater: LayoutInflater = LayoutInflater.from(context)
+ private var itemClickListener: ItemClickListener? = null
+
+ @NonNull
+ override fun onCreateViewHolder(@NonNull parent: ViewGroup, viewType: Int): ViewHolder {
+ val view: View = layoutInflater.inflate(R.layout.bottom_sheet_item_layout, parent, false)
+ return ViewHolder(view)
+ }
+
+ override fun onBindViewHolder(@NonNull holder: ViewHolder, position: Int) {
+ val item = itemList[position]
+ holder.imageView.setImageDrawable(
+ ContextCompat.getDrawable(
+ getContext(),
+ item.imageResourceId
+ )
+ )
+ holder.title.setText(item.title)
+ }
+
+ /**
+ * Returns the total number of items in the data set held by the adapter.
+ *
+ * @return The total number of items in this adapter.
+ */
+ override fun getItemCount(): Int {
+ return itemList.size
+ }
+
+ /**
+ * Updates the icon for bookmark item.
+ *
+ * @param icon The resource ID of the new icon to set.
+ */
+ fun updateBookmarkIcon(icon: Int) {
+ itemList.forEachIndexed { index, item ->
+ if (item.imageResourceId == R.drawable.ic_round_star_filled_24px || item.imageResourceId == R.drawable.ic_round_star_border_24px) {
+ item.imageResourceId = icon
+ this.notifyItemChanged(index)
+ return
+ }
+ }
+ }
+
+ inner class ViewHolder internal constructor(itemView: View) : RecyclerView.ViewHolder(itemView),
+ View.OnClickListener, OnLongClickListener {
+ var imageView: ImageView = itemView.findViewById(R.id.buttonImage)
+ var title: TextView = itemView.findViewById(R.id.buttonText)
+
+ init {
+ itemView.setOnClickListener(this)
+ itemView.setOnLongClickListener(this)
+ }
+
+ override fun onClick(view: View) {
+ if (itemClickListener != null) itemClickListener!!.onBottomSheetItemClick(
+ view,
+ adapterPosition
+ )
+ }
+
+ override fun onLongClick(view: View): Boolean {
+ if (itemClickListener != null) itemClickListener!!.onBottomSheetItemLongClick(
+ view,
+ adapterPosition
+ )
+ return true
+ }
+ }
+
+ fun setClickListener(itemClickListener: ItemClickListener?) {
+ this.itemClickListener = itemClickListener
+ }
+
+ fun getContext(): Context {
+ return layoutInflater.context
+ }
+
+ interface ItemClickListener {
+ fun onBottomSheetItemClick(view: View?, position: Int)
+ fun onBottomSheetItemLongClick(view: View?, position: Int)
+ }
+}
+
diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/PageEditHelper.java b/app/src/main/java/fr/free/nrw/commons/nearby/PageEditHelper.java
new file mode 100644
index 000000000..9d4b1069c
--- /dev/null
+++ b/app/src/main/java/fr/free/nrw/commons/nearby/PageEditHelper.java
@@ -0,0 +1,164 @@
+package fr.free.nrw.commons.nearby;
+
+
+import static fr.free.nrw.commons.notification.NotificationHelper.NOTIFICATION_DELETE;
+
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.net.Uri;
+import androidx.appcompat.app.AlertDialog;
+import fr.free.nrw.commons.BuildConfig;
+import fr.free.nrw.commons.R;
+import fr.free.nrw.commons.actions.PageEditClient;
+import fr.free.nrw.commons.auth.csrf.InvalidLoginTokenException;
+import fr.free.nrw.commons.notification.NotificationHelper;
+import fr.free.nrw.commons.utils.ViewUtilWrapper;
+import io.reactivex.Observable;
+import io.reactivex.Single;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+import timber.log.Timber;
+
+/**
+ * Singleton class for making edits to wiki pages asynchronously using RxJava.
+ *
+ * @property notificationHelper A helper class for displaying notifications.
+ * @property pageEditClient A client for making page edit requests.
+ * @property viewUtil A utility class for common view operations.
+ * @property username The username used for page edits.
+ * @constructor Initializes the PageEditHelper with required dependencies.
+ */
+@Singleton
+public class PageEditHelper {
+
+ private final NotificationHelper notificationHelper;
+ private final PageEditClient pageEditClient;
+ private final ViewUtilWrapper viewUtil;
+ private final String username;
+ private AlertDialog d;
+ private DialogInterface.OnMultiChoiceClickListener listener;
+
+ @Inject
+ public PageEditHelper(NotificationHelper notificationHelper,
+ @Named("wikidata-page-edit") PageEditClient pageEditClient,
+ ViewUtilWrapper viewUtil,
+ @Named("username") String username) {
+ this.notificationHelper = notificationHelper;
+ this.pageEditClient = pageEditClient;
+ this.viewUtil = viewUtil;
+ this.username = username;
+ }
+
+ /**
+ * Public interface to make a page edit request asynchronously.
+ *
+ * @param context The context for displaying messages.
+ * @param title The title of the page to edit.
+ * @param preText The existing content of the page.
+ * @param description The description of the issue to be fixed.
+ * @param details Additional details about the issue.
+ * @param lat The latitude of the location related to the page.
+ * @param lng The longitude of the location related to the page.
+ * @return A Single emitting true if the edit was successful, false otherwise.
+ */
+ public Single makePageEdit(Context context, String title, String preText,
+ String description,
+ String details, Double lat, Double lng) {
+ viewUtil.showShortToast(context, "Trying to edit " + title);
+
+ return editPage(title, preText, description, details, lat, lng)
+ .flatMapSingle(result -> Single.just(showNotification(context, title, result)))
+ .firstOrError()
+ .onErrorResumeNext(throwable -> {
+ if (throwable instanceof InvalidLoginTokenException) {
+ return Single.error(throwable);
+ }
+ return Single.error(throwable);
+ });
+ }
+
+ /**
+ * Creates the text content for the page edit based on provided parameters.
+ *
+ * @param title The title of the page to edit.
+ * @param preText The existing content of the page.
+ * @param description The description of the issue to be fixed.
+ * @param details Additional details about the issue.
+ * @param lat The latitude of the location related to the page.
+ * @param lng The longitude of the location related to the page.
+ * @return An Observable emitting true if the edit was successful, false otherwise.
+ */
+ private Observable editPage(String title, String preText, String description,
+ String details, Double lat, Double lng) {
+ Timber.d("thread is edit %s", Thread.currentThread().getName());
+ String summary = "Please fix this item";
+ String text = "";
+ String marker = "Please anyone fix the item accordingly, then reply to mark this section as fixed. Thanks a lot for your cooperation!";
+ int markerIndex = preText.indexOf(marker);
+ if (preText == "" || markerIndex == -1) {
+ text = "==Please fix this item==\n"
+ + "Someone using the [[Commons:Mobile_app|Commons Android app]] went to this item's geographical location ("
+ + lat + "," + lng
+ + ") and noted the following problem(s):\n"
+ + "* " + description + "\n"
+ + "\n"
+ + "Details: " + details + "\n"
+ + "\n"
+ + "Please anyone fix the item accordingly, then reply to mark this section as fixed. Thanks a lot for your cooperation!\n"
+ + "\n"
+ + "~~~~";
+ } else {
+ text = preText.substring(0, markerIndex);
+ text = text + "* " + description + "\n"
+ + "\n"
+ + "Details: " + details + "\n"
+ + "\n"
+ + "Please anyone fix the item accordingly, then reply to mark this section as fixed. Thanks a lot for your cooperation!\n"
+ + "\n"
+ + "~~~~";
+ }
+
+ return pageEditClient.postCreate(title, text, summary);
+ }
+
+ /**
+ * Displays a notification based on the result of the page edit.
+ *
+ * @param context The context for displaying the notification.
+ * @param title The title of the page edited.
+ * @param result The result of the edit operation.
+ * @return true if the edit was successful, false otherwise.
+ */
+ private boolean showNotification(Context context, String title, boolean result) {
+ String message;
+
+ if (result) {
+ message = title + " Edited Successfully";
+ } else {
+ message = context.getString(R.string.delete_helper_show_deletion_message_else);
+ }
+
+ String url = BuildConfig.WIKIDATA_URL + "/wiki/" + title;
+ Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
+ notificationHelper.showNotification(context, title, message, NOTIFICATION_DELETE,
+ browserIntent);
+ return result;
+ }
+
+ /**
+ * returns the instance of shown AlertDialog, used for taking reference during unit test
+ */
+ public AlertDialog getDialog() {
+ return d;
+ }
+
+ /**
+ * returns the instance of shown DialogInterface.OnMultiChoiceClickListener, used for taking
+ * reference during unit test
+ */
+ public DialogInterface.OnMultiChoiceClickListener getListener() {
+ return listener;
+ }
+}
diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/WikidataFeedback.kt b/app/src/main/java/fr/free/nrw/commons/nearby/WikidataFeedback.kt
new file mode 100644
index 000000000..7c62b3646
--- /dev/null
+++ b/app/src/main/java/fr/free/nrw/commons/nearby/WikidataFeedback.kt
@@ -0,0 +1,96 @@
+package fr.free.nrw.commons.nearby
+
+import android.annotation.SuppressLint
+import android.os.Bundle
+import android.widget.RadioButton
+import android.widget.Toast
+import fr.free.nrw.commons.R
+import fr.free.nrw.commons.databinding.ActivityWikidataFeedbackBinding
+import fr.free.nrw.commons.theme.BaseActivity
+import io.reactivex.Single
+import io.reactivex.SingleSource
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.schedulers.Schedulers
+import timber.log.Timber
+import java.util.concurrent.Callable
+import javax.inject.Inject
+
+/**
+ * Activity for providing feedback about Wikidata items.
+ */
+class WikidataFeedback : BaseActivity() {
+ private lateinit var binding: ActivityWikidataFeedbackBinding
+ var place: String = ""
+ var wikidataQId: String = ""
+ var pageTitle: String = ""
+ var preText: String = ""
+ var lat: Double = 0.0
+ var lng: Double = 0.0
+
+ @Inject
+ lateinit var pageEditHelper: PageEditHelper
+
+ @Inject
+ lateinit var nearbyController: NearbyController
+
+ @SuppressLint("CheckResult")
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = ActivityWikidataFeedbackBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+ lat = intent.getDoubleExtra("lat", 0.0)
+ lng = intent.getDoubleExtra("lng", 0.0)
+ place = intent.getStringExtra("place") ?: ""
+ wikidataQId = intent.getStringExtra("qid") ?: ""
+ pageTitle = getString(R.string.talk) + ":" + wikidataQId
+ binding.toolbarBinding.toolbar.title = pageTitle
+ binding.textHeader.text =
+ getString(R.string.write_something_about_the) + "'$place'" + getString(R.string.item_it_will_be_publicly_visible)
+ binding.radioButton1.setText(
+ getString(
+ R.string.does_not_exist_anymore_no_picture_can_ever_be_taken_of_it,
+ place
+ ))
+ binding.radioButton2.setText(
+ getString(
+ R.string.is_at_a_different_place_please_specify_the_correct_place_below_if_possible_tell_us_the_correct_latitude_longitude,
+ place
+ ))
+ binding.radioButton3.setText(getString(R.string.other_problem_or_information_please_explain_below))
+ setSupportActionBar(binding.toolbarBinding.toolbar)
+ supportActionBar!!.setDisplayHomeAsUpEnabled(true)
+
+ binding.appCompatButton.setOnClickListener {
+ var desc = findViewById(binding.radioGroup.checkedRadioButtonId).text
+ var det = binding.detailsEditText.text.toString()
+ if (binding.radioGroup.checkedRadioButtonId == R.id.radioButton3 && binding.detailsEditText.text.isNullOrEmpty()) {
+ Toast.makeText(
+ this,
+ getString(R.string.please_enter_some_comments), Toast.LENGTH_SHORT
+ ).show()
+ } else {
+ binding.radioGroup.clearCheck()
+ binding.detailsEditText.setText("")
+ Single.defer(Callable> {
+ pageEditHelper.makePageEdit(
+ this, pageTitle, preText,
+ desc.toString(),
+ det, lat, lng
+ )
+ } as Callable>)
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe({ aBoolean: Boolean? ->
+ }, { throwable: Throwable? ->
+ Timber.e(throwable!!)
+ })
+ }
+ }
+ }
+
+ override fun onSupportNavigateUp(): Boolean {
+ onBackPressed()
+ return true
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/fragments/NearbyParentFragment.java b/app/src/main/java/fr/free/nrw/commons/nearby/fragments/NearbyParentFragment.java
index 877f22f5a..d1e28eb7e 100644
--- a/app/src/main/java/fr/free/nrw/commons/nearby/fragments/NearbyParentFragment.java
+++ b/app/src/main/java/fr/free/nrw/commons/nearby/fragments/NearbyParentFragment.java
@@ -48,6 +48,7 @@ import androidx.appcompat.app.AlertDialog;
import androidx.core.content.ContextCompat;
import androidx.core.content.FileProvider;
import androidx.recyclerview.widget.DividerItemDecoration;
+import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.snackbar.Snackbar;
@@ -70,6 +71,7 @@ import fr.free.nrw.commons.location.LocationPermissionsHelper;
import fr.free.nrw.commons.location.LocationPermissionsHelper.LocationPermissionCallback;
import fr.free.nrw.commons.location.LocationServiceManager;
import fr.free.nrw.commons.location.LocationUpdateListener;
+import fr.free.nrw.commons.nearby.BottomSheetAdapter;
import fr.free.nrw.commons.nearby.CheckBoxTriStates;
import fr.free.nrw.commons.nearby.Label;
import fr.free.nrw.commons.nearby.MarkerPlaceGroup;
@@ -77,8 +79,10 @@ import fr.free.nrw.commons.nearby.NearbyController;
import fr.free.nrw.commons.nearby.NearbyFilterSearchRecyclerViewAdapter;
import fr.free.nrw.commons.nearby.NearbyFilterState;
import fr.free.nrw.commons.nearby.Place;
+import fr.free.nrw.commons.nearby.WikidataFeedback;
import fr.free.nrw.commons.nearby.contract.NearbyParentFragmentContract;
import fr.free.nrw.commons.nearby.fragments.AdvanceQueryFragment.Callback;
+import fr.free.nrw.commons.nearby.model.BottomSheetItem;
import fr.free.nrw.commons.nearby.presenter.NearbyParentFragmentPresenter;
import fr.free.nrw.commons.upload.FileUtils;
import fr.free.nrw.commons.utils.DialogUtil;
@@ -131,7 +135,7 @@ import timber.log.Timber;
public class NearbyParentFragment extends CommonsDaggerSupportFragment
implements NearbyParentFragmentContract.View,
WikidataEditListener.WikidataP18EditListener, LocationUpdateListener,
- LocationPermissionCallback {
+ LocationPermissionCallback, BottomSheetAdapter.ItemClickListener {
FragmentNearbyParentBinding binding;
@@ -189,6 +193,9 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
private NearbyParentFragmentInstanceReadyCallback nearbyParentFragmentInstanceReadyCallback;
private boolean isAdvancedQueryFragmentVisible = false;
private Place nearestPlace;
+ private GridLayoutManager gridLayoutManager;
+ private List dataList;
+ private BottomSheetAdapter bottomSheetAdapter;
private ActivityResultLauncher inAppCameraLocationPermissionLauncher = registerForActivityResult(
new ActivityResultContracts.RequestMultiplePermissions(),
new ActivityResultCallback
Please remember that all images in a multi-upload get the same categories and depictions. If the images do not share depictions and categories, please perform several separate uploads.
Note about multi-uploads
+ Report a problem about this item to Wikidata
+ Please enter some comments
+ Talk
+ "Write something about the "
+ " item. It will be publicly visible."
+ \'%1$s\' does not exist anymore, no picture can ever be taken of it.
+ \'%1$s\' is at a different place (please specify the correct place below, if possible tell us the correct latitude/longitude).
+ Other problem or information (please explain below).
Your feedback gets posted to the following wiki page: Commons:Mobile app/Feedback ]]>