diff --git a/.travis.yml b/.travis.yml
index bdf6f0634..e1c34ac7d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -15,7 +15,7 @@ android:
components:
- tools
- platform-tools
- - build-tools-28.0.3
+ - build-tools-29.0.2
- extra-google-m2repository
- extra-android-m2repository
- android-22
diff --git a/app/build.gradle b/app/build.gradle
index 1464de56b..d4758f332 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -134,7 +134,6 @@ dependencies {
android {
compileSdkVersion 28
- buildToolsVersion "28.0.3"
defaultConfig {
//applicationId 'fr.free.nrw.commons'
@@ -152,7 +151,6 @@ android {
testOptions {
execution 'ANDROIDX_TEST_ORCHESTRATOR'
}
- multiDexEnabled true
vectorDrawables.useSupportLibrary = true
}
diff --git a/app/src/main/java/fr/free/nrw/commons/Media.java b/app/src/main/java/fr/free/nrw/commons/Media.java
index 032f3fb93..87f8c268e 100644
--- a/app/src/main/java/fr/free/nrw/commons/Media.java
+++ b/app/src/main/java/fr/free/nrw/commons/Media.java
@@ -285,6 +285,14 @@ public class Media implements Parcelable {
this.coordinates = coordinates;
}
+ /**
+ * Returns wikicode to use the media file on a MediaWiki site
+ * @return
+ */
+ public String getWikiCode() {
+ return String.format("[[%s|thumb|%s]]", filename, getDisplayTitle());
+ }
+
/**
* Sets the categories the file falls under.
*
diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionDao.java b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionDao.java
index e288a84af..20de34eb9 100644
--- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionDao.java
+++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionDao.java
@@ -53,6 +53,9 @@ public abstract class ContributionDao {
@Query("SELECT * from contribution WHERE filename=:fileName")
public abstract List getContributionWithTitle(String fileName);
+ @Query("SELECT * from contribution WHERE pageId=:pageId")
+ public abstract Contribution getContribution(String pageId);
+
@Query("UPDATE contribution SET state=:state WHERE state in (:toUpdateStates)")
public abstract Single updateStates(int state, int[] toUpdateStates);
diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionViewHolder.java b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionViewHolder.java
index 5bade13da..5d8aefa2f 100644
--- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionViewHolder.java
+++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionViewHolder.java
@@ -3,8 +3,9 @@ package fr.free.nrw.commons.contributions;
import android.net.Uri;
import android.text.TextUtils;
import android.view.View;
-import android.widget.LinearLayout;
+import android.widget.ImageButton;
import android.widget.ProgressBar;
+import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
@@ -17,137 +18,181 @@ import com.facebook.imagepipeline.request.ImageRequestBuilder;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.contributions.ContributionsListAdapter.Callback;
import fr.free.nrw.commons.media.MediaClient;
+import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
+import io.reactivex.schedulers.Schedulers;
public class ContributionViewHolder extends RecyclerView.ViewHolder {
- private final Callback callback;
- @BindView(R.id.contributionImage)
- SimpleDraweeView imageView;
- @BindView(R.id.contributionTitle) TextView titleView;
- @BindView(R.id.contributionState) TextView stateView;
- @BindView(R.id.contributionSequenceNumber) TextView seqNumView;
- @BindView(R.id.contributionProgress) ProgressBar progressView;
- @BindView(R.id.failed_image_options) LinearLayout failedImageOptions;
+ private final Callback callback;
+ @BindView(R.id.contributionImage)
+ SimpleDraweeView imageView;
+ @BindView(R.id.contributionTitle)
+ TextView titleView;
+ @BindView(R.id.contributionState)
+ TextView stateView;
+ @BindView(R.id.contributionSequenceNumber)
+ TextView seqNumView;
+ @BindView(R.id.contributionProgress)
+ ProgressBar progressView;
+ @BindView(R.id.image_options)
+ RelativeLayout imageOptions;
+ @BindView(R.id.wikipediaButton)
+ ImageButton addToWikipediaButton;
+ @BindView(R.id.retryButton)
+ ImageButton retryButton;
+ @BindView(R.id.cancelButton)
+ ImageButton cancelButton;
- private int position;
- private Contribution contribution;
- private final CompositeDisposable compositeDisposable = new CompositeDisposable();
- private final MediaClient mediaClient;
+ private int position;
+ private Contribution contribution;
+ private final CompositeDisposable compositeDisposable = new CompositeDisposable();
+ private final MediaClient mediaClient;
- ContributionViewHolder(final View parent, final Callback callback,
- final MediaClient mediaClient) {
- super(parent);
- this.mediaClient = mediaClient;
- ButterKnife.bind(this, parent);
- this.callback=callback;
+ ContributionViewHolder(final View parent, final Callback callback,
+ final MediaClient mediaClient) {
+ super(parent);
+ this.mediaClient = mediaClient;
+ ButterKnife.bind(this, parent);
+ this.callback = callback;
+ }
+
+ public void init(final int position, final Contribution contribution) {
+ this.contribution = contribution;
+ this.position = position;
+ titleView.setText(getTitle(contribution));
+ final String imageSource = chooseImageSource(contribution.getThumbUrl(),
+ contribution.getLocalUri());
+ if (!TextUtils.isEmpty(imageSource)) {
+ final ImageRequest imageRequest =
+ ImageRequestBuilder.newBuilderWithSource(Uri.parse(imageSource))
+ .setProgressiveRenderingEnabled(true)
+ .build();
+ imageView.setImageRequest(imageRequest);
}
- public void init(final int position, final Contribution contribution) {
- this.contribution = contribution;
- fetchAndDisplayCaption(contribution);
- this.position = position;
- final String imageSource = chooseImageSource(contribution.getThumbUrl(), contribution.getLocalUri());
- if (!TextUtils.isEmpty(imageSource)) {
- final ImageRequest imageRequest =
- ImageRequestBuilder.newBuilderWithSource(Uri.parse(imageSource))
- .setProgressiveRenderingEnabled(true)
- .build();
- imageView.setImageRequest(imageRequest);
- }
+ seqNumView.setText(String.valueOf(position + 1));
+ seqNumView.setVisibility(View.VISIBLE);
- seqNumView.setText(String.valueOf(position + 1));
- seqNumView.setVisibility(View.VISIBLE);
-
- switch (contribution.getState()) {
- case Contribution.STATE_COMPLETED:
- stateView.setVisibility(View.GONE);
- progressView.setVisibility(View.GONE);
- failedImageOptions.setVisibility(View.GONE);
- stateView.setText("");
- break;
- case Contribution.STATE_QUEUED:
- stateView.setVisibility(View.VISIBLE);
- progressView.setVisibility(View.GONE);
- stateView.setText(R.string.contribution_state_queued);
- failedImageOptions.setVisibility(View.GONE);
- break;
- case Contribution.STATE_IN_PROGRESS:
- stateView.setVisibility(View.GONE);
- progressView.setVisibility(View.VISIBLE);
- failedImageOptions.setVisibility(View.GONE);
- final long total = contribution.getDataLength();
- final long transferred = contribution.getTransferred();
- if (transferred == 0 || transferred >= total) {
- progressView.setIndeterminate(true);
- } else {
- progressView.setProgress((int)(((double)transferred / (double)total) * 100));
- }
- break;
- case Contribution.STATE_FAILED:
- stateView.setVisibility(View.VISIBLE);
- stateView.setText(R.string.contribution_state_failed);
- progressView.setVisibility(View.GONE);
- failedImageOptions.setVisibility(View.VISIBLE);
- break;
- }
- }
-
- /**
- * In contributions first we show the title for the image stored in cache,
- * then we fetch captions associated with the image and replace title on the thumbnail with caption
- *
- * @param contribution
- */
- private void fetchAndDisplayCaption(final Contribution contribution) {
- if ((contribution.getState() != Contribution.STATE_COMPLETED)) {
- titleView.setText(contribution.getDisplayTitle());
+ addToWikipediaButton.setVisibility(View.GONE);
+ switch (contribution.getState()) {
+ case Contribution.STATE_COMPLETED:
+ stateView.setVisibility(View.GONE);
+ progressView.setVisibility(View.GONE);
+ imageOptions.setVisibility(View.GONE);
+ stateView.setText("");
+ checkIfMediaExistsOnWikipediaPage(contribution);
+ break;
+ case Contribution.STATE_QUEUED:
+ stateView.setVisibility(View.VISIBLE);
+ progressView.setVisibility(View.GONE);
+ stateView.setText(R.string.contribution_state_queued);
+ imageOptions.setVisibility(View.GONE);
+ break;
+ case Contribution.STATE_IN_PROGRESS:
+ stateView.setVisibility(View.GONE);
+ progressView.setVisibility(View.VISIBLE);
+ imageOptions.setVisibility(View.GONE);
+ final long total = contribution.getDataLength();
+ final long transferred = contribution.getTransferred();
+ if (transferred == 0 || transferred >= total) {
+ progressView.setIndeterminate(true);
} else {
- titleView.setText(getTitle(contribution));
+ progressView.setProgress((int) (((double) transferred / (double) total) * 100));
}
+ break;
+ case Contribution.STATE_FAILED:
+ stateView.setVisibility(View.VISIBLE);
+ stateView.setText(R.string.contribution_state_failed);
+ progressView.setVisibility(View.GONE);
+ imageOptions.setVisibility(View.VISIBLE);
+ break;
}
+ }
- private String getTitle(Contribution contribution) {
- for (String value : contribution.getCaptions().values()) {
- return value;
- }
- return contribution.getDisplayTitle();
+ private String getTitle(Contribution contribution) {
+ for (String value : contribution.getCaptions().values()) {
+ return value;
}
+ return contribution.getDisplayTitle();
+ }
- /**
- * Returns the image source for the image view, first preference is given to thumbUrl if that is
- * null, moves to local uri and if both are null return null
- *
- * @param thumbUrl
- * @param localUri
- * @return
- */
- @Nullable
- private String chooseImageSource(final String thumbUrl, final Uri localUri) {
- return !TextUtils.isEmpty(thumbUrl) ? thumbUrl :
- localUri != null ? localUri.toString() :
- null;
- }
- /**
- * Retry upload when it is failed
- */
- @OnClick(R.id.retryButton)
- public void retryUpload() {
- callback.retryUpload(contribution);
+ /**
+ * Checks if a media exists on the corresponding Wikipedia article Currently the check is made for
+ * the device's current language Wikipedia
+ *
+ * @param contribution
+ */
+ private void checkIfMediaExistsOnWikipediaPage(final Contribution contribution) {
+ if (contribution.getWikidataPlace() == null
+ || contribution.getWikidataPlace().getWikipediaArticle() == null) {
+ return;
}
+ final String wikipediaArticle = contribution.getWikidataPlace().getWikipediaPageTitle();
+ compositeDisposable.add(mediaClient.doesPageContainMedia(wikipediaArticle)
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(mediaExists -> {
+ displayWikipediaButton(mediaExists);
+ }));
+ }
- /**
- * Delete a failed upload attempt
- */
- @OnClick(R.id.cancelButton)
- public void deleteUpload() {
- callback.deleteUpload(contribution);
+ /**
+ * Handle action buttons visibility if the corresponding wikipedia page doesn't contain any media.
+ * This method needs to control the state of just the scenario where media does not exists as
+ * other scenarios are already handled in the init method.
+ *
+ * @param mediaExists
+ */
+ private void displayWikipediaButton(Boolean mediaExists) {
+ if (!mediaExists) {
+ addToWikipediaButton.setVisibility(View.VISIBLE);
+ cancelButton.setVisibility(View.GONE);
+ retryButton.setVisibility(View.GONE);
+ imageOptions.setVisibility(View.VISIBLE);
}
+ }
- @OnClick(R.id.contributionImage)
- public void imageClicked(){
- callback.openMediaDetail(position);
- }
+ /**
+ * Returns the image source for the image view, first preference is given to thumbUrl if that is
+ * null, moves to local uri and if both are null return null
+ *
+ * @param thumbUrl
+ * @param localUri
+ * @return
+ */
+ @Nullable
+ private String chooseImageSource(final String thumbUrl, final Uri localUri) {
+ return !TextUtils.isEmpty(thumbUrl) ? thumbUrl :
+ localUri != null ? localUri.toString() :
+ null;
+ }
+
+ /**
+ * Retry upload when it is failed
+ */
+ @OnClick(R.id.retryButton)
+ public void retryUpload() {
+ callback.retryUpload(contribution);
+ }
+
+ /**
+ * Delete a failed upload attempt
+ */
+ @OnClick(R.id.cancelButton)
+ public void deleteUpload() {
+ callback.deleteUpload(contribution);
+ }
+
+ @OnClick(R.id.contributionImage)
+ public void imageClicked() {
+ callback.openMediaDetail(position);
+ }
+
+ @OnClick(R.id.wikipediaButton)
+ public void wikipediaButtonClicked() {
+ callback.addImageToWikipedia(contribution);
+ }
}
diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsFragment.java b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsFragment.java
index 8e3221ea9..1c445852d 100644
--- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsFragment.java
+++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsFragment.java
@@ -223,7 +223,7 @@ public class ContributionsFragment
private void initFragments() {
if (null == contributionsListFragment) {
- contributionsListFragment = new ContributionsListFragment(this);
+ contributionsListFragment = new ContributionsListFragment();
}
if (shouldShowMediaDetailsFragment) {
diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListAdapter.java b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListAdapter.java
index bf44c7c65..0b777043b 100644
--- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListAdapter.java
+++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListAdapter.java
@@ -7,8 +7,9 @@ import androidx.paging.PagedListAdapter;
import androidx.recyclerview.widget.DiffUtil;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.media.MediaClient;
+import org.wikipedia.dataclient.WikiSite;
-/**
+ /**
* Represents The View Adapter for the List of Contributions
*/
public class ContributionsListAdapter extends
@@ -63,7 +64,8 @@ public class ContributionsListAdapter extends
final int viewType) {
final ContributionViewHolder viewHolder = new ContributionViewHolder(
LayoutInflater.from(parent.getContext())
- .inflate(R.layout.layout_contribution, parent, false), callback, mediaClient);
+ .inflate(R.layout.layout_contribution, parent, false),
+ callback, mediaClient);
return viewHolder;
}
@@ -74,5 +76,7 @@ public class ContributionsListAdapter extends
void deleteUpload(Contribution contribution);
void openMediaDetail(int contribution);
+
+ void addImageToWikipedia(Contribution contribution);
}
}
diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListFragment.java b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListFragment.java
index d707409e4..e1bb1968e 100644
--- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListFragment.java
+++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListFragment.java
@@ -2,8 +2,11 @@ package fr.free.nrw.commons.contributions;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
+import static fr.free.nrw.commons.di.NetworkingModule.NAMED_LANGUAGE_WIKI_PEDIA_WIKI_SITE;
+import android.content.Context;
import android.content.res.Configuration;
+import android.net.Uri;
import android.os.Bundle;
import android.os.Parcelable;
import android.view.LayoutInflater;
@@ -16,25 +19,29 @@ import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.fragment.app.FragmentManager;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
-import androidx.recyclerview.widget.RecyclerView.LayoutManager;
import butterknife.BindView;
import butterknife.ButterKnife;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import fr.free.nrw.commons.Media;
import fr.free.nrw.commons.R;
+import fr.free.nrw.commons.Utils;
import fr.free.nrw.commons.di.CommonsDaggerSupportFragment;
import fr.free.nrw.commons.media.MediaClient;
-import fr.free.nrw.commons.media.MediaDetailPagerFragment;
+import fr.free.nrw.commons.utils.DialogUtil;
+import java.util.Locale;
import javax.inject.Inject;
+import javax.inject.Named;
+import org.wikipedia.dataclient.WikiSite;
/**
* Created by root on 01.06.2018.
*/
public class ContributionsListFragment extends CommonsDaggerSupportFragment implements
- ContributionsListContract.View, ContributionsListAdapter.Callback {
+ ContributionsListContract.View, ContributionsListAdapter.Callback, WikipediaInstructionsDialogFragment.Callback {
private static final String RV_STATE = "rv_scroll_state";
@@ -58,6 +65,10 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment impl
@Inject
MediaClient mediaClient;
+ @Named(NAMED_LANGUAGE_WIKI_PEDIA_WIKI_SITE)
+ @Inject
+ WikiSite languageWikipediaSite;
+
@Inject
ContributionsListPresenter contributionsListPresenter;
@@ -71,14 +82,11 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment impl
private ContributionsListAdapter adapter;
- private final Callback callback;
+ private Callback callback;
private final int SPAN_COUNT_LANDSCAPE = 3;
private final int SPAN_COUNT_PORTRAIT = 1;
- ContributionsListFragment(final Callback callback) {
- this.callback = callback;
- }
public View onCreateView(
final LayoutInflater inflater, @Nullable final ViewGroup container,
@@ -90,6 +98,20 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment impl
return view;
}
+ @Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
+ if (getParentFragment() != null && getParentFragment() instanceof ContributionsFragment) {
+ callback = ((ContributionsFragment) getParentFragment());
+ }
+ }
+
+ @Override
+ public void onDetach() {
+ super.onDetach();
+ callback = null;//To avoid possible memory leak
+ }
+
private void initAdapter() {
adapter = new ContributionsListAdapter(this, mediaClient);
}
@@ -188,7 +210,8 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment impl
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
- final GridLayoutManager layoutManager = (GridLayoutManager) rvContributionsList.getLayoutManager();
+ final GridLayoutManager layoutManager = (GridLayoutManager) rvContributionsList
+ .getLayoutManager();
outState.putParcelable(RV_STATE, layoutManager.onSaveInstanceState());
}
@@ -203,7 +226,9 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment impl
@Override
public void retryUpload(final Contribution contribution) {
- callback.retryUpload(contribution);
+ if (null != callback) {//Just being safe, ideally they won't be called when detached
+ callback.retryUpload(contribution);
+ }
}
@Override
@@ -213,9 +238,44 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment impl
@Override
public void openMediaDetail(final int position) {
- callback.showDetail(position);
+ if (null != callback) {//Just being safe, ideally they won't be called when detached
+ callback.showDetail(position);
+ }
}
+ /**
+ * Handle callback for wikipedia icon clicked
+ *
+ * @param contribution
+ */
+ @Override
+ public void addImageToWikipedia(Contribution contribution) {
+ DialogUtil.showAlertDialog(getActivity(),
+ getString(R.string.add_picture_to_wikipedia_article_title),
+ String.format(getString(R.string.add_picture_to_wikipedia_article_desc),
+ Locale.getDefault().getDisplayLanguage()),
+ () -> {
+ showAddImageToWikipediaInstructions(contribution);
+ }, () -> {
+ // do nothing
+ });
+ }
+
+ /**
+ * Display confirmation dialog with instructions when the user tries to add image to wikipedia
+ *
+ * @param contribution
+ */
+ private void showAddImageToWikipediaInstructions(Contribution contribution) {
+ FragmentManager fragmentManager = getFragmentManager();
+ WikipediaInstructionsDialogFragment fragment = WikipediaInstructionsDialogFragment
+ .newInstance(contribution);
+ fragment.setCallback(this::onConfirmClicked);
+ fragment.show(fragmentManager, "WikimediaFragment");
+ }
+
+
+
public Media getMediaAtPosition(final int i) {
return adapter.getContributionForPosition(i);
}
@@ -224,6 +284,23 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment impl
return adapter.getItemCount();
}
+ /**
+ * Open the editor for the language Wikipedia
+ *
+ * @param contribution
+ */
+ @Override
+ public void onConfirmClicked(@Nullable Contribution contribution, boolean copyWikicode) {
+ if(copyWikicode) {
+ String wikicode = contribution.getWikiCode();
+ Utils.copy("wikicode", wikicode, getContext());
+ }
+
+ final String url = languageWikipediaSite.mobileUrl() + "/wiki/" + contribution.getWikidataPlace()
+ .getWikipediaPageTitle();
+ Utils.handleWebUrl(getContext(), Uri.parse(url));
+ }
+
public interface Callback {
void retryUpload(Contribution contribution);
diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsLocalDataSource.java b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsLocalDataSource.java
index 3b94d0fa7..5e21940b5 100644
--- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsLocalDataSource.java
+++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsLocalDataSource.java
@@ -2,6 +2,7 @@ package fr.free.nrw.commons.contributions;
import androidx.paging.DataSource.Factory;
import io.reactivex.Completable;
+import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
@@ -67,7 +68,15 @@ class ContributionsLocalDataSource {
}
public Single> saveContributions(List contributions) {
- return contributionDao.save(contributions);
+ List contributionList = new ArrayList<>();
+ for(Contribution contribution: contributions) {
+ Contribution oldContribution = contributionDao.getContribution(contribution.getPageId());
+ if(oldContribution != null) {
+ contribution.setWikidataPlace(oldContribution.getWikidataPlace());
+ }
+ contributionList.add(contribution);
+ }
+ return contributionDao.save(contributionList);
}
public void set(String key, long value) {
diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/WikipediaInstructionsDialogFragment.kt b/app/src/main/java/fr/free/nrw/commons/contributions/WikipediaInstructionsDialogFragment.kt
new file mode 100644
index 000000000..3032f718e
--- /dev/null
+++ b/app/src/main/java/fr/free/nrw/commons/contributions/WikipediaInstructionsDialogFragment.kt
@@ -0,0 +1,67 @@
+package fr.free.nrw.commons.contributions
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.view.WindowManager
+import androidx.fragment.app.DialogFragment
+import fr.free.nrw.commons.R
+import kotlinx.android.synthetic.main.dialog_add_to_wikipedia_instructions.*
+
+/**
+ * Dialog fragment for displaying instructions for editing wikipedia
+ */
+class WikipediaInstructionsDialogFragment : DialogFragment() {
+
+ var contribution: Contribution? = null
+ var callback: Callback? = null
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ return inflater.inflate(R.layout.dialog_add_to_wikipedia_instructions, container)
+ }
+
+ override fun onViewCreated(
+ view: View,
+ savedInstanceState: Bundle?
+ ) {
+ super.onViewCreated(view, savedInstanceState)
+ contribution = arguments!!.getParcelable(ARG_CONTRIBUTION)
+ tv_wikicode.setText(contribution?.wikiCode)
+ instructions_cancel.setOnClickListener {
+ dismiss()
+ }
+
+ instructions_confirm.setOnClickListener {
+ callback?.onConfirmClicked(contribution, checkbox_copy_wikicode.isChecked)
+ }
+
+ dialog!!.window.setSoftInputMode(
+ WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN
+ )
+ }
+
+ /**
+ * Callback for handling confirm button clicked
+ */
+ interface Callback {
+ fun onConfirmClicked(contribution: Contribution?, copyWikicode: Boolean)
+ }
+
+ companion object {
+
+ val ARG_CONTRIBUTION = "contribution"
+
+ @JvmStatic
+ fun newInstance(contribution: Contribution): WikipediaInstructionsDialogFragment {
+ val frag = WikipediaInstructionsDialogFragment()
+ val args = Bundle()
+ args.putParcelable(ARG_CONTRIBUTION, contribution)
+ frag.arguments = args
+ return frag
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/fr/free/nrw/commons/di/NetworkingModule.java b/app/src/main/java/fr/free/nrw/commons/di/NetworkingModule.java
index f2a95b9d4..495a8d01e 100644
--- a/app/src/main/java/fr/free/nrw/commons/di/NetworkingModule.java
+++ b/app/src/main/java/fr/free/nrw/commons/di/NetworkingModule.java
@@ -13,6 +13,7 @@ import fr.free.nrw.commons.explore.depictions.DepictsClient;
import fr.free.nrw.commons.kvstore.JsonKvStore;
import fr.free.nrw.commons.media.MediaDetailInterface;
import fr.free.nrw.commons.media.MediaInterface;
+import fr.free.nrw.commons.media.PageMediaInterface;
import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient;
import fr.free.nrw.commons.mwapi.UserInterface;
import fr.free.nrw.commons.review.ReviewInterface;
@@ -21,6 +22,7 @@ import fr.free.nrw.commons.upload.WikiBaseInterface;
import fr.free.nrw.commons.upload.depicts.DepictsInterface;
import fr.free.nrw.commons.wikidata.WikidataInterface;
import java.io.File;
+import java.util.Locale;
import java.util.concurrent.TimeUnit;
import javax.inject.Named;
import javax.inject.Singleton;
@@ -49,6 +51,9 @@ public class NetworkingModule {
public static final String NAMED_COMMONS_WIKI_SITE = "commons-wikisite";
private static final String NAMED_WIKI_DATA_WIKI_SITE = "wikidata-wikisite";
+ private static final String NAMED_WIKI_PEDIA_WIKI_SITE = "wikipedia-wikisite";
+
+ public static final String NAMED_LANGUAGE_WIKI_PEDIA_WIKI_SITE = "language-wikipedia-wikisite";
public static final String NAMED_COMMONS_CSRF = "commons-csrf";
@@ -234,4 +239,21 @@ public class NetworkingModule {
public WikidataInterface provideWikidataInterface(@Named(NAMED_WIKI_DATA_WIKI_SITE) WikiSite wikiDataWikiSite) {
return ServiceFactory.get(wikiDataWikiSite, BuildConfig.WIKIDATA_URL, WikidataInterface.class);
}
+
+ /**
+ * Add provider for PageMediaInterface
+ * It creates a retrofit service for the wiki site using device's current language
+ */
+ @Provides
+ @Singleton
+ public PageMediaInterface providePageMediaInterface(@Named(NAMED_LANGUAGE_WIKI_PEDIA_WIKI_SITE) WikiSite wikiSite) {
+ return ServiceFactory.get(wikiSite, wikiSite.url(), PageMediaInterface.class);
+ }
+
+ @Provides
+ @Singleton
+ @Named(NAMED_LANGUAGE_WIKI_PEDIA_WIKI_SITE)
+ public WikiSite provideLanguageWikipediaSite() {
+ return WikiSite.forLanguageCode(Locale.getDefault().getLanguage());
+ }
}
diff --git a/app/src/main/java/fr/free/nrw/commons/explore/BaseSearchFragment.kt b/app/src/main/java/fr/free/nrw/commons/explore/BaseSearchFragment.kt
index 377d8e40e..ae4c2cd9c 100644
--- a/app/src/main/java/fr/free/nrw/commons/explore/BaseSearchFragment.kt
+++ b/app/src/main/java/fr/free/nrw/commons/explore/BaseSearchFragment.kt
@@ -5,6 +5,7 @@ import android.content.res.Configuration
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
+import android.view.View.*
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.LiveData
@@ -67,11 +68,11 @@ abstract class BaseSearchFragment : CommonsDaggerSupportFragment(),
}
override fun hideInitialLoadProgress() {
- paginatedSearchInitialLoadProgress.visibility = View.GONE
+ paginatedSearchInitialLoadProgress.visibility = GONE
}
override fun showInitialLoadInProgress() {
- paginatedSearchInitialLoadProgress.visibility = View.VISIBLE
+ paginatedSearchInitialLoadProgress.visibility = VISIBLE
}
override fun showSnackbar() {
@@ -84,11 +85,11 @@ abstract class BaseSearchFragment : CommonsDaggerSupportFragment(),
override fun showEmptyText(query: String) {
contentNotFound.text = getString(emptyTemplateTextId, query)
- contentNotFound.visibility = View.VISIBLE
+ contentNotFound.visibility = VISIBLE
}
override fun hideEmptyText() {
- contentNotFound.visibility = View.GONE
+ contentNotFound.visibility = GONE
}
}
diff --git a/app/src/main/java/fr/free/nrw/commons/media/MediaClient.kt b/app/src/main/java/fr/free/nrw/commons/media/MediaClient.kt
index 293a2fc5a..f0fe5f3bd 100644
--- a/app/src/main/java/fr/free/nrw/commons/media/MediaClient.kt
+++ b/app/src/main/java/fr/free/nrw/commons/media/MediaClient.kt
@@ -19,6 +19,7 @@ import javax.inject.Singleton
@Singleton
class MediaClient @Inject constructor(
private val mediaInterface: MediaInterface,
+ private val pageMediaInterface: PageMediaInterface,
private val mediaDetailInterface: MediaDetailInterface,
private val mediaConverter: MediaConverter
) {
@@ -105,10 +106,12 @@ class MediaClient @Inject constructor(
* @return list of images for a particular depict entity
*/
fun fetchImagesForDepictedItem(query: String, sroffset: Int): Single> {
- return responseToMediaList(mediaInterface.fetchImagesForDepictedItem(
- "haswbstatement:" + BuildConfig.DEPICTS_PROPERTY + "=" + query,
- sroffset.toString()
- ))
+ return responseToMediaList(
+ mediaInterface.fetchImagesForDepictedItem(
+ "haswbstatement:" + BuildConfig.DEPICTS_PROPERTY + "=" + query,
+ sroffset.toString()
+ )
+ )
}
@@ -181,4 +184,9 @@ class MediaClient @Inject constructor(
val key = "user_$userName"
return if (continuationExists.containsKey(key)) continuationExists[key]!! else true
}
+
+ fun doesPageContainMedia(title: String?): Single {
+ return pageMediaInterface.getMediaList(title)
+ .map { it.items.isNotEmpty() }
+ }
}
diff --git a/app/src/main/java/fr/free/nrw/commons/media/MediaDetailFragment.java b/app/src/main/java/fr/free/nrw/commons/media/MediaDetailFragment.java
index cf96dfe87..0bd70b9ea 100644
--- a/app/src/main/java/fr/free/nrw/commons/media/MediaDetailFragment.java
+++ b/app/src/main/java/fr/free/nrw/commons/media/MediaDetailFragment.java
@@ -43,6 +43,7 @@ import fr.free.nrw.commons.MediaDataExtractor;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.Utils;
import fr.free.nrw.commons.auth.AccountUtil;
+import fr.free.nrw.commons.category.CategoryClient;
import fr.free.nrw.commons.category.CategoryDetailsActivity;
import fr.free.nrw.commons.contributions.ContributionsFragment;
import fr.free.nrw.commons.delete.DeleteHelper;
diff --git a/app/src/main/java/fr/free/nrw/commons/media/PageMediaInterface.kt b/app/src/main/java/fr/free/nrw/commons/media/PageMediaInterface.kt
new file mode 100644
index 000000000..2e8927778
--- /dev/null
+++ b/app/src/main/java/fr/free/nrw/commons/media/PageMediaInterface.kt
@@ -0,0 +1,19 @@
+package fr.free.nrw.commons.media
+
+import fr.free.nrw.commons.media.model.PageMediaListResponse
+import io.reactivex.Single
+import retrofit2.http.GET
+import retrofit2.http.Path
+
+/**
+ * Interface for MediaWiki Page REST APIs
+ */
+interface PageMediaInterface {
+ /**
+ * Get a list of media used on a page
+ *
+ * @param title the title of the page
+ */
+ @GET("api/rest_v1/page/media-list/{title}")
+ fun getMediaList(@Path("title") title: String?): Single
+}
diff --git a/app/src/main/java/fr/free/nrw/commons/media/model/PageMediaListResponse.kt b/app/src/main/java/fr/free/nrw/commons/media/model/PageMediaListResponse.kt
new file mode 100644
index 000000000..01306f05c
--- /dev/null
+++ b/app/src/main/java/fr/free/nrw/commons/media/model/PageMediaListResponse.kt
@@ -0,0 +1,9 @@
+package fr.free.nrw.commons.media.model
+
+data class PageMediaListResponse(
+ val revision: String,
+ val tid: String,
+ val items: List
+)
+
+data class PageMediaListItem(val title: String)
diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/Place.java b/app/src/main/java/fr/free/nrw/commons/nearby/Place.java
index 1af1c3af6..1da57e48e 100644
--- a/app/src/main/java/fr/free/nrw/commons/nearby/Place.java
+++ b/app/src/main/java/fr/free/nrw/commons/nearby/Place.java
@@ -125,7 +125,6 @@ public class Place implements Parcelable {
}
String wikiDataLink = siteLinks.getWikidataLink().toString();
- Timber.d("Wikidata entity is %s", wikiDataLink);
return wikiDataLink.replace("http://www.wikidata.org/entity/", "");
}
diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/fragments/NearbyParentFragment.java b/app/src/main/java/fr/free/nrw/commons/nearby/fragments/NearbyParentFragment.java
index 9094d8547..90fe7f598 100644
--- a/app/src/main/java/fr/free/nrw/commons/nearby/fragments/NearbyParentFragment.java
+++ b/app/src/main/java/fr/free/nrw/commons/nearby/fragments/NearbyParentFragment.java
@@ -1419,14 +1419,17 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
if (fabGallery.isShown()) {
Timber.d("Gallery button tapped. Place: %s", selectedPlace.toString());
storeSharedPrefs(selectedPlace);
+
controller.initiateGalleryPick(getActivity(), false);
}
});
}
private void storeSharedPrefs(final Place selectedPlace) {
- Timber.d("Store place object %s", selectedPlace.toString());
applicationKvStore.putJson(PLACE_OBJECT, selectedPlace);
+ Place place = applicationKvStore.getJson(PLACE_OBJECT, Place.class);
+
+ Timber.d("Stored place object %s", place.toString());
}
private void updateBookmarkButtonImage(final Place place) {
diff --git a/app/src/main/java/fr/free/nrw/commons/upload/UploadService.java b/app/src/main/java/fr/free/nrw/commons/upload/UploadService.java
index 0f88be382..58c8631d8 100644
--- a/app/src/main/java/fr/free/nrw/commons/upload/UploadService.java
+++ b/app/src/main/java/fr/free/nrw/commons/upload/UploadService.java
@@ -47,300 +47,335 @@ import timber.log.Timber;
public class UploadService extends CommonsDaggerService {
- private static final String EXTRA_PREFIX = "fr.free.nrw.commons.upload";
+ private static final String EXTRA_PREFIX = "fr.free.nrw.commons.upload";
- public static final String ACTION_START_SERVICE = EXTRA_PREFIX + ".upload";
- public static final String EXTRA_FILES = EXTRA_PREFIX + ".files";
- @Inject WikidataEditService wikidataEditService;
- @Inject SessionManager sessionManager;
- @Inject
- ContributionDao contributionDao;
- @Inject UploadClient uploadClient;
- @Inject MediaClient mediaClient;
- @Inject
- @Named(CommonsApplicationModule.MAIN_THREAD)
- Scheduler mainThreadScheduler;
- @Inject
- @Named(CommonsApplicationModule.IO_THREAD) Scheduler ioThreadScheduler;
+ public static final String ACTION_START_SERVICE = EXTRA_PREFIX + ".upload";
+ public static final String EXTRA_FILES = EXTRA_PREFIX + ".files";
+ @Inject
+ WikidataEditService wikidataEditService;
+ @Inject
+ SessionManager sessionManager;
+ @Inject
+ ContributionDao contributionDao;
+ @Inject
+ UploadClient uploadClient;
+ @Inject
+ MediaClient mediaClient;
+ @Inject
+ @Named(CommonsApplicationModule.MAIN_THREAD)
+ Scheduler mainThreadScheduler;
+ @Inject
+ @Named(CommonsApplicationModule.IO_THREAD)
+ Scheduler ioThreadScheduler;
- private NotificationManagerCompat notificationManager;
- private NotificationCompat.Builder curNotification;
- private int toUpload;
- private CompositeDisposable compositeDisposable;
+ private NotificationManagerCompat notificationManager;
+ private NotificationCompat.Builder curNotification;
+ private int toUpload;
+ private CompositeDisposable compositeDisposable;
- /**
- * The filePath names of unfinished uploads, used to prevent overwriting
- */
- private Set unfinishedUploads = new HashSet<>();
+ /**
+ * The filePath names of unfinished uploads, used to prevent overwriting
+ */
+ private Set unfinishedUploads = new HashSet<>();
- // DO NOT HAVE NOTIFICATION ID OF 0 FOR ANYTHING
- // See http://stackoverflow.com/questions/8725909/startforeground-does-not-show-my-notification
- // Seriously, Android?
- public static final int NOTIFICATION_UPLOAD_IN_PROGRESS = 1;
- public static final int NOTIFICATION_UPLOAD_FAILED = 3;
+ // DO NOT HAVE NOTIFICATION ID OF 0 FOR ANYTHING
+ // See http://stackoverflow.com/questions/8725909/startforeground-does-not-show-my-notification
+ // Seriously, Android?
+ public static final int NOTIFICATION_UPLOAD_IN_PROGRESS = 1;
+ public static final int NOTIFICATION_UPLOAD_FAILED = 3;
- protected class NotificationUpdateProgressListener{
+ protected class NotificationUpdateProgressListener {
- String notificationTag;
- boolean notificationTitleChanged;
- Contribution contribution;
+ String notificationTag;
+ boolean notificationTitleChanged;
+ Contribution contribution;
- String notificationProgressTitle;
- String notificationFinishingTitle;
-
- NotificationUpdateProgressListener(String notificationTag, String notificationProgressTitle, String notificationFinishingTitle, Contribution contribution) {
- this.notificationTag = notificationTag;
- this.notificationProgressTitle = notificationProgressTitle;
- this.notificationFinishingTitle = notificationFinishingTitle;
- this.contribution = contribution;
- }
-
- public void onProgress(long transferred, long total) {
- if (!notificationTitleChanged) {
- curNotification.setContentTitle(notificationProgressTitle);
- notificationTitleChanged = true;
- contribution.setState(Contribution.STATE_IN_PROGRESS);
- }
- if (transferred == total) {
- // Completed!
- curNotification.setContentTitle(notificationFinishingTitle)
- .setTicker(notificationFinishingTitle)
- .setProgress(0, 100, true);
- } else {
- curNotification.setProgress(100, (int) (((double) transferred / (double) total) * 100), false);
- }
- notificationManager.notify(notificationTag, NOTIFICATION_UPLOAD_IN_PROGRESS, curNotification.build());
-
- contribution.setTransferred(transferred);
-
- compositeDisposable.add(contributionDao.update(contribution)
- .subscribeOn(ioThreadScheduler)
- .subscribe());
- }
+ String notificationProgressTitle;
+ String notificationFinishingTitle;
+ NotificationUpdateProgressListener(String notificationTag, String notificationProgressTitle,
+ String notificationFinishingTitle, Contribution contribution) {
+ this.notificationTag = notificationTag;
+ this.notificationProgressTitle = notificationProgressTitle;
+ this.notificationFinishingTitle = notificationFinishingTitle;
+ this.contribution = contribution;
}
- @Override
- public void onDestroy() {
- super.onDestroy();
- compositeDisposable.dispose();
- Timber.d("UploadService.onDestroy; %s are yet to be uploaded", unfinishedUploads);
+ public void onProgress(long transferred, long total) {
+ if (!notificationTitleChanged) {
+ curNotification.setContentTitle(notificationProgressTitle);
+ notificationTitleChanged = true;
+ contribution.setState(Contribution.STATE_IN_PROGRESS);
+ }
+ if (transferred == total) {
+ // Completed!
+ curNotification.setContentTitle(notificationFinishingTitle)
+ .setTicker(notificationFinishingTitle)
+ .setProgress(0, 100, true);
+ } else {
+ curNotification
+ .setProgress(100, (int) (((double) transferred / (double) total) * 100), false);
+ }
+ notificationManager
+ .notify(notificationTag, NOTIFICATION_UPLOAD_IN_PROGRESS, curNotification.build());
+
+ contribution.setTransferred(transferred);
+
+ compositeDisposable.add(contributionDao.update(contribution)
+ .subscribeOn(ioThreadScheduler)
+ .subscribe());
}
- public class UploadServiceLocalBinder extends Binder {
- public UploadService getService() {
- return UploadService.this;
- }
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ compositeDisposable.dispose();
+ Timber.d("UploadService.onDestroy; %s are yet to be uploaded", unfinishedUploads);
+ }
+
+ public class UploadServiceLocalBinder extends Binder {
+
+ public UploadService getService() {
+ return UploadService.this;
+ }
+ }
+
+ private final IBinder localBinder = new UploadServiceLocalBinder();
+
+ private PublishProcessor contributionsToUpload;
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return localBinder;
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ CommonsApplication.createNotificationChannel(getApplicationContext());
+ compositeDisposable = new CompositeDisposable();
+ notificationManager = NotificationManagerCompat.from(this);
+ curNotification = getNotificationBuilder(CommonsApplication.NOTIFICATION_CHANNEL_ID_ALL);
+ contributionsToUpload = PublishProcessor.create();
+ compositeDisposable.add(contributionsToUpload.subscribe(this::handleUpload));
+ }
+
+ public void handleUpload(Contribution contribution) {
+ contribution.setState(Contribution.STATE_QUEUED);
+ contribution.setTransferred(0);
+ toUpload++;
+ if (curNotification != null && toUpload != 1) {
+ curNotification.setContentText(getResources()
+ .getQuantityString(R.plurals.uploads_pending_notification_indicator, toUpload, toUpload));
+ Timber.d("%d uploads left", toUpload);
+ notificationManager
+ .notify(contribution.getLocalUri().toString(), NOTIFICATION_UPLOAD_IN_PROGRESS,
+ curNotification.build());
}
- private final IBinder localBinder = new UploadServiceLocalBinder();
+ compositeDisposable.add(contributionDao
+ .save(contribution)
+ .subscribeOn(ioThreadScheduler)
+ .subscribe(() -> uploadContribution(contribution)));
+ }
- private PublishProcessor contributionsToUpload;
+ private boolean freshStart = true;
- @Override
- public IBinder onBind(Intent intent) {
- return localBinder;
+ public void queue(Contribution contribution) {
+ contributionsToUpload.offer(contribution);
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ if (ACTION_START_SERVICE.equals(intent.getAction()) && freshStart) {
+ compositeDisposable.add(contributionDao.updateStates(Contribution.STATE_FAILED,
+ new int[]{Contribution.STATE_QUEUED, Contribution.STATE_IN_PROGRESS})
+ .observeOn(mainThreadScheduler)
+ .subscribeOn(ioThreadScheduler)
+ .subscribe());
+ freshStart = false;
}
+ return START_REDELIVER_INTENT;
+ }
- @Override
- public void onCreate() {
- super.onCreate();
- CommonsApplication.createNotificationChannel(getApplicationContext());
- compositeDisposable = new CompositeDisposable();
- notificationManager = NotificationManagerCompat.from(this);
- curNotification = getNotificationBuilder(CommonsApplication.NOTIFICATION_CHANNEL_ID_ALL);
- contributionsToUpload = PublishProcessor.create();
- compositeDisposable.add(contributionsToUpload.subscribe(this::handleUpload));
+ @SuppressLint("StringFormatInvalid")
+ private NotificationCompat.Builder getNotificationBuilder(String channelId) {
+ return new NotificationCompat.Builder(this, channelId).setAutoCancel(true)
+ .setSmallIcon(R.drawable.ic_launcher)
+ .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher))
+ .setAutoCancel(true)
+ .setOnlyAlertOnce(true)
+ .setProgress(100, 0, true)
+ .setOngoing(true)
+ .setContentIntent(
+ PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0));
+ }
+
+ @SuppressLint("CheckResult")
+ private void uploadContribution(Contribution contribution) {
+ Uri localUri = contribution.getLocalUri();
+ if (localUri == null || localUri.getPath() == null) {
+ Timber.d("localUri/path is null");
+ return;
}
+ String notificationTag = localUri.toString();
+ File localFile = new File(localUri.getPath());
- public void handleUpload(Contribution contribution) {
- contribution.setState(Contribution.STATE_QUEUED);
- contribution.setTransferred(0);
- toUpload++;
- if (curNotification != null && toUpload != 1) {
- curNotification.setContentText(getResources().getQuantityString(R.plurals.uploads_pending_notification_indicator, toUpload, toUpload));
- Timber.d("%d uploads left", toUpload);
- notificationManager.notify(contribution.getLocalUri().toString(), NOTIFICATION_UPLOAD_IN_PROGRESS, curNotification.build());
- }
+ Timber.d("Before execution!");
+ curNotification.setContentTitle(getString(R.string.upload_progress_notification_title_start,
+ contribution.getDisplayTitle()))
+ .setContentText(getResources()
+ .getQuantityString(R.plurals.uploads_pending_notification_indicator, toUpload,
+ toUpload))
+ .setTicker(getString(R.string.upload_progress_notification_title_in_progress,
+ contribution.getDisplayTitle()))
+ .setOngoing(true);
+ notificationManager
+ .notify(notificationTag, NOTIFICATION_UPLOAD_IN_PROGRESS, curNotification.build());
- compositeDisposable.add(contributionDao
- .save(contribution)
- .subscribeOn(ioThreadScheduler)
- .subscribe(() -> uploadContribution(contribution)));
- }
+ String filename = contribution.getFilename();
- private boolean freshStart = true;
+ NotificationUpdateProgressListener notificationUpdater = new NotificationUpdateProgressListener(
+ notificationTag,
+ getString(R.string.upload_progress_notification_title_in_progress,
+ contribution.getDisplayTitle()),
+ getString(R.string.upload_progress_notification_title_finishing,
+ contribution.getDisplayTitle()),
+ contribution
+ );
- public void queue(Contribution contribution) {
- contributionsToUpload.offer(contribution);
- }
+ Observable.fromCallable(() -> "Temp_" + contribution.hashCode() + filename)
+ .flatMap(stashFilename -> uploadClient
+ .uploadFileToStash(getApplicationContext(), stashFilename, localFile,
+ notificationUpdater))
+ .subscribeOn(Schedulers.io())
+ .observeOn(Schedulers.io())
+ .doFinally(() -> {
+ if (filename != null) {
+ unfinishedUploads.remove(filename);
+ }
+ toUpload--;
+ if (toUpload == 0) {
+ // Sync modifications right after all uploads are processed
+ ContentResolver
+ .requestSync(sessionManager.getCurrentAccount(), BuildConfig.MODIFICATION_AUTHORITY,
+ new Bundle());
+ stopForeground(true);
+ }
+ })
+ .flatMap(uploadStash -> {
+ notificationManager.cancel(notificationTag, NOTIFICATION_UPLOAD_IN_PROGRESS);
- @Override
- public int onStartCommand(Intent intent, int flags, int startId) {
- if (ACTION_START_SERVICE.equals(intent.getAction()) && freshStart) {
- compositeDisposable.add(contributionDao.updateStates(Contribution.STATE_FAILED, new int[]{Contribution.STATE_QUEUED, Contribution.STATE_IN_PROGRESS})
- .observeOn(mainThreadScheduler)
- .subscribeOn(ioThreadScheduler)
- .subscribe());
- freshStart = false;
- }
- return START_REDELIVER_INTENT;
- }
+ Timber.d("Stash upload response 1 is %s", uploadStash.toString());
- @SuppressLint("StringFormatInvalid")
- private NotificationCompat.Builder getNotificationBuilder(String channelId) {
- return new NotificationCompat.Builder(this, channelId).setAutoCancel(true)
- .setSmallIcon(R.drawable.ic_launcher)
- .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher))
- .setAutoCancel(true)
- .setOnlyAlertOnce(true)
- .setProgress(100, 0, true)
- .setOngoing(true)
- .setContentIntent(PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0));
- }
-
- @SuppressLint("CheckResult")
- private void uploadContribution(Contribution contribution) {
- Uri localUri = contribution.getLocalUri();
- if (localUri == null || localUri.getPath() == null) {
- Timber.d("localUri/path is null");
- return;
- }
- String notificationTag = localUri.toString();
- File localFile = new File(localUri.getPath());
-
- Timber.d("Before execution!");
- curNotification.setContentTitle(getString(R.string.upload_progress_notification_title_start, contribution.getDisplayTitle()))
- .setContentText(getResources().getQuantityString(R.plurals.uploads_pending_notification_indicator, toUpload, toUpload))
- .setTicker(getString(R.string.upload_progress_notification_title_in_progress, contribution.getDisplayTitle()))
- .setOngoing(true);
- notificationManager
- .notify(notificationTag, NOTIFICATION_UPLOAD_IN_PROGRESS, curNotification.build());
-
- String filename = contribution.getFilename();
-
- NotificationUpdateProgressListener notificationUpdater = new NotificationUpdateProgressListener(notificationTag,
- getString(R.string.upload_progress_notification_title_in_progress, contribution.getDisplayTitle()),
- getString(R.string.upload_progress_notification_title_finishing, contribution.getDisplayTitle()),
- contribution
- );
-
- Observable.fromCallable(() -> "Temp_" + contribution.hashCode() + filename)
- .flatMap(stashFilename -> uploadClient
- .uploadFileToStash(getApplicationContext(), stashFilename, localFile,
- notificationUpdater))
- .subscribeOn(Schedulers.io())
- .observeOn(Schedulers.io())
- .doFinally(() -> {
- if (filename != null) {
- unfinishedUploads.remove(filename);
- }
- toUpload--;
- if (toUpload == 0) {
- // Sync modifications right after all uploads are processed
- ContentResolver.requestSync(sessionManager.getCurrentAccount(), BuildConfig.MODIFICATION_AUTHORITY, new Bundle());
- stopForeground(true);
- }
- })
- .flatMap(uploadStash -> {
- notificationManager.cancel(notificationTag, NOTIFICATION_UPLOAD_IN_PROGRESS);
-
- Timber.d("Stash upload response 1 is %s", uploadStash.toString());
-
- if (uploadStash.isSuccessful()) {
- Timber.d("making sure of uniqueness of name: %s", filename);
- String uniqueFilename = findUniqueFilename(filename);
- unfinishedUploads.add(uniqueFilename);
- return uploadClient.uploadFileFromStash(
- getApplicationContext(),
- contribution,
- uniqueFilename,
- uploadStash.getFilekey());
- } else {
- Timber.d("Contribution upload failed. Wikidata entity won't be edited");
- showFailedNotification(contribution);
- return Observable.never();
- }
- })
- .subscribe(
- uploadResult -> onUpload(contribution, notificationTag, uploadResult),
- throwable -> {
- Timber.w(throwable, "Exception during upload");
- notificationManager.cancel(notificationTag, NOTIFICATION_UPLOAD_IN_PROGRESS);
- showFailedNotification(contribution);
- });
- }
-
- private void onUpload(Contribution contribution, String notificationTag,
- UploadResult uploadResult) {
- Timber.d("Stash upload response 2 is %s", uploadResult.toString());
-
- notificationManager.cancel(notificationTag, NOTIFICATION_UPLOAD_IN_PROGRESS);
-
- if (uploadResult.isSuccessful()) {
- onSuccessfulUpload(contribution, uploadResult);
- } else {
+ if (uploadStash.isSuccessful()) {
+ Timber.d("making sure of uniqueness of name: %s", filename);
+ String uniqueFilename = findUniqueFilename(filename);
+ unfinishedUploads.add(uniqueFilename);
+ return uploadClient.uploadFileFromStash(
+ getApplicationContext(),
+ contribution,
+ uniqueFilename,
+ uploadStash.getFilekey());
+ } else {
Timber.d("Contribution upload failed. Wikidata entity won't be edited");
showFailedNotification(contribution);
- }
- }
+ return Observable.never();
+ }
+ })
+ .subscribe(
+ uploadResult -> onUpload(contribution, notificationTag, uploadResult),
+ throwable -> {
+ Timber.w(throwable, "Exception during upload");
+ notificationManager.cancel(notificationTag, NOTIFICATION_UPLOAD_IN_PROGRESS);
+ showFailedNotification(contribution);
+ });
+ }
- private void onSuccessfulUpload(Contribution contribution, UploadResult uploadResult) {
- compositeDisposable
- .add(wikidataEditService.addDepictionsAndCaptions(uploadResult, contribution));
- WikidataPlace wikidataPlace = contribution.getWikidataPlace();
- if (wikidataPlace != null && wikidataPlace.getImageValue() == null) {
- wikidataEditService.createImageClaim(wikidataPlace, uploadResult);
- }
- saveCompletedContribution(contribution, uploadResult);
- }
+ private void onUpload(Contribution contribution, String notificationTag,
+ UploadResult uploadResult) {
+ Timber.d("Stash upload response 2 is %s", uploadResult.toString());
- private void saveCompletedContribution(Contribution contribution, UploadResult uploadResult) {
- compositeDisposable.add(mediaClient.getMedia("File:" + uploadResult.getFilename())
- .map(media -> new Contribution(media, Contribution.STATE_COMPLETED))
- .flatMapCompletable(newContribution -> contributionDao.saveAndDelete(contribution, newContribution))
+ notificationManager.cancel(notificationTag, NOTIFICATION_UPLOAD_IN_PROGRESS);
+
+ if (uploadResult.isSuccessful()) {
+ onSuccessfulUpload(contribution, uploadResult);
+ } else {
+ Timber.d("Contribution upload failed. Wikidata entity won't be edited");
+ showFailedNotification(contribution);
+ }
+ }
+
+ private void onSuccessfulUpload(Contribution contribution, UploadResult uploadResult) {
+ compositeDisposable
+ .add(wikidataEditService.addDepictionsAndCaptions(uploadResult, contribution));
+ WikidataPlace wikidataPlace = contribution.getWikidataPlace();
+ Timber.d("Wikidata place %s", wikidataPlace.toString());
+ if (wikidataPlace != null && wikidataPlace.getImageValue() == null) {
+ wikidataEditService.createImageClaim(wikidataPlace, uploadResult);
+ }
+ saveCompletedContribution(contribution, uploadResult);
+ }
+
+ private void saveCompletedContribution(Contribution contribution, UploadResult uploadResult) {
+ compositeDisposable.add(mediaClient.getMedia("File:" + uploadResult.getFilename())
+ .map(media -> {
+ Contribution newContribution = new Contribution(media, Contribution.STATE_COMPLETED);
+ if (contribution.getWikidataPlace() != null) {
+ newContribution.setWikidataPlace(contribution.getWikidataPlace());
+ }
+ return newContribution;
+ })
+ .flatMapCompletable(
+ newContribution -> contributionDao.saveAndDelete(contribution, newContribution))
.subscribe());
- }
+ }
- @SuppressLint("StringFormatInvalid")
- @SuppressWarnings("deprecation")
- private void showFailedNotification(Contribution contribution) {
- curNotification.setTicker(getString(R.string.upload_failed_notification_title, contribution.getDisplayTitle()))
- .setContentTitle(getString(R.string.upload_failed_notification_title, contribution.getDisplayTitle()))
- .setContentText(getString(R.string.upload_failed_notification_subtitle))
- .setProgress(0, 0, false)
- .setOngoing(false);
- notificationManager.notify(contribution.getLocalUri().toString(), NOTIFICATION_UPLOAD_FAILED, curNotification.build());
+ @SuppressLint("StringFormatInvalid")
+ @SuppressWarnings("deprecation")
+ private void showFailedNotification(Contribution contribution) {
+ curNotification.setTicker(
+ getString(R.string.upload_failed_notification_title, contribution.getDisplayTitle()))
+ .setContentTitle(
+ getString(R.string.upload_failed_notification_title, contribution.getDisplayTitle()))
+ .setContentText(getString(R.string.upload_failed_notification_subtitle))
+ .setProgress(0, 0, false)
+ .setOngoing(false);
+ notificationManager.notify(contribution.getLocalUri().toString(), NOTIFICATION_UPLOAD_FAILED,
+ curNotification.build());
- contribution.setState(Contribution.STATE_FAILED);
+ contribution.setState(Contribution.STATE_FAILED);
- compositeDisposable.add(contributionDao
- .update(contribution)
- .subscribeOn(ioThreadScheduler)
- .subscribe());
- }
+ compositeDisposable.add(contributionDao
+ .update(contribution)
+ .subscribeOn(ioThreadScheduler)
+ .subscribe());
+ }
- private String findUniqueFilename(String fileName) throws IOException {
- String sequenceFileName;
- for (int sequenceNumber = 1; true; sequenceNumber++) {
- if (sequenceNumber == 1) {
- sequenceFileName = fileName;
- } else {
- if (fileName.indexOf('.') == -1) {
- // We really should have appended a filePath type suffix already.
- // But... we might not.
- sequenceFileName = fileName + " " + sequenceNumber;
- } else {
- Pattern regex = Pattern.compile("^(.*)(\\..+?)$");
- Matcher regexMatcher = regex.matcher(fileName);
- sequenceFileName = regexMatcher.replaceAll("$1 " + sequenceNumber + "$2");
- }
- }
- if (!mediaClient.checkPageExistsUsingTitle(String.format("File:%s",sequenceFileName)).blockingGet()
- && !unfinishedUploads.contains(sequenceFileName)) {
- break;
- }
+ private String findUniqueFilename(String fileName) throws IOException {
+ String sequenceFileName;
+ for (int sequenceNumber = 1; true; sequenceNumber++) {
+ if (sequenceNumber == 1) {
+ sequenceFileName = fileName;
+ } else {
+ if (fileName.indexOf('.') == -1) {
+ // We really should have appended a filePath type suffix already.
+ // But... we might not.
+ sequenceFileName = fileName + " " + sequenceNumber;
+ } else {
+ Pattern regex = Pattern.compile("^(.*)(\\..+?)$");
+ Matcher regexMatcher = regex.matcher(fileName);
+ sequenceFileName = regexMatcher.replaceAll("$1 " + sequenceNumber + "$2");
}
- return sequenceFileName;
+ }
+ if (!mediaClient.checkPageExistsUsingTitle(String.format("File:%s", sequenceFileName))
+ .blockingGet()
+ && !unfinishedUploads.contains(sequenceFileName)) {
+ break;
+ }
}
+ return sequenceFileName;
+ }
}
diff --git a/app/src/main/java/fr/free/nrw/commons/upload/WikidataPlace.kt b/app/src/main/java/fr/free/nrw/commons/upload/WikidataPlace.kt
index 0e1573881..8027f1d81 100644
--- a/app/src/main/java/fr/free/nrw/commons/upload/WikidataPlace.kt
+++ b/app/src/main/java/fr/free/nrw/commons/upload/WikidataPlace.kt
@@ -5,12 +5,19 @@ import fr.free.nrw.commons.nearby.Place
import kotlinx.android.parcel.Parcelize
@Parcelize
-data class WikidataPlace(override val id: String, override val name: String, val imageValue: String?) :
- WikidataItem,Parcelable {
+internal data class WikidataPlace(
+ override val id: String,
+ override val name: String,
+ val imageValue: String?,
+ val wikipediaArticle: String?
+) :
+ WikidataItem, Parcelable {
constructor(place: Place) : this(
place.wikiDataEntityId!!,
place.name,
- place.pic.takeIf { it.isNotBlank() })
+ place.pic.takeIf { it.isNotBlank() },
+ place.siteLinks.wikipediaLink?.toString() ?: ""
+ )
companion object {
@JvmStatic
@@ -18,4 +25,8 @@ data class WikidataPlace(override val id: String, override val name: String, val
return place?.let { WikidataPlace(it) }
}
}
+
+ fun getWikipediaPageTitle(): String? {
+ return wikipediaArticle?.substringAfterLast("/")
+ }
}
diff --git a/app/src/main/res/drawable-hdpi/ic_wikipedia.png b/app/src/main/res/drawable-hdpi/ic_wikipedia.png
new file mode 100644
index 000000000..2fa42ff7d
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_wikipedia.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_wikipedia.png b/app/src/main/res/drawable-mdpi/ic_wikipedia.png
new file mode 100644
index 000000000..679100a6d
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_wikipedia.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_wikipedia.png b/app/src/main/res/drawable-xhdpi/ic_wikipedia.png
new file mode 100644
index 000000000..525abba82
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_wikipedia.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_wikipedia.png b/app/src/main/res/drawable-xxhdpi/ic_wikipedia.png
new file mode 100644
index 000000000..40daa3955
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_wikipedia.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_wikipedia.png b/app/src/main/res/drawable-xxxhdpi/ic_wikipedia.png
new file mode 100644
index 000000000..6e3f9443a
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_wikipedia.png differ
diff --git a/app/src/main/res/layout/dialog_add_to_wikipedia_instructions.xml b/app/src/main/res/layout/dialog_add_to_wikipedia_instructions.xml
new file mode 100644
index 000000000..d46affaf4
--- /dev/null
+++ b/app/src/main/res/layout/dialog_add_to_wikipedia_instructions.xml
@@ -0,0 +1,110 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/layout_contribution.xml b/app/src/main/res/layout/layout_contribution.xml
index ae92d7db0..d63bda70a 100644
--- a/app/src/main/res/layout/layout_contribution.xml
+++ b/app/src/main/res/layout/layout_contribution.xml
@@ -74,14 +74,16 @@
-
-
+
+
+
diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml
index 212a79183..0035e568e 100644
--- a/app/src/main/res/values-ar/strings.xml
+++ b/app/src/main/res/values-ar/strings.xml
@@ -635,4 +635,6 @@
تشغيل الموقع؟خدمة قريب من هنا تحتاج إلى تفعيل خدمة الموقع للعمل بشكل صحيحهل قمت بتصوير هاتين الصورتين في نفس المكان؟ هل تريد استخدام دائرة العرض / خط الطول للصورة على اليمين؟
+ تحميل المزيد
+ لم يتم العثور على أي أماكن، جرب تغيير محددات بحثك.
diff --git a/app/src/main/res/values-ast/strings.xml b/app/src/main/res/values-ast/strings.xml
index eca372099..7f0f078d2 100644
--- a/app/src/main/res/values-ast/strings.xml
+++ b/app/src/main/res/values-ast/strings.xml
@@ -51,8 +51,10 @@
Les mios xubesCompartirVer nel navegador
- Títulu (Riquíu)
+ Pie (Riquíu)
+ Apurre un pie pa esti ficheruDescripción
+ Pie (llende 255 caráuteres)Nun se pudo aniciar sesión – error de redeNun pudo aniciase sesión. Revisa\'l nome d\'usuariu y la contraseñaDemasiaos intentos incorreutos. Téntalo otra vuelta n\'unos minutos.
@@ -65,6 +67,7 @@
CambeosXubirGuetar categoríes
+ Buscar elementos retrataos nel mediu (monte, Taj Mahal, etc.)GuardarRefrescarLlista
@@ -84,6 +87,10 @@
%1$d carguesNun s\'alcontró denguna categoría que case con %1$s
+ Nun s\'alcontraron elementos de Wikidata que casen con %1$s
+ %1$s nun tien clases fíes
+ %1$s nun tien clases madres
+ Nun hai Imaxe pal RetratuAmiesta categoríes pa facer les imaxes más fáciles d\'alcontrar en Wikimedia Commons.\nPrincipia a escribir p\'amestar categoríes.CategoríesConfiguración
@@ -100,6 +107,7 @@
Unviar comentarios (per corréu)Nun s\'instaló nengún veceru de corréuCategoríes usaes de recién
+ Retratos usaos de reciénEsperando pola primera sincronización…Inda nun xubió denguna foto.Reintentar
@@ -159,6 +167,8 @@
CategoríesCargando…Nenguna seleicionada
+ Nun tien pie
+ Nun tien retratuEnsin descripciónNun hai alderiqueLlicencia desconocida
@@ -177,7 +187,9 @@
XubirSíNon
+ PieTítulu
+ RetratosDescripciónAlderiqueAutor
@@ -239,6 +251,7 @@
Error al poner les fotos na cachéUn títulu descriptivu únicu pal ficheru, que sirvirá para da-y nome al mesmu. Puede usase llinguaxe normal con espacios. Nun incluyas la estensión del ficheruPor favor, describi l\'elementu multimedia tantu como sía posible: ¿ónde se tomó?, ¿qué amuesa?, ¿cuál ye\'l contestu? Por favor, describi los oxetos o persones. Revela la información que nun pueda aldovinase de mou cenciellu, por casu el momentu del día si ye un paisaxe. Si\'l mediu amuesa daqué desacostumao, esplica qué lo fai raro.
+ Escribi una descripción curtia de la imaxe. (Llende de 255 caráuteres)Esta imaxe ye escura enforma, ¿tas seguru de que quies xubila? Wikimedia Commons ye sólo pa imaxes con valor enciclopédicu.Esta imaxe ta borrosa, ¿tas seguru de que quies xubila? Wikimedia Commons ye sólo pa imaxes con valor enciclopédicu.Problemes potenciales con esta imaxe:
@@ -318,9 +331,11 @@
Guetao de recién:Consultes buscaes apocayáAsocedió un error al cargar les categoríes.
+ Asocedió un error al cargar les imáxenes.Asocedió un error al cargar les subcategoríes.MultimediaCategoríes
+ ElementosDestacadaXubío dende\'l móvilAñadióse la imaxe a %1$s en Wikidata.
@@ -423,7 +438,9 @@
AsiaPacíficuNun hai categoríes seleicionaes
- Les imaxes ensin categoríes raramente puen usase. ¿Seguro que quies unviar ensin escoyer categoría dala?
+ Les imáxenes ensin categoríes raramente puen usase. ¿Seguro que quies siguir ensin escoyer categoría dala?
+ Nun tien retratos seleicionaos
+ Les imáxenes con retratos alcuéntrense más fácilmente y ye más fácil que s\'usen. ¿Seguro que quies siguir ensin retratos?(Pa toles imaxes del conxuntu)Buscar nesta áreaSolicitú de permisu
@@ -502,6 +519,7 @@
Les imaxes destacaes son creaciones de talentosos fotógrafos y ilustradores que la comunidá de Wikimedia Commons reconoció como les de mayor calidá del sitiu.Les imaxes xubíes via Llugares Cercanos son les imaxes que se cargaron descubriendo llugares nel mapa.Esta función permite que los editores unvien una nota Gracies a los usuarios que realicen ediciones útiles usando un pequeñu enllaz d\'agradecimientu na páxina d\'historial o na de diferencies.
+ Copiar los retratos y descripción anterioresFai clic para reutilizar el títulu y descripción qu\'escribisti na imaxe anterior y cambialu p\'adautalu a la imaxe actualExemplos d\'imaxes bones pa xubir a CommonsExemplos d\'imaxes que nun tienen de xubise
@@ -520,6 +538,7 @@
Compartir l\'aplicación per...Información de la imaxeNun s\'alcontró nenguna categoría
+ Nun s\'alcontraron retratosCarga encaboxadaNun hai datos sobro\'l títulu o la descripción de la imaxe anterior¿Por qué tien de desaniciase %1$s?
@@ -552,6 +571,9 @@
Tipu de llugar:Ponte, muséu, hotel etc.¡¡Falló daqué al aniciar sesión, tienes de reaniciar la contraseña!!
+ MEDIOS
+ CLASES FÍES
+ CLASES PADRESLlugar cercanu alcontráu¿Ye esta una foto del Llugar %1$s?Esplorar
@@ -570,4 +592,6 @@
¿Activar l\'allugamientu?«Cercano» precisa activar l\'allugamientu pa funcionar correutamente¿Sacasti estes dos semeyes nel mesmu llugar? ¿Quies usar la llatitú/llonxitú da la semeya de la derecha?
+ Cargar más
+ Nun s\'alcontraron llugares, tenta cambiar los criterios de gueta.
diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml
index dac54d3ec..57967b0a6 100644
--- a/app/src/main/res/values-da/strings.xml
+++ b/app/src/main/res/values-da/strings.xml
@@ -387,4 +387,5 @@
StandardMørktLyst
+ Indlæs mere
diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml
index 3b59df6b2..0f139f763 100644
--- a/app/src/main/res/values-fr/strings.xml
+++ b/app/src/main/res/values-fr/strings.xml
@@ -618,5 +618,6 @@
Activer la localisation ?À proximité nécessite que la localisation soit activée pour bien fonctionnerAvez-vous pris ces deux photos du même endroit ? Voulez-vous utiliser les latitude/longitude de l’image sur la droite ?
+ Charger davantagePas d’endroit trouvé, essayez de modifier vos critères de recherche.
diff --git a/app/src/main/res/values-hr/strings.xml b/app/src/main/res/values-hr/strings.xml
index ed129d428..605abb5a7 100644
--- a/app/src/main/res/values-hr/strings.xml
+++ b/app/src/main/res/values-hr/strings.xml
@@ -312,6 +312,7 @@
Ako nastavite postavljati slike koje je potrebno izbrisati, Vaš će račun vjerojatno biti blokiran. Jeste li sigurni da želite završiti kviz?Slike koje prikazuju tehnologiju ili kulturu dobrodošle su na Zajedničkom poslužitelju.Izaberite jednu opciju od dvije da biste odgovorili na pitanje
+ Sesija prijavljivanja istekla je, molimo Vas, prijavite se ponovo.Podijelite kviz s prijateljima!Točan odgovorPogrešan odgovor
@@ -347,4 +348,5 @@
ZadanoTamnoSvijetlo
+ Učitaj više
diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml
index 585094922..51c252400 100644
--- a/app/src/main/res/values-it/strings.xml
+++ b/app/src/main/res/values-it/strings.xml
@@ -530,4 +530,5 @@
Segui sistemaScuroChiaro
+ Caricane ancora
diff --git a/app/src/main/res/values-jv/strings.xml b/app/src/main/res/values-jv/strings.xml
index cef6e83c9..a41a0e976 100644
--- a/app/src/main/res/values-jv/strings.xml
+++ b/app/src/main/res/values-jv/strings.xml
@@ -5,6 +5,7 @@
* N219
* NoiX180
* Notanotheramy
+* Sumbukompor
-->
Dlajah
@@ -24,7 +25,7 @@
Lali Tembung Sandi?DhaftarLagi mlebu log
- Entènana sadhela…
+ Entènana sadhéla…Kasil mlebu log!Wurung mlebu log!Berkas ora tinemu. Jajal berkas liyané.
@@ -195,7 +196,7 @@
Pinilihdhèksripsi ora tinemuKaca barkas Commons
- Wiji Wikidata
+ Wiji WikidhataArtikel WikipédiaAwèh idinAnggo panyimpenan njaba
diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml
index d492eb4a1..2d3cbf673 100644
--- a/app/src/main/res/values-ko/strings.xml
+++ b/app/src/main/res/values-ko/strings.xml
@@ -13,6 +13,7 @@
* Nuevo Paso
* Revi
* Ykhwong
+* YuzaTea
* 그냥기여자
* 아라
-->
@@ -186,7 +187,7 @@
새로 고침기억 장치 권한 요청 중권한 필요: 외부 저장소 읽기. 이것이 없으면 앱은 갤러리에 접근할 수 없습니다.
- 권한 필요: 외부 저장소 쓰기. 이것이 없으면 앱은 카메라에 접근할 수 없습니다.
+ 권한 필요: 외부 저장소 쓰기. 이것이 없으면 앱은 카메라/갤러리에 접근할 수 없습니다.위치 권한 요청 중선택적 권한: 분류 추천을 위해 현재 위치 정보를 가져옵니다.확인
@@ -253,6 +254,7 @@
강좌알림알참
+ 검토위치 권한이 없으면 주변 장소를 표시할 수 없습니다설명이 없습니다공용 파일 문서
@@ -269,8 +271,10 @@
이미지가 흐릿합니다.이미지가 이미 공용에 있습니다.이 사진은 다른 위치에서 찍었습니다.
+ 당신이 직접 찍은 사진만 업로드하세요. 다른 사람의 페이스북 계정에서 찾은 사진을 업로드하지마세요.그래도 이 사진을 업로드하시겠습니까?이미지에 문제가 있습니다
+ 직접 찍은 사진만 업로드하세요. 인터넷에서 다운로드한 사진을 업로드하지 마세요.권한 부여외부 저장소 사용하기장치의 인앱 카메라로 찍은 사진 저장하기
@@ -310,6 +314,8 @@
인터넷 사용 불가인터넷 사용 가능알림 가져오기 오류
+ 검토할 이미지를 가져오는 중 오류 발생. 새로 고침을 눌러 다시 시도하세요.
+ 검토할 이미지의 범주를 가져오는 중 오류 발생. 새로 고침을 눌러 다시 시도하세요.알림이 없습니다번역언어
@@ -340,6 +346,7 @@
미디어분류항목
+ 추천됨모바일을 통해 업로드됨위키데이터의 %1$s에 그림을 추가했습니다!일치하는 위키데이터 엔티티의 업데이트를 실패했습니다!
@@ -382,6 +389,7 @@
\"주변 장소\" 경유 이미지레벨사진 업로드됨
+ 사용된 이미지친구와 성과를 공유하세요!최소 요구사항:업로드 소프트웨어를 통해 공용에 업로드한 그림 수
@@ -496,7 +504,7 @@
셀카흐림기타
- 인터넷의 임의 사진
+ 인터넷상의 무작위 이미지로고기타왜냐하면
@@ -525,5 +533,6 @@
어두움밝음위치를 켭니까?
+ 더 불러오기발견된 장소가 없습니다. 검색 기준을 바꾸어 보십시오.
diff --git a/app/src/main/res/values-lb/strings.xml b/app/src/main/res/values-lb/strings.xml
index 4747b0633..baaf33367 100644
--- a/app/src/main/res/values-lb/strings.xml
+++ b/app/src/main/res/values-lb/strings.xml
@@ -366,4 +366,6 @@
System suivéierenDäischterHell
+ Méi lueden
+ Keng Plaze fonnt, probéiert Är Sich-Critèren z\'änneren.
diff --git a/app/src/main/res/values-mk/strings.xml b/app/src/main/res/values-mk/strings.xml
index dad288e67..63e49983e 100644
--- a/app/src/main/res/values-mk/strings.xml
+++ b/app/src/main/res/values-mk/strings.xml
@@ -594,5 +594,6 @@
Да ја вклучам местоположбата?„Во близина“ бара местоположба за да работиДали ги направивте ови две слики на истото место? Дали сакате да ја искористите географската ширина/должина од десната слика?
+ Вчитај уштеНе пронајдов места. Изменете ги критериумите во барањето.
diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml
index 29bd43a85..2409367a2 100644
--- a/app/src/main/res/values-pl/strings.xml
+++ b/app/src/main/res/values-pl/strings.xml
@@ -83,6 +83,7 @@
ZmianyPrześlijSzukaj kategorii
+ Wyszukiwanie elementów, które przedstawiają twoje media (góra, Tadż Mahal itp.)ZapiszOdświeżLista
@@ -104,6 +105,7 @@
Nie znaleziono kategorii pasujących do %1$sNie znaleziono przedmiotów Wikidata pasujących do %1$s
+ Brak obrazu do przedstawieniaDodaj kategorie, aby ułatwić odnalezienie plików w Wikimedia Commons.\nZacznij pisać, aby dodać kategorie.KategorieUstawienia
@@ -113,7 +115,7 @@
RecenzjaO aplikacjiAplikacja Wikimedia Commons jest oprogramowaniem typu open-source tworzonym i rozwijanym przez stypendystów i wolontariuszy ze społeczności Wikimedii. Fundacja Wikimedia nie bierze udziału w tworzeniu, rozwijaniu ani utrzymywaniu aplikacji.
- <a href=\"https://github.com/commons-app/apps-android-commons\">Kod źródłowy</a> oraz <a href=\"https://commons-app.github.io/\">strona internetowa</a> na GitHub. Aby zgłosić błąd lub sugestię, utwórz nowe <a href=\"%1$s\">zgłoszenie na GitHub</a>.
+ Utwórz nowe <a href=\"%1$s\">zgłoszenie na GitHub</a>, aby zgłosić błąd lub sugestię.Polityka prywatnościTwórcyO aplikacji
@@ -180,6 +182,7 @@
Ładowanie…Nic nie zaznaczonoBrak podpisu
+ Bez opisuBrak opisuBrak dyskusjiNieznana licencja
@@ -193,6 +196,7 @@
Pobliskie miejscaNie znaleziono niczego w pobliżuOstrzeżenie
+ Znaleziono zduplikowany obrazTen plik już istnieje na Commons. Jesteś pewien, że chcesz kontynuować?PrześlijTak
@@ -225,6 +229,7 @@
Strona Commons na FacebookuKod źródłowy Commons na GitHubieObraz w tle
+ Błąd obrazu multimedialnegoNie znaleziono obrazuNie znaleziono podkategoriiNie znaleziono kategorii nadrzędnych
@@ -235,7 +240,7 @@
TulipanBrak SelfieWitaj na Wikipedii
- Witaj Prawa Autorskie.
+ Witamy Prawa Autorskie.Opera SydnejAnulujOtwórz
@@ -259,6 +264,7 @@
Błąd podczas buforowania zdjęćPodaj krótką, opisową i unikalną nazwę, która będzie służyła jako nazwa pliku. Możesz używać prostego języka i spacji. Nie dodawaj rozszerzenia pliku.Opisz jak najwięcej mediów: Gdzie zostało zrobione? Co to pokazuje? Jaki jest kontekst? Proszę opisać przedmioty lub osoby. Ujawnij informacje, których nie można łatwo odgadnąć, na przykład porę dnia, jeśli jest to krajobraz. Jeśli media pokazują coś niezwykłego, wyjaśnij, co sprawia, że jest to niezwykłe.
+ Proszę napisać krótki opis obrazu. (Limit do 255 znaków)To zdjęcie jest zbyt ciemne, czy na pewno chcesz je załadować? Wikimedia Commons jest tylko dla zdjęć o wartości encyklopedycznej.To zdjęcie jest rozmazane, czy na pewno chcesz je załadować? Wikimedia Commons jest tylko dla zdjęć o wartości encyklopedycznej.Potencjalne problemy z tym obrazem:
@@ -268,6 +274,7 @@
To zdjęcie zostało zrobione w innym miejscu.Prześlij tylko zdjęcia, które sam wykonałeś. Nie przesyłaj zdjęć znalezionych na kontach innych osób na Facebooku.Czy nadal chcesz przesłać to zdjęcie?
+ Problemy znalezione na obraziePrześlij tylko zdjęcia, które sam wykonałeś. Nie przesyłaj zdjęć pobranych z Internetu.Uzyskaj uprawnienieUżyj pamięci zewnętrznej
@@ -337,7 +344,9 @@
Ostatnie wyszukiwania:Ostatnio wyszukiwane zapytaniaWystąpił błąd podczas ładowania kategorii.
+ Wystąpił błąd podczas ładowania obrazów.Wystąpił błąd podczas ładowania podkategorii.
+ MultimediaKategorieElementyWyróżnione
@@ -396,15 +405,23 @@
Użyj niestandardowej nazwy autoraPodczas przesyłania zdjęć użyj niestandardowej nazwy autora zamiast nazwy użytkownikaNiestandardowa nazwa autora
+ WkładW pobliżuPowiadomieniaPowiadomienia (przeczytaj)
+ Wyświetl powiadomienie w pobliżuStuknij tutaj, aby zobaczyć najbliższe miejsce, które wymaga zdjęć
+ ListaUprawnienie do przechowywania
+ Potrzebujemy Twojej zgody na dostęp do zewnętrznej pamięci urządzenia w celu przesyłania obrazów.
+ Nie zobaczysz już najbliższego miejsca, które potrzebuje zdjęć. Możesz jednak ponownie włączyć to powiadomienie w Ustawieniach, jeśli chcesz.Krok %1$d z %2$d
+ Obraz %1$d w zestawieNastępnyPoprzedniPrześlij
+ Plik o nazwie pliku %1$s już istnieje. Czy na pewno chcesz kontynuować?
+ W twoim urządzeniu nie znaleziono kompatybilnej aplikacji mapowej. Zainstaluj aplikację mapową, aby korzystać z tej funkcji.ZakładkiZakładkiZdjęcia
@@ -413,17 +430,45 @@
ZakładkiNie dodałeś żadnych zakładekZakładki
+ Rozpoczęto zbieranie dzienników. Uruchom ponownie aplikację, wykonaj działanie, które chcesz zarejestrować, a następnie ponownie dotknij opcji „Wyślij plik dziennika”
+ Przesłałem go przez pomyłkę
+ Nie wiedziałem, że będzie to publicznie widoczne
+ Zdałem sobie sprawę, że jest to szkodliwe dla mojej prywatności
+ Zmieniłem zdanie, nie chcę, aby było to już publicznie widoczne
+ Przepraszamy, to zdjęcie nie jest interesujące dla encyklopedii
+ Przesłane przeze mnie na %1$s, używane w artykułach %2$d.
+ Prześlij swoje pierwsze multimedia, dotykając przycisku Dodaj.
+ Cały światAmerykaEuropaBliski WschódAfrykaAzja
+ Pacyfik
+ Nie wybrano kategorii
+ Obrazy bez kategorii rzadko nadają się do użycia. Czy na pewno chcesz kontynuować bez wybierania kategorii?
+ Nie wybrano żadnych obrazów
+ (Dla wszystkich obrazów w zestawie)Przeszukaj ten obszar
+ Prośba o pozwolenie
+ Czy chcesz, abyśmy użyli Twojej bieżącej lokalizacji do wyświetlenia najbliższego miejsca, w którym będą potrzebne zdjęcia?
+ Nie można wyświetlić najbliższego miejsca wymagającego zdjęć bez uprawnień do lokalizacjiNigdy więcej nie pytaj o toWyświetl pozwolenie na lokalizacjęW razie potrzeby zapytaj o pozwolenie na lokalizację w przypadku funkcji widoku pobliskiej karty powiadomień.Coś poszło nie tak, nie mogliśmy pobrać twoich osiągnięć
+ Zrobiłeś tak wiele wkładu, że nasz system obliczania osiągnięć nie może sobie poradzić. To jest najwyższym osiągnięciem.Kończy się na:
+ Zobacz trwające kampanie
+ Kampanie już nie będą widoczne. Jednak w razie potrzeby możesz ponownie włączyć to powiadomienie w ustawieniach.
+ Ta funkcja wymaga połączenia sieciowego, sprawdź ustawienia połączenia.
+ Przesyłanie nie powiodło się z powodu problemów z edytowaniem tokenu. Spróbuj się wylogować i zalogować ponownie.
+ Wystąpił błąd podczas przetwarzania obrazu. Spróbuj ponownie!
+ Pobieranie tokenu do edycji
+ Dodawanie szablonu do sprawdzania kategorii
+ Żądanie sprawdzania kategorii dla %1$s
+ Żądanie sprawdzenia kategorii
+ Wymagana kontrola kategoriiŻądanie sprawdzania kategorii nie zadziałałoZażądano sprawdzenia kategorii dla %1$sNie można zażądać sprawdzania kategorii dla %1$s
@@ -431,6 +476,8 @@
Dodawanie wiadomości usuwania do plikuZrobionePowiadomienie użytkownika na stronie dyskusji
+ Dodanie pliku do Usuń dziennik żądań
+ Tworzenie podstrony Usuń żądaniaNie jestem pewienWysyłanie podziękowań: PowodzeniePomyślnie wysłano podziękowania do %1$s
@@ -459,9 +506,12 @@
Następny obrazKliknięcie tego przycisku spowoduje wyświetlenie kolejnego ostatnio przesłanego obrazu z Wikimedia CommonsMożesz przeglądać obrazy i poprawiać jakość Wikimedia Commons.\n Cztery parametry przeglądu to:\n - Czy ten obraz jest objęty zakresem?\n - Czy ten obraz jest zgodny z zasadami praw autorskich?\n - Czy ten obraz jest poprawnie sklasyfikowany?\n - Jeśli wszystko pójdzie dobrze, możesz również podziękować autorowi.
+ Nie użyto żadnych obrazów
+ Żadne obrazy nie zostały przywróconeNie przesłano żadnych obrazówNie masz nieprzeczytanych powiadomieńNie masz powiadomień o przeczytaniu
+ Udostępniaj dzienniki za pomocąZobacz przeczytaneWyświetl nieprzeczytaneWystąpił błąd podczas pobierania zdjęć
@@ -470,6 +520,7 @@
Polecane zdjęcia to zdjęcia wysoko wykwalifikowanych fotografów i ilustratorów, które społeczność Wikimedia Commons wybrała jako jedne z najwyższych jakości na stronie.Obrazy przesłane przez Pobliskie miejsca to obrazy, które są przesyłane przez odkrywanie miejsc na mapie.Ta funkcja umożliwia redaktorom wysyłanie powiadomień z podziękowaniem do użytkowników, którzy dokonują przydatnych zmian - za pomocą małego linku z podziękowaniem na stronie historii lub na stronie diff.
+ Skopiuj poprzednie podpisy i opisKliknij, aby ponownie użyć tytułu i opisu podanego na poprzednim zdjęciu i zmodyfikuj go, aby pasował do bieżącegoPrzykłady dobrych zdjęć do przesłania na CommonsPrzykłady obrazów, których nie można przesyłać
@@ -488,6 +539,7 @@
Udostępnij za pośrednictwem…Informacje o obrazieNie znaleziono kategorii
+ Nie znaleziono zdjęćAnulowano przesyłanieBrakuje danych co do poprzedniego tytułu lub opisu obrazuDlaczego należy usunąć %1$s?
@@ -520,8 +572,10 @@
Typ miejsca:Most, muzeum, hotel itp.Coś poszło nie tak podczas logowania, musisz zresetować hasło!
+ MEDIAZnaleziono miejsce w pobliżuCzy jest to zdjęcie miejsca %1$s?
+ OdkryjZakładkiUstawieniaUsunięto z zakładek
@@ -529,10 +583,14 @@
Coś poszło nie tak. Nie można ustawić tapetyUstaw jako tapetęUstawianie tapety. Proszę czekać…
- Domyślny
+ Śledź systemCiemnyJasnyNie można otworzyć ustawień lokalizacji. Włącz lokalizację ręcznieAby uzyskać najlepsze wyniki, wybierz tryb wysokiej dokładności.Włączyć lokalizację?
+ Lokalizacja W pobliżu wymaga włączonej lokalizacji, aby działać poprawnie
+ Czy zrobiłeś te dwa zdjęcia w tym samym miejscu? Czy chcesz użyć szerokości/długości geograficznej obrazu po prawej stronie?
+ Załaduj więcej
+ Nie znaleziono miejsc, spróbuj zmienić kryteria wyszukiwania.
diff --git a/app/src/main/res/values-pms/strings.xml b/app/src/main/res/values-pms/strings.xml
index c440ed242..641f304cb 100644
--- a/app/src/main/res/values-pms/strings.xml
+++ b/app/src/main/res/values-pms/strings.xml
@@ -592,5 +592,6 @@
Anvisché la localisassion?Nearby a l\'ha damanca dla localisassion abilità për marcé \'me ch\'as devA la fàit se doe fòto ant l\'istess pòst? A veul dovré la latitùdin e la longitùdin ëd la fòto an sla drita?
+ Carié \'d piGnun pòst trovà, ch\'a preuva a modifiché ij sò criteri d\'arserca.
diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml
index 00a3e78a8..918a030a5 100644
--- a/app/src/main/res/values-pt-rBR/strings.xml
+++ b/app/src/main/res/values-pt-rBR/strings.xml
@@ -606,5 +606,6 @@
Ativar a localização?Proximidade precisa de localização ativado para funcionar corretamenteVocê tirou essas duas fotos no mesmo lugar? Deseja usar a latitude/longitude da imagem à direita?
+ Carregar maisNenhum local encontrado, tente alterar seus critérios de pesquisa.
diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml
index 65297d360..cf5578bb3 100644
--- a/app/src/main/res/values-ro/strings.xml
+++ b/app/src/main/res/values-ro/strings.xml
@@ -56,8 +56,10 @@
Încărcările melePartajareAfișează în navigator
- Titlu
+ Descriere (Necesară)
+ Vă rugăm să oferiți o descriere pentru acest fișierDescriere
+ Descriere (limită 255 caractere)Autentificare nereușită – defecțiune de rețeaNu poți să te autentifici - verifică-ți numele de utilizator și parolaPrea multe încercări nereușite. Încercați din nou peste câteva minute.
@@ -70,6 +72,7 @@
ModificăriÎncărcareCăutare categorii
+ Căutați articole pe care media dvs. le înfățișează (munte, Taj Mahal etc.)SalvareReîncarcăListă
@@ -92,36 +95,43 @@
%1$d de încărcăriNu s-a găsit nicio categorie corespunzătoare cu %1$s
+ Nu s-au găsit articole Wikidata care corespund %1$s
+ %1$s nu are clase copil
+ %1$s nu are clase părinte
+ Nicio imagine pentru reprezentareAdăugați categorii pentru a facilita găsirea imaginilor dumneavoastră la Wikimedia Commons.\n\nÎncepeți să tastați pentru a adăuga categorii.CategoriiSetăriÎnregistrareImagini recomandateCategorie
+ Evaluare colegialăDespreAplicația Wikimedia Commons este un software cu sursă deschisă creat și menținut de bursieri și voluntari ai comunității Wikimedia. Fundația Wikimedia nu este implicată în crearea, dezvoltarea sau mentenanța aplicației.Creați un nou <a href=\"%1$s\">tichet pe GitHub</a> pentru a raporta buguri sau sugestii.
- <u>Politica de confidențialitate</u>
- <u>Autori</u>
+ Politica de confidențialitate
+ <u>Mulţumiri</u>DespreTrimitere reacții (prin e-mail)Niciun client de email instalatCategorii utilizate recent
+ Reprezentări folosite recentSe așteaptă prima sincronizare…Încă nu ați încărcat nicio fotografie.ReîncercareRevocare
-
+ Această imagine va fi licențiată sub %1$s
- Această imagine va fi licențiată sub %1$s
+ Aceste imagini vor fi licenţiate sub %1$s
+ Prin prezentarea acestei imagini, declar că aceasta este lucrarea mea proprie, că nu conține materiale protejate prin drepturi de autor sau selfiuri și că aderă la <a href=\"https://commons.wikimedia.org/wiki/Commons:Policies_and_guidelines\">Wikimedia Commons policies</a>.DescarcăLicență implicită
- Folosiți titlul/descrierea anterioară
+ Utilizați titlul și descrierea anterioarăObține în mod automat locația curentăPreia locația curentă dacă imaginea nu are salvată locația și salvează imaginea cu ea. Avertisment: Aceasta va dezvălui locația dvs. curentă.
- Mod de noapte
+ TemaAtribuire și distribuire în condiții identice 4.0Atribuire 4.0Atribuire și distribuire în condiții identice 3.0
@@ -162,26 +172,33 @@
Evitați materialele cu drepturi de autor găsite pe Internet, precum și imagini ale posterelor, coperților de cărți etc.Credeți că ați înțeles?Da!
- <u>Mai multe informații</u>
+ Mai multe informațiiCategoriiSe încarcă…Niciuna selectată
+ Fără descriere
+ Fără ilustrareFără descriereNu există discuțiiLicență necunoscutăReîncarcăSolicitarea Permisiunilor de StocareNecesită permisiune: Citiți spațiul de stocare extern. Aplicația nu poate accesa galeria dvs. fără aceasta.
- Necesită permisiune: Scrieți un spațiu de stocare extern. Aplicația nu poate accesa camera fără acest lucru.
+ Permisiune necesară: Scrieți stocare externă. Aplicația nu vă poate accesa camera/galeria fără acest lucru.
+ Solicitarea Permisiunii de LocațiePermisiune opțională: Obțineți locația curentă pentru sugestiile de categoriiOKLocurile din ApropiereNu au fost găsite locații din apropiereAvertisment
+ Imagine Duplicată GăsităAcest fișier există deja pe Commons. Sunteți sigur că doriți să continuați?
+ ÎncarcăDaNu
+ DescriereTitlu
+ ÎnfățiseazăDescriereDiscuțieAutor
@@ -195,6 +212,7 @@
Limita mea de încărcare recentăLimită maximăZero nu este valid
+ Input nevalidNu pot afișa mai mult de 500Introduceți un număr validLimita de încărcări nu poate fi 0
@@ -242,6 +260,7 @@
Eroare la cache imaginilorUn titlu descriptiv unic pentru fișier, care va servi ca nume de fișier. Puteți utiliza un limbaj simplu cu spații. Nu includeți extensia de fișierVă rugăm să descrieți media cât mai mult posibil: Unde a fost făcut? Ce arată? Care este contextul? Descrieți obiectele sau persoanele. Dezvăluiți informații care nu pot fi ușor ghicite, cum ar fi timpul zilei dacă este un peisaj. În cazul în care materialul transmis arată ceva neobișnuit, vă rugăm să explicați ceea ce o face neobișnuită.
+ Vă rugăm să scrieți o scurtă descriere a imaginii. (Limită la 255 de caractere)Această imagine este prea întunecată, sunteți sigur că doriți să o încărcați? Wikimedia Commons este numai pentru imagini cu valoare enciclopedică.Această imagine este neclară, sunteți sigur că doriți să o încărcați? Wikimedia Commons este numai pentru imagini cu valoare enciclopedică.Probleme potențiale cu această imagine:
@@ -251,6 +270,8 @@
Această fotografie a fost făcută într-o altă locație.Vă rugăm să nu încărcați decât imagini pe care le-ați făcut personal. Nu încărcați imagini găsite pe conturile de Facebook ale altor persoane.Încă doriți să încărcați această imagine?
+ Probleme găsite în imagine
+ Vă rugăm să încărcați doar fotografiile realizate de dvs. Nu încărcați imaginile pe care le-ați descărcat de pe Internet.Obțineți permisiuneaUtilizați spațiul de stocare externSalvați fotografiile realizate cu aparatul foto în aplicație de pe dispozitiv
@@ -261,7 +282,7 @@
Eroare! Adresa URL nu a fost găsităNominalizați pentru ștergereAceastă imagine a fost nominalizată pentru ștergere.
- <u>Vedeți pagina web pentru detalii</u>
+ Consultați pagina web pentru detaliiPropun %1$s pentru ștergere.Propun fișierul pentru ștergere: %1$sVizualizează cu navigatorul
@@ -273,7 +294,7 @@
Copiați wikitext-ul în clipboardWikitext-ul a fost copiat în clipboardLocația nu s-a schimbat.
- Locația nu este disponibilă.
+ Este posibil să nu funcționeze Apropiere, Locația nu este disponibilă.Permisiunea necesară pentru a afișa o listă de locații din apropiereObțineți indicații de orientareCitiți articolul
@@ -286,26 +307,29 @@
WikidataWikipediaCommons
- <u>Dă-ne o notă</u>
- <u>FAQ</u>
+ Recenzie
+ Întrebări frecventeSari peste tutorialNu aveți internetAveți internetEroare la preluarea notificărilor
+ Eroare la preluarea imaginii pentru revizuire. Apăsați actualizare pentru a încerca din nou.
+ Eroare la preluarea categoriilor de imagini pentru revizuire. Apăsați actualizare pentru a încerca din nou.Nu au fost găsite notificări
- <u>Traduceți</u>
+ TraducețiLimbiSelectați limba în care doriți să trimiteți traduceri pentruContinuăAnulareReîncercareAm înțeles!
- Acestea sunt locurile din apropierea ta care au nevoie de imagini pentru a ilustra articolele lor Wikipedia
+ Acestea sunt locurile din apropierea dvs. care au nevoie de imagini pentru a ilustra articolele lor Wikipedia.\n\nFăcând click pe „CAUTĂ ACEASTĂ ZONĂ”, se blochează harta și se lansează o căutare în apropiere în jurul locației respective.Atingând acest buton, se afișează o listă a acestor locuriPuteți încărca o imagine pentru orice loc din galerie sau camera fotoNu s-au gasit imagini!A apărut o eroare la încărcarea imaginilor.Încărcată de: %1$s
+ BlocatSunteți blocat de la editarea CommonsImaginea zileiImaginea zilei
@@ -316,12 +340,14 @@
Căutări recente:Interogări căutate recentA apărut o eroare la încărcarea categoriilor.
+ A apărut o eroare la încărcarea reprezentărilor.A apărut o eroare la încărcarea subcategoriilor.MediaCategorii
+ ElementeRecomandateÎncărcat de pe telefon
- Imaginea a fost adăugată cu succes la %1$s pe Wikidata!
+ Imaginea adăugată la %1$s pe Wikidata!Nu s-a actualizat entitatea corespunzătoare Wikidata!Setează ca Imagine de fundalWallpaper setat cu succes!
@@ -359,6 +385,7 @@
StatisticiMulțumiri primiteImagini recomandate
+ Imagini prin „Locații în apropiere”NivelImaginile au fost încărcateImaginile nu au fost reluate
@@ -377,7 +404,7 @@
ContribuțiiÎn apropiereNotificări
- Notificări (arhivate)
+ Notificări (citite)Afișați notificarea din apropiereApăsați aici pentru a vedea cel mai apropiat loc care are nevoie de imaginiNu există locuri apropiate găsite în apropierea dvs.
@@ -392,9 +419,10 @@
TrimiteExistă un fișier cu numele de fișier %1$s. Sunteți sigur că doriți să continuați?Nu s-a găsit nicio aplicație de hartă compatibilă pe dispozitiv. Instalați o aplicație de hartă pentru a utiliza această caracteristică.
-
- %1$d Încărcați
- %1$d Încărcări
+
+ %1$d Încarcă
+ %1$d Încărcări
+ Semne de carteSemne de carte
@@ -410,8 +438,8 @@
Mi-am dat seama că este rău pentru intimitatea meaM-am răzgândit, nu mai vreau să fie publicăNe pare rău că această imagine nu este interesantă pentru o enciclopedie
- Încărcat de mine însumi
- Bun venit la Commons!\n\nÎncărcați primul dvs. suport media atingând pictograma camerei sau galeria de mai sus.
+ Încărcat de mine pe %1$s, folosit în %2$d articol(e).
+ Bine ați venit la Commons!\n\nÎncărcați primul dvs. media apăsând pe butonul de adăugare.La nivel mondialAmericaEuropa
@@ -420,7 +448,9 @@
AsiaPacificNici o categorie selectată
- Imaginile fără categorii sunt rareori utilizabile. Sigur doriți să trimiteți fără a selecta categorii?
+ Imaginile fără categorii sunt rareori utilizabile. Sigur doriți să continuați fără a selecta categorii?
+ Nu Sunt Selectate Reprezentări
+ Imaginile cu ilustrații sunt mai ușor de găsit și mai probabil să fie utilizate. Sunteți sigur că doriți să continuați fără a selecta reprezentări?(Pentru toate imaginile din set)Căutați în acest domeniuCerere de permisiune
@@ -430,31 +460,149 @@
Afișați permisiunea de locațieSolicitați permisiunea de localizare atunci când este necesar pentru a utiliza funcția notificărilor de localizare.Ceva a mers prost, nu am reușit să ne aducem realizările
+ Ai făcut atâtea contribuții sistemul nostru de calcul al realizărilor nu poate face față. Aceasta este realizarea finală.Se încheie la:Campaniile de afișare
- Atingeți aici pentru a vedea campaniile în desfășurare
+ Vedeți campaniile în cursNu veți mai vedea campaniile. Cu toate acestea, puteți reactiva această notificare în Setări, dacă doriți.Această funcție necesită conectare la rețea, verificați setările de conectare.Încărcarea a eșuat din cauza problemelor cu Edit token. Încearcă să te deconectezi și să intri din nou.A apărut o eroare la procesarea imaginii. Vă rugăm să încercați din nou!
+ Obținerea de jeton pentru editare
+ Adăugarea formatului pentru verificarea categoriei
+ Solicitați verificarea categoriei pentru %1$s
+ Solicitarea verificării categoriei
+ Verificare de categorie solicitată
+ Cererea de verificare a categoriei nu a funcționat
+ Solicitare de verificare a categoriei pentru %1$s
+ Nu s-a putut solicita verificarea categoriei pentru %1$s
+ Solicitați verificarea categoriei pentru %1$s
+ Adăugarea mesajului de ștergere în fișierRealizat
+ Notificarea utilizatorului pe pagina de discuţie
+ Adăugarea fișierului la Ștergerea jurnalului de solicitări
+ Crearea subpaginii Ștergere solicităriNu sunt sigur
+ Se Trimit Mulțumiri: Succes
+ Trimis mulţumiri cu succes datorită %1$s
+ Nu a reușit să trimită mulțumiri %1$s
+ Se trimite mulțumiri: EșecTrimitere mulțumiriTrimitere mulțumiri
+ Se trimite Mulțumiri pentru %1$s
+ Respectă acest lucru regulile dreptului de autor?
+ Este corect catalogat acest lucru?
+ Este acesta obiectiv?
+ Ați dori să mulțumiți contribuitorului?
+ Faceți click pe NU pentru a nominaliza această imagine pentru ștergere, dacă nu este deloc utilă.
+ Logo-uri, capturi de ecran, afișe de filme sunt adesea încălcări ale drepturilor de autor.\nFaceți clic pe NU pentru a nominaliza această imagine pentru ștergere
+ %1$s va fi încurajat de apreciere ta
+ Oh, asta nici măcar nu este categorizat!
+ Această imagine este sub %1$s categorii.
+ Este în afara scopului, deoarece este
+ Este încălcare a dreptului de autor, deoarece este
+ Nu, categorizat greșit
+ Pare bine
+ Nu, în afara scopului
+ Pare bine
+ Nu, încălcarea dreptului de autor
+ Pare bineDa, de ce nuUrmătoarea imagine
-
- Primirea conținutului partajat. Procesarea imaginii poate dura ceva timp, în funcție de dimensiunea imaginii și a dispozitivului dvs.
- Primirea conținutului partajat. Procesarea imaginilor poate dura ceva timp, în funcție de mărimea imaginilor și a dispozitivului
+ Dacă faceți click pe acest buton vă va oferi o altă imagine încărcată recent de pe Wikimedia Commons
+ Puteți revizui imaginile și îmbunătăți calitatea Wikimedia Commons.\n Cei patru parametri ai revizuirii sunt:\n - Această imagine este în scopul de aplicare?\n - Această imagine respectă regulile dreptului de autor?\n - Această imagine este corect clasificată?\n - Dacă totul merge bine, puteți, de asemenea, să îi mulțumiți contribuitorului.
+
+ Primirea de conținut partajat. Prelucrarea imaginii poate dura ceva timp, în funcție de dimensiunea imaginii și de dispozitivul dvs.
+ Primirea de conținut partajat. Prelucrarea imaginilor poate dura ceva timp, în funcție de dimensiunea imaginilor și de dispozitivul dvs.
+ Nu s-au folosit imaginiNici o imagine nu a fost anulatăNu au fost încărcate imagini
+ Nu aveți notificări necitite
+ Nu aveți notificări de cititDistribuiți jurnalele folosind
+ Vezi citit
+ Vezi necitit
+ A apărut o eroare la alegerea imaginilor
+ Alegeți Imagini de încărcatVă rugăm să așteptați ...
+ Imaginile de Calitate sunt imagini ale unor fotografi și ilustratori de înaltă calificare, pe care comunitatea Wikimedia Commons a ales-o ca fiind de cea mai înaltă calitate pe site.
+ Imaginile Încărcate prin Locurile din Apropiere sunt imaginile care sunt încărcate prin descoperirea locurilor de pe hartă.
+ Această caracteristică permite editorilor să trimită o notificare de Mulțumire utilizatorilor care fac modificări utile - folosind un mic link de mulțumire pe pagina istoric sau pe pagina dif.
+ Copiați legendele și descrierea anterioară
+ Faceți click pentru a reutiliza titlul și descrierea introdusă în imaginea anterioară și modificați-l pentru a se potrivi cu cel actual
+ Exemple de imagini bune de încărcat pe Commons
+ Exemple de imagini care nu trebuie încărcate
+ Săriți această imagine
+ Descarcare Eşuată!!. Nu putem descărca fișierul fără permisiunea de stocare externă.
+ Gestionați etichetele EXIF
+ Selectați ce etichete EXIF de păstrat în încărcăriAutorDrepturi de autor
+ Locația
+ Model Cameră
+ Model Lentilă
+ Numere Serie
+ Software
+ Încărcați fotografii pe Wikimedia Commons direct de pe telefon. Descărcați aplicația Commons acum: %1$s
+ Partajează aplicația prin ...
+ Informații despre imagine
+ Nu s-au găsit categorii
+ Nu s-au Găsit Reprezentări
+ Încărcare anulată
+ Nu există date pentru titlul sau descrierea imaginii anterioare
+ De ce trebuie șterse %1$s?
+ %1$s este încărcat de: %2$s
+ Limbă de descriere implicită
+ Încercați să nominalizați %1$s pentru ștergere
+ Nominalizare pentru ștergere
+ Succes
+ Nominalizat %1$s pentru ștergere.
+ Eșuat
+ Nu s-a putut solicita ștergerea.
+ Un selfie
+ În ceață
+ Prostii
+ Altele
+ Foto din presă
+ Fotografie aleatorie de pe internetLogoAltul
+ Pentru că este
+ Partajează imaginea prin
+ Încă nu ați făcut contribuțiiCont creat!
+ Text copiat în clipboard
+ Notificare marcată ca citită
+ A fost o eroare!
+ Starea locului:
+ Există
+ Are nevoie de foto
+ Tipul locului:
+ Pod, muzeu, hotel etc.
+ Ceva nu a mers corect la autentificare, trebuie să vă resetați parola !!
+ MEDIA
+ CLASE COPIl
+ CLASE PĂRINTE
+ Locație Găsită în Apropiere
+ Este o fotografie a Locului %1$s?
+ Explorează
+ Semne de carte
+ Setări
+ Eliminat din semne de carte
+ Adăugat la semne de carte
+ Ceva n-a mers bine. Imposibil de setat imaginea de fundal
+ Setează ca Imagine de fundal
+ Setează Imaginea de fundal. Te rog aşteaptă…
+ Urmăriți sistemul
+ Întunecat
+ Deschis
+ Eroare la deschiderea setărilor locației. Vă rugăm să activați locația manual
+ Pentru cele mai bune rezultate, alegeți modul de Înaltă precizie.
+ Activați locația?
+ În apropiere este nevoie de locația activată pentru a funcționa corect
+ Ai fotografiat aceste două poze în același loc? Doriți să folosiți latitudinea/longitudinea imaginii din dreapta?
+ Încarcă mai mult
+ Nu s-au găsit locuri, încercați să schimbați criteriile de căutare.
diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml
index e0ba05a01..b9f5ce426 100644
--- a/app/src/main/res/values-ru/strings.xml
+++ b/app/src/main/res/values-ru/strings.xml
@@ -79,6 +79,7 @@
Подпись (Обязательна)Пожалуйста, укажите название этого файлаОписание
+ Подпись (не более 255 символов)Не удаётся войти — сбой сетиНе удаётся войти — проверьте ваше имя пользователя и парольСлишком много неудачных попыток. Пожалуйста, попробуйте ещё раз через несколько минут.
@@ -210,6 +211,7 @@
ЗагрузитьДаНет
+ ПодписьНазваниеОписаниеОбсуждение
@@ -272,6 +274,7 @@
Ошибка при кэшировании картинокУникальное описание, которое будет сохранено как имя файла. Вы можете использовать естественный язык, разделяя слова пробелами. Пожалуйста, не указывайте расширение файла.Пожалуйста, подробно опишите загружаемый файл: где он был снят? что на нём изображено? каков его контекст? Пожалуйста опишите изображённых персон или объекты. Добавьте информацию, о которой нельзя легко догадаться, например, время суток, когда снимался файл. Если снято что-то необычное, постарайтесь пояснить, что именно в этом необычного.
+ Пожалуйста, напишите краткое описание изображения (не более 255 символов).Это изображение слишком тёмное. Вы уверены, что хотите его загрузить? Викисклад подходит только для изображений, имеющих энциклопедическую ценность.Это изображение размыто. Вы уверены, что хотите его загрузить? Викисклад подходит только для изображений, имеющих энциклопедическую ценность.Потенциальные проблемы с этим изображением:
@@ -281,6 +284,7 @@
Это изображение было сделано в другом месте.Пожалуйста, загружайте только те изображения, которые были сделаны вами. Не загружайте изображений, которые вы нашли в Фейсбуке.Всё равно желаете загрузить это изображение?
+ Проблемы, найденные в изображенииПожалуйста, загружайте только те изображения, которые были сделаны вами. Не загружайте изображений, которые вы скачали из Интернета.РазрешитьИспользовать внешний носитель
@@ -610,5 +614,7 @@
Для достижения наилучших результатов выберите режим высокой точности.Включить местоположение?Рядом необходимо, чтобы местоположение было включено для правильной работы.
+ Вы снимали эти две фотографии в одном месте? Хотите использовать широту/долготу изображения справа?
+ Загрузить ещёМест не найдено, попытайтесь изменить критерии поиска.
diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml
index 10953ae28..b994c94a9 100644
--- a/app/src/main/res/values-sv/strings.xml
+++ b/app/src/main/res/values-sv/strings.xml
@@ -598,5 +598,6 @@
Aktivera plats?I närheten behöver ha plats aktiverat för att fungera ordentligtTog du dessa två bilder på samma plats? Vill du använda den högra bildens latitud/longitud?
+ Läs in flerInga platser hittades, försök ändra dina sökkriterier.
diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml
index 30ac59c2e..04c94a67c 100644
--- a/app/src/main/res/values-tr/strings.xml
+++ b/app/src/main/res/values-tr/strings.xml
@@ -610,5 +610,6 @@
Konum açılsın mı?Yakınımdakilerin düzgün çalışması için konumun açık olması gerekiyorBu iki fotoğrafı aynı yerde mi çektiniz? Sağdaki resmin enlem/boylamını kullanmak ister misiniz?
+ Daha Fazla YükleYer bulunamadı, arama kriterlerinizi değiştirmeyi deneyin.
diff --git a/app/src/main/res/values-vec/strings.xml b/app/src/main/res/values-vec/strings.xml
index 3e60e9259..99a7f74aa 100644
--- a/app/src/main/res/values-vec/strings.xml
+++ b/app/src/main/res/values-vec/strings.xml
@@ -1,5 +1,6 @@
@@ -48,8 +49,10 @@
I me cargamentiSpartisi in jiroVarda sol navegadore web
- Titoło (obligatorio)
+ Didascalia (obligatorio)
+ Par piaser, daghe na didascalia a sto fileDescrision
+ Didascalia (màsimo 255 caràteri)No xé posibiłe ndarghe drento - erore de reteEntrada no riusia - Daghe na ociada al nome utente e ciaveMasa volte te ghè provà. Riprova tra on fià de minudi.
@@ -62,6 +65,7 @@
ModifegheCargaSerca łe categorie
+ Serca le robe che se vede nel to file (le montagne, el Taj Mahal, ec.)SalvaAjornaLista
@@ -82,6 +86,7 @@
%1$d cargamentiNo ła xé sta catada na categoria che ła contegna %1$s
+ No gò catà nisun elemento Wikidata che corisponda a %1$sXonta categorie par far sì che łe to someje e imajini łe sia pì façilmente riçercae so Wikimedia Commons.\nScumisia a dijitare par xontare categorie.CategorieInpostasion
@@ -562,4 +567,6 @@
Ativar ła poxision?La locałixasion n\'te łe viçinanse ła ga da esare inpisada parché ła funsionee in modo justo.Ste do foto łe gheto fate in tel steso posto? Vuto doparar ła stesa latitudine/lonxitudine de l\'imajine a drita?
+ Carga \'ncora
+ No go catà nisun posto, pròa a canbiar la to riserca.
diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml
index 0e3bc5894..c4928f786 100644
--- a/app/src/main/res/values-zh-rTW/strings.xml
+++ b/app/src/main/res/values-zh-rTW/strings.xml
@@ -603,5 +603,6 @@
打開位置?附近功能需要啟用位置才能運作正常您是否在同一地點拍攝了這兩張圖片?您要使用圖片右側的緯度/經度嗎?
+ 載入更多查無地點,請嘗試更改您的搜尋條件。
diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml
index 1a1262d3c..792a1fa41 100644
--- a/app/src/main/res/values-zh/strings.xml
+++ b/app/src/main/res/values-zh/strings.xml
@@ -14,6 +14,7 @@
* Looong
* Qiyue2001
* Shizhao
+* SomeyaMako
* VulpesVulpes825
* Wxyveronica
* Yfdyh000
@@ -577,4 +578,5 @@
出错了。无法设置壁纸设为壁纸正在设置壁纸。请稍等…
+ 加载更多
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 500c2db30..ceb3986d1 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1,5 +1,35 @@
+
+ %1$d file uploading
+ %1$d files uploading
+
+
+
+ @string/contributions_subtitle_zero
+ (%1$d)
+ (%1$d)
+
+
+ Starting %1$d upload
+ Starting %1$d uploads
+
+
+ %1$d upload
+ %1$d uploads
+
+
+ This image will be licensed under %1$s
+ These images will be licensed under %1$s
+
+
+ %1$d Upload
+ %1$d Uploads
+
+
+ Receiving shared content. Processing the image might take some time depending on the size of the image and your device
+ Receiving shared content. Processing the images might take some time depending on the size of the images and your device
+ ExploreExploreAppearance
@@ -31,10 +61,6 @@
Finishing uploading %1$sUploading %1$s failedTap to view
-
- %1$d file uploading
- %1$d files uploading
- My Recent UploadsQueuedFailed
@@ -69,20 +95,6 @@
GPS is disabled in your device. Would you like to enable it?Enable GPSNo uploads yet
-
-
- @string/contributions_subtitle_zero
- (%1$d)
- (%1$d)
-
-
- Starting %1$d upload
- Starting %1$d uploads
-
-
- %1$d upload
- %1$d uploads
- No categories matching %1$s foundNo Wikidata items matching %1$s found%1$s has no child classes
@@ -110,10 +122,6 @@
You have not yet uploaded any photos.RetryCancel
-
- This image will be licensed under %1$s
- These images will be licensed under %1$s
- By submitting this picture, I declare that this is my own work, that it does not contain copyrighted material or selfies, and otherwise adheres to <a href=\"https://commons.wikimedia.org/wiki/Commons:Policies_and_guidelines\">Wikimedia Commons policies</a>.DownloadDefault License
@@ -254,9 +262,9 @@
A unique descriptive title for the file, which will serve as a filename. You may use plain language with spaces. Do not include the file extensionPlease describe the media as much as possible: Where was it taken? What does it show? What is the context? Please describe the objects or persons. Reveal information that can not be easily guessed, for instance the time of day if it is a landscape. If the media shows something unusual, please explain what makes it unusual.Please write a brief description of the image. (Limit to 255 characters)
+
This picture is too dark, are you sure you want to upload it? Wikimedia Commons is only for pictures with encyclopedic value.This picture is blurry, are you sure you want to upload it? Wikimedia Commons is only for pictures with encyclopedic value.
-
Potential problems with this image:Image is too dark.Image is blurry.
@@ -264,10 +272,10 @@
This picture was taken at a different location.Please only upload pictures that you have taken by yourself. Don\'t upload pictures that you have found on other people\'s Facebook accounts.Do you still want to upload this picture?
+
+
Problems found in imagePlease only upload pictures that you have taken by yourself. Don\'t upload pictures that you have downloaded from the Internet.
-
-
Give permissionUse external storageSave pictures taken with the in-app camera on your device
@@ -287,15 +295,15 @@
Do you really want to skip login?You would have to log in to upload pictures in the future.Please log in to use this feature
+
Copy the wikitext to the clipboardThe wikitext was copied to the clipboard
-
Location has not changed.Nearby might not work properly, Location not available.Permission required to display a list of nearby places
+
Get directionsRead article
-
Welcome to Wikimedia Commons, %1$s! We\'re glad you\'re here.%1$s left a message on your talk pageThank you for making an edit
@@ -318,18 +326,18 @@
LanguagesSelect the language that you would like to submit translations forProceed
+
CancelRetry
-
Got it!These are the places near you that need pictures to illustrate their Wikipedia articles.\n\nClicking on \'SEARCH THIS AREA\' locks the map and launches a nearby search around that location.
+
Tapping this button brings up a list of these placesYou can upload a picture for any place from your gallery or camera
-
No images found!
+
Error occurred while loading images.Uploaded by: %1$s
-
BlockedYou are blocked from editing CommonsPic of the Day
@@ -346,9 +354,9 @@
MediaCategoriesItems
+
FeaturedUploaded via mobile
-
Image added to %1$s on Wikidata!Failed to update corresponding Wikidata entity!Set as wallpaper
@@ -375,16 +383,16 @@
Is this screenshot OK to upload?Share AppCoordinates were not specified during image selection
+
Error fetching nearby places.+ Add description
-
No recent searchesAre you sure you want to clear your search history?Do you want to delete this search?Search history deleted
+
Nominate For DeletionDelete
-
AchievementsStatisticsThanks Received
@@ -398,12 +406,12 @@
Your level increases as you meet these requirements. Items in the "statistics" section do not count towards your level.minimum required: The number of images you have uploaded to Commons, via any upload software
+
The percentage of images you have uploaded to Commons that were not deletedThe number of images you have uploaded to Commons that were used in Wikimedia articlesError occurred!Commons Notification
-
Use custom author nameUse a custom author name instead of your username while uploading photosCustom author name
@@ -413,24 +421,20 @@
Notifications (read)Display nearby notificationTap here to see the nearest place that needs pictures
+
No nearby places found close to youList
-
Storage Permission
+
We need your permission to access the external storage of your device in order to upload images.You won\'t see the nearest place that needs pictures anymore. However, you can re-enable this notification in Settings if you wish.
-
Step %1$d of %2$dImage %1$d in setNextPreviousSubmit
- A file with the file name %1$s exists. Are you sure you want to proceed?
+ A file with the file name %1$s exists. Are you sure you want to proceed?No compatible map application could be found on your device. Please install a map application to use this feature.
-
- %1$d Upload
- %1$d Uploads
- BookmarksBookmarksPictures
@@ -439,32 +443,32 @@
BookmarksYou haven\'t added any bookmarksBookmarks
- Log collection started. Please RESTART the app, perform action that you wish to log, and then tap \'Send log file\' again
+ Log collection started. Please RESTART the app, perform action that you wish to log, and then tap \'Send log file\' againI uploaded it by mistakeI did not know it would be publicly visibleI realized it is bad for my privacyI changed my mind, I don\'t want it to be publicly visible anymoreSorry this picture is not interesting for an encyclopedia
+
Uploaded by myself on %1$s, used in %2$d article(s).Welcome to Commons!\n
Upload your first media by tapping on the add button.
-
WorldwideAmericaEuropeMiddle EastAfricaAsia
+
Pacific
-
No Categories Selected
+
Images without categories are rarely usable. Are you sure you want to continue without selecting categories?
-
No Depictions Selected
- Images with depictions are more easily found and more likely to be used. Are you sure you want to continue without selecting depictions?
+ Images with depictions are more easily found and more likely to be used. Are you sure you want to continue without selecting depictions?(For all images in set)Search this areaPermission Request
@@ -478,15 +482,15 @@ Upload your first media by tapping on the add button.Ends on:Display campaignsSee the ongoing campaigns
- You won\'t see the campaigns anymore. However, you can re-enable this notification in Settings if you wish.
+ You won\'t see the campaigns anymore. However, you can re-enable this notification in Settings if you wish.This function requires network connection, please check your connection settings.Upload failed due to issues with edit token. Please try logging out and in again.
- Error occurred while processing the image. Please try again!
+ Error occurred while processing the image. Please try again!Getting token for editingAdding template for category checkRequesting category check for %1$s
- Requesting category check
+ Requesting category checkCategory check requestedCategory check request didn\'t workRequested category check for %1$s
@@ -498,14 +502,14 @@ Upload your first media by tapping on the add button.Adding file to Delete requests logCreating Delete requests subpageNot sure
- Sending Thanks: Success
+ Sending Thanks: SuccessSuccessfully sent thanks to %1$sFailed to send thanks %1$sSending Thanks: FailureSending thanksSending thanks
- Sending Thanks for %1$s
+ Sending Thanks for %1$sDoes this follow the rules of copyright?Is this correctly categorized?Is this in-scope?
@@ -517,21 +521,17 @@ Upload your first media by tapping on the add button.
This image is under %1$s categories.It is out of scope because it isIt is copyright violation because it is
- No, mis-categorized
- Seems fine
- No, out of scope
- Seems fine
- No, copyright violation
- Seems fine
- Yes, why not
- Next image
- Clicking this button will give you another recently uploaded image from Wikimedia Commons
- You can review images and improve the quality of Wikimedia Commons.\n The four parameters of review are: \n - Is this image in-scope? \n - Does this image follow the rules of copyright? \n - Is this image correctly categorized? \n - If all goes well you can also thank the contributor.
+ No, mis-categorized
+ Seems fine
+ No, out of scope
+ Seems fine
+ No, copyright violation
+ Seems fine
+ Yes, why not
+ Next image
+ Clicking this button will give you another recently uploaded image from Wikimedia Commons
-
- Receiving shared content. Processing the image might take some time depending on the size of the image and your device
- Receiving shared content. Processing the images might take some time depending on the size of the images and your device
-
+ You can review images and improve the quality of Wikimedia Commons.\n The four parameters of review are: \n - Is this image in-scope? \n - Does this image follow the rules of copyright? \n - Is this image correctly categorized? \n - If all goes well you can also thank the contributor.No images usedNo images reverted
@@ -549,7 +549,7 @@ Upload your first media by tapping on the add button.
Please wait…Featured pictures are images from highly skilled photographers and illustrators that the Wikimedia Commons community has chosen as some of the highest quality on the site.Images Uploaded via Nearby places are the images which are uploaded by discovering places on the map.
- This feature allows editors to send a Thank you notification to users who make useful edits – by using a small thank link on the history page or diff page.
+ This feature allows editors to send a Thank you notification to users who make useful edits – by using a small thank link on the history page or diff page.Copy previous captions & descriptionClick to reuse the title and description you entered in your previous picture and modify it to fit your current oneExamples of good images to upload to Commons
@@ -630,4 +630,20 @@ Upload your first media by tapping on the add button.
Did you shoot these two pictures at the same place? Do you want to use the latitude/longitude of the picture on the right?Load MoreNo places found, try changing your search criteria.
+
+ Add image to Wikipedia
+ Do you want to add this picture to the %1$s language Wikipedia article?
+
+ Instructions
+ Take care to follow editing guidelines!
+ Confirm
+ Instructions
+ 1. Use the following wikitext:
+ 2. Clicking on Confirm will open the Wikipedia article
+ 3. Find an appropriate section in the article for your image
+ 4. Click on the Edit icon (the one like a pencil) for that section.
+ 5. Paste the wikitext in the appropriate place.
+ 6. Edit the wikitext for appropriate positioning, if necessary. For more information, see <a href="https://en.wikipedia.org/wiki/Wikipedia:Manual_of_Style/Images#How_to_place_an_image">here</a>.
+ 7. Publish the article
+ Copy wikicode to clipboard
diff --git a/app/src/test/kotlin/fr/free/nrw/commons/contributions/ContributionBoundaryCallbackTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/contributions/ContributionBoundaryCallbackTest.kt
index b2b08d185..365c0ae7f 100644
--- a/app/src/test/kotlin/fr/free/nrw/commons/contributions/ContributionBoundaryCallbackTest.kt
+++ b/app/src/test/kotlin/fr/free/nrw/commons/contributions/ContributionBoundaryCallbackTest.kt
@@ -1,27 +1,21 @@
package fr.free.nrw.commons.contributions
-import android.content.Context
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import com.nhaarman.mockitokotlin2.*
import fr.free.nrw.commons.Media
import fr.free.nrw.commons.auth.SessionManager
import fr.free.nrw.commons.media.MediaClient
-import fr.free.nrw.commons.utils.NetworkUtilsTest
-import fr.free.nrw.commons.utils.createMockDataSourceFactory
import io.reactivex.Scheduler
import io.reactivex.Single
import io.reactivex.schedulers.Schedulers
-import io.reactivex.schedulers.TestScheduler
import org.junit.Before
import org.junit.Rule
import org.junit.Test
-import org.mockito.ArgumentMatchers.*
-import org.mockito.InjectMocks
+import org.mockito.ArgumentMatchers.anyList
+import org.mockito.ArgumentMatchers.anyString
import org.mockito.Mock
import org.mockito.Mockito.mock
import org.mockito.MockitoAnnotations
-import java.lang.RuntimeException
-import java.util.*
/**
* The unit test class for ContributionBoundaryCallbackTest
@@ -136,4 +130,4 @@ class ContributionBoundaryCallbackTest {
verifyZeroInteractions(repository);
verify(mediaClient).getMediaListForUser(anyString());
}
-}
\ No newline at end of file
+}
diff --git a/app/src/test/kotlin/fr/free/nrw/commons/contributions/ContributionsRepositoryTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/contributions/ContributionsRepositoryTest.kt
index 0b11c4bb4..b90b4420c 100644
--- a/app/src/test/kotlin/fr/free/nrw/commons/contributions/ContributionsRepositoryTest.kt
+++ b/app/src/test/kotlin/fr/free/nrw/commons/contributions/ContributionsRepositoryTest.kt
@@ -6,11 +6,9 @@ import com.nhaarman.mockitokotlin2.whenever
import fr.free.nrw.commons.utils.createMockDataSourceFactory
import io.reactivex.Scheduler
import io.reactivex.Single
-import junit.framework.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import org.mockito.*
-import org.mockito.Mockito.any
import org.mockito.Mockito.mock
/**
diff --git a/app/src/test/kotlin/fr/free/nrw/commons/media/MediaClientTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/media/MediaClientTest.kt
index 2ad07517d..4dfe7c433 100644
--- a/app/src/test/kotlin/fr/free/nrw/commons/media/MediaClientTest.kt
+++ b/app/src/test/kotlin/fr/free/nrw/commons/media/MediaClientTest.kt
@@ -4,6 +4,8 @@ import com.nhaarman.mockitokotlin2.mock
import com.nhaarman.mockitokotlin2.whenever
import fr.free.nrw.commons.Media
import fr.free.nrw.commons.explore.media.MediaConverter
+import fr.free.nrw.commons.media.model.PageMediaListItem
+import fr.free.nrw.commons.media.model.PageMediaListResponse
import fr.free.nrw.commons.utils.CommonsDateUtil
import io.reactivex.Single
import junit.framework.Assert.*
@@ -29,6 +31,10 @@ class MediaClientTest {
@Mock
internal var mediaDetailInterface: MediaDetailInterface? = null
+ @Mock
+ internal var pageMediaInterface: PageMediaInterface? = null
+
+
@InjectMocks
var mediaClient: MediaClient? = null
@@ -228,6 +234,26 @@ class MediaClientTest {
assertEquals("Test", mediaClient!!.getPageHtml("abcde").blockingGet())
}
+ @Test
+ fun doesPageContainMedia() {
+ val mock = mock(PageMediaListResponse::class.java)
+ whenever(mock.items).thenReturn(listOf(mock(PageMediaListItem::class.java)))
+ `when`(pageMediaInterface!!.getMediaList(ArgumentMatchers.anyString()))
+ .thenReturn(Single.just(mock))
+
+ mediaClient!!.doesPageContainMedia("Test").test().assertValue(true)
+ }
+
+ @Test
+ fun doesPageContainMediaWithNoMedia() {
+ val mock = mock(PageMediaListResponse::class.java)
+ whenever(mock.items).thenReturn(listOf())
+ `when`(pageMediaInterface!!.getMediaList(ArgumentMatchers.anyString()))
+ .thenReturn(Single.just(mock))
+
+ mediaClient!!.doesPageContainMedia("Test").test().assertValue(false)
+ }
+
@Test
fun getPageHtmlTestNull() {
val mockResponse = MwParseResponse()
diff --git a/build.gradle b/build.gradle
index 33b98d18a..ae676d842 100644
--- a/build.gradle
+++ b/build.gradle
@@ -7,7 +7,7 @@ buildscript {
maven { url "https://plugins.gradle.org/m2/" }
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.6.3'
+ classpath 'com.android.tools.build:gradle:4.0.0'
classpath "com.hiya:jacoco-android:0.2"
classpath 'com.getkeepsafe.dexcount:dexcount-gradle-plugin:0.8.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$KOTLIN_VERSION"
diff --git a/data-client/src/main/java/org/wikipedia/dataclient/WikiSite.java b/data-client/src/main/java/org/wikipedia/dataclient/WikiSite.java
index cac1f681c..37f603e60 100644
--- a/data-client/src/main/java/org/wikipedia/dataclient/WikiSite.java
+++ b/data-client/src/main/java/org/wikipedia/dataclient/WikiSite.java
@@ -138,6 +138,15 @@ public class WikiSite implements Parcelable {
return authorityToMobile(authority());
}
+ /**
+ * Get wiki's mobile URL
+ * Eg. https://en.m.wikipedia.org
+ * @return
+ */
+ public String mobileUrl() {
+ return String.format("%1$s://%2$s", scheme(), mobileAuthority());
+ }
+
/**
* @return The canonical "desktop" form of the authority. For example, if the authority
* is in a "mobile" form, e.g. en.m.wikipedia.org, this will become en.wikipedia.org.