mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-27 04:43:54 +01:00
Merge branch 'main' into issue5583
This commit is contained in:
commit
45681f7a41
22 changed files with 968 additions and 348 deletions
|
|
@ -4,6 +4,7 @@ import fr.free.nrw.commons.auth.csrf.InvalidLoginTokenException
|
||||||
import io.reactivex.Observable
|
import io.reactivex.Observable
|
||||||
import io.reactivex.Single
|
import io.reactivex.Single
|
||||||
import fr.free.nrw.commons.auth.csrf.CsrfTokenClient
|
import fr.free.nrw.commons.auth.csrf.CsrfTokenClient
|
||||||
|
import timber.log.Timber
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class acts as a Client to facilitate wiki page editing
|
* 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<Boolean> {
|
fun edit(pageTitle: String, text: String, summary: String): Observable<Boolean> {
|
||||||
return try {
|
return try {
|
||||||
pageEditInterface.postEdit(pageTitle, summary, text, csrfTokenClient.getTokenBlocking())
|
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<Boolean> {
|
||||||
|
return try {
|
||||||
|
pageEditInterface.postCreate(
|
||||||
|
pageTitle,
|
||||||
|
summary,
|
||||||
|
text,
|
||||||
|
"text/x-wiki",
|
||||||
|
"wikitext",
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
csrfTokenClient.getTokenBlocking()
|
||||||
|
).map { editResponse ->
|
||||||
|
editResponse.edit()!!.editSucceeded()
|
||||||
|
}
|
||||||
} catch (throwable: Throwable) {
|
} catch (throwable: Throwable) {
|
||||||
if (throwable is InvalidLoginTokenException) {
|
if (throwable is InvalidLoginTokenException) {
|
||||||
throw throwable
|
throw throwable
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,33 @@ interface PageEditInterface {
|
||||||
@Field("token") token: String
|
@Field("token") token: String
|
||||||
): Observable<Edit>
|
): Observable<Edit>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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<Edit>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method posts such that the Content which the page
|
* This method posts such that the Content which the page
|
||||||
* has will be appended with the value being passed to the
|
* has will be appended with the value being passed to the
|
||||||
|
|
|
||||||
|
|
@ -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.depictions.WikidataItemDetailsActivity;
|
||||||
import fr.free.nrw.commons.explore.SearchActivity;
|
import fr.free.nrw.commons.explore.SearchActivity;
|
||||||
import fr.free.nrw.commons.media.ZoomableActivity;
|
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.notification.NotificationActivity;
|
||||||
import fr.free.nrw.commons.profile.ProfileActivity;
|
import fr.free.nrw.commons.profile.ProfileActivity;
|
||||||
import fr.free.nrw.commons.review.ReviewActivity;
|
import fr.free.nrw.commons.review.ReviewActivity;
|
||||||
|
|
@ -83,4 +84,5 @@ public abstract class ActivityBuilderModule {
|
||||||
|
|
||||||
@ContributesAndroidInjector
|
@ContributesAndroidInjector
|
||||||
abstract UploadProgressActivity bindUploadProgressActivity();
|
abstract UploadProgressActivity bindUploadProgressActivity();
|
||||||
|
abstract WikidataFeedback bindWikiFeedback();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,11 @@ package fr.free.nrw.commons.di;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
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.explore.categories.CategoriesModule;
|
||||||
import fr.free.nrw.commons.navtab.MoreBottomSheetFragment;
|
import fr.free.nrw.commons.navtab.MoreBottomSheetFragment;
|
||||||
import fr.free.nrw.commons.navtab.MoreBottomSheetLoggedOutFragment;
|
import fr.free.nrw.commons.navtab.MoreBottomSheetLoggedOutFragment;
|
||||||
|
import fr.free.nrw.commons.nearby.NearbyController;
|
||||||
import fr.free.nrw.commons.upload.worker.UploadWorker;
|
import fr.free.nrw.commons.upload.worker.UploadWorker;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
|
@ -68,6 +70,9 @@ public interface CommonsApplicationComponent extends AndroidInjector<Application
|
||||||
|
|
||||||
void inject(PicOfDayAppWidget picOfDayAppWidget);
|
void inject(PicOfDayAppWidget picOfDayAppWidget);
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
void inject(NearbyController nearbyController);
|
||||||
|
|
||||||
Gson gson();
|
Gson gson();
|
||||||
|
|
||||||
@Component.Builder
|
@Component.Builder
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,7 @@ public class NetworkingModule {
|
||||||
public static final String NAMED_LANGUAGE_WIKI_PEDIA_WIKI_SITE = "language-wikipedia-wikisite";
|
public static final String NAMED_LANGUAGE_WIKI_PEDIA_WIKI_SITE = "language-wikipedia-wikisite";
|
||||||
|
|
||||||
public static final String NAMED_COMMONS_CSRF = "commons-csrf";
|
public static final String NAMED_COMMONS_CSRF = "commons-csrf";
|
||||||
|
public static final String NAMED_WIKI_CSRF = "wiki-csrf";
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
|
|
@ -128,10 +129,41 @@ public class NetworkingModule {
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
public CsrfTokenClient provideCommonsCsrfTokenClient(SessionManager sessionManager,
|
public CsrfTokenClient provideCommonsCsrfTokenClient(SessionManager sessionManager,
|
||||||
CsrfTokenInterface tokenInterface, LoginClient loginClient, LogoutClient logoutClient) {
|
@Named("commons-csrf-interface") CsrfTokenInterface tokenInterface, LoginClient loginClient, LogoutClient logoutClient) {
|
||||||
return new CsrfTokenClient(sessionManager, tokenInterface, loginClient, logoutClient);
|
return new CsrfTokenClient(sessionManager, tokenInterface, loginClient, logoutClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a singleton instance of CsrfTokenClient for Wikidata.
|
||||||
|
*
|
||||||
|
* @param sessionManager The session manager to manage user sessions.
|
||||||
|
* @param tokenInterface The interface for obtaining CSRF tokens.
|
||||||
|
* @param loginClient The client for handling login operations.
|
||||||
|
* @param logoutClient The client for handling logout operations.
|
||||||
|
* @return A singleton instance of CsrfTokenClient.
|
||||||
|
*/
|
||||||
|
@Named(NAMED_WIKI_CSRF)
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
public CsrfTokenClient provideWikiCsrfTokenClient(SessionManager sessionManager,
|
||||||
|
@Named("wikidata-csrf-interface") CsrfTokenInterface tokenInterface, LoginClient loginClient, LogoutClient logoutClient) {
|
||||||
|
return new CsrfTokenClient(sessionManager, tokenInterface, loginClient, logoutClient);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a singleton instance of CsrfTokenInterface for Wikidata.
|
||||||
|
*
|
||||||
|
* @param serviceFactory The factory used to create service interfaces.
|
||||||
|
* @return A singleton instance of CsrfTokenInterface for Wikidata.
|
||||||
|
*/
|
||||||
|
@Named("wikidata-csrf-interface")
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
public CsrfTokenInterface provideWikidataCsrfTokenInterface(CommonsServiceFactory serviceFactory) {
|
||||||
|
return serviceFactory.create(BuildConfig.WIKIDATA_URL, CsrfTokenInterface.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Named("commons-csrf-interface")
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
public CsrfTokenInterface provideCsrfTokenInterface(CommonsServiceFactory serviceFactory) {
|
public CsrfTokenInterface provideCsrfTokenInterface(CommonsServiceFactory serviceFactory) {
|
||||||
|
|
@ -230,6 +262,21 @@ public class NetworkingModule {
|
||||||
return new PageEditClient(csrfTokenClient, pageEditInterface);
|
return new PageEditClient(csrfTokenClient, pageEditInterface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a singleton instance of PageEditClient for Wikidata.
|
||||||
|
*
|
||||||
|
* @param csrfTokenClient The client used to manage CSRF tokens.
|
||||||
|
* @param pageEditInterface The interface for page edit operations.
|
||||||
|
* @return A singleton instance of PageEditClient for Wikidata.
|
||||||
|
*/
|
||||||
|
@Named("wikidata-page-edit")
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
public PageEditClient provideWikidataPageEditClient(@Named(NAMED_WIKI_CSRF) CsrfTokenClient csrfTokenClient,
|
||||||
|
@Named("wikidata-page-edit-service") PageEditInterface pageEditInterface) {
|
||||||
|
return new PageEditClient(csrfTokenClient, pageEditInterface);
|
||||||
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
public MediaInterface provideMediaInterface(CommonsServiceFactory serviceFactory) {
|
public MediaInterface provideMediaInterface(CommonsServiceFactory serviceFactory) {
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,10 @@ import fr.free.nrw.commons.campaigns.CampaignResponseDTO;
|
||||||
import fr.free.nrw.commons.explore.depictions.DepictsClient;
|
import fr.free.nrw.commons.explore.depictions.DepictsClient;
|
||||||
import fr.free.nrw.commons.location.LatLng;
|
import fr.free.nrw.commons.location.LatLng;
|
||||||
import fr.free.nrw.commons.nearby.Place;
|
import fr.free.nrw.commons.nearby.Place;
|
||||||
import fr.free.nrw.commons.nearby.model.PlaceBindings;
|
|
||||||
import fr.free.nrw.commons.nearby.model.ItemsClass;
|
import fr.free.nrw.commons.nearby.model.ItemsClass;
|
||||||
import fr.free.nrw.commons.nearby.model.NearbyResponse;
|
import fr.free.nrw.commons.nearby.model.NearbyResponse;
|
||||||
import fr.free.nrw.commons.nearby.model.NearbyResultItem;
|
import fr.free.nrw.commons.nearby.model.NearbyResultItem;
|
||||||
|
import fr.free.nrw.commons.nearby.model.PlaceBindings;
|
||||||
import fr.free.nrw.commons.profile.achievements.FeaturedImages;
|
import fr.free.nrw.commons.profile.achievements.FeaturedImages;
|
||||||
import fr.free.nrw.commons.profile.achievements.FeedbackResponse;
|
import fr.free.nrw.commons.profile.achievements.FeedbackResponse;
|
||||||
import fr.free.nrw.commons.profile.leaderboard.LeaderboardResponse;
|
import fr.free.nrw.commons.profile.leaderboard.LeaderboardResponse;
|
||||||
|
|
@ -476,7 +476,7 @@ public class OkHttpJsonApiClient {
|
||||||
" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd\">"
|
" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd\">"
|
||||||
+ "\n<bounds minlat=\"$MIN_LATITUDE\" minlon=\"$MIN_LONGITUDE\" maxlat=\"$MAX_LATITUDE\" maxlon=\"$MAX_LONGITUDE\"/>";
|
+ "\n<bounds minlat=\"$MIN_LATITUDE\" minlon=\"$MIN_LONGITUDE\" maxlat=\"$MAX_LATITUDE\" maxlon=\"$MAX_LONGITUDE\"/>";
|
||||||
|
|
||||||
List<PlaceBindings> placeBindings = runQuery(leftLatLng,rightLatLng);
|
List<PlaceBindings> placeBindings = runQuery(leftLatLng, rightLatLng);
|
||||||
if (placeBindings != null) {
|
if (placeBindings != null) {
|
||||||
for (PlaceBindings item : placeBindings) {
|
for (PlaceBindings item : placeBindings) {
|
||||||
if (item.getItem() != null && item.getLabel() != null && item.getClas() != null) {
|
if (item.getItem() != null && item.getLabel() != null && item.getClas() != null) {
|
||||||
|
|
|
||||||
|
|
@ -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<BottomSheetItem>) :
|
||||||
|
RecyclerView.Adapter<BottomSheetAdapter.ViewHolder>() {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
164
app/src/main/java/fr/free/nrw/commons/nearby/PageEditHelper.java
Normal file
164
app/src/main/java/fr/free/nrw/commons/nearby/PageEditHelper.java
Normal file
|
|
@ -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<Boolean> 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<Boolean> 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"
|
||||||
|
+ "* <i><nowiki>" + description + "</nowiki></i>\n"
|
||||||
|
+ "\n"
|
||||||
|
+ "Details: <i><nowiki>" + details + "</nowiki></i>\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 + "* <i><nowiki>" + description + "</nowiki></i>\n"
|
||||||
|
+ "\n"
|
||||||
|
+ "Details: <i><nowiki>" + details + "</nowiki></i>\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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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<RadioButton>(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<Boolean?>(Callable<SingleSource<Boolean?>> {
|
||||||
|
pageEditHelper.makePageEdit(
|
||||||
|
this, pageTitle, preText,
|
||||||
|
desc.toString(),
|
||||||
|
det, lat, lng
|
||||||
|
)
|
||||||
|
} as Callable<SingleSource<Boolean?>>)
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe({ aBoolean: Boolean? ->
|
||||||
|
}, { throwable: Throwable? ->
|
||||||
|
Timber.e(throwable!!)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSupportNavigateUp(): Boolean {
|
||||||
|
onBackPressed()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -48,6 +48,7 @@ import androidx.appcompat.app.AlertDialog;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.core.content.FileProvider;
|
import androidx.core.content.FileProvider;
|
||||||
import androidx.recyclerview.widget.DividerItemDecoration;
|
import androidx.recyclerview.widget.DividerItemDecoration;
|
||||||
|
import androidx.recyclerview.widget.GridLayoutManager;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import com.google.android.material.bottomsheet.BottomSheetBehavior;
|
import com.google.android.material.bottomsheet.BottomSheetBehavior;
|
||||||
import com.google.android.material.snackbar.Snackbar;
|
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.LocationPermissionsHelper.LocationPermissionCallback;
|
||||||
import fr.free.nrw.commons.location.LocationServiceManager;
|
import fr.free.nrw.commons.location.LocationServiceManager;
|
||||||
import fr.free.nrw.commons.location.LocationUpdateListener;
|
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.CheckBoxTriStates;
|
||||||
import fr.free.nrw.commons.nearby.Label;
|
import fr.free.nrw.commons.nearby.Label;
|
||||||
import fr.free.nrw.commons.nearby.MarkerPlaceGroup;
|
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.NearbyFilterSearchRecyclerViewAdapter;
|
||||||
import fr.free.nrw.commons.nearby.NearbyFilterState;
|
import fr.free.nrw.commons.nearby.NearbyFilterState;
|
||||||
import fr.free.nrw.commons.nearby.Place;
|
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.contract.NearbyParentFragmentContract;
|
||||||
import fr.free.nrw.commons.nearby.fragments.AdvanceQueryFragment.Callback;
|
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.nearby.presenter.NearbyParentFragmentPresenter;
|
||||||
import fr.free.nrw.commons.upload.FileUtils;
|
import fr.free.nrw.commons.upload.FileUtils;
|
||||||
import fr.free.nrw.commons.utils.DialogUtil;
|
import fr.free.nrw.commons.utils.DialogUtil;
|
||||||
|
|
@ -131,7 +135,7 @@ import timber.log.Timber;
|
||||||
public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
||||||
implements NearbyParentFragmentContract.View,
|
implements NearbyParentFragmentContract.View,
|
||||||
WikidataEditListener.WikidataP18EditListener, LocationUpdateListener,
|
WikidataEditListener.WikidataP18EditListener, LocationUpdateListener,
|
||||||
LocationPermissionCallback {
|
LocationPermissionCallback, BottomSheetAdapter.ItemClickListener {
|
||||||
|
|
||||||
|
|
||||||
FragmentNearbyParentBinding binding;
|
FragmentNearbyParentBinding binding;
|
||||||
|
|
@ -189,6 +193,9 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
||||||
private NearbyParentFragmentInstanceReadyCallback nearbyParentFragmentInstanceReadyCallback;
|
private NearbyParentFragmentInstanceReadyCallback nearbyParentFragmentInstanceReadyCallback;
|
||||||
private boolean isAdvancedQueryFragmentVisible = false;
|
private boolean isAdvancedQueryFragmentVisible = false;
|
||||||
private Place nearestPlace;
|
private Place nearestPlace;
|
||||||
|
private GridLayoutManager gridLayoutManager;
|
||||||
|
private List<BottomSheetItem> dataList;
|
||||||
|
private BottomSheetAdapter bottomSheetAdapter;
|
||||||
private ActivityResultLauncher<String[]> inAppCameraLocationPermissionLauncher = registerForActivityResult(
|
private ActivityResultLauncher<String[]> inAppCameraLocationPermissionLauncher = registerForActivityResult(
|
||||||
new ActivityResultContracts.RequestMultiplePermissions(),
|
new ActivityResultContracts.RequestMultiplePermissions(),
|
||||||
new ActivityResultCallback<Map<String, Boolean>>() {
|
new ActivityResultCallback<Map<String, Boolean>>() {
|
||||||
|
|
@ -203,7 +210,8 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
||||||
controller.locationPermissionCallback.onLocationPermissionGranted();
|
controller.locationPermissionCallback.onLocationPermissionGranted();
|
||||||
} else {
|
} else {
|
||||||
if (shouldShowRequestPermissionRationale(permission.ACCESS_FINE_LOCATION)) {
|
if (shouldShowRequestPermissionRationale(permission.ACCESS_FINE_LOCATION)) {
|
||||||
controller.handleShowRationaleFlowCameraLocation(getActivity(), inAppCameraLocationPermissionLauncher);
|
controller.handleShowRationaleFlowCameraLocation(getActivity(),
|
||||||
|
inAppCameraLocationPermissionLauncher);
|
||||||
} else {
|
} else {
|
||||||
controller.locationPermissionCallback.onLocationPermissionDenied(
|
controller.locationPermissionCallback.onLocationPermissionDenied(
|
||||||
getActivity().getString(
|
getActivity().getString(
|
||||||
|
|
@ -434,10 +442,10 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
||||||
moveCameraToPosition(lastMapFocus);
|
moveCameraToPosition(lastMapFocus);
|
||||||
initRvNearbyList();
|
initRvNearbyList();
|
||||||
onResume();
|
onResume();
|
||||||
binding.tvAttribution.setText(Html.fromHtml(getString(R.string.map_attribution)));
|
binding.tvAttribution.setText(Html.fromHtml(getString(R.string.map_attribution)));
|
||||||
binding.tvAttribution.setMovementMethod(LinkMovementMethod.getInstance());
|
binding.tvAttribution.setMovementMethod(LinkMovementMethod.getInstance());
|
||||||
binding.nearbyFilterList.btnAdvancedOptions.setOnClickListener(v -> {
|
binding.nearbyFilterList.btnAdvancedOptions.setOnClickListener(v -> {
|
||||||
binding.nearbyFilter.searchViewLayout.searchView.clearFocus();
|
binding.nearbyFilter.searchViewLayout.searchView.clearFocus();
|
||||||
showHideAdvancedQueryFragment(true);
|
showHideAdvancedQueryFragment(true);
|
||||||
final AdvanceQueryFragment fragment = new AdvanceQueryFragment();
|
final AdvanceQueryFragment fragment = new AdvanceQueryFragment();
|
||||||
final Bundle bundle = new Bundle();
|
final Bundle bundle = new Bundle();
|
||||||
|
|
@ -473,7 +481,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
||||||
.commit();
|
.commit();
|
||||||
});
|
});
|
||||||
|
|
||||||
binding.tvLearnMore.setOnClickListener(v ->onLearnMoreClicked());
|
binding.tvLearnMore.setOnClickListener(v -> onLearnMoreClicked());
|
||||||
binding.nearbyFilter.ivToggleChips.setOnClickListener(v -> onToggleChipsClicked());
|
binding.nearbyFilter.ivToggleChips.setOnClickListener(v -> onToggleChipsClicked());
|
||||||
|
|
||||||
if (!locationPermissionsHelper.checkLocationPermission(getActivity())) {
|
if (!locationPermissionsHelper.checkLocationPermission(getActivity())) {
|
||||||
|
|
@ -510,7 +518,8 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initRvNearbyList() {
|
private void initRvNearbyList() {
|
||||||
binding.bottomSheetNearby.rvNearbyList.setLayoutManager(new LinearLayoutManager(getContext()));
|
binding.bottomSheetNearby.rvNearbyList.setLayoutManager(
|
||||||
|
new LinearLayoutManager(getContext()));
|
||||||
adapter = new PlaceAdapter(bookmarkLocationDao,
|
adapter = new PlaceAdapter(bookmarkLocationDao,
|
||||||
place -> {
|
place -> {
|
||||||
moveCameraToPosition(
|
moveCameraToPosition(
|
||||||
|
|
@ -566,7 +575,8 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
||||||
locationManager.requestLocationUpdatesFromProvider(LocationManager.GPS_PROVIDER);
|
locationManager.requestLocationUpdatesFromProvider(LocationManager.GPS_PROVIDER);
|
||||||
setProgressBarVisibility(true);
|
setProgressBarVisibility(true);
|
||||||
} else {
|
} else {
|
||||||
locationPermissionsHelper.showLocationOffDialog(getActivity(), R.string.ask_to_turn_location_on_text);
|
locationPermissionsHelper.showLocationOffDialog(getActivity(),
|
||||||
|
R.string.ask_to_turn_location_on_text);
|
||||||
}
|
}
|
||||||
presenter.onMapReady();
|
presenter.onMapReady();
|
||||||
registerUnregisterLocationListener(false);
|
registerUnregisterLocationListener(false);
|
||||||
|
|
@ -591,7 +601,6 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
||||||
* Starts the map without GPS and without permission By default it points to 51.50550,-0.07520
|
* Starts the map without GPS and without permission By default it points to 51.50550,-0.07520
|
||||||
* coordinates, other than that it points to the last known location which can be get by the key
|
* coordinates, other than that it points to the last known location which can be get by the key
|
||||||
* "LastLocation" from applicationKvStore
|
* "LastLocation" from applicationKvStore
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
private void startMapWithoutPermission() {
|
private void startMapWithoutPermission() {
|
||||||
if (applicationKvStore.getString("LastLocation") != null) {
|
if (applicationKvStore.getString("LastLocation") != null) {
|
||||||
|
|
@ -649,7 +658,6 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
||||||
initBottomSheets();
|
initBottomSheets();
|
||||||
loadAnimations();
|
loadAnimations();
|
||||||
setBottomSheetCallbacks();
|
setBottomSheetCallbacks();
|
||||||
decideButtonVisibilities();
|
|
||||||
addActionToTitle();
|
addActionToTitle();
|
||||||
if (!Utils.isMonumentsEnabled(new Date())) {
|
if (!Utils.isMonumentsEnabled(new Date())) {
|
||||||
NearbyFilterState.setWlmSelected(false);
|
NearbyFilterState.setWlmSelected(false);
|
||||||
|
|
@ -673,26 +681,46 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
||||||
bottomSheetListBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
|
bottomSheetListBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the number of spans (columns) in the RecyclerView based on device orientation
|
||||||
|
* and adapter item count.
|
||||||
|
*
|
||||||
|
* @return The number of spans to be used in the RecyclerView.
|
||||||
|
*/
|
||||||
|
private int getSpanCount() {
|
||||||
|
int orientation = getResources().getConfiguration().orientation;
|
||||||
|
if (bottomSheetAdapter != null) {
|
||||||
|
return (orientation == Configuration.ORIENTATION_PORTRAIT) ? 3
|
||||||
|
: bottomSheetAdapter.getItemCount();
|
||||||
|
} else {
|
||||||
|
return (orientation == Configuration.ORIENTATION_PORTRAIT) ? 3 : 6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void initNearbyFilter() {
|
public void initNearbyFilter() {
|
||||||
binding.nearbyFilterList.getRoot().setVisibility(View.GONE);
|
binding.nearbyFilterList.getRoot().setVisibility(View.GONE);
|
||||||
hideBottomSheet();
|
hideBottomSheet();
|
||||||
binding.nearbyFilter.searchViewLayout.searchView.setOnQueryTextFocusChangeListener((v, hasFocus) -> {
|
binding.nearbyFilter.searchViewLayout.searchView.setOnQueryTextFocusChangeListener(
|
||||||
LayoutUtils.setLayoutHeightAllignedToWidth(1.25, binding.nearbyFilterList.getRoot());
|
(v, hasFocus) -> {
|
||||||
if (hasFocus) {
|
LayoutUtils.setLayoutHeightAllignedToWidth(1.25,
|
||||||
binding.nearbyFilterList.getRoot().setVisibility(View.VISIBLE);
|
binding.nearbyFilterList.getRoot());
|
||||||
presenter.searchViewGainedFocus();
|
if (hasFocus) {
|
||||||
} else {
|
binding.nearbyFilterList.getRoot().setVisibility(View.VISIBLE);
|
||||||
binding.nearbyFilterList.getRoot().setVisibility(View.GONE);
|
presenter.searchViewGainedFocus();
|
||||||
}
|
} else {
|
||||||
});
|
binding.nearbyFilterList.getRoot().setVisibility(View.GONE);
|
||||||
binding.nearbyFilterList.searchListView.setHasFixedSize(true);
|
}
|
||||||
binding.nearbyFilterList.searchListView.addItemDecoration(new DividerItemDecoration(getContext(),
|
});
|
||||||
DividerItemDecoration.VERTICAL));
|
binding.nearbyFilterList.searchListView.setHasFixedSize(true);
|
||||||
|
binding.nearbyFilterList.searchListView.addItemDecoration(
|
||||||
|
new DividerItemDecoration(getContext(),
|
||||||
|
DividerItemDecoration.VERTICAL));
|
||||||
final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
|
final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
|
||||||
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
|
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
|
||||||
binding.nearbyFilterList.searchListView.setLayoutManager(linearLayoutManager);
|
binding.nearbyFilterList.searchListView.setLayoutManager(linearLayoutManager);
|
||||||
nearbyFilterSearchRecyclerViewAdapter = new NearbyFilterSearchRecyclerViewAdapter(
|
nearbyFilterSearchRecyclerViewAdapter = new NearbyFilterSearchRecyclerViewAdapter(
|
||||||
getContext(), new ArrayList<>(Label.valuesAsList()), binding.nearbyFilterList.searchListView);
|
getContext(), new ArrayList<>(Label.valuesAsList()),
|
||||||
|
binding.nearbyFilterList.searchListView);
|
||||||
nearbyFilterSearchRecyclerViewAdapter.setCallback(
|
nearbyFilterSearchRecyclerViewAdapter.setCallback(
|
||||||
new NearbyFilterSearchRecyclerViewAdapter.Callback() {
|
new NearbyFilterSearchRecyclerViewAdapter.Callback() {
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -711,18 +739,20 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
||||||
return isDarkTheme;
|
return isDarkTheme;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
binding.nearbyFilterList.getRoot().getLayoutParams().width = (int) LayoutUtils.getScreenWidth(getActivity(),
|
binding.nearbyFilterList.getRoot()
|
||||||
|
.getLayoutParams().width = (int) LayoutUtils.getScreenWidth(getActivity(),
|
||||||
0.75);
|
0.75);
|
||||||
binding.nearbyFilterList.searchListView.setAdapter(nearbyFilterSearchRecyclerViewAdapter);
|
binding.nearbyFilterList.searchListView.setAdapter(nearbyFilterSearchRecyclerViewAdapter);
|
||||||
LayoutUtils.setLayoutHeightAllignedToWidth(1.25, binding.nearbyFilterList.getRoot());
|
LayoutUtils.setLayoutHeightAllignedToWidth(1.25, binding.nearbyFilterList.getRoot());
|
||||||
compositeDisposable.add(RxSearchView.queryTextChanges( binding.nearbyFilter.searchViewLayout.searchView)
|
compositeDisposable.add(
|
||||||
.takeUntil(RxView.detaches(binding.nearbyFilter.searchViewLayout.searchView))
|
RxSearchView.queryTextChanges(binding.nearbyFilter.searchViewLayout.searchView)
|
||||||
.debounce(500, TimeUnit.MILLISECONDS)
|
.takeUntil(RxView.detaches(binding.nearbyFilter.searchViewLayout.searchView))
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.debounce(500, TimeUnit.MILLISECONDS)
|
||||||
.subscribe(query -> {
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
((NearbyFilterSearchRecyclerViewAdapter) binding.nearbyFilterList.searchListView.getAdapter()).getFilter()
|
.subscribe(query -> {
|
||||||
.filter(query.toString());
|
((NearbyFilterSearchRecyclerViewAdapter) binding.nearbyFilterList.searchListView.getAdapter()).getFilter()
|
||||||
}));
|
.filter(query.toString());
|
||||||
|
}));
|
||||||
initFilterChips();
|
initFilterChips();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -739,9 +769,12 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setFilterState() {
|
public void setFilterState() {
|
||||||
binding.nearbyFilter.chipView.choiceChipNeedsPhoto.setChecked(NearbyFilterState.getInstance().isNeedPhotoSelected());
|
binding.nearbyFilter.chipView.choiceChipNeedsPhoto.setChecked(
|
||||||
binding.nearbyFilter.chipView.choiceChipExists.setChecked(NearbyFilterState.getInstance().isExistsSelected());
|
NearbyFilterState.getInstance().isNeedPhotoSelected());
|
||||||
binding.nearbyFilter.chipView.choiceChipWlm.setChecked(NearbyFilterState.getInstance().isWlmSelected());
|
binding.nearbyFilter.chipView.choiceChipExists.setChecked(
|
||||||
|
NearbyFilterState.getInstance().isExistsSelected());
|
||||||
|
binding.nearbyFilter.chipView.choiceChipWlm.setChecked(
|
||||||
|
NearbyFilterState.getInstance().isWlmSelected());
|
||||||
if (NearbyController.currentLocation != null) {
|
if (NearbyController.currentLocation != null) {
|
||||||
presenter.filterByMarkerType(nearbyFilterSearchRecyclerViewAdapter.selectedLabels,
|
presenter.filterByMarkerType(nearbyFilterSearchRecyclerViewAdapter.selectedLabels,
|
||||||
binding.nearbyFilterList.checkboxTriStates.getState(), true, false);
|
binding.nearbyFilterList.checkboxTriStates.getState(), true, false);
|
||||||
|
|
@ -749,44 +782,53 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initFilterChips() {
|
private void initFilterChips() {
|
||||||
binding.nearbyFilter.chipView.choiceChipNeedsPhoto.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
binding.nearbyFilter.chipView.choiceChipNeedsPhoto.setOnCheckedChangeListener(
|
||||||
if (NearbyController.currentLocation != null) {
|
(buttonView, isChecked) -> {
|
||||||
binding.nearbyFilterList.checkboxTriStates.setState(CheckBoxTriStates.CHECKED);
|
if (NearbyController.currentLocation != null) {
|
||||||
NearbyFilterState.setNeedPhotoSelected(isChecked);
|
binding.nearbyFilterList.checkboxTriStates.setState(CheckBoxTriStates.CHECKED);
|
||||||
presenter.filterByMarkerType(nearbyFilterSearchRecyclerViewAdapter.selectedLabels,
|
NearbyFilterState.setNeedPhotoSelected(isChecked);
|
||||||
binding.nearbyFilterList.checkboxTriStates.getState(), true, true);
|
presenter.filterByMarkerType(
|
||||||
updatePlaceList( binding.nearbyFilter.chipView.choiceChipNeedsPhoto.isChecked(),
|
nearbyFilterSearchRecyclerViewAdapter.selectedLabels,
|
||||||
binding.nearbyFilter.chipView.choiceChipExists.isChecked(), binding.nearbyFilter.chipView.choiceChipWlm.isChecked());
|
binding.nearbyFilterList.checkboxTriStates.getState(), true, true);
|
||||||
} else {
|
updatePlaceList(binding.nearbyFilter.chipView.choiceChipNeedsPhoto.isChecked(),
|
||||||
binding.nearbyFilter.chipView.choiceChipNeedsPhoto.setChecked(!isChecked);
|
binding.nearbyFilter.chipView.choiceChipExists.isChecked(),
|
||||||
}
|
binding.nearbyFilter.chipView.choiceChipWlm.isChecked());
|
||||||
});
|
} else {
|
||||||
|
binding.nearbyFilter.chipView.choiceChipNeedsPhoto.setChecked(!isChecked);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
binding.nearbyFilter.chipView.choiceChipExists.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
binding.nearbyFilter.chipView.choiceChipExists.setOnCheckedChangeListener(
|
||||||
if (NearbyController.currentLocation != null) {
|
(buttonView, isChecked) -> {
|
||||||
binding.nearbyFilterList.checkboxTriStates.setState(CheckBoxTriStates.CHECKED);
|
if (NearbyController.currentLocation != null) {
|
||||||
NearbyFilterState.setExistsSelected(isChecked);
|
binding.nearbyFilterList.checkboxTriStates.setState(CheckBoxTriStates.CHECKED);
|
||||||
presenter.filterByMarkerType(nearbyFilterSearchRecyclerViewAdapter.selectedLabels,
|
NearbyFilterState.setExistsSelected(isChecked);
|
||||||
binding.nearbyFilterList.checkboxTriStates.getState(), true, true);
|
presenter.filterByMarkerType(
|
||||||
updatePlaceList( binding.nearbyFilter.chipView.choiceChipNeedsPhoto.isChecked(),
|
nearbyFilterSearchRecyclerViewAdapter.selectedLabels,
|
||||||
binding.nearbyFilter.chipView.choiceChipExists.isChecked(), binding.nearbyFilter.chipView.choiceChipWlm.isChecked());
|
binding.nearbyFilterList.checkboxTriStates.getState(), true, true);
|
||||||
} else {
|
updatePlaceList(binding.nearbyFilter.chipView.choiceChipNeedsPhoto.isChecked(),
|
||||||
binding.nearbyFilter.chipView.choiceChipExists.setChecked(!isChecked);
|
binding.nearbyFilter.chipView.choiceChipExists.isChecked(),
|
||||||
}
|
binding.nearbyFilter.chipView.choiceChipWlm.isChecked());
|
||||||
});
|
} else {
|
||||||
|
binding.nearbyFilter.chipView.choiceChipExists.setChecked(!isChecked);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
binding.nearbyFilter.chipView.choiceChipWlm.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
binding.nearbyFilter.chipView.choiceChipWlm.setOnCheckedChangeListener(
|
||||||
if (NearbyController.currentLocation != null) {
|
(buttonView, isChecked) -> {
|
||||||
binding.nearbyFilterList.checkboxTriStates.setState(CheckBoxTriStates.CHECKED);
|
if (NearbyController.currentLocation != null) {
|
||||||
NearbyFilterState.setWlmSelected(isChecked);
|
binding.nearbyFilterList.checkboxTriStates.setState(CheckBoxTriStates.CHECKED);
|
||||||
presenter.filterByMarkerType(nearbyFilterSearchRecyclerViewAdapter.selectedLabels,
|
NearbyFilterState.setWlmSelected(isChecked);
|
||||||
binding.nearbyFilterList.checkboxTriStates.getState(), true, true);
|
presenter.filterByMarkerType(
|
||||||
updatePlaceList( binding.nearbyFilter.chipView.choiceChipNeedsPhoto.isChecked(),
|
nearbyFilterSearchRecyclerViewAdapter.selectedLabels,
|
||||||
binding.nearbyFilter.chipView.choiceChipExists.isChecked(), binding.nearbyFilter.chipView.choiceChipWlm.isChecked());
|
binding.nearbyFilterList.checkboxTriStates.getState(), true, true);
|
||||||
} else {
|
updatePlaceList(binding.nearbyFilter.chipView.choiceChipNeedsPhoto.isChecked(),
|
||||||
binding.nearbyFilter.chipView.choiceChipWlm.setChecked(!isChecked);
|
binding.nearbyFilter.chipView.choiceChipExists.isChecked(),
|
||||||
}
|
binding.nearbyFilter.chipView.choiceChipWlm.isChecked());
|
||||||
});
|
} else {
|
||||||
|
binding.nearbyFilter.chipView.choiceChipWlm.setChecked(!isChecked);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -838,7 +880,8 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
||||||
}
|
}
|
||||||
|
|
||||||
adapter.setItems(updatedPlaces);
|
adapter.setItems(updatedPlaces);
|
||||||
binding.bottomSheetNearby.noResultsMessage.setVisibility(updatedPlaces.isEmpty() ? View.VISIBLE : View.GONE);
|
binding.bottomSheetNearby.noResultsMessage.setVisibility(
|
||||||
|
updatedPlaces.isEmpty() ? View.VISIBLE : View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -867,8 +910,9 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
binding.bottomSheetNearby.bottomSheet.getLayoutParams().height = getActivity().getWindowManager()
|
binding.bottomSheetNearby.bottomSheet.getLayoutParams().height =
|
||||||
.getDefaultDisplay().getHeight() / 16 * 9;
|
getActivity().getWindowManager()
|
||||||
|
.getDefaultDisplay().getHeight() / 16 * 9;
|
||||||
bottomSheetListBehavior = BottomSheetBehavior.from(binding.bottomSheetNearby.bottomSheet);
|
bottomSheetListBehavior = BottomSheetBehavior.from(binding.bottomSheetNearby.bottomSheet);
|
||||||
bottomSheetListBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
|
bottomSheetListBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
|
||||||
bottomSheetListBehavior.setBottomSheetCallback(new BottomSheetBehavior
|
bottomSheetListBehavior.setBottomSheetCallback(new BottomSheetBehavior
|
||||||
|
|
@ -897,26 +941,13 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
||||||
rotate_backward = AnimationUtils.loadAnimation(getActivity(), R.anim.rotate_backward);
|
rotate_backward = AnimationUtils.loadAnimation(getActivity(), R.anim.rotate_backward);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Fits buttons according to our layout
|
|
||||||
*/
|
|
||||||
private void decideButtonVisibilities() {
|
|
||||||
// Remove button text if they exceed 1 line or if internal layout has not been built
|
|
||||||
// Only need to check for directions button because it is the longest
|
|
||||||
if ( binding.bottomSheetDetails.directionsButtonText.getLineCount() > 1 || binding.bottomSheetDetails.directionsButtonText.getLineCount() == 0) {
|
|
||||||
binding.bottomSheetDetails.wikipediaButtonText.setVisibility(View.GONE);
|
|
||||||
binding.bottomSheetDetails.wikidataButtonText.setVisibility(View.GONE);
|
|
||||||
binding.bottomSheetDetails.commonsButtonText.setVisibility(View.GONE);
|
|
||||||
binding.bottomSheetDetails.directionsButtonText.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private void addActionToTitle() {
|
private void addActionToTitle() {
|
||||||
binding.bottomSheetDetails.title.setOnLongClickListener(view -> {
|
binding.bottomSheetDetails.title.setOnLongClickListener(view -> {
|
||||||
Utils.copy("place", binding.bottomSheetDetails.title.getText().toString(), getContext());
|
Utils.copy("place", binding.bottomSheetDetails.title.getText().toString(),
|
||||||
|
getContext());
|
||||||
Toast.makeText(getContext(), R.string.text_copy, Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), R.string.text_copy, Toast.LENGTH_SHORT).show();
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
@ -963,7 +994,8 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
||||||
public void updateListFragment(final List<Place> placeList) {
|
public void updateListFragment(final List<Place> placeList) {
|
||||||
places = placeList;
|
places = placeList;
|
||||||
adapter.setItems(placeList);
|
adapter.setItems(placeList);
|
||||||
binding.bottomSheetNearby.noResultsMessage.setVisibility(placeList.isEmpty() ? View.VISIBLE : View.GONE);
|
binding.bottomSheetNearby.noResultsMessage.setVisibility(
|
||||||
|
placeList.isEmpty() ? View.VISIBLE : View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -1006,7 +1038,8 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
||||||
@Override
|
@Override
|
||||||
public fr.free.nrw.commons.location.LatLng getMapFocus() {
|
public fr.free.nrw.commons.location.LatLng getMapFocus() {
|
||||||
fr.free.nrw.commons.location.LatLng mapFocusedLatLng = new fr.free.nrw.commons.location.LatLng(
|
fr.free.nrw.commons.location.LatLng mapFocusedLatLng = new fr.free.nrw.commons.location.LatLng(
|
||||||
binding.map.getMapCenter().getLatitude(), binding.map.getMapCenter().getLongitude(), 100);
|
binding.map.getMapCenter().getLatitude(), binding.map.getMapCenter().getLongitude(),
|
||||||
|
100);
|
||||||
return mapFocusedLatLng;
|
return mapFocusedLatLng;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1077,8 +1110,10 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void populatePlaces(final fr.free.nrw.commons.location.LatLng currentLatLng) {
|
public void populatePlaces(final fr.free.nrw.commons.location.LatLng currentLatLng) {
|
||||||
IGeoPoint screenTopRight = binding.map.getProjection().fromPixels(binding.map.getWidth(), 0);
|
IGeoPoint screenTopRight = binding.map.getProjection()
|
||||||
IGeoPoint screenBottomLeft = binding.map.getProjection().fromPixels(0, binding.map.getHeight());
|
.fromPixels(binding.map.getWidth(), 0);
|
||||||
|
IGeoPoint screenBottomLeft = binding.map.getProjection()
|
||||||
|
.fromPixels(0, binding.map.getHeight());
|
||||||
fr.free.nrw.commons.location.LatLng screenTopRightLatLng = new fr.free.nrw.commons.location.LatLng(
|
fr.free.nrw.commons.location.LatLng screenTopRightLatLng = new fr.free.nrw.commons.location.LatLng(
|
||||||
screenBottomLeft.getLatitude(), screenBottomLeft.getLongitude(), 0);
|
screenBottomLeft.getLatitude(), screenBottomLeft.getLongitude(), 0);
|
||||||
fr.free.nrw.commons.location.LatLng screenBottomLeftLatLng = new fr.free.nrw.commons.location.LatLng(
|
fr.free.nrw.commons.location.LatLng screenBottomLeftLatLng = new fr.free.nrw.commons.location.LatLng(
|
||||||
|
|
@ -1135,8 +1170,10 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
||||||
populatePlaces(currentLatLng);
|
populatePlaces(currentLatLng);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
IGeoPoint screenTopRight = binding.map.getProjection().fromPixels(binding.map.getWidth(), 0);
|
IGeoPoint screenTopRight = binding.map.getProjection()
|
||||||
IGeoPoint screenBottomLeft = binding.map.getProjection().fromPixels(0, binding.map.getHeight());
|
.fromPixels(binding.map.getWidth(), 0);
|
||||||
|
IGeoPoint screenBottomLeft = binding.map.getProjection()
|
||||||
|
.fromPixels(0, binding.map.getHeight());
|
||||||
fr.free.nrw.commons.location.LatLng screenTopRightLatLng = new fr.free.nrw.commons.location.LatLng(
|
fr.free.nrw.commons.location.LatLng screenTopRightLatLng = new fr.free.nrw.commons.location.LatLng(
|
||||||
screenBottomLeft.getLatitude(), screenBottomLeft.getLongitude(), 0);
|
screenBottomLeft.getLatitude(), screenBottomLeft.getLongitude(), 0);
|
||||||
fr.free.nrw.commons.location.LatLng screenBottomLeftLatLng = new fr.free.nrw.commons.location.LatLng(
|
fr.free.nrw.commons.location.LatLng screenBottomLeftLatLng = new fr.free.nrw.commons.location.LatLng(
|
||||||
|
|
@ -1250,7 +1287,8 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
||||||
(isGPX) ? getString(R.string.do_you_want_to_open_gpx_file)
|
(isGPX) ? getString(R.string.do_you_want_to_open_gpx_file)
|
||||||
: getString(R.string.do_you_want_to_open_kml_file);
|
: getString(R.string.do_you_want_to_open_kml_file);
|
||||||
Runnable runnable = () -> openFile(context, fileName, isGPX);
|
Runnable runnable = () -> openFile(context, fileName, isGPX);
|
||||||
DialogUtil.showAlertDialog(getActivity(), title, message, runnable,() -> {});
|
DialogUtil.showAlertDialog(getActivity(), title, message, runnable, () -> {
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void openFile(Context context, String fileName, Boolean isGPX) {
|
private void openFile(Context context, String fileName, Boolean isGPX) {
|
||||||
|
|
@ -1418,9 +1456,9 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
||||||
@Override
|
@Override
|
||||||
public void setProgressBarVisibility(final boolean isVisible) {
|
public void setProgressBarVisibility(final boolean isVisible) {
|
||||||
if (isVisible) {
|
if (isVisible) {
|
||||||
binding.mapProgressBar.setVisibility(View.VISIBLE);
|
binding.mapProgressBar.setVisibility(View.VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
binding.mapProgressBar.setVisibility(View.GONE);
|
binding.mapProgressBar.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1444,7 +1482,8 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showFABs() {
|
private void showFABs() {
|
||||||
NearbyFABUtils.addAnchorToBigFABs(binding.fabPlus, binding.bottomSheetDetails.getRoot().getId());
|
NearbyFABUtils.addAnchorToBigFABs(binding.fabPlus,
|
||||||
|
binding.bottomSheetDetails.getRoot().getId());
|
||||||
binding.fabPlus.show();
|
binding.fabPlus.show();
|
||||||
NearbyFABUtils.addAnchorToSmallFABs(binding.fabGallery,
|
NearbyFABUtils.addAnchorToSmallFABs(binding.fabGallery,
|
||||||
getView().findViewById(R.id.empty_view).getId());
|
getView().findViewById(R.id.empty_view).getId());
|
||||||
|
|
@ -1576,17 +1615,17 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setFABRecenterAction(final View.OnClickListener onClickListener) {
|
public void setFABRecenterAction(final View.OnClickListener onClickListener) {
|
||||||
binding.fabRecenter.setOnClickListener(onClickListener);
|
binding.fabRecenter.setOnClickListener(onClickListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void disableFABRecenter() {
|
public void disableFABRecenter() {
|
||||||
binding.fabRecenter.setEnabled(false);
|
binding.fabRecenter.setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void enableFABRecenter() {
|
public void enableFABRecenter() {
|
||||||
binding.fabRecenter.setEnabled(true);
|
binding.fabRecenter.setEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1865,7 +1904,8 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extracts text between the first occurrence of '(' and its corresponding ')' in the input string.
|
* Extracts text between the first occurrence of '(' and its corresponding ')' in the input
|
||||||
|
* string.
|
||||||
*
|
*
|
||||||
* @param input The input string from which to extract text between parentheses.
|
* @param input The input string from which to extract text between parentheses.
|
||||||
* @return The text between parentheses if found, or {@code null} if no parentheses are found.
|
* @return The text between parentheses if found, or {@code null} if no parentheses are found.
|
||||||
|
|
@ -1890,14 +1930,17 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
||||||
return input.contains("(") || input.contains(")");
|
return input.contains("(") || input.contains(")");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeMarker(Place place){
|
private void removeMarker(Place place) {
|
||||||
List<Overlay> overlays = binding.map.getOverlays();
|
List<Overlay> overlays = binding.map.getOverlays();
|
||||||
for (int i = 0; i < overlays.size();i++){
|
for (int i = 0; i < overlays.size(); i++) {
|
||||||
if (overlays.get(i) instanceof ItemizedOverlayWithFocus){
|
if (overlays.get(i) instanceof ItemizedOverlayWithFocus) {
|
||||||
ItemizedOverlayWithFocus item = (ItemizedOverlayWithFocus)overlays.get(i);
|
ItemizedOverlayWithFocus item = (ItemizedOverlayWithFocus) overlays.get(i);
|
||||||
OverlayItem overlayItem = item.getItem(0);
|
OverlayItem overlayItem = item.getItem(0);
|
||||||
fr.free.nrw.commons.location.LatLng diffLatLang = new fr.free.nrw.commons.location.LatLng(overlayItem.getPoint().getLatitude(),overlayItem.getPoint().getLongitude(),100);
|
fr.free.nrw.commons.location.LatLng diffLatLang = new fr.free.nrw.commons.location.LatLng(
|
||||||
if (place.location.getLatitude() == overlayItem.getPoint().getLatitude() && place.location.getLongitude() == overlayItem.getPoint().getLongitude()){
|
overlayItem.getPoint().getLatitude(), overlayItem.getPoint().getLongitude(),
|
||||||
|
100);
|
||||||
|
if (place.location.getLatitude() == overlayItem.getPoint().getLatitude()
|
||||||
|
&& place.location.getLongitude() == overlayItem.getPoint().getLongitude()) {
|
||||||
binding.map.getOverlays().remove(i);
|
binding.map.getOverlays().remove(i);
|
||||||
binding.map.invalidate();
|
binding.map.invalidate();
|
||||||
break;
|
break;
|
||||||
|
|
@ -2020,50 +2063,33 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
||||||
*/
|
*/
|
||||||
private void passInfoToSheet(final Place place) {
|
private void passInfoToSheet(final Place place) {
|
||||||
selectedPlace = place;
|
selectedPlace = place;
|
||||||
|
dataList = new ArrayList<>();
|
||||||
|
// TODO: Decide button text for fitting in the screen
|
||||||
|
dataList.add(new BottomSheetItem(R.drawable.ic_round_star_border_24px, ""));
|
||||||
|
dataList.add(new BottomSheetItem(R.drawable.ic_directions_black_24dp,
|
||||||
|
getResources().getString(R.string.nearby_directions)));
|
||||||
|
if (place.hasWikidataLink()) {
|
||||||
|
dataList.add(new BottomSheetItem(R.drawable.ic_wikidata_logo_24dp,
|
||||||
|
getResources().getString(R.string.nearby_wikidata)));
|
||||||
|
}
|
||||||
|
dataList.add(new BottomSheetItem(R.drawable.ic_feedback_black_24dp,
|
||||||
|
getResources().getString(R.string.nearby_wikitalk)));
|
||||||
|
if (place.hasWikipediaLink()) {
|
||||||
|
dataList.add(new BottomSheetItem(R.drawable.ic_wikipedia_logo_24dp,
|
||||||
|
getResources().getString(R.string.nearby_wikipedia)));
|
||||||
|
}
|
||||||
|
if (selectedPlace.hasCommonsLink()) {
|
||||||
|
dataList.add(new BottomSheetItem(R.drawable.ic_commons_icon_vector,
|
||||||
|
getResources().getString(R.string.nearby_commons)));
|
||||||
|
}
|
||||||
|
int spanCount = getSpanCount();
|
||||||
|
gridLayoutManager = new GridLayoutManager(this.getContext(), spanCount);
|
||||||
|
binding.bottomSheetDetails.bottomSheetRecyclerView.setLayoutManager(gridLayoutManager);
|
||||||
|
bottomSheetAdapter = new BottomSheetAdapter(this.getContext(), dataList);
|
||||||
|
bottomSheetAdapter.setClickListener(this);
|
||||||
|
binding.bottomSheetDetails.bottomSheetRecyclerView.setAdapter(bottomSheetAdapter);
|
||||||
updateBookmarkButtonImage(selectedPlace);
|
updateBookmarkButtonImage(selectedPlace);
|
||||||
|
|
||||||
binding.bottomSheetDetails.bookmarkButton.setOnClickListener(view -> {
|
|
||||||
final boolean isBookmarked = bookmarkLocationDao.updateBookmarkLocation(selectedPlace);
|
|
||||||
updateBookmarkButtonImage(selectedPlace);
|
|
||||||
updateMarker(isBookmarked, selectedPlace, locationManager.getLastLocation());
|
|
||||||
binding.map.invalidate();
|
|
||||||
});
|
|
||||||
binding.bottomSheetDetails.bookmarkButton.setOnLongClickListener(view -> {
|
|
||||||
Toast.makeText(getContext(), R.string.menu_bookmark, Toast.LENGTH_SHORT).show();
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
binding.bottomSheetDetails.wikipediaButton.setVisibility(place.hasWikipediaLink() ? View.VISIBLE : View.GONE);
|
|
||||||
binding.bottomSheetDetails.wikipediaButton.setOnClickListener(
|
|
||||||
view -> Utils.handleWebUrl(getContext(), selectedPlace.siteLinks.getWikipediaLink()));
|
|
||||||
binding.bottomSheetDetails.wikipediaButton.setOnLongClickListener(view -> {
|
|
||||||
Toast.makeText(getContext(), R.string.nearby_wikipedia, Toast.LENGTH_SHORT).show();
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
binding.bottomSheetDetails.wikidataButton.setVisibility(place.hasWikidataLink() ? View.VISIBLE : View.GONE);
|
|
||||||
binding.bottomSheetDetails.wikidataButton.setOnClickListener(
|
|
||||||
view -> Utils.handleWebUrl(getContext(), selectedPlace.siteLinks.getWikidataLink()));
|
|
||||||
binding.bottomSheetDetails.wikidataButton.setOnLongClickListener(view -> {
|
|
||||||
Toast.makeText(getContext(), R.string.nearby_wikidata, Toast.LENGTH_SHORT).show();
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
binding.bottomSheetDetails.directionsButton.setOnClickListener(view -> Utils.handleGeoCoordinates(getActivity(),
|
|
||||||
selectedPlace.getLocation()));
|
|
||||||
binding.bottomSheetDetails.directionsButton.setOnLongClickListener(view -> {
|
|
||||||
Toast.makeText(getContext(), R.string.nearby_directions, Toast.LENGTH_SHORT).show();
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
binding.bottomSheetDetails.commonsButton.setVisibility(selectedPlace.hasCommonsLink() ? View.VISIBLE : View.GONE);
|
|
||||||
binding.bottomSheetDetails.commonsButton.setOnClickListener(
|
|
||||||
view -> Utils.handleWebUrl(getContext(), selectedPlace.siteLinks.getCommonsLink()));
|
|
||||||
binding.bottomSheetDetails.commonsButton.setOnLongClickListener(view -> {
|
|
||||||
Toast.makeText(getContext(), R.string.nearby_commons, Toast.LENGTH_SHORT).show();
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
binding.bottomSheetDetails.icon.setImageResource(selectedPlace.getLabel().getIcon());
|
binding.bottomSheetDetails.icon.setImageResource(selectedPlace.getLabel().getIcon());
|
||||||
|
|
||||||
binding.bottomSheetDetails.title.setText(selectedPlace.name);
|
binding.bottomSheetDetails.title.setText(selectedPlace.name);
|
||||||
|
|
@ -2074,7 +2100,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
||||||
descriptionText = (descriptionText.equals(selectedPlace.getLongDescription())
|
descriptionText = (descriptionText.equals(selectedPlace.getLongDescription())
|
||||||
? descriptionText : descriptionText.replaceFirst(".$", ""));
|
? descriptionText : descriptionText.replaceFirst(".$", ""));
|
||||||
// Set the short description after we remove place name from long description
|
// Set the short description after we remove place name from long description
|
||||||
binding.bottomSheetDetails.description.setText(descriptionText);
|
binding.bottomSheetDetails.description.setText(descriptionText);
|
||||||
|
|
||||||
binding.fabCamera.setOnClickListener(view -> {
|
binding.fabCamera.setOnClickListener(view -> {
|
||||||
if (binding.fabCamera.isShown()) {
|
if (binding.fabCamera.isShown()) {
|
||||||
|
|
@ -2088,7 +2114,8 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
||||||
if (binding.fabGallery.isShown()) {
|
if (binding.fabGallery.isShown()) {
|
||||||
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(), binding.nearbyFilter.chipView.choiceChipWlm.isChecked());
|
controller.initiateGalleryPick(getActivity(),
|
||||||
|
binding.nearbyFilter.chipView.choiceChipWlm.isChecked());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -2115,9 +2142,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
||||||
} else {
|
} else {
|
||||||
bookmarkIcon = R.drawable.ic_round_star_border_24px;
|
bookmarkIcon = R.drawable.ic_round_star_border_24px;
|
||||||
}
|
}
|
||||||
if ( binding.bottomSheetDetails.bookmarkButtonImage != null) {
|
bottomSheetAdapter.updateBookmarkIcon(bookmarkIcon);
|
||||||
binding.bottomSheetDetails.bookmarkButtonImage.setImageResource(bookmarkIcon);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -2295,6 +2320,83 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
||||||
binding.map.getController().animateTo(geoPoint);
|
binding.map.getController().animateTo(geoPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBottomSheetItemClick(@Nullable View view, int position) {
|
||||||
|
BottomSheetItem item = dataList.get(position);
|
||||||
|
boolean isBookmarked = bookmarkLocationDao.findBookmarkLocation(selectedPlace);
|
||||||
|
switch (item.getImageResourceId()) {
|
||||||
|
case R.drawable.ic_round_star_border_24px:
|
||||||
|
bookmarkLocationDao.updateBookmarkLocation(selectedPlace);
|
||||||
|
updateBookmarkButtonImage(selectedPlace);
|
||||||
|
isBookmarked = bookmarkLocationDao.findBookmarkLocation(selectedPlace);
|
||||||
|
updateMarker(isBookmarked, selectedPlace, locationManager.getLastLocation());
|
||||||
|
binding.map.invalidate();
|
||||||
|
break;
|
||||||
|
case R.drawable.ic_round_star_filled_24px:
|
||||||
|
bookmarkLocationDao.updateBookmarkLocation(selectedPlace);
|
||||||
|
updateBookmarkButtonImage(selectedPlace);
|
||||||
|
isBookmarked = bookmarkLocationDao.findBookmarkLocation(selectedPlace);
|
||||||
|
updateMarker(isBookmarked, selectedPlace, locationManager.getLastLocation());
|
||||||
|
binding.map.invalidate();
|
||||||
|
break;
|
||||||
|
case R.drawable.ic_directions_black_24dp:
|
||||||
|
Utils.handleGeoCoordinates(this.getContext(), selectedPlace.getLocation());
|
||||||
|
break;
|
||||||
|
case R.drawable.ic_wikidata_logo_24dp:
|
||||||
|
Utils.handleWebUrl(this.getContext(), selectedPlace.siteLinks.getWikidataLink());
|
||||||
|
break;
|
||||||
|
case R.drawable.ic_feedback_black_24dp:
|
||||||
|
Intent intent = new Intent(this.getContext(), WikidataFeedback.class);
|
||||||
|
intent.putExtra("lat", selectedPlace.location.getLatitude());
|
||||||
|
intent.putExtra("lng", selectedPlace.location.getLongitude());
|
||||||
|
intent.putExtra("place", selectedPlace.name);
|
||||||
|
intent.putExtra("qid", selectedPlace.getWikiDataEntityId());
|
||||||
|
startActivity(intent);
|
||||||
|
break;
|
||||||
|
case R.drawable.ic_wikipedia_logo_24dp:
|
||||||
|
Utils.handleWebUrl(this.getContext(), selectedPlace.siteLinks.getWikipediaLink());
|
||||||
|
break;
|
||||||
|
case R.drawable.ic_commons_icon_vector:
|
||||||
|
Utils.handleWebUrl(this.getContext(), selectedPlace.siteLinks.getCommonsLink());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBottomSheetItemLongClick(@Nullable View view, int position) {
|
||||||
|
BottomSheetItem item = dataList.get(position);
|
||||||
|
String message;
|
||||||
|
switch (item.getImageResourceId()) {
|
||||||
|
case R.drawable.ic_round_star_border_24px:
|
||||||
|
message = getString(R.string.menu_bookmark);
|
||||||
|
break;
|
||||||
|
case R.drawable.ic_round_star_filled_24px:
|
||||||
|
message = getString(R.string.menu_bookmark);
|
||||||
|
break;
|
||||||
|
case R.drawable.ic_directions_black_24dp:
|
||||||
|
message = getString(R.string.nearby_directions);
|
||||||
|
break;
|
||||||
|
case R.drawable.ic_wikidata_logo_24dp:
|
||||||
|
message = getString(R.string.nearby_wikidata);
|
||||||
|
break;
|
||||||
|
case R.drawable.ic_feedback_black_24dp:
|
||||||
|
message = getString(R.string.nearby_wikitalk);
|
||||||
|
break;
|
||||||
|
case R.drawable.ic_wikipedia_logo_24dp:
|
||||||
|
message = getString(R.string.nearby_wikipedia);
|
||||||
|
break;
|
||||||
|
case R.drawable.ic_commons_icon_vector:
|
||||||
|
message = getString(R.string.nearby_commons);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
message = "Long click";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Toast.makeText(this.getContext(), message, Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
|
||||||
public interface NearbyParentFragmentInstanceReadyCallback {
|
public interface NearbyParentFragmentInstanceReadyCallback {
|
||||||
|
|
||||||
void onReady();
|
void onReady();
|
||||||
|
|
@ -2312,9 +2414,12 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
||||||
rlBottomSheetLayoutParams.height =
|
rlBottomSheetLayoutParams.height =
|
||||||
getActivity().getWindowManager().getDefaultDisplay().getHeight() / 16 * 9;
|
getActivity().getWindowManager().getDefaultDisplay().getHeight() / 16 * 9;
|
||||||
binding.bottomSheetNearby.bottomSheet.setLayoutParams(rlBottomSheetLayoutParams);
|
binding.bottomSheetNearby.bottomSheet.setLayoutParams(rlBottomSheetLayoutParams);
|
||||||
|
int spanCount = getSpanCount();
|
||||||
|
if (gridLayoutManager != null) {
|
||||||
|
gridLayoutManager.setSpanCount(spanCount);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void onLearnMoreClicked() {
|
public void onLearnMoreClicked() {
|
||||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||||
intent.setData(Uri.parse(WLM_URL));
|
intent.setData(Uri.parse(WLM_URL));
|
||||||
|
|
@ -2322,11 +2427,12 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onToggleChipsClicked() {
|
public void onToggleChipsClicked() {
|
||||||
if ( binding.nearbyFilter.chipView.getRoot().getVisibility() == View.VISIBLE) {
|
if (binding.nearbyFilter.chipView.getRoot().getVisibility() == View.VISIBLE) {
|
||||||
binding.nearbyFilter.chipView.getRoot().setVisibility(View.GONE);
|
binding.nearbyFilter.chipView.getRoot().setVisibility(View.GONE);
|
||||||
} else {
|
} else {
|
||||||
binding.nearbyFilter.chipView.getRoot().setVisibility(View.VISIBLE);
|
binding.nearbyFilter.chipView.getRoot().setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
binding.nearbyFilter.ivToggleChips.setRotation(binding.nearbyFilter.ivToggleChips.getRotation() + 180);
|
binding.nearbyFilter.ivToggleChips.setRotation(
|
||||||
|
binding.nearbyFilter.ivToggleChips.getRotation() + 180);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
package fr.free.nrw.commons.nearby.model
|
||||||
|
|
||||||
|
class BottomSheetItem(var imageResourceId: Int, val title: String)
|
||||||
111
app/src/main/res/layout/activity_wikidata_feedback.xml
Normal file
111
app/src/main/res/layout/activity_wikidata_feedback.xml
Normal file
|
|
@ -0,0 +1,111 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:context=".nearby.WikidataFeedback">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/toolbarLayout"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="?attr/actionBarSize"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/toolbarBinding"
|
||||||
|
layout="@layout/toolbar" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progress_bar"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="invisible"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:id="@+id/activity_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/toolbarLayout">
|
||||||
|
|
||||||
|
<RadioGroup
|
||||||
|
android:id="@+id/radioGroup"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/detailsEditText"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent">
|
||||||
|
|
||||||
|
<RadioButton
|
||||||
|
android:id="@+id/radioButton1"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="5dp" />
|
||||||
|
|
||||||
|
<RadioButton
|
||||||
|
android:id="@+id/radioButton2"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="5dp" />
|
||||||
|
|
||||||
|
<RadioButton
|
||||||
|
android:id="@+id/radioButton3"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="5dp"/>
|
||||||
|
|
||||||
|
</RadioGroup>
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
|
android:id="@+id/textHeader"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:layout_marginBottom="6dp"
|
||||||
|
android:text="Write something about the item. It will be publicly visible."
|
||||||
|
android:textSize="@dimen/normal_text"
|
||||||
|
android:visibility="visible"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/radioGroup"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintHorizontal_bias="0.0"
|
||||||
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatEditText
|
||||||
|
android:id="@+id/detailsEditText"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:hint="Comments"
|
||||||
|
android:singleLine="false"
|
||||||
|
android:visibility="visible"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/appCompatButton"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatButton
|
||||||
|
android:id="@+id/appCompatButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:text="SEND"
|
||||||
|
android:visibility="visible"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="@+id/textHeader"
|
||||||
|
app:layout_constraintHorizontal_bias="1.0"
|
||||||
|
app:layout_constraintStart_toStartOf="@+id/textHeader" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
@ -53,169 +53,21 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="@dimen/tiny_height"
|
android:layout_height="@dimen/tiny_height"
|
||||||
android:layout_marginTop="@dimen/small_height"
|
android:layout_marginTop="@dimen/small_height"
|
||||||
android:layout_marginBottom="@dimen/activity_margin_horizontal"
|
android:layout_marginBottom="@dimen/activity_margin_horizontal"
|
||||||
android:background="@android:color/darker_gray"/>
|
android:background="@android:color/darker_gray" />
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
>
|
|
||||||
|
|
||||||
<LinearLayout
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/bookmarkButton"
|
android:id="@+id/bottom_sheet_recycler_view"
|
||||||
android:layout_width="@dimen/dimen_0"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content" />
|
||||||
android:layout_weight="1"
|
|
||||||
android:padding="@dimen/standard_gap"
|
|
||||||
android:clickable="true"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:background="@drawable/button_background_selector"
|
|
||||||
>
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/bookmarkButtonImage"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center_horizontal"
|
|
||||||
app:srcCompat="@drawable/ic_round_star_border_24px"
|
|
||||||
android:tint="?attr/rowButtonColor"/>
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:id="@+id/bookmarkButtonText"
|
|
||||||
android:paddingTop="@dimen/activity_margin_horizontal"
|
|
||||||
android:layout_gravity="center_horizontal"
|
|
||||||
android:text="CAMERA"
|
|
||||||
android:visibility="gone"
|
|
||||||
/>
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/directionsButton"
|
|
||||||
android:layout_width="@dimen/dimen_0"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:padding="@dimen/standard_gap"
|
|
||||||
android:clickable="true"
|
|
||||||
android:background="@drawable/button_background_selector"
|
|
||||||
android:orientation="vertical"
|
|
||||||
>
|
|
||||||
<ImageView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center_horizontal"
|
|
||||||
android:duplicateParentState="true"
|
|
||||||
app:srcCompat="@drawable/ic_directions_black_24dp"
|
|
||||||
android:tint="?attr/rowButtonColor"
|
|
||||||
/>
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:id="@+id/directionsButtonText"
|
|
||||||
android:paddingTop="@dimen/activity_margin_horizontal"
|
|
||||||
android:duplicateParentState="true"
|
|
||||||
android:textColor="@color/text_color_selector"
|
|
||||||
android:layout_gravity="center_horizontal"
|
|
||||||
android:text="@string/nearby_directions"
|
|
||||||
android:textAllCaps="true"
|
|
||||||
/>
|
|
||||||
</LinearLayout>
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/wikidataButton"
|
|
||||||
android:layout_width="@dimen/dimen_0"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:padding="@dimen/standard_gap"
|
|
||||||
android:clickable="true"
|
|
||||||
android:background="@drawable/button_background_selector"
|
|
||||||
android:orientation="vertical"
|
|
||||||
>
|
|
||||||
<ImageView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center_horizontal"
|
|
||||||
android:duplicateParentState="true"
|
|
||||||
app:srcCompat="@drawable/ic_wikidata_logo_24dp"
|
|
||||||
android:tint="?attr/rowButtonColor"/>
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:id="@+id/wikidataButtonText"
|
|
||||||
android:paddingTop="@dimen/activity_margin_horizontal"
|
|
||||||
android:duplicateParentState="true"
|
|
||||||
android:textColor="@color/text_color_selector"
|
|
||||||
android:layout_gravity="center_horizontal"
|
|
||||||
android:text="@string/nearby_wikidata"
|
|
||||||
android:textAllCaps="true"
|
|
||||||
/>
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/wikipediaButton"
|
|
||||||
android:layout_width="@dimen/dimen_0"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:padding="@dimen/standard_gap"
|
|
||||||
android:clickable="true"
|
|
||||||
android:background="@drawable/button_background_selector"
|
|
||||||
android:orientation="vertical"
|
|
||||||
>
|
|
||||||
<ImageView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center_horizontal"
|
|
||||||
android:duplicateParentState="true"
|
|
||||||
app:srcCompat="@drawable/ic_wikipedia_logo_24dp"
|
|
||||||
android:tint="?attr/rowButtonColor"
|
|
||||||
/>
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:id="@+id/wikipediaButtonText"
|
|
||||||
android:paddingTop="@dimen/activity_margin_horizontal"
|
|
||||||
android:duplicateParentState="true"
|
|
||||||
android:textColor="@color/text_color_selector"
|
|
||||||
android:layout_gravity="center_horizontal"
|
|
||||||
android:text="@string/nearby_wikipedia"
|
|
||||||
android:textAllCaps="true"
|
|
||||||
/>
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/commonsButton"
|
|
||||||
android:layout_width="@dimen/dimen_0"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:padding="@dimen/standard_gap"
|
|
||||||
android:clickable="true"
|
|
||||||
android:background="@drawable/button_background_selector"
|
|
||||||
android:orientation="vertical"
|
|
||||||
>
|
|
||||||
<ImageView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center_horizontal"
|
|
||||||
android:duplicateParentState="true"
|
|
||||||
app:srcCompat="@drawable/ic_commons_icon_vector"
|
|
||||||
/>
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:id="@+id/commonsButtonText"
|
|
||||||
android:paddingTop="@dimen/activity_margin_horizontal"
|
|
||||||
android:duplicateParentState="true"
|
|
||||||
android:textColor="@color/text_color_selector"
|
|
||||||
android:layout_gravity="center_horizontal"
|
|
||||||
android:text="@string/nearby_commons"
|
|
||||||
android:textAllCaps="true"
|
|
||||||
/>
|
|
||||||
</LinearLayout>
|
|
||||||
</LinearLayout>
|
|
||||||
<View
|
<View
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="@dimen/tiny_height"
|
android:layout_height="@dimen/tiny_height"
|
||||||
android:layout_marginTop="@dimen/small_height"
|
android:layout_marginTop="@dimen/small_height"
|
||||||
android:layout_marginBottom="@dimen/activity_margin_horizontal"
|
android:layout_marginBottom="@dimen/activity_margin_horizontal"
|
||||||
android:background="@android:color/darker_gray"/>
|
android:background="@android:color/darker_gray" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/description"
|
android:id="@+id/description"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
||||||
27
app/src/main/res/layout/bottom_sheet_item_layout.xml
Normal file
27
app/src/main/res/layout/bottom_sheet_item_layout.xml
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/bookmarkButton"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_columnWeight="1"
|
||||||
|
android:background="@drawable/button_background_selector"
|
||||||
|
android:clickable="true"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="@dimen/standard_gap">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/buttonImage"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:tint="?attr/rowButtonColor" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/buttonText"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:paddingTop="@dimen/activity_margin_horizontal"
|
||||||
|
android:text="CAMERA"
|
||||||
|
android:visibility="gone" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
@ -88,6 +88,7 @@
|
||||||
<string name="media_detail_discussion">Müzakirə</string>
|
<string name="media_detail_discussion">Müzakirə</string>
|
||||||
<string name="media_detail_author">Müəllif</string>
|
<string name="media_detail_author">Müəllif</string>
|
||||||
<string name="media_detail_license">Lisenziya</string>
|
<string name="media_detail_license">Lisenziya</string>
|
||||||
|
<string name="nearby_wikidata">Vikidata</string>
|
||||||
<string name="nearby_wikipedia">Vikipediya</string>
|
<string name="nearby_wikipedia">Vikipediya</string>
|
||||||
<string name="send_thank_success_title">Təşəkkür uğurla göndərildi</string>
|
<string name="send_thank_success_title">Təşəkkür uğurla göndərildi</string>
|
||||||
<string name="send_thank_failure_message">Təşəkkür göndərilə bilmədi %1$s</string>
|
<string name="send_thank_failure_message">Təşəkkür göndərilə bilmədi %1$s</string>
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@
|
||||||
<string name="navigation_item_explore">Udforsk</string>
|
<string name="navigation_item_explore">Udforsk</string>
|
||||||
<string name="preference_category_appearance">Udseende</string>
|
<string name="preference_category_appearance">Udseende</string>
|
||||||
<string name="preference_category_general">Generelt</string>
|
<string name="preference_category_general">Generelt</string>
|
||||||
<string name="preference_category_feedback">Tilbagemelding</string>
|
<string name="preference_category_feedback">Feedback</string>
|
||||||
<string name="preference_category_privacy">Privatliv</string>
|
<string name="preference_category_privacy">Privatliv</string>
|
||||||
<string name="app_name">Commons</string>
|
<string name="app_name">Commons</string>
|
||||||
<string name="bullet">•</string>
|
<string name="bullet">•</string>
|
||||||
|
|
@ -90,11 +90,11 @@
|
||||||
<string name="authentication_failed">Godkendelse mislykkedes. Log venligst ind igen.</string>
|
<string name="authentication_failed">Godkendelse mislykkedes. Log venligst ind igen.</string>
|
||||||
<string name="uploading_started">Upload påbegyndt!</string>
|
<string name="uploading_started">Upload påbegyndt!</string>
|
||||||
<string name="uploading_queued">Upload i kø (begrænset forbindelsestilstand aktiveret)</string>
|
<string name="uploading_queued">Upload i kø (begrænset forbindelsestilstand aktiveret)</string>
|
||||||
<string name="upload_completed_notification_title">%1$s overført!</string>
|
<string name="upload_completed_notification_title">%1$s uploadet!</string>
|
||||||
<string name="upload_completed_notification_text">Tryk for at få vist dit upload</string>
|
<string name="upload_completed_notification_text">Tryk for at få vist dit upload</string>
|
||||||
<string name="upload_progress_notification_title_start">Uploader fil: %s</string>
|
<string name="upload_progress_notification_title_start">Uploader fil: %s</string>
|
||||||
<string name="upload_progress_notification_title_in_progress">%1$s overføres</string>
|
<string name="upload_progress_notification_title_in_progress">%1$s uploades</string>
|
||||||
<string name="upload_progress_notification_title_finishing">Afslutter uploadning af %1$s</string>
|
<string name="upload_progress_notification_title_finishing">Afslutter upload af %1$s</string>
|
||||||
<string name="upload_failed_notification_title">Upload af %1$s mislykkedes</string>
|
<string name="upload_failed_notification_title">Upload af %1$s mislykkedes</string>
|
||||||
<string name="upload_paused_notification_title">Upload af %1$s sat på pause</string>
|
<string name="upload_paused_notification_title">Upload af %1$s sat på pause</string>
|
||||||
<string name="upload_failed_notification_subtitle">Tryk for at se</string>
|
<string name="upload_failed_notification_subtitle">Tryk for at se</string>
|
||||||
|
|
@ -103,8 +103,8 @@
|
||||||
<string name="contribution_state_queued">I kø</string>
|
<string name="contribution_state_queued">I kø</string>
|
||||||
<string name="contribution_state_failed">Mislykkedes</string>
|
<string name="contribution_state_failed">Mislykkedes</string>
|
||||||
<string name="contribution_state_in_progress">%1$d%% færdig</string>
|
<string name="contribution_state_in_progress">%1$d%% færdig</string>
|
||||||
<string name="contribution_state_starting">Overfører</string>
|
<string name="contribution_state_starting">Uploader</string>
|
||||||
<string name="menu_from_gallery">Fra galleriet</string>
|
<string name="menu_from_gallery">Fra galleri</string>
|
||||||
<string name="menu_from_camera">Tag billede</string>
|
<string name="menu_from_camera">Tag billede</string>
|
||||||
<string name="menu_nearby">I nærheden</string>
|
<string name="menu_nearby">I nærheden</string>
|
||||||
<string name="provider_contributions">Mine uploads</string>
|
<string name="provider_contributions">Mine uploads</string>
|
||||||
|
|
@ -147,7 +147,7 @@
|
||||||
<string name="about_privacy_policy">Privatlivspolitik</string>
|
<string name="about_privacy_policy">Privatlivspolitik</string>
|
||||||
<string name="about_credits">Tak til</string>
|
<string name="about_credits">Tak til</string>
|
||||||
<string name="title_activity_about">Om</string>
|
<string name="title_activity_about">Om</string>
|
||||||
<string name="menu_feedback">Send tilbagemelding (med e-mail)</string>
|
<string name="menu_feedback">Send feedback (via e-mail)</string>
|
||||||
<string name="no_email_client">Ingen e-mail-klient installeret</string>
|
<string name="no_email_client">Ingen e-mail-klient installeret</string>
|
||||||
<string name="provider_categories">Nyligt anvendte kategorier</string>
|
<string name="provider_categories">Nyligt anvendte kategorier</string>
|
||||||
<string name="waiting_first_sync">Venter på den første synkronisering…</string>
|
<string name="waiting_first_sync">Venter på den første synkronisering…</string>
|
||||||
|
|
@ -203,7 +203,7 @@
|
||||||
<string name="location_permission_title">Anmoder om placeringstilladelse</string>
|
<string name="location_permission_title">Anmoder om placeringstilladelse</string>
|
||||||
<string name="in_app_camera_location_permission_title">Registrer placering for billeder, der tages i appen</string>
|
<string name="in_app_camera_location_permission_title">Registrer placering for billeder, der tages i appen</string>
|
||||||
<string name="in_app_camera_location_switch_pref_summary">Aktiver dette for at registrere placering for billeder i appen, i tilfælde af at enhedens kamera ikke gør det</string>
|
<string name="in_app_camera_location_switch_pref_summary">Aktiver dette for at registrere placering for billeder i appen, i tilfælde af at enhedens kamera ikke gør det</string>
|
||||||
<string name="ok">O.k.</string>
|
<string name="ok">Ok</string>
|
||||||
<string name="warning">Advarsel</string>
|
<string name="warning">Advarsel</string>
|
||||||
<string name="duplicate_file_name">Dublet filnavn fundet</string>
|
<string name="duplicate_file_name">Dublet filnavn fundet</string>
|
||||||
<string name="upload">Overfør</string>
|
<string name="upload">Overfør</string>
|
||||||
|
|
@ -214,7 +214,7 @@
|
||||||
<string name="media_detail_depiction">Afbildning</string>
|
<string name="media_detail_depiction">Afbildning</string>
|
||||||
<string name="media_detail_description">Beskrivelse</string>
|
<string name="media_detail_description">Beskrivelse</string>
|
||||||
<string name="media_detail_discussion">Diskussion</string>
|
<string name="media_detail_discussion">Diskussion</string>
|
||||||
<string name="media_detail_author">Ophavsmand</string>
|
<string name="media_detail_author">Forfatter</string>
|
||||||
<string name="media_detail_uploaded_date">Upload-dato</string>
|
<string name="media_detail_uploaded_date">Upload-dato</string>
|
||||||
<string name="media_detail_license">Licens</string>
|
<string name="media_detail_license">Licens</string>
|
||||||
<string name="media_detail_coordinates">Koordinater</string>
|
<string name="media_detail_coordinates">Koordinater</string>
|
||||||
|
|
@ -241,7 +241,7 @@
|
||||||
<string name="navigation_item_nearby">I nærheden</string>
|
<string name="navigation_item_nearby">I nærheden</string>
|
||||||
<string name="navigation_item_about">Om</string>
|
<string name="navigation_item_about">Om</string>
|
||||||
<string name="navigation_item_settings">Indstillinger</string>
|
<string name="navigation_item_settings">Indstillinger</string>
|
||||||
<string name="navigation_item_feedback">Tilbagemelding</string>
|
<string name="navigation_item_feedback">Feedback</string>
|
||||||
<string name="navigation_item_feedback_github">Feedback via GitHub</string>
|
<string name="navigation_item_feedback_github">Feedback via GitHub</string>
|
||||||
<string name="navigation_item_logout">Log af</string>
|
<string name="navigation_item_logout">Log af</string>
|
||||||
<string name="navigation_item_info">Vejledning</string>
|
<string name="navigation_item_info">Vejledning</string>
|
||||||
|
|
@ -381,9 +381,9 @@
|
||||||
<string name="images_used_explanation">Antallet af billeder, du har uploadet til Commons, som blev brugt i Wikimedia-artikler</string>
|
<string name="images_used_explanation">Antallet af billeder, du har uploadet til Commons, som blev brugt i Wikimedia-artikler</string>
|
||||||
<string name="error_occurred">Der opstod en fejl!</string>
|
<string name="error_occurred">Der opstod en fejl!</string>
|
||||||
<string name="notifications_channel_name_all">Commons-notifikationer</string>
|
<string name="notifications_channel_name_all">Commons-notifikationer</string>
|
||||||
<string name="preference_author_name_toggle">Brug brugerdefineret navn for ophavsmand</string>
|
<string name="preference_author_name_toggle">Brug brugerdefineret forfatternavn</string>
|
||||||
<string name="preference_author_name_toggle_summary">Brug et brugerdefineret navn for ophavsmand i stedet for dit brugernavn, når du uploader billeder</string>
|
<string name="preference_author_name_toggle_summary">Brug et brugerdefineret forfatternavn i stedet for dit brugernavn, når du uploader billeder</string>
|
||||||
<string name="preference_author_name">Brugerdefineret ophavsmandsnavn</string>
|
<string name="preference_author_name">Brugerdefineret forfatternavn</string>
|
||||||
<string name="contributions_fragment">Bidrag</string>
|
<string name="contributions_fragment">Bidrag</string>
|
||||||
<string name="nearby_fragment">I nærheden</string>
|
<string name="nearby_fragment">I nærheden</string>
|
||||||
<string name="notifications">Notifikationer</string>
|
<string name="notifications">Notifikationer</string>
|
||||||
|
|
@ -413,7 +413,7 @@
|
||||||
<string name="deletion_reason_not_interesting">Beklager dette billede er ikke interessant for en encyklopædi</string>
|
<string name="deletion_reason_not_interesting">Beklager dette billede er ikke interessant for en encyklopædi</string>
|
||||||
<string name="uploaded_by_myself">Uploadet af mig selv på %1$s , brugt i %2$d artikel(er).</string>
|
<string name="uploaded_by_myself">Uploadet af mig selv på %1$s , brugt i %2$d artikel(er).</string>
|
||||||
<string name="no_uploads">Velkommen til Commons!\n\nUpload dit første medie ved at trykke på Tilføj-knappen.</string>
|
<string name="no_uploads">Velkommen til Commons!\n\nUpload dit første medie ved at trykke på Tilføj-knappen.</string>
|
||||||
<string name="no_categories_selected">Ingen valgte kategorier</string>
|
<string name="no_categories_selected">Ingen kategorier valgt</string>
|
||||||
<string name="no_categories_selected_warning_desc">Billeder uden kategorier er sjældent brugbare. Er du sikker på, at du vil fortsætte uden at vælge kategorier?</string>
|
<string name="no_categories_selected_warning_desc">Billeder uden kategorier er sjældent brugbare. Er du sikker på, at du vil fortsætte uden at vælge kategorier?</string>
|
||||||
<string name="no_depictions_selected">Ingen afbildninger valgt</string>
|
<string name="no_depictions_selected">Ingen afbildninger valgt</string>
|
||||||
<string name="no_depictions_selected_warning_desc">Billeder med afbildninger er lettere at finde og mere tilbøjelige til at blive brugt. Er du sikker på, at du vil fortsætte uden at vælge afbildninger?</string>
|
<string name="no_depictions_selected_warning_desc">Billeder med afbildninger er lettere at finde og mere tilbøjelige til at blive brugt. Er du sikker på, at du vil fortsætte uden at vælge afbildninger?</string>
|
||||||
|
|
@ -497,7 +497,7 @@
|
||||||
<string name="download_failed_we_cannot_download_the_file_without_storage_permission">Download mislykkedes!!. Vi kan ikke downloade filen uden tilladelse til ekstern lagring.</string>
|
<string name="download_failed_we_cannot_download_the_file_without_storage_permission">Download mislykkedes!!. Vi kan ikke downloade filen uden tilladelse til ekstern lagring.</string>
|
||||||
<string name="manage_exif_tags">Administrer EXIF-tags</string>
|
<string name="manage_exif_tags">Administrer EXIF-tags</string>
|
||||||
<string name="manage_exif_tags_summary">Vælg hvilke EXIF-tags, der skal beholdes i uploads</string>
|
<string name="manage_exif_tags_summary">Vælg hvilke EXIF-tags, der skal beholdes i uploads</string>
|
||||||
<string name="exif_tag_name_author">Ophavsmand</string>
|
<string name="exif_tag_name_author">Forfatter</string>
|
||||||
<string name="exif_tag_name_copyright">Ophavsret</string>
|
<string name="exif_tag_name_copyright">Ophavsret</string>
|
||||||
<string name="exif_tag_name_location">Placering</string>
|
<string name="exif_tag_name_location">Placering</string>
|
||||||
<string name="exif_tag_name_cameraModel">Kameramodel</string>
|
<string name="exif_tag_name_cameraModel">Kameramodel</string>
|
||||||
|
|
@ -609,7 +609,7 @@
|
||||||
<string name="wikipedia_instructions_step_2">2. Hvis du klikker på Bekræft, åbnes Wikipedia-artiklen</string>
|
<string name="wikipedia_instructions_step_2">2. Hvis du klikker på Bekræft, åbnes Wikipedia-artiklen</string>
|
||||||
<string name="wikipedia_instructions_step_3">3. Find en passende sektion i artiklen til dit billede</string>
|
<string name="wikipedia_instructions_step_3">3. Find en passende sektion i artiklen til dit billede</string>
|
||||||
<string name="wikipedia_instructions_step_4">4. Klik på Rediger-ikonet (det som ligner en blyant) for den sektion.</string>
|
<string name="wikipedia_instructions_step_4">4. Klik på Rediger-ikonet (det som ligner en blyant) for den sektion.</string>
|
||||||
<string name="wikipedia_instructions_step_5">5. Indsæt wikiteksten på det rigtige sted.</string>
|
<string name="wikipedia_instructions_step_5">5. Indsæt wikiteksten på det rette sted.</string>
|
||||||
<string name="wikipedia_instructions_step_6">6. Rediger wikiteksten for passende placering, hvis det er nødvendigt. For mere information, se <a href=\"https://en.wikipedia.org/wiki/Wikipedia:Manual_of_Style/Images#How_to_place_an_image\">her</a>.</string>
|
<string name="wikipedia_instructions_step_6">6. Rediger wikiteksten for passende placering, hvis det er nødvendigt. For mere information, se <a href=\"https://en.wikipedia.org/wiki/Wikipedia:Manual_of_Style/Images#How_to_place_an_image\">her</a>.</string>
|
||||||
<string name="wikipedia_instructions_step_7">7. Udgiv artiklen</string>
|
<string name="wikipedia_instructions_step_7">7. Udgiv artiklen</string>
|
||||||
<string name="copy_wikicode_to_clipboard">Kopier wikikode til udklipsholder</string>
|
<string name="copy_wikicode_to_clipboard">Kopier wikikode til udklipsholder</string>
|
||||||
|
|
@ -660,7 +660,7 @@
|
||||||
<string name="app_ui_language">Appens brugergrænsefladesprog</string>
|
<string name="app_ui_language">Appens brugergrænsefladesprog</string>
|
||||||
<string name="remove">Fjerner en billedtekst og beskrivelse</string>
|
<string name="remove">Fjerner en billedtekst og beskrivelse</string>
|
||||||
<string name="read_help_link">Læs mere</string>
|
<string name="read_help_link">Læs mere</string>
|
||||||
<string name="media_detail_in_all_languages">For alle sprog</string>
|
<string name="media_detail_in_all_languages">På alle sprog</string>
|
||||||
<string name="choose_a_location">Vælg en placering</string>
|
<string name="choose_a_location">Vælg en placering</string>
|
||||||
<string name="pan_and_zoom_to_adjust">Panorer og zoom for at justere</string>
|
<string name="pan_and_zoom_to_adjust">Panorer og zoom for at justere</string>
|
||||||
<string name="select_location_location_picker">Vælg placering</string>
|
<string name="select_location_location_picker">Vælg placering</string>
|
||||||
|
|
@ -718,7 +718,7 @@
|
||||||
<string name="device_model">Enhedsmodel</string>
|
<string name="device_model">Enhedsmodel</string>
|
||||||
<string name="device_name">Enhedsnavn</string>
|
<string name="device_name">Enhedsnavn</string>
|
||||||
<string name="network_type">Netværkstype</string>
|
<string name="network_type">Netværkstype</string>
|
||||||
<string name="thanks_feedback">Tak for tilbagemeldingen</string>
|
<string name="thanks_feedback">Tak for din feedback</string>
|
||||||
<string name="error_feedback">Fejl under afsendelse af feedback</string>
|
<string name="error_feedback">Fejl under afsendelse af feedback</string>
|
||||||
<string name="enter_description">Hvad er din feedback?</string>
|
<string name="enter_description">Hvad er din feedback?</string>
|
||||||
<string name="your_feedback">Din feedback</string>
|
<string name="your_feedback">Din feedback</string>
|
||||||
|
|
@ -758,8 +758,8 @@
|
||||||
<string name="remove_location_warning_title">Fjern placering-advarsel</string>
|
<string name="remove_location_warning_title">Fjern placering-advarsel</string>
|
||||||
<string name="remove_location_warning_desc">Placering gør billeder mere nyttige og nemmere at finde. Ønsker du virkelig at fjerne placering fra dette billede?</string>
|
<string name="remove_location_warning_desc">Placering gør billeder mere nyttige og nemmere at finde. Ønsker du virkelig at fjerne placering fra dette billede?</string>
|
||||||
<string name="location_removed">Placering fjernet!</string>
|
<string name="location_removed">Placering fjernet!</string>
|
||||||
<string name="send_thanks_to_author">Tak ophavsmanden</string>
|
<string name="send_thanks_to_author">Tak forfatteren</string>
|
||||||
<string name="error_sending_thanks">Fejl ved afsendelse af tak til ophavsmand.</string>
|
<string name="error_sending_thanks">Fejl ved afsendelse af tak til forfatter.</string>
|
||||||
<string name="invalid_login_message">Login udløb. Log venligst ind igen.</string>
|
<string name="invalid_login_message">Login udløb. Log venligst ind igen.</string>
|
||||||
<string name="no_application_available_to_open_gpx_files">Der er ingen tilgængelig applikation til at åbne GPX-filer</string>
|
<string name="no_application_available_to_open_gpx_files">Der er ingen tilgængelig applikation til at åbne GPX-filer</string>
|
||||||
<string name="file_saved_successfully">Fil gemt</string>
|
<string name="file_saved_successfully">Fil gemt</string>
|
||||||
|
|
@ -775,5 +775,13 @@
|
||||||
</plurals>
|
</plurals>
|
||||||
<string name="multiple_files_depiction">Husk, at alle billeder i et multi-upload får de samme kategorier og afbildninger. Hvis billederne ikke deler afbildninger og kategorier, skal du udføre flere separate uploads.</string>
|
<string name="multiple_files_depiction">Husk, at alle billeder i et multi-upload får de samme kategorier og afbildninger. Hvis billederne ikke deler afbildninger og kategorier, skal du udføre flere separate uploads.</string>
|
||||||
<string name="multiple_files_depiction_header">Bemærkning om at uploade flere billeder</string>
|
<string name="multiple_files_depiction_header">Bemærkning om at uploade flere billeder</string>
|
||||||
|
<string name="nearby_wikitalk">Rapporter et problem med dette element til Wikidata</string>
|
||||||
|
<string name="please_enter_some_comments">Skriv nogle kommentarer</string>
|
||||||
|
<string name="talk">Tal</string>
|
||||||
|
<string name="write_something_about_the">\"Skriv noget om\"</string>
|
||||||
|
<string name="item_it_will_be_publicly_visible">\" elementet. Det vil være offentligt synligt.\"</string>
|
||||||
|
<string name="does_not_exist_anymore_no_picture_can_ever_be_taken_of_it">\'%1$s\' eksisterer ikke længere, der kan aldrig tages et billede af det.</string>
|
||||||
|
<string name="is_at_a_different_place_please_specify_the_correct_place_below_if_possible_tell_us_the_correct_latitude_longitude">\'%1$s\' ligger et andet sted (angiv venligst det korrekte sted nedenfor, fortæl os om muligt den korrekte breddegrad/længdegrad).</string>
|
||||||
|
<string name="other_problem_or_information_please_explain_below">Andet problem eller anden information (forklar venligst nedenfor).</string>
|
||||||
<string name="feedback_destination_note">Din feedback bliver slået op på følgende wiki-side: <a href=\"https://commons.wikimedia.org/wiki/Commons:Mobile_app/Feedback\">Commons:Mobile app/Feedback</a></string>
|
<string name="feedback_destination_note">Din feedback bliver slået op på følgende wiki-side: <a href=\"https://commons.wikimedia.org/wiki/Commons:Mobile_app/Feedback\">Commons:Mobile app/Feedback</a></string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
* FF11
|
* FF11
|
||||||
* Ferdinand0101
|
* Ferdinand0101
|
||||||
* Icke
|
* Icke
|
||||||
|
* Ignatgg
|
||||||
* Inkowik
|
* Inkowik
|
||||||
* Justman10000
|
* Justman10000
|
||||||
* Kghbln
|
* Kghbln
|
||||||
|
|
@ -800,4 +801,5 @@
|
||||||
</plurals>
|
</plurals>
|
||||||
<string name="multiple_files_depiction">Bitte beachte, dass bei einem Multiupload alle Bilder die gleichen Kategorien und Bezeichnungen erhalten. Sollten die Bilder keine gemeinsamen Bezeichnungen und Kategorien haben, führe bitte mehrere separate Uploads durch.</string>
|
<string name="multiple_files_depiction">Bitte beachte, dass bei einem Multiupload alle Bilder die gleichen Kategorien und Bezeichnungen erhalten. Sollten die Bilder keine gemeinsamen Bezeichnungen und Kategorien haben, führe bitte mehrere separate Uploads durch.</string>
|
||||||
<string name="multiple_files_depiction_header">Hinweis zu Mehrfach-Uploads</string>
|
<string name="multiple_files_depiction_header">Hinweis zu Mehrfach-Uploads</string>
|
||||||
|
<string name="feedback_destination_note">Ihr Feedback wird auf der folgenden Wiki-Seite veröffentlicht: <a href=\"https://commons.wikimedia.org/wiki/Commons:Mobile_app/Feedback\">Commons:Mobile App/Feedback</a></string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -707,7 +707,7 @@
|
||||||
<string name="back">חזרה</string>
|
<string name="back">חזרה</string>
|
||||||
<string name="welcome_custom_picture_selector_text">ברוך בואך לבוחר התמונות המותאמות</string>
|
<string name="welcome_custom_picture_selector_text">ברוך בואך לבוחר התמונות המותאמות</string>
|
||||||
<string name="custom_selector_info_text1">הבורר מציג לך אילו תמונות כבר העלית לוויקישיתוף.</string>
|
<string name="custom_selector_info_text1">הבורר מציג לך אילו תמונות כבר העלית לוויקישיתוף.</string>
|
||||||
<string name="custom_selector_info_text2">בניגוד לתמונה מימין, על התמונה שמשמאל יש את הלוגו של ויקישיתוף שמעיד שהיא כבר הועלתה. יש לגעת ולהחזיר לקבלת תצוגה מקדימה של התמונה.</string>
|
<string name="custom_selector_info_text2">בניגוד לתמונה מימין, על התמונה שמשמאל מופיע הסמל של ויקישיתוף שמציין שהיא כבר הועלתה. יש לגעת ולהחזיק לקבלת תצוגה מקדימה של התמונה.</string>
|
||||||
<string name="welcome_custom_selector_ok">מגניב</string>
|
<string name="welcome_custom_selector_ok">מגניב</string>
|
||||||
<string name="custom_selector_already_uploaded_image_text">התמונה הזאת כבר הועלתה לוויקישיתוף.</string>
|
<string name="custom_selector_already_uploaded_image_text">התמונה הזאת כבר הועלתה לוויקישיתוף.</string>
|
||||||
<string name="custom_selector_over_limit_warning">מסיבות טכניות, היישום לא יכול להעלות יותר מ־%1$d תמונות בבת אחת בצורה מהימנה. חרגת ממגבלת ההעלאה על סך %1$d ב־%2$d.</string>
|
<string name="custom_selector_over_limit_warning">מסיבות טכניות, היישום לא יכול להעלות יותר מ־%1$d תמונות בבת אחת בצורה מהימנה. חרגת ממגבלת ההעלאה על סך %1$d ב־%2$d.</string>
|
||||||
|
|
@ -807,5 +807,11 @@
|
||||||
</plurals>
|
</plurals>
|
||||||
<string name="multiple_files_depiction">נא לזכור שכשמועלות כמה תמונות, כולן מקבלות את אותן הקטגוריות והמוצגים. אם התמונות אינן חולקות מוצגים וקטגוריות, נא לעשות כמה העלאות נפרדות.</string>
|
<string name="multiple_files_depiction">נא לזכור שכשמועלות כמה תמונות, כולן מקבלות את אותן הקטגוריות והמוצגים. אם התמונות אינן חולקות מוצגים וקטגוריות, נא לעשות כמה העלאות נפרדות.</string>
|
||||||
<string name="multiple_files_depiction_header">הערה על העלאות מרובות</string>
|
<string name="multiple_files_depiction_header">הערה על העלאות מרובות</string>
|
||||||
|
<string name="nearby_wikitalk">דווח על בעיה בפריט הזה לוויקינתונים</string>
|
||||||
|
<string name="please_enter_some_comments">נא להזין הערות כלשהן</string>
|
||||||
|
<string name="talk">שיחה</string>
|
||||||
|
<string name="write_something_about_the">\"נא לכתוב משהו על הפריט \"</string>
|
||||||
|
<string name="item_it_will_be_publicly_visible">\" . זה יהיה גלוי לציבור.\"</string>
|
||||||
|
<string name="does_not_exist_anymore_no_picture_can_ever_be_taken_of_it">\"%1$s\" כבר לא קיים, אי־אפשר לצלם אותו.</string>
|
||||||
<string name="feedback_destination_note">המשוב שלך מתפרסם בדף הוויקי הבא: <a href=\"https://commons.wikimedia.org/wiki/Commons:Mobile_app/Feedback\">Commons:Mobile app/Feedback</a></string>
|
<string name="feedback_destination_note">המשוב שלך מתפרסם בדף הוויקי הבא: <a href=\"https://commons.wikimedia.org/wiki/Commons:Mobile_app/Feedback\">Commons:Mobile app/Feedback</a></string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -771,5 +771,13 @@
|
||||||
</plurals>
|
</plurals>
|
||||||
<string name="multiple_files_depiction">Запомнете дека сите слики што ги подигате наеднаш се очекуваат да ја прикажуваат истата работа и ги добиваат истите категории и описи. Ако сликите прикажуваат различни нешта и треба да имаат различни категории, извршете неколку одделни подигања.</string>
|
<string name="multiple_files_depiction">Запомнете дека сите слики што ги подигате наеднаш се очекуваат да ја прикажуваат истата работа и ги добиваат истите категории и описи. Ако сликите прикажуваат различни нешта и треба да имаат различни категории, извршете неколку одделни подигања.</string>
|
||||||
<string name="multiple_files_depiction_header">Напомена за подигање повеќе слики наеднаш</string>
|
<string name="multiple_files_depiction_header">Напомена за подигање повеќе слики наеднаш</string>
|
||||||
|
<string name="nearby_wikitalk">Пријавете проблем со овој предмет на Википодатоци</string>
|
||||||
|
<string name="please_enter_some_comments">Внесете коментар</string>
|
||||||
|
<string name="talk">Разговор</string>
|
||||||
|
<string name="write_something_about_the">„Напишете нешто за предметот “</string>
|
||||||
|
<string name="item_it_will_be_publicly_visible">“. Ова ќе биде јавно видливо.“</string>
|
||||||
|
<string name="does_not_exist_anymore_no_picture_can_ever_be_taken_of_it">„%1$s“ повеќе не постои, нема да може да се фотографира.</string>
|
||||||
|
<string name="is_at_a_different_place_please_specify_the_correct_place_below_if_possible_tell_us_the_correct_latitude_longitude">„%1$s“ се наоѓа на друго место (подолу укажете го сегашното место, ако е можно со географска ширина и должина).</string>
|
||||||
|
<string name="other_problem_or_information_please_explain_below">Друг проблем или информација (објаснете подолу).</string>
|
||||||
<string name="feedback_destination_note">Вашите мислења се објавуваат на следнава викистраница: <a href=\"https://commons.wikimedia.org/wiki/Commons:Mobile_app/Feedback\">Commons:Mobile app/Feedback</a></string>
|
<string name="feedback_destination_note">Вашите мислења се објавуваат на следнава викистраница: <a href=\"https://commons.wikimedia.org/wiki/Commons:Mobile_app/Feedback\">Commons:Mobile app/Feedback</a></string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -204,4 +204,6 @@
|
||||||
<string name="explore_map_details">{{Identical|Detail}}</string>
|
<string name="explore_map_details">{{Identical|Detail}}</string>
|
||||||
<string name="set_up_avatar_toast_string">\"Set as avatar\" should be translated the same as {{msg-wm|Commons-android-strings-menu set avatar}}.</string>
|
<string name="set_up_avatar_toast_string">\"Set as avatar\" should be translated the same as {{msg-wm|Commons-android-strings-menu set avatar}}.</string>
|
||||||
<string name="multiple_files_depiction">{{Doc-commons-app-depicts}}</string>
|
<string name="multiple_files_depiction">{{Doc-commons-app-depicts}}</string>
|
||||||
|
<string name="write_something_about_the">Shown before {{msg-wm|Commons-android-strings-item it will be publicly visible}}. Between them, the item name is shown.</string>
|
||||||
|
<string name="item_it_will_be_publicly_visible">Shown after {{msg-wm|Commons-android-strings-write something about the}}. Between them, the item name is shown.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -731,4 +731,6 @@
|
||||||
<item quantity="one">%d слика је одабрана</item>
|
<item quantity="one">%d слика је одабрана</item>
|
||||||
<item quantity="other">%d слика је одабрано</item>
|
<item quantity="other">%d слика је одабрано</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
|
<string name="talk">Разговор</string>
|
||||||
|
<string name="does_not_exist_anymore_no_picture_can_ever_be_taken_of_it">„%1$s” не постоји више, и није га могуће више сликати.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -820,6 +820,14 @@ Upload your first media by tapping on the add button.</string>
|
||||||
<string name="multiple_files_depiction_header">Note about multi-uploads</string>
|
<string name="multiple_files_depiction_header">Note about multi-uploads</string>
|
||||||
<!-- TODO: Remove or change this placeholder text -->
|
<!-- TODO: Remove or change this placeholder text -->
|
||||||
<string name="hello_blank_fragment">Hello blank fragment</string>
|
<string name="hello_blank_fragment">Hello blank fragment</string>
|
||||||
|
<string name="nearby_wikitalk">Report a problem about this item to Wikidata</string>
|
||||||
|
<string name="please_enter_some_comments">Please enter some comments</string>
|
||||||
|
<string name="talk">Talk</string>
|
||||||
|
<string name="write_something_about_the">"Write something about the "</string>
|
||||||
|
<string name="item_it_will_be_publicly_visible">" item. It will be publicly visible."</string>
|
||||||
|
<string name="does_not_exist_anymore_no_picture_can_ever_be_taken_of_it">\'%1$s\' does not exist anymore, no picture can ever be taken of it.</string>
|
||||||
|
<string name="is_at_a_different_place_please_specify_the_correct_place_below_if_possible_tell_us_the_correct_latitude_longitude">\'%1$s\' is at a different place. Please specify the correct place below, and if possible, write the correct latitude and longitude.</string>
|
||||||
|
<string name="other_problem_or_information_please_explain_below">Other problem or information (please explain below).</string>
|
||||||
<string name="feedback_destination_note">Your feedback gets posted to the following wiki page: <![CDATA[ <a href="https://commons.wikimedia.org/wiki/Commons:Mobile_app/Feedback">Commons:Mobile app/Feedback</a> ]]></string>
|
<string name="feedback_destination_note">Your feedback gets posted to the following wiki page: <![CDATA[ <a href="https://commons.wikimedia.org/wiki/Commons:Mobile_app/Feedback">Commons:Mobile app/Feedback</a> ]]></string>
|
||||||
<string name="are_you_sure_that_you_want_cancel_all_the_uploads">Are you sure that you want cancel all the uploads?</string>
|
<string name="are_you_sure_that_you_want_cancel_all_the_uploads">Are you sure that you want cancel all the uploads?</string>
|
||||||
<string name="cancelling_all_the_uploads">Cancelling all the uploads...</string>
|
<string name="cancelling_all_the_uploads">Cancelling all the uploads...</string>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue