Merge remote-tracking branch 'refs/remotes/origin/master' into feedback-gamification

This commit is contained in:
misaochan 2018-05-16 19:07:21 +10:00
commit e028658051
77 changed files with 1862 additions and 546 deletions

View file

@ -5,15 +5,30 @@ If you're not sure where to start head on to [this wiki page](https://github.com
Here's a gist of the guidelines,
# Make separate commits for logically separate changes
1. Make separate commits for logically separate changes
# Describe your changes well in the commit message
1. Describe your changes well in the commit message
The first line of the commit message should be a short description of what has
The first line of the commit message should be a short description of what has
changed. It is also good to prefix the first line with "area: " where the "area"
is a filename or identifier for the general area of the code being modified.
The body should provide a meaningful commit message.
# Write tests for your code (if possible)
1. Write Javadocs
# Make sure the Wiki pages don't become stale by updating them (if needed)
We require contributors to include Javadocs for all new methods and classes
submitted via PRs (after 1 May 2018). This is aimed at making it easier for
new contributors to dive into our codebase, especially those who are new to
Android development. A few things to note:
- This should not replace the need for code that is easily-readable in
and of itself
- Please make sure that your Javadocs are reasonably descriptive, not just
a copy of the method name
- Please do not use `@author` tags - we aim for collective code ownership,
and if needed, Git allows us to see who wrote something without needing
to add these tags (`git blame`)
1. Write tests for your code (if possible)
1. Make sure the Wiki pages don't become stale by updating them (if needed)

View file

@ -1,15 +1,15 @@
## Description
## Description (required)
Fixes #{GitHub issue number}
Fixes #{GitHub issue number and title}
{Describe the changes made and why they were made.}
## Tests performed
## Tests performed (required)
Tested on {API level & name of device/emulator}, with {build variant, e.g. ProdDebug}.
{Please test your PR at least once before submitting.}
## Screenshots showing what changed
## Screenshots showing what changed (optional)
{Only for user interface changes, otherwise remove this section. See [how to take a screenshot](https://android.stackexchange.com/questions/1759/how-to-take-a-screenshot-with-an-android-device)}
_Note: Please ensure that you have read CONTRIBUTING.md if this is your first pull request._

View file

@ -25,6 +25,8 @@ dependencies {
transitive=true
}
implementation "com.github.deano2390:MaterialShowcaseView:1.2.0"
implementation "com.android.support:support-v4:$SUPPORT_LIB_VERSION"
implementation "com.android.support:appcompat-v7:$SUPPORT_LIB_VERSION"
implementation "com.android.support:design:$SUPPORT_LIB_VERSION"
@ -49,6 +51,8 @@ dependencies {
implementation 'com.jakewharton.rxbinding2:rxbinding-appcompat-v7:2.0.0'
implementation 'com.jakewharton.rxbinding2:rxbinding-design:2.0.0'
implementation 'org.jsoup:jsoup:1.11.3'
implementation 'com.facebook.fresco:fresco:1.5.0'
implementation 'com.facebook.stetho:stetho:1.5.0'

View file

@ -92,8 +92,9 @@
android:label="@string/navigation_item_notification" />
<activity
android:name=".featured.FeaturedImagesActivity"
android:label="@string/title_activity_featured_images" />
android:name=".category.CategoryImagesActivity"
android:label="@string/title_activity_featured_images"
android:parentActivityName=".contributions.ContributionsActivity" />
<service android:name=".upload.UploadService" />

View file

@ -135,9 +135,10 @@ public class AboutActivity extends NavigationBaseActivity {
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.share_app_icon:
String shareText = "Upload photos to Wikimedia Commons on your phone\nDownload the Commons app: http://play.google.com/store/apps/details?id=fr.free.nrw.commons";
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, "http://play.google.com/store/apps/details?id=fr.free.nrw.commons");
sendIntent.putExtra(Intent.EXTRA_TEXT, shareText);
sendIntent.setType("text/plain");
startActivity(Intent.createChooser(sendIntent, "Share app via..."));
return true;

View file

@ -61,8 +61,8 @@ public class MediaDataExtractor {
}
try{
Timber.d("Nominated for deletion: " + mediaWikiApi.pageExists("Commons:Deletion_requests/"+filename));
deletionStatus = mediaWikiApi.pageExists("Commons:Deletion_requests/"+filename);
deletionStatus = mediaWikiApi.pageExists("Commons:Deletion_requests/" + filename);
Timber.d("Nominated for deletion: " + deletionStatus);
}
catch (Exception e){
Timber.d(e.getMessage());

View file

@ -47,6 +47,7 @@ import fr.free.nrw.commons.di.ApplicationlessInjection;
import fr.free.nrw.commons.mwapi.MediaWikiApi;
import fr.free.nrw.commons.theme.NavigationBaseActivity;
import fr.free.nrw.commons.ui.widget.HtmlTextView;
import fr.free.nrw.commons.utils.ViewUtil;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
@ -109,14 +110,14 @@ public class LoginActivity extends AccountAuthenticatorActivity {
usernameEdit.addTextChangedListener(textWatcher);
usernameEdit.setOnFocusChangeListener((v, hasFocus) -> {
if (!hasFocus) {
hideKeyboard(v);
ViewUtil.hideKeyboard(v);
}
});
passwordEdit.addTextChangedListener(textWatcher);
passwordEdit.setOnFocusChangeListener((v, hasFocus) -> {
if (!hasFocus) {
hideKeyboard(v);
ViewUtil.hideKeyboard(v);
}
});
@ -144,16 +145,6 @@ public class LoginActivity extends AccountAuthenticatorActivity {
Utils.handleWebUrl(this,Uri.parse("https://github.com/commons-app/apps-android-commons/wiki/Privacy-policy\\"));
}
public void hideKeyboard(View view) {
if (view != null) {
InputMethodManager inputMethodManager = (InputMethodManager) this.getSystemService(Activity.INPUT_METHOD_SERVICE);
if (inputMethodManager != null) {
inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
}
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);

View file

@ -1,7 +1,6 @@
package fr.free.nrw.commons.category;
import android.app.Activity;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
@ -16,7 +15,6 @@ import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.TextView;
@ -43,6 +41,7 @@ import fr.free.nrw.commons.di.CommonsDaggerSupportFragment;
import fr.free.nrw.commons.mwapi.MediaWikiApi;
import fr.free.nrw.commons.upload.MwVolleyApi;
import fr.free.nrw.commons.utils.StringSortingUtils;
import fr.free.nrw.commons.utils.ViewUtil;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
@ -116,7 +115,7 @@ public class CategorizationFragment extends CommonsDaggerSupportFragment {
categoriesFilter.setOnFocusChangeListener((v, hasFocus) -> {
if (!hasFocus) {
hideKeyboard(v);
ViewUtil.hideKeyboard(v);
}
});
@ -128,16 +127,6 @@ public class CategorizationFragment extends CommonsDaggerSupportFragment {
return rootView;
}
public void hideKeyboard(View view) {
if (view != null) {
InputMethodManager inputMethodManager = (InputMethodManager) getActivity().getSystemService(Activity.INPUT_METHOD_SERVICE);
if (inputMethodManager != null) {
inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
}
}
@Override
public void onDestroyView() {
categoriesFilter.removeTextChangedListener(textWatcher);

View file

@ -0,0 +1,29 @@
package fr.free.nrw.commons.category;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Singleton;
import fr.free.nrw.commons.Media;
import fr.free.nrw.commons.mwapi.MediaWikiApi;
@Singleton
public class CategoryImageController {
private MediaWikiApi mediaWikiApi;
@Inject
public CategoryImageController(MediaWikiApi mediaWikiApi) {
this.mediaWikiApi = mediaWikiApi;
}
/**
* Takes a category name as input and calls the API to get a list of images for that category
* @param categoryName
* @return
*/
public List<Media> getCategoryImages(String categoryName) {
return mediaWikiApi.getCategoryImages(categoryName);
}
}

View file

@ -0,0 +1,225 @@
package fr.free.nrw.commons.category;
import org.jsoup.Jsoup;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.annotation.Nullable;
import fr.free.nrw.commons.Media;
import timber.log.Timber;
public class CategoryImageUtils {
/**
* The method iterates over the child nodes to return a list of Media objects
* @param childNodes
* @return
*/
public static List<Media> getMediaList(NodeList childNodes) {
List<Media> categoryImages = new ArrayList<>();
for (int i = 0; i < childNodes.getLength(); i++) {
Node node = childNodes.item(i);
categoryImages.add(getMediaFromPage(node));
}
return categoryImages;
}
/**
* Creates a new Media object from the XML response as received by the API
* @param node
* @return
*/
private static Media getMediaFromPage(Node node) {
Media media = new Media(null,
getImageUrl(node),
getFileName(node),
getDescription(node),
getDataLength(node),
getDateCreated(node),
getDateCreated(node),
getCreator(node)
);
media.setLicense(getLicense(node));
return media;
}
/**
* Extracts the filename of the uploaded image
* @param document
* @return
*/
private static String getFileName(Node document) {
Element element = (Element) document;
return element.getAttribute("title");
}
/**
* Extracts the image description for that particular upload
* @param document
* @return
*/
private static String getDescription(Node document) {
return getMetaDataValue(document, "ImageDescription");
}
/**
* Extracts license information from the image meta data
* @param document
* @return
*/
private static String getLicense(Node document) {
return getMetaDataValue(document, "License");
}
/**
* Returns the parsed value of artist from the response
* The artist information is returned as a HTML string from the API. Jsoup library parses the HTML string
* to extract just the text value
* @param document
* @return
*/
private static String getCreator(Node document) {
String artist = getMetaDataValue(document, "Artist");
if (artist != null) {
return Jsoup.parse(artist).text();
}
return null;
}
/**
* Returns the parsed date of creation of the image
* @param document
* @return
*/
private static Date getDateCreated(Node document) {
String dateTime = getMetaDataValue(document, "DateTime");
if (dateTime != null && !dateTime.equals("")) {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
return format.parse(dateTime);
} catch (ParseException e) {
Timber.d("Error occurred while parsing date %s", dateTime);
return new Date();
}
}
return new Date();
}
/**
* @param document
* @return Returns the url attribute from the imageInfo node
*/
private static String getImageUrl(Node document) {
Element element = (Element) getImageInfo(document);
if (element != null) {
return element.getAttribute("url");
}
return null;
}
/**
* Takes the node document and gives out the attribute length from the node document
* @param document
* @return
*/
private static long getDataLength(Node document) {
Element element = (Element) document;
if (element != null) {
String length = element.getAttribute("length");
if (length != null && !length.equals("")) {
return Long.parseLong(length);
}
}
return 0L;
}
/**
* Generic method to get the value of any meta as returned by the getMetaData function
* @param document node document as returned by API
* @param metaName the name of meta node to be returned
* @return
*/
private static String getMetaDataValue(Node document, String metaName) {
Element metaData = getMetaData(document, metaName);
if (metaData != null) {
return metaData.getAttribute("value");
}
return null;
}
/**
* Generic method to return an element taking the node document and metaName as input
* @param document node document as returned by API
* @param metaName the name of meta node to be returned
* @return
*/
@Nullable
private static Element getMetaData(Node document, String metaName) {
Node extraMetaData = getExtraMetaData(document);
if (extraMetaData != null) {
Node node = getNode(extraMetaData, metaName);
if (node != null) {
return (Element) node;
}
}
return null;
}
/**
* Extracts extmetadata from the response XML
* @param document
* @return
*/
@Nullable
private static Node getExtraMetaData(Node document) {
Node imageInfo = getImageInfo(document);
if (imageInfo != null) {
return getNode(imageInfo, "extmetadata");
}
return null;
}
/**
* Extracts the ii node from the imageinfo node
* @param document
* @return
*/
@Nullable
private static Node getImageInfo(Node document) {
Node imageInfo = getNode(document, "imageinfo");
if (imageInfo != null) {
return getNode(imageInfo, "ii");
}
return null;
}
/**
* Takes a parent node as input and returns a child node if present
* @param node parent node
* @param nodeName child node name
* @return
*/
@Nullable
public static Node getNode(Node node, String nodeName) {
NodeList childNodes = node.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
Node nodeItem = childNodes.item(i);
Element item = (Element) nodeItem;
if (item.getTagName().equals(nodeName)) {
return nodeItem;
}
}
return null;
}
}

View file

@ -0,0 +1,160 @@
package fr.free.nrw.commons.category;
import android.content.Context;
import android.content.Intent;
import android.database.DataSetObserver;
import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.view.View;
import android.widget.AdapterView;
import butterknife.ButterKnife;
import fr.free.nrw.commons.Media;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.auth.AuthenticatedActivity;
import fr.free.nrw.commons.media.MediaDetailPagerFragment;
import timber.log.Timber;
/**
* This activity displays pictures of a particular category
* Its generic and simply takes the name of category name in its start intent to load all images in
* a particular category. This activity is currently being used to display a list of featured images,
* which is nothing but another category on wikimedia commons.
*/
public class CategoryImagesActivity
extends AuthenticatedActivity
implements FragmentManager.OnBackStackChangedListener,
MediaDetailPagerFragment.MediaDetailProvider,
AdapterView.OnItemClickListener{
private FragmentManager supportFragmentManager;
private CategoryImagesListFragment categoryImagesListFragment;
private MediaDetailPagerFragment mediaDetails;
@Override
protected void onAuthCookieAcquired(String authCookie) {
}
@Override
protected void onAuthFailure() {
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_category_images);
ButterKnife.bind(this);
// Activity can call methods in the fragment by acquiring a
// reference to the Fragment from FragmentManager, using findFragmentById()
supportFragmentManager = getSupportFragmentManager();
setCategoryImagesFragment();
supportFragmentManager.addOnBackStackChangedListener(this);
if (savedInstanceState != null) {
mediaDetails = (MediaDetailPagerFragment) supportFragmentManager
.findFragmentById(R.id.fragmentContainer);
}
requestAuthToken();
initDrawer();
setPageTitle();
}
/**
* Gets the categoryName from the intent and initializes the fragment for showing images of that category
*/
private void setCategoryImagesFragment() {
categoryImagesListFragment = new CategoryImagesListFragment();
String categoryName = getIntent().getStringExtra("categoryName");
if (getIntent() != null && categoryName != null) {
Bundle arguments = new Bundle();
arguments.putString("categoryName", categoryName);
categoryImagesListFragment.setArguments(arguments);
FragmentTransaction transaction = supportFragmentManager.beginTransaction();
transaction
.add(R.id.fragmentContainer, categoryImagesListFragment)
.commit();
}
}
/**
* Gets the passed title from the intents and displays it as the page title
*/
private void setPageTitle() {
if (getIntent() != null && getIntent().getStringExtra("title") != null) {
setTitle(getIntent().getStringExtra("title"));
}
}
@Override
public void onBackStackChanged() {
}
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
if (mediaDetails == null || !mediaDetails.isVisible()) {
// set isFeaturedImage true for featured images, to include author field on media detail
mediaDetails = new MediaDetailPagerFragment(false, true);
FragmentManager supportFragmentManager = getSupportFragmentManager();
supportFragmentManager
.beginTransaction()
.replace(R.id.fragmentContainer, mediaDetails)
.addToBackStack(null)
.commit();
supportFragmentManager.executePendingTransactions();
}
mediaDetails.showImage(i);
}
/**
* Consumers should be simply using this method to use this activity.
* @param context
* @param title Page title
* @param categoryName Name of the category for displaying its images
*/
public static void startYourself(Context context, String title, String categoryName) {
Intent intent = new Intent(context, CategoryImagesActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
intent.putExtra("title", title);
intent.putExtra("categoryName", categoryName);
context.startActivity(intent);
}
@Override
public Media getMediaAtPosition(int i) {
if (categoryImagesListFragment.getAdapter() == null) {
// not yet ready to return data
return null;
} else {
return (Media) categoryImagesListFragment.getAdapter().getItem(i);
}
}
@Override
public int getTotalMediaCount() {
if (categoryImagesListFragment.getAdapter() == null) {
return 0;
}
return categoryImagesListFragment.getAdapter().getCount();
}
@Override
public void notifyDatasetChanged() {
}
@Override
public void registerDataSetObserver(DataSetObserver observer) {
}
@Override
public void unregisterDataSetObserver(DataSetObserver observer) {
}
}

View file

@ -0,0 +1,227 @@
package fr.free.nrw.commons.category;
import android.annotation.SuppressLint;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.GridView;
import android.widget.ListAdapter;
import android.widget.ProgressBar;
import android.widget.TextView;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import javax.inject.Named;
import butterknife.BindView;
import butterknife.ButterKnife;
import dagger.android.support.DaggerFragment;
import fr.free.nrw.commons.Media;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.utils.NetworkUtils;
import fr.free.nrw.commons.utils.ViewUtil;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import timber.log.Timber;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
/**
* Displays images for a particular category with load more on scrolling incorporated
*/
public class CategoryImagesListFragment extends DaggerFragment {
private static int TIMEOUT_SECONDS = 15;
private GridViewAdapter gridAdapter;
@BindView(R.id.statusMessage)
TextView statusTextView;
@BindView(R.id.loadingImagesProgressBar) ProgressBar progressBar;
@BindView(R.id.categoryImagesList) GridView gridView;
private boolean hasMoreImages = true;
private boolean isLoading;
private String categoryName = null;
@Inject CategoryImageController controller;
@Inject @Named("category_prefs") SharedPreferences categoryPreferences;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_category_images, container, false);
ButterKnife.bind(this, v);
return v;
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
gridView.setOnItemClickListener((AdapterView.OnItemClickListener) getActivity());
initViews();
}
/**
* Initializes the UI elements for the fragment
* Setup the grid view to and scroll listener for it
*/
private void initViews() {
String categoryName = getArguments().getString("categoryName");
if (getArguments() != null && categoryName != null) {
this.categoryName = categoryName;
resetQueryContinueValues(categoryName);
initList();
setScrollListener();
}
}
/**
* Query continue values determine the last page that was loaded for the particular keyword
* This method resets those values, so that the results can be queried from the first page itself
* @param keyword
*/
private void resetQueryContinueValues(String keyword) {
SharedPreferences.Editor editor = categoryPreferences.edit();
editor.remove(keyword);
editor.apply();
}
/**
* Checks for internet connection and then initializes the grid view with first 10 images of that category
*/
@SuppressLint("CheckResult")
private void initList() {
if(!NetworkUtils.isInternetConnectionEstablished(getContext())) {
handleNoInternet();
return;
}
isLoading = true;
progressBar.setVisibility(VISIBLE);
Observable.fromCallable(() -> controller.getCategoryImages(categoryName))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.timeout(TIMEOUT_SECONDS, TimeUnit.SECONDS)
.subscribe(this::handleSuccess, this::handleError);
}
/**
* Handles the UI updates for no internet scenario
*/
private void handleNoInternet() {
progressBar.setVisibility(GONE);
if (gridAdapter == null || gridAdapter.isEmpty()) {
statusTextView.setVisibility(VISIBLE);
statusTextView.setText(getString(R.string.no_internet));
} else {
ViewUtil.showSnackbar(gridView, R.string.no_internet);
}
}
/**
* Logs and handles API error scenario
* @param throwable
*/
private void handleError(Throwable throwable) {
Timber.e(throwable, "Error occurred while loading featured images");
initErrorView();
}
/**
* Handles the UI updates for a error scenario
*/
private void initErrorView() {
ViewUtil.showSnackbar(gridView, R.string.error_loading_images);
progressBar.setVisibility(GONE);
if (gridAdapter == null || gridAdapter.isEmpty()) {
statusTextView.setVisibility(VISIBLE);
statusTextView.setText(getString(R.string.no_images_found));
} else {
statusTextView.setVisibility(GONE);
}
}
/**
* Initializes the adapter with a list of Media objects
* @param mediaList
*/
private void setAdapter(List<Media> mediaList) {
gridAdapter = new GridViewAdapter(this.getContext(), R.layout.layout_category_images, mediaList);
gridView.setAdapter(gridAdapter);
}
/**
* Sets the scroll listener for the grid view so that more images are fetched when the user scrolls down
* Checks if the category has more images before loading
* Also checks whether images are currently being fetched before triggering another request
*/
private void setScrollListener() {
gridView.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (hasMoreImages && !isLoading && (firstVisibleItem + visibleItemCount + 1 >= totalItemCount)) {
isLoading = true;
fetchMoreImages();
}
}
});
}
/**
* Fetches more images for the category and adds it to the grid view adapter
*/
@SuppressLint("CheckResult")
private void fetchMoreImages() {
if(!NetworkUtils.isInternetConnectionEstablished(getContext())) {
handleNoInternet();
return;
}
progressBar.setVisibility(VISIBLE);
Observable.fromCallable(() -> controller.getCategoryImages(categoryName))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.timeout(TIMEOUT_SECONDS, TimeUnit.SECONDS)
.subscribe(this::handleSuccess, this::handleError);
}
/**
* Handles the success scenario
* On first load, it initializes the grid view. On subsequent loads, it adds items to the adapter
* @param collection
*/
private void handleSuccess(List<Media> collection) {
if(collection == null || collection.isEmpty()) {
initErrorView();
hasMoreImages = false;
return;
}
if(gridAdapter == null) {
setAdapter(collection);
} else {
gridAdapter.addItems(collection);
}
progressBar.setVisibility(GONE);
isLoading = false;
statusTextView.setVisibility(GONE);
}
public ListAdapter getAdapter() {
return gridView.getAdapter();
}
}

View file

@ -0,0 +1,88 @@
package fr.free.nrw.commons.category;
import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
import fr.free.nrw.commons.Media;
import fr.free.nrw.commons.MediaWikiImageView;
import fr.free.nrw.commons.R;
/**
* This is created to only display UI implementation. Needs to be changed in real implementation
*/
public class GridViewAdapter extends ArrayAdapter {
private Context context;
private List<Media> data;
public GridViewAdapter(Context context, int layoutResourceId, List<Media> data) {
super(context, layoutResourceId, data);
this.context = context;
this.data = data;
}
/**
* Adds more item to the list
* Its triggered on scrolling down in the list
* @param images
*/
public void addItems(List<Media> images) {
if (data == null) {
data = new ArrayList<>();
}
data.addAll(images);
notifyDataSetChanged();
}
@Override
public boolean isEmpty() {
return data == null || data.isEmpty();
}
/**
* Sets up the UI for the category image item
* @param position
* @param convertView
* @param parent
* @return
*/
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
convertView = inflater.inflate(R.layout.layout_category_images, null);
}
Media item = data.get(position);
MediaWikiImageView imageView = convertView.findViewById(R.id.categoryImageView);
TextView fileName = convertView.findViewById(R.id.categoryImageTitle);
TextView author = convertView.findViewById(R.id.categoryImageAuthor);
fileName.setText(item.getFilename());
setAuthorView(item, author);
imageView.setMedia(item);
return convertView;
}
/**
* Shows author information if its present
* @param item
* @param author
*/
private void setAuthorView(Media item, TextView author) {
if (item.getCreator() != null && !item.getCreator().equals("")) {
String uploadedByTemplate = context.getString(R.string.image_uploaded_by);
author.setText(String.format(uploadedByTemplate, item.getCreator()));
} else {
author.setVisibility(View.GONE);
}
}
}

View file

@ -0,0 +1,24 @@
package fr.free.nrw.commons.category;
/**
* For APIs that return paginated responses, MediaWiki APIs uses the QueryContinue to facilitate fetching of subsequent pages
* https://www.mediawiki.org/wiki/API:Raw_query_continue
*/
public class QueryContinue {
private String continueParam;
private String gcmContinueParam;
public QueryContinue(String continueParam, String gcmContinueParam) {
this.continueParam = continueParam;
this.gcmContinueParam = gcmContinueParam;
}
public String getGcmContinueParam() {
return gcmContinueParam;
}
public String getContinueParam() {
return continueParam;
}
}

View file

@ -7,7 +7,7 @@ import fr.free.nrw.commons.WelcomeActivity;
import fr.free.nrw.commons.auth.LoginActivity;
import fr.free.nrw.commons.auth.SignupActivity;
import fr.free.nrw.commons.contributions.ContributionsActivity;
import fr.free.nrw.commons.featured.FeaturedImagesActivity;
import fr.free.nrw.commons.category.CategoryImagesActivity;
import fr.free.nrw.commons.nearby.NearbyActivity;
import fr.free.nrw.commons.notification.NotificationActivity;
import fr.free.nrw.commons.settings.SettingsActivity;
@ -49,5 +49,5 @@ public abstract class ActivityBuilderModule {
abstract NotificationActivity bindNotificationActivity();
@ContributesAndroidInjector
abstract FeaturedImagesActivity bindFeaturedImagesActivity();
abstract CategoryImagesActivity bindFeaturedImagesActivity();
}

View file

@ -6,6 +6,8 @@ import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.support.v4.util.LruCache;
import com.google.gson.Gson;
import javax.inject.Named;
import javax.inject.Singleton;
@ -85,6 +87,17 @@ public class CommonsApplicationModule {
return context.getSharedPreferences("prefs", MODE_PRIVATE);
}
/**
*
* @param context
* @return returns categoryPrefs
*/
@Provides
@Named("category_prefs")
public SharedPreferences providesCategorySharedPreferences(Context context) {
return context.getSharedPreferences("categoryPrefs", MODE_PRIVATE);
}
@Provides
@Named("direct_nearby_upload_prefs")
public SharedPreferences providesDirectNearbyUploadPreferences(Context context) {
@ -106,8 +119,11 @@ public class CommonsApplicationModule {
@Provides
@Singleton
public MediaWikiApi provideMediaWikiApi(Context context, @Named("default_preferences") SharedPreferences sharedPreferences) {
return new ApacheHttpClientMediaWikiApi(context, BuildConfig.WIKIMEDIA_API_HOST, sharedPreferences);
public MediaWikiApi provideMediaWikiApi(Context context,
@Named("default_preferences") SharedPreferences defaultPreferences,
@Named("category_prefs") SharedPreferences categoryPrefs,
Gson gson) {
return new ApacheHttpClientMediaWikiApi(context, BuildConfig.WIKIMEDIA_API_HOST, defaultPreferences, categoryPrefs, gson);
}
@Provides
@ -116,6 +132,16 @@ public class CommonsApplicationModule {
return new LocationServiceManager(context);
}
/**
* Gson objects are very heavy. The app should ideally be using just one instance of it instead of creating new instances everywhere.
* @return returns a singleton Gson instance
*/
@Provides
@Singleton
public Gson provideGson() {
return new Gson();
}
@Provides
@Singleton
public CacheController provideCacheController() {

View file

@ -4,7 +4,7 @@ import dagger.Module;
import dagger.android.ContributesAndroidInjector;
import fr.free.nrw.commons.category.CategorizationFragment;
import fr.free.nrw.commons.contributions.ContributionsListFragment;
import fr.free.nrw.commons.featured.FeaturedImagesListFragment;
import fr.free.nrw.commons.category.CategoryImagesListFragment;
import fr.free.nrw.commons.media.MediaDetailFragment;
import fr.free.nrw.commons.media.MediaDetailPagerFragment;
import fr.free.nrw.commons.nearby.NearbyListFragment;
@ -49,6 +49,6 @@ public abstract class FragmentBuilderModule {
abstract SingleUploadFragment bindSingleUploadFragment();
@ContributesAndroidInjector
abstract FeaturedImagesListFragment bindFeaturedImagesListFragment();
abstract CategoryImagesListFragment bindFeaturedImagesListFragment();
}

View file

@ -1,44 +0,0 @@
package fr.free.nrw.commons.featured;
import fr.free.nrw.commons.Media;
/**
* Object to hold FeaturedImage
*/
public class FeaturedImage {
private Media image;
private String author;
private String fileName;
public FeaturedImage(Media image, String author, String fileName) {
this.image = image;
this.author = author;
this.fileName = fileName;
}
public Media getImage() {
return image;
}
public void setImage(Media image) {
this.image = image;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
}

View file

@ -1,114 +0,0 @@
package fr.free.nrw.commons.featured;
import android.database.DataSetObserver;
import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.view.View;
import android.widget.AdapterView;
import butterknife.ButterKnife;
import fr.free.nrw.commons.Media;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.auth.AuthenticatedActivity;
import fr.free.nrw.commons.media.MediaDetailPagerFragment;
/**
* This activity displays pic of the days of last xx days
*/
public class FeaturedImagesActivity
extends AuthenticatedActivity
implements FragmentManager.OnBackStackChangedListener,
MediaDetailPagerFragment.MediaDetailProvider,
AdapterView.OnItemClickListener{
private FeaturedImagesListFragment featuredImagesListFragment;
private MediaDetailPagerFragment mediaDetails;
@Override
protected void onAuthCookieAcquired(String authCookie) {
}
@Override
protected void onAuthFailure() {
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_featured_images);
ButterKnife.bind(this);
// Activity can call methods in the fragment by acquiring a
// reference to the Fragment from FragmentManager, using findFragmentById()
FragmentManager supportFragmentManager = getSupportFragmentManager();
featuredImagesListFragment = (FeaturedImagesListFragment)supportFragmentManager
.findFragmentById(R.id.featuedListFragment);
supportFragmentManager.addOnBackStackChangedListener(this);
if (savedInstanceState != null) {
mediaDetails = (MediaDetailPagerFragment)supportFragmentManager
.findFragmentById(R.id.featuredFragmentContainer);
}
requestAuthToken();
initDrawer();
setTitle(getString(R.string.title_activity_featured_images));
}
@Override
public void onBackStackChanged() {
}
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
if (mediaDetails == null || !mediaDetails.isVisible()) {
// set isFeaturedImage true for featured images, to include author field on media detail
mediaDetails = new MediaDetailPagerFragment(false, true);
FragmentManager supportFragmentManager = getSupportFragmentManager();
supportFragmentManager
.beginTransaction()
.replace(R.id.featuredFragmentContainer, mediaDetails)
.addToBackStack(null)
.commit();
supportFragmentManager.executePendingTransactions();
}
mediaDetails.showImage(i);
}
@Override
public Media getMediaAtPosition(int i) {
if (featuredImagesListFragment.getAdapter() == null) {
// not yet ready to return data
return null;
} else {
return ((FeaturedImage)featuredImagesListFragment.getAdapter().getItem(i)).getImage();
}
}
@Override
public int getTotalMediaCount() {
if (featuredImagesListFragment.getAdapter() == null) {
return 0;
}
return featuredImagesListFragment.getAdapter().getCount();
}
@Override
public void notifyDatasetChanged() {
}
@Override
public void registerDataSetObserver(DataSetObserver observer) {
}
@Override
public void unregisterDataSetObserver(DataSetObserver observer) {
}
}

View file

@ -1,52 +0,0 @@
package fr.free.nrw.commons.featured;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.GridView;
import android.widget.ListAdapter;
import java.util.ArrayList;
import butterknife.ButterKnife;
import dagger.android.support.DaggerFragment;
import fr.free.nrw.commons.Media;
import fr.free.nrw.commons.R;
public class FeaturedImagesListFragment extends DaggerFragment {
private GridView gridView;
private MockGridViewAdapter gridAdapter;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_featured_images, container, false);
ButterKnife.bind(this, v);
return v;
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
gridView = getView().findViewById(R.id.featuredImagesList);
gridView.setOnItemClickListener((AdapterView.OnItemClickListener) getActivity());
gridAdapter = new MockGridViewAdapter(this.getContext(), R.layout.layout_featured_images, getMockFeaturedImages());
gridView.setAdapter(gridAdapter);
}
private ArrayList<FeaturedImage> getMockFeaturedImages(){
ArrayList<FeaturedImage> featuredImages = new ArrayList<>();
for (int i=0; i<10; i++){
featuredImages.add(new FeaturedImage(new Media("test.jpg"), "username: test", "test file name"));
}
return featuredImages;
}
public ListAdapter getAdapter() {
return gridView.getAdapter();
}
}

View file

@ -1,50 +0,0 @@
package fr.free.nrw.commons.featured;
import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import java.util.ArrayList;
import fr.free.nrw.commons.MediaWikiImageView;
import fr.free.nrw.commons.R;
/**
* This is created to only display UI implementation. Needs to be changed in real implementation
*/
public class MockGridViewAdapter extends ArrayAdapter {
private Context context;
private int layoutResourceId;
private ArrayList<FeaturedImage> data = new ArrayList();
public MockGridViewAdapter(Context context, int layoutResourceId, ArrayList<FeaturedImage> data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
convertView = inflater.inflate(R.layout.layout_featured_images, null);
}
FeaturedImage item = data.get(position);
MediaWikiImageView imageView = convertView.findViewById(R.id.featuredImageView);
TextView fileName = convertView.findViewById(R.id.featuredImageTitle);
TextView author = convertView.findViewById(R.id.featuredImageAuthor);
fileName.setText("Test file name");
author.setText("Uploaded by: Test user name");
imageView.setMedia(item.getImage());
return convertView;
}
}

View file

@ -1,6 +1,7 @@
package fr.free.nrw.commons.location;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
@ -10,9 +11,10 @@ import android.location.LocationManager;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import timber.log.Timber;
@ -29,6 +31,7 @@ public class LocationServiceManager implements LocationListener {
private Location lastLocation;
private final List<LocationUpdateListener> locationListeners = new CopyOnWriteArrayList<>();
private boolean isLocationManagerRegistered = false;
private Set<Activity> locationExplanationDisplayed = new HashSet<>();
/**
* Constructs a new instance of LocationServiceManager.
@ -51,7 +54,6 @@ public class LocationServiceManager implements LocationListener {
/**
* Returns whether the location permission is granted.
*
* @return true if the location permission is granted
*/
public boolean isLocationPermissionGranted() {
@ -73,10 +75,23 @@ public class LocationServiceManager implements LocationListener {
LOCATION_REQUEST);
}
/**
* The permission explanation dialog box is now displayed just once for a particular activity. We are subscribing
* to updates from multiple providers so its important to show the dialog just once. Otherwise it will be displayed
* once for every provider, which in our case currently is 2.
* @param activity
* @return
*/
public boolean isPermissionExplanationRequired(Activity activity) {
return !activity.isFinishing() &&
ActivityCompat.shouldShowRequestPermissionRationale(activity,
Manifest.permission.ACCESS_FINE_LOCATION);
if (activity.isFinishing()) {
return false;
}
boolean showRequestPermissionRationale = ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.ACCESS_FINE_LOCATION);
if (showRequestPermissionRationale && !locationExplanationDisplayed.contains(activity)) {
locationExplanationDisplayed.add(activity);
return true;
}
return false;
}
/**
@ -84,8 +99,9 @@ public class LocationServiceManager implements LocationListener {
* (e.g. when Location permission just granted)
* @return last known LatLng
*/
@SuppressLint("MissingPermission")
public LatLng getLKL() {
if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
if (isLocationPermissionGranted()) {
Location lastKL = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (lastKL == null) {
lastKL = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
@ -107,9 +123,10 @@ public class LocationServiceManager implements LocationListener {
* Registers a LocationManager to listen for current location.
*/
public void registerLocationManager() {
if (!isLocationManagerRegistered)
if (!isLocationManagerRegistered) {
isLocationManagerRegistered = requestLocationUpdatesFromProvider(LocationManager.NETWORK_PROVIDER)
&& requestLocationUpdatesFromProvider(LocationManager.GPS_PROVIDER);
}
}
/**
@ -142,7 +159,7 @@ public class LocationServiceManager implements LocationListener {
* @return LOCATION_SIGNIFICANTLY_CHANGED if location changed significantly
* LOCATION_SLIGHTLY_CHANGED if location changed slightly
*/
protected LocationChangeType isBetterLocation(Location location, Location currentBestLocation) {
private LocationChangeType isBetterLocation(Location location, Location currentBestLocation) {
if (currentBestLocation == null) {
// A new location is always better than no location

View file

@ -9,6 +9,7 @@ import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.TypedValue;
import android.view.LayoutInflater;
@ -22,6 +23,9 @@ import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
@ -45,6 +49,8 @@ import fr.free.nrw.commons.mwapi.MediaWikiApi;
import fr.free.nrw.commons.ui.widget.CompatTextView;
import timber.log.Timber;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
import static android.widget.Toast.LENGTH_SHORT;
public class MediaDetailFragment extends CommonsDaggerSupportFragment {
@ -74,23 +80,37 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment {
@Inject
MediaWikiApi mwApi;
private MediaWikiImageView image;
private MediaDetailSpacer spacer;
private int initialListTop = 0;
private TextView title;
private TextView desc;
private TextView author;
private TextView license;
private TextView coordinates;
private TextView uploadedDate;
private TextView seeMore;
private LinearLayout nominatedforDeletion;
private LinearLayout categoryContainer;
private LinearLayout authorLayout;
private Button delete;
private ScrollView scrollView;
@BindView(R.id.mediaDetailImage)
MediaWikiImageView image;
@BindView(R.id.mediaDetailSpacer)
MediaDetailSpacer spacer;
@BindView(R.id.mediaDetailTitle)
TextView title;
@BindView(R.id.mediaDetailDesc)
TextView desc;
@BindView(R.id.mediaDetailAuthor)
TextView author;
@BindView(R.id.mediaDetailLicense)
TextView license;
@BindView(R.id.mediaDetailCoordinates)
TextView coordinates;
@BindView(R.id.mediaDetailuploadeddate)
TextView uploadedDate;
@BindView(R.id.seeMore)
TextView seeMore;
@BindView(R.id.nominatedDeletionBanner)
LinearLayout nominatedForDeletion;
@BindView(R.id.mediaDetailCategoryContainer)
LinearLayout categoryContainer;
@BindView(R.id.authorLinearLayout)
LinearLayout authorLayout;
@BindView(R.id.nominateDeletion)
Button delete;
@BindView(R.id.mediaDetailScrollView)
ScrollView scrollView;
private ArrayList<String> categoryNames;
private boolean categoriesLoaded = false;
private boolean categoriesPresent = false;
@ -100,6 +120,9 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment {
private AsyncTask<Void, Void, Boolean> detailFetchTask;
private LicenseList licenseList;
//Had to make this class variable, to implement various onClicks, which access the media, also I fell why make separate variables when one can serve the purpose
private Media media;
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
@ -136,27 +159,12 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment {
final View view = inflater.inflate(R.layout.fragment_media_detail, container, false);
image = (MediaWikiImageView) view.findViewById(R.id.mediaDetailImage);
scrollView = (ScrollView) view.findViewById(R.id.mediaDetailScrollView);
// Detail consists of a list view with main pane in header view, plus category list.
spacer = (MediaDetailSpacer) view.findViewById(R.id.mediaDetailSpacer);
title = (TextView) view.findViewById(R.id.mediaDetailTitle);
desc = (TextView) view.findViewById(R.id.mediaDetailDesc);
author = (TextView) view.findViewById(R.id.mediaDetailAuthor);
license = (TextView) view.findViewById(R.id.mediaDetailLicense);
coordinates = (TextView) view.findViewById(R.id.mediaDetailCoordinates);
uploadedDate = (TextView) view.findViewById(R.id.mediaDetailuploadeddate);
seeMore = (TextView) view.findViewById(R.id.seeMore);
nominatedforDeletion = (LinearLayout) view.findViewById(R.id.nominatedDeletionBanner);
delete = (Button) view.findViewById(R.id.nominateDeletion);
categoryContainer = (LinearLayout) view.findViewById(R.id.mediaDetailCategoryContainer);
authorLayout = (LinearLayout) view.findViewById(R.id.authorLinearLayout);
ButterKnife.bind(this,view);
if (isFeaturedMedia){
authorLayout.setVisibility(View.VISIBLE);
authorLayout.setVisibility(VISIBLE);
} else {
authorLayout.setVisibility(View.GONE);
authorLayout.setVisibility(GONE);
}
licenseList = new LicenseList(getActivity());
@ -195,7 +203,7 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment {
@Override
public void onResume() {
super.onResume();
Media media = detailProvider.getMediaAtPosition(index);
media = detailProvider.getMediaAtPosition(index);
if (media == null) {
// Ask the detail provider to ping us when we're ready
Timber.d("MediaDetailFragment not yet ready to display details; registering observer");
@ -208,17 +216,18 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment {
Timber.d("MediaDetailFragment ready to display delayed details!");
detailProvider.unregisterDataSetObserver(dataObserver);
dataObserver = null;
displayMediaDetails(detailProvider.getMediaAtPosition(index));
media=detailProvider.getMediaAtPosition(index);
displayMediaDetails();
}
};
detailProvider.registerDataSetObserver(dataObserver);
} else {
Timber.d("MediaDetailFragment ready to display details");
displayMediaDetails(media);
displayMediaDetails();
}
}
private void displayMediaDetails(final Media media) {
private void displayMediaDetails() {
//Always load image from Internet to allow viewing the desc, license, and cats
image.setMedia(media);
@ -255,7 +264,6 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment {
if (success) {
extractor.fill(media);
setTextFields(media);
setOnClickListeners(media);
} else {
Timber.d("Failed to load photo details.");
}
@ -306,73 +314,90 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment {
}
rebuildCatList();
if(media.getCreator() == null || media.getCreator().equals("")) {
authorLayout.setVisibility(GONE);
} else {
author.setText(media.getCreator());
}
checkDeletion(media);
}
private void setOnClickListeners(final Media media) {
if (licenseLink(media) != null) {
license.setOnClickListener(v -> openWebBrowser(licenseLink(media)));
@OnClick(R.id.mediaDetailLicense)
public void onMediaDetailLicenceClicked(){
if (!TextUtils.isEmpty(licenseLink(media))) {
openWebBrowser(licenseLink(media));
} else {
Toast toast = Toast.makeText(getContext(), getString(R.string.null_url), Toast.LENGTH_SHORT);
toast.show();
if(isFeaturedMedia) {
Timber.d("Unable to fetch license URL for %s", media.getLicense());
} else {
Toast toast = Toast.makeText(getContext(), getString(R.string.null_url), Toast.LENGTH_SHORT);
toast.show();
}
}
}
@OnClick(R.id.mediaDetailCoordinates)
public void onMediaDetailCoordinatesClicked(){
if (media.getCoordinates() != null) {
coordinates.setOnClickListener(v -> openMap(media.getCoordinates()));
openMap(media.getCoordinates());
}
if (delete.getVisibility() == View.VISIBLE) {
enableDeleteButton(true);
}
delete.setOnClickListener(v -> {
@OnClick(R.id.nominateDeletion)
public void onDeleteButtonClicked(){
//Reviewer correct me if i have misunderstood something over here
//But how does this if (delete.getVisibility() == View.VISIBLE) {
// enableDeleteButton(true); makes sense ?
AlertDialog.Builder alert = new AlertDialog.Builder(getActivity());
alert.setMessage("Why should this file be deleted?");
final EditText input = new EditText(getActivity());
alert.setView(input);
input.requestFocus();
alert.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
String reason = input.getText().toString();
DeleteTask deleteTask = new DeleteTask(getActivity(), media, reason);
deleteTask.execute();
enableDeleteButton(false);
}
});
alert.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
}
});
AlertDialog d = alert.create();
input.addTextChangedListener(new TextWatcher() {
private void handleText() {
final Button okButton = d.getButton(AlertDialog.BUTTON_POSITIVE);
if (input.getText().length() == 0) {
okButton.setEnabled(false);
} else {
okButton.setEnabled(true);
}
}
AlertDialog.Builder alert = new AlertDialog.Builder(getActivity());
alert.setMessage("Why should this file be deleted?");
final EditText input = new EditText(getActivity());
alert.setView(input);
input.requestFocus();
alert.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
String reason = input.getText().toString();
DeleteTask deleteTask = new DeleteTask(getActivity(), media, reason);
deleteTask.execute();
enableDeleteButton(false);
}
});
alert.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
}
});
AlertDialog d = alert.create();
input.addTextChangedListener(new TextWatcher() {
private void handleText() {
final Button okButton = d.getButton(AlertDialog.BUTTON_POSITIVE);
if (input.getText().length() == 0) {
okButton.setEnabled(false);
} else {
okButton.setEnabled(true);
}
}
@Override
public void afterTextChanged(Editable arg0) {
handleText();
}
@Override
public void afterTextChanged(Editable arg0) {
handleText();
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
});
d.show();
d.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
});
d.show();
d.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
});
}
if (nominatedforDeletion.getVisibility() == View.VISIBLE){
seeMore.setOnClickListener(v -> {
openWebBrowser(media.getFilePageTitle().getMobileUri().toString());
});
@OnClick(R.id.seeMore)
public void onSeeMoreClicked(){
if(nominatedForDeletion.getVisibility()== VISIBLE) {
openWebBrowser(media.getFilePageTitle().getMobileUri().toString());
}
}
@ -476,12 +501,12 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment {
private void checkDeletion(Media media){
if (media.getRequestedDeletion()){
delete.setVisibility(View.GONE);
nominatedforDeletion.setVisibility(View.VISIBLE);
delete.setVisibility(GONE);
nominatedForDeletion.setVisibility(VISIBLE);
}
else{
delete.setVisibility(View.VISIBLE);
nominatedforDeletion.setVisibility(View.GONE);
delete.setVisibility(VISIBLE);
nominatedForDeletion.setVisibility(GONE);
}
}

View file

@ -26,6 +26,8 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import butterknife.BindView;
import butterknife.ButterKnife;
import javax.inject.Inject;
import javax.inject.Named;
@ -53,7 +55,8 @@ public class MediaDetailPagerFragment extends CommonsDaggerSupportFragment imple
@Named("default_preferences")
SharedPreferences prefs;
private ViewPager pager;
@BindView(R.id.mediaDetailsPager)
ViewPager pager;
private Boolean editable;
private boolean isFeaturedImage;
@ -72,7 +75,7 @@ public class MediaDetailPagerFragment extends CommonsDaggerSupportFragment imple
ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_media_detail_pager, container, false);
pager = (ViewPager) view.findViewById(R.id.mediaDetailsPager);
ButterKnife.bind(this,view);
pager.addOnPageChangeListener(this);
final MediaDetailAdapter adapter = new MediaDetailAdapter(getChildFragmentManager());

View file

@ -9,6 +9,8 @@ import android.support.annotation.VisibleForTesting;
import android.text.TextUtils;
import android.util.Log;
import com.google.gson.Gson;
import org.apache.http.HttpResponse;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.PlainSocketFactory;
@ -38,7 +40,10 @@ import java.util.Locale;
import java.util.concurrent.Callable;
import fr.free.nrw.commons.BuildConfig;
import fr.free.nrw.commons.Media;
import fr.free.nrw.commons.PageTitle;
import fr.free.nrw.commons.category.CategoryImageUtils;
import fr.free.nrw.commons.category.QueryContinue;
import fr.free.nrw.commons.notification.Notification;
import fr.free.nrw.commons.notification.NotificationUtils;
import in.yuvi.http.fluent.Http;
@ -46,6 +51,8 @@ import io.reactivex.Observable;
import io.reactivex.Single;
import timber.log.Timber;
import static fr.free.nrw.commons.utils.ContinueUtils.getQueryContinue;
/**
* @author Addshore
*/
@ -56,9 +63,15 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
private AbstractHttpClient httpClient;
private MWApi api;
private Context context;
private SharedPreferences sharedPreferences;
private SharedPreferences defaultPreferences;
private SharedPreferences categoryPreferences;
private Gson gson;
public ApacheHttpClientMediaWikiApi(Context context, String apiURL, SharedPreferences sharedPreferences) {
public ApacheHttpClientMediaWikiApi(Context context,
String apiURL,
SharedPreferences defaultPreferences,
SharedPreferences categoryPreferences,
Gson gson) {
this.context = context;
BasicHttpParams params = new BasicHttpParams();
SchemeRegistry schemeRegistry = new SchemeRegistry();
@ -69,7 +82,9 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
params.setParameter(CoreProtocolPNames.USER_AGENT, getUserAgent());
httpClient = new DefaultHttpClient(cm, params);
api = new MWApi(apiURL, httpClient);
this.sharedPreferences = sharedPreferences;
this.defaultPreferences = defaultPreferences;
this.categoryPreferences = categoryPreferences;
this.gson = gson;
}
@Override
@ -160,7 +175,7 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
}
private void setAuthCookieOnLogin(boolean isLoggedIn) {
SharedPreferences.Editor editor = sharedPreferences.edit();
SharedPreferences.Editor editor = defaultPreferences.edit();
if (isLoggedIn) {
editor.putBoolean("isUserLoggedIn", true);
editor.putString("getAuthCookie", api.getAuthCookie());
@ -448,6 +463,81 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
return NotificationUtils.getNotificationsFromList(context, childNodes);
}
/**
* The method takes categoryName as input and returns a List of Media objects
* It uses the generator query API to get the images in a category, 10 at a time.
* Uses the query continue values for fetching paginated responses
* @param categoryName Category name as defined on commons
* @return
*/
@Override
@NonNull
public List<Media> getCategoryImages(String categoryName) {
ApiResult apiResult = null;
try {
MWApi.RequestBuilder requestBuilder = api.action("query")
.param("generator", "categorymembers")
.param("format", "xml")
.param("gcmtype", "file")
.param("gcmtitle", categoryName)
.param("prop", "imageinfo")
.param("gcmlimit", "10")
.param("iiprop", "url|extmetadata");
QueryContinue queryContinueValues = getQueryContinueValues(categoryName);
if (queryContinueValues != null) {
requestBuilder.param("continue", queryContinueValues.getContinueParam());
requestBuilder.param("gcmcontinue", queryContinueValues.getGcmContinueParam());
}
apiResult = requestBuilder.get();
} catch (IOException e) {
Timber.e("Failed to obtain searchCategories", e);
}
if (apiResult == null) {
return new ArrayList<>();
}
ApiResult categoryImagesNode = apiResult.getNode("/api/query/pages");
if (categoryImagesNode == null
|| categoryImagesNode.getDocument() == null
|| categoryImagesNode.getDocument().getChildNodes() == null
|| categoryImagesNode.getDocument().getChildNodes().getLength() == 0) {
return new ArrayList<>();
}
QueryContinue queryContinue = getQueryContinue(apiResult.getNode("/api/continue").getDocument());
setQueryContinueValues(categoryName, queryContinue);
NodeList childNodes = categoryImagesNode.getDocument().getChildNodes();
return CategoryImageUtils.getMediaList(childNodes);
}
/**
* For APIs that return paginated responses, MediaWiki APIs uses the QueryContinue to facilitate fetching of subsequent pages
* https://www.mediawiki.org/wiki/API:Raw_query_continue
* After fetching images a page of image for a particular category, shared prefs are updated with the latest QueryContinue Values
* @param keyword
* @param queryContinue
*/
private void setQueryContinueValues(String keyword, QueryContinue queryContinue) {
SharedPreferences.Editor editor = categoryPreferences.edit();
editor.putString(keyword, gson.toJson(queryContinue));
editor.apply();
}
/**
* Before making a paginated API call, this method is called to get the latest query continue values to be used
* @param keyword
* @return
*/
@Nullable
private QueryContinue getQueryContinueValues(String keyword) {
String queryContinueString = categoryPreferences.getString(keyword, null);
return gson.fromJson(queryContinueString, QueryContinue.class);
}
@Override
public boolean existingFile(String fileSha1) throws IOException {
return api.action("query")

View file

@ -7,6 +7,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import fr.free.nrw.commons.Media;
import fr.free.nrw.commons.notification.Notification;
import io.reactivex.Observable;
import io.reactivex.Single;
@ -34,6 +35,8 @@ public interface MediaWikiApi {
boolean logEvents(LogBuilder[] logBuilders);
List<Media> getCategoryImages(String categoryName);
@NonNull
UploadResult uploadFile(String filename, InputStream file, long dataLength, String pageContents, String editSummary, ProgressListener progressListener) throws IOException;

View file

@ -4,14 +4,19 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.graphics.Typeface;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.design.widget.BottomSheetBehavior;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AlertDialog;
import android.text.TextUtils;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
@ -19,12 +24,18 @@ import android.view.View;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.Toast;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import io.reactivex.functions.Consumer;
import java.io.IOException;
import java.net.ConnectException;
import java.net.UnknownHostException;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Named;
import butterknife.BindView;
import butterknife.ButterKnife;
@ -41,6 +52,8 @@ import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import timber.log.Timber;
import uk.co.deanwild.materialshowcaseview.IShowcaseListener;
import uk.co.deanwild.materialshowcaseview.MaterialShowcaseView;
public class NearbyActivity extends NavigationBaseActivity implements LocationUpdateListener {
@ -56,12 +69,15 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
LinearLayout bottomSheetDetails;
@BindView(R.id.transparentView)
View transparentView;
@BindView(R.id.fab_recenter)
View fabRecenter;
@Inject
LocationServiceManager locationManager;
@Inject
NearbyController nearbyController;
@Inject
@Named("application_preferences") SharedPreferences applicationPrefs;
private LatLng curLatLng;
private Bundle bundle;
private Disposable placesDisposable;
@ -72,11 +88,18 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
private NearbyListFragment nearbyListFragment;
private static final String TAG_RETAINED_MAP_FRAGMENT = NearbyMapFragment.class.getSimpleName();
private static final String TAG_RETAINED_LIST_FRAGMENT = NearbyListFragment.class.getSimpleName();
private View listButton; // Reference to list button to use in tutorial
private final String NETWORK_INTENT_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
private BroadcastReceiver broadcastReceiver;
private boolean isListShowcaseAdded = false;
private boolean isMapShowCaseAdded = false;
private LatLng lastKnownLocation;
private MaterialShowcaseView secondSingleShowCaseView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@ -126,6 +149,39 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_nearby, menu);
new Handler().post(() -> {
listButton = findViewById(R.id.action_display_list);
secondSingleShowCaseView = new MaterialShowcaseView.Builder(this)
.setTarget(listButton)
.setDismissText(getString(R.string.showcase_view_got_it_button))
.setContentText(getString(R.string.showcase_view_list_icon))
.setDelay(500) // optional but starting animations immediately in onCreate can make them choppy
.singleUse(ViewUtil.SHOWCASE_VIEW_ID_1) // provide a unique ID used to ensure it is only shown once
.setDismissStyle(Typeface.defaultFromStyle(Typeface.BOLD))
.setListener(new IShowcaseListener() {
@Override
public void onShowcaseDisplayed(MaterialShowcaseView materialShowcaseView) {
}
// If dismissed, we can inform fragment to start showcase sequence there
@Override
public void onShowcaseDismissed(MaterialShowcaseView materialShowcaseView) {
nearbyMapFragment.onNearbyMaterialShowcaseDismissed();
}
})
.build();
isListShowcaseAdded = true;
if (isMapShowCaseAdded) { // If map showcase is also ready, start ShowcaseSequence
// Probably this case is not possible. Just added to be careful
setMapViewTutorialShowCase();
}
});
return super.onCreateOptionsMenu(menu);
}
@ -266,7 +322,7 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
protected void onStart() {
super.onStart();
locationManager.addLocationListener(this);
locationManager.registerLocationManager();
registerLocationUpdates();
}
@Override
@ -344,7 +400,7 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
return;
}
locationManager.registerLocationManager();
registerLocationUpdates();
LatLng lastLocation = locationManager.getLastLocation();
if (curLatLng != null && curLatLng.equals(lastLocation)) { //refresh view only if location has changed
@ -377,8 +433,14 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
.loadAttractionsFromLocation(curLatLng))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::populatePlaces);
} else if (locationChangeType.equals(LocationServiceManager.LocationChangeType.LOCATION_SLIGHTLY_CHANGED)) {
.subscribe(this::populatePlaces,
throwable -> {
Timber.d(throwable);
showErrorMessage(getString(R.string.error_fetching_nearby_places));
progressBar.setVisibility(View.GONE);
});
} else if (locationChangeType
.equals(LocationServiceManager.LocationChangeType.LOCATION_SLIGHTLY_CHANGED)) {
Gson gson = new GsonBuilder()
.registerTypeAdapter(Uri.class, new UriSerializer())
.create();
@ -388,6 +450,39 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
}
}
/**
* This method first checks if the location permissions has been granted and then register the location manager for updates.
*/
private void registerLocationUpdates() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (locationManager.isLocationPermissionGranted()) {
locationManager.registerLocationManager();
} else {
// Should we show an explanation?
if (locationManager.isPermissionExplanationRequired(this)) {
new AlertDialog.Builder(this)
.setMessage(getString(R.string.location_permission_rationale_nearby))
.setPositiveButton("OK", (dialog, which) -> {
requestLocationPermissions();
dialog.dismiss();
})
.setNegativeButton("Cancel", (dialog, id) -> {
showLocationPermissionDeniedErrorDialog();
dialog.cancel();
})
.create()
.show();
} else {
// No explanation needed, we can request the permission.
requestLocationPermissions();
}
}
} else {
locationManager.registerLocationManager();
}
}
private void populatePlaces(NearbyController.NearbyPlacesInfo nearbyPlacesInfo) {
List<Place> placeList = nearbyPlacesInfo.placeList;
LatLng[] boundaryCoordinates = nearbyPlacesInfo.boundaryCoordinates;
@ -401,7 +496,7 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
if (placeList.size() == 0) {
ViewUtil.showSnackbar(findViewById(R.id.container), R.string.no_nearby);
}
bundle.putString("PlaceList", gsonPlaceList);
//bundle.putString("CurLatLng", gsonCurLatLng);
bundle.putString("BoundaryCoord", gsonBoundaryCoordinates);
@ -420,6 +515,45 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
updateMapFragment(false);
updateListFragment();
}
isMapShowCaseAdded = true;
}
public void setMapViewTutorialShowCase() {
/*
*This showcase view will be the first step of our nearbyMaterialShowcaseSequence. The reason we use a
* single item instead of adding another step to nearbyMaterialShowcaseSequence is that we are not able to
* call withoutShape() method on steps. For mapView we need an showcase view without
* any circle on it, it should cover the whole page.
* */
MaterialShowcaseView firstSingleShowCaseView = new MaterialShowcaseView.Builder(this)
.setTarget(nearbyMapFragment.mapView)
.setDismissText(getString(R.string.showcase_view_got_it_button))
.setContentText(getString(R.string.showcase_view_whole_nearby_activity))
.setDelay(500) // optional but starting animations immediately in onCreate can make them choppy
.singleUse(ViewUtil.SHOWCASE_VIEW_ID_2) // provide a unique ID used to ensure it is only shown once
.withoutShape() // no shape on map view since there are no view to focus on
.setDismissStyle(Typeface.defaultFromStyle(Typeface.BOLD))
.setListener(new IShowcaseListener() {
@Override
public void onShowcaseDisplayed(MaterialShowcaseView materialShowcaseView) {
}
@Override
public void onShowcaseDismissed(MaterialShowcaseView materialShowcaseView) {
/* Add other nearbyMaterialShowcaseSequence here, it will make the user feel as they are a
* nearbyMaterialShowcaseSequence whole together.
* */
secondSingleShowCaseView.show(NearbyActivity.this);
}
})
.build();
if (applicationPrefs.getBoolean("firstRunNearby", true)) {
applicationPrefs.edit().putBoolean("firstRunNearby", false).apply();
firstSingleShowCaseView.show(this);
}
}
private void lockNearbyView(boolean lock) {
@ -429,7 +563,7 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
locationManager.removeLocationListener(this);
} else {
lockNearbyView = false;
locationManager.registerLocationManager();
registerLocationUpdates();
locationManager.addLocationListener(this);
}
}
@ -491,7 +625,12 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
.loadAttractionsFromLocation(curLatLng))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::populatePlaces);
.subscribe(this::populatePlaces,
throwable -> {
Timber.d(throwable);
showErrorMessage(getString(R.string.error_fetching_nearby_places));
progressBar.setVisibility(View.GONE);
});
nearbyMapFragment.setBundleForUpdtes(bundle);
nearbyMapFragment.updateMapSignificantly();
updateListFragment();
@ -557,4 +696,8 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
public void prepareViewsForSheetPosition(int bottomSheetState) {
// TODO
}
private void showErrorMessage(String message) {
ViewUtil.showLongToast(NearbyActivity.this, message);
}
}

View file

@ -7,6 +7,7 @@ import android.support.graphics.drawable.VectorDrawableCompat;
import com.mapbox.mapboxsdk.annotations.IconFactory;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@ -44,7 +45,7 @@ public class NearbyController {
* @return NearbyPlacesInfo a variable holds Place list without distance information
* and boundary coordinates of current Place List
*/
public NearbyPlacesInfo loadAttractionsFromLocation(LatLng curLatLng) {
public NearbyPlacesInfo loadAttractionsFromLocation(LatLng curLatLng) throws IOException {
Timber.d("Loading attractions near %s", curLatLng);
NearbyPlacesInfo nearbyPlacesInfo = new NearbyPlacesInfo();

View file

@ -7,6 +7,7 @@ import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.graphics.Typeface;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
@ -58,13 +59,14 @@ import fr.free.nrw.commons.contributions.ContributionController;
import fr.free.nrw.commons.utils.UriDeserializer;
import fr.free.nrw.commons.utils.ViewUtil;
import timber.log.Timber;
import uk.co.deanwild.materialshowcaseview.MaterialShowcaseView;
import static android.app.Activity.RESULT_OK;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
public class NearbyMapFragment extends DaggerFragment {
private MapView mapView;
public MapView mapView;
private List<NearbyBaseMarker> baseMarkerOptions;
private fr.free.nrw.commons.location.LatLng curLatLng;
public fr.free.nrw.commons.location.LatLng[] boundaryCoordinates;
@ -111,6 +113,10 @@ public class NearbyMapFragment extends DaggerFragment {
private final double CAMERA_TARGET_SHIFT_FACTOR_PORTRAIT = 0.06;
private final double CAMERA_TARGET_SHIFT_FACTOR_LANDSCAPE = 0.04;
private boolean isSecondMaterialShowcaseDismissed;
private boolean isMapReady;
private MaterialShowcaseView thirdSingleShowCaseView;
private Bundle bundleForUpdtes;// Carry information from activity about changed nearby places and current location
@Inject
@ -163,7 +169,6 @@ public class NearbyMapFragment extends DaggerFragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Timber.d("onCreateView called");
if (curLatLng != null) {
Timber.d("curLatLng found, setting up map view...");
@ -476,6 +481,7 @@ public class NearbyMapFragment extends DaggerFragment {
mapView.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(MapboxMap mapboxMap) {
((NearbyActivity)getActivity()).setMapViewTutorialShowCase();
NearbyMapFragment.this.mapboxMap = mapboxMap;
updateMapSignificantly();
}
@ -519,6 +525,7 @@ public class NearbyMapFragment extends DaggerFragment {
private void addNearbyMarkerstoMapBoxMap() {
mapboxMap.addMarkers(baseMarkerOptions);
mapboxMap.setOnInfoWindowCloseListener(marker -> {
if (marker == selected) {
bottomSheetDetailsBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
@ -534,6 +541,7 @@ public class NearbyMapFragment extends DaggerFragment {
});
mapboxMap.setOnMarkerClickListener(marker -> {
if (marker instanceof NearbyMarker) {
this.selected = marker;
NearbyMarker nearbyMarker = (NearbyMarker) marker;
@ -541,6 +549,7 @@ public class NearbyMapFragment extends DaggerFragment {
passInfoToSheet(place);
bottomSheetListBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
bottomSheetDetailsBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
}
return false;
});
@ -634,7 +643,19 @@ public class NearbyMapFragment extends DaggerFragment {
addAnchorToSmallFABs(fabGallery, getActivity().findViewById(R.id.empty_view).getId());
addAnchorToSmallFABs(fabCamera, getActivity().findViewById(R.id.empty_view1).getId());
thirdSingleShowCaseView = new MaterialShowcaseView.Builder(this.getActivity())
.setTarget(fabPlus)
.setDismissText(getString(R.string.showcase_view_got_it_button))
.setContentText(getString(R.string.showcase_view_plus_fab))
.setDelay(500) // optional but starting animations immediately in onCreate can make them choppy
.singleUse(ViewUtil.SHOWCASE_VIEW_ID_3) // provide a unique ID used to ensure it is only shown once
.setDismissStyle(Typeface.defaultFromStyle(Typeface.BOLD))
.build();
isMapReady = true;
if (isSecondMaterialShowcaseDismissed) {
thirdSingleShowCaseView.show(getActivity());
}
}
@ -791,6 +812,13 @@ public class NearbyMapFragment extends DaggerFragment {
this.bundleForUpdtes = bundleForUpdtes;
}
public void onNearbyMaterialShowcaseDismissed() {
isSecondMaterialShowcaseDismissed = true;
if (isMapReady) {
thirdSingleShowCaseView.show(getActivity());
}
}
@Override
public void onStart() {

View file

@ -0,0 +1,18 @@
package fr.free.nrw.commons.nearby;
import android.app.Activity;
import uk.co.deanwild.materialshowcaseview.MaterialShowcaseSequence;
import uk.co.deanwild.materialshowcaseview.ShowcaseConfig;
public class NearbyMaterialShowcaseSequence extends MaterialShowcaseSequence {
public NearbyMaterialShowcaseSequence(Activity activity, String sequenceID) {
super(activity, sequenceID);
ShowcaseConfig config = new ShowcaseConfig();
config.setDelay(500); // half second between each showcase view
this.setConfig(config);
this.singleUse(sequenceID); // Display tutorial only once
}
}

View file

@ -40,10 +40,9 @@ public class NearbyPlaces {
}
}
List<Place> getFromWikidataQuery(LatLng curLatLng, String lang) {
List<Place> getFromWikidataQuery(LatLng curLatLng, String lang) throws IOException {
List<Place> places = Collections.emptyList();
try {
// increase the radius gradually to find a satisfactory number of nearby places
while (radius <= MAX_RADIUS) {
places = getFromWikidataQuery(curLatLng, lang, radius);
@ -54,13 +53,6 @@ public class NearbyPlaces {
radius *= RADIUS_MULTIPLIER;
}
}
} catch (IOException e) {
Timber.d(e.toString());
// errors tend to be caused by too many results (and time out)
// try a small radius next time
Timber.d("back to initial radius: %f", radius);
radius = INITIAL_RADIUS;
}
// make sure we will be able to send at least one request next time
if (radius > MAX_RADIUS) {
radius = MAX_RADIUS;

View file

@ -23,12 +23,11 @@ import fr.free.nrw.commons.AboutActivity;
import fr.free.nrw.commons.BuildConfig;
import fr.free.nrw.commons.CommonsApplication;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.Utils;
import fr.free.nrw.commons.WelcomeActivity;
import fr.free.nrw.commons.auth.AccountUtil;
import fr.free.nrw.commons.auth.LoginActivity;
import fr.free.nrw.commons.contributions.ContributionsActivity;
import fr.free.nrw.commons.featured.FeaturedImagesActivity;
import fr.free.nrw.commons.category.CategoryImagesActivity;
import fr.free.nrw.commons.nearby.NearbyActivity;
import fr.free.nrw.commons.notification.NotificationActivity;
import fr.free.nrw.commons.settings.SettingsActivity;
@ -37,6 +36,8 @@ import timber.log.Timber;
public abstract class NavigationBaseActivity extends BaseActivity
implements NavigationView.OnNavigationItemSelectedListener {
private static final String FEATURED_IMAGES_CATEGORY = "Category:Featured_pictures_on_Wikimedia_Commons";
@BindView(R.id.toolbar)
Toolbar toolbar;
@BindView(R.id.navigation_view)
@ -157,7 +158,7 @@ public abstract class NavigationBaseActivity extends BaseActivity
return true;
case R.id.action_featured_images:
drawerLayout.closeDrawer(navigationView);
startActivityWithFlags(this, FeaturedImagesActivity.class, Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
CategoryImagesActivity.startYourself(this, getString(R.string.title_activity_featured_images), FEATURED_IMAGES_CATEGORY);
return true;
default:
Timber.e("Unknown option [%s] selected from the navigation menu", itemId);

View file

@ -33,6 +33,7 @@ import dagger.android.support.AndroidSupportInjection;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.contributions.Contribution;
import fr.free.nrw.commons.media.MediaDetailPagerFragment;
import fr.free.nrw.commons.utils.ViewUtil;
public class MultipleUploadListFragment extends Fragment {
@ -129,7 +130,7 @@ public class MultipleUploadListFragment extends Fragment {
// FIXME: Stops the keyboard from being shown 'stale' while moving out of this fragment into the next
View target = getActivity().getCurrentFocus();
hideKeyboard(target);
ViewUtil.hideKeyboard(target);
}
// FIXME: Wrong result type
@ -178,22 +179,13 @@ public class MultipleUploadListFragment extends Fragment {
baseTitle.setOnFocusChangeListener((v, hasFocus) -> {
if (!hasFocus) {
hideKeyboard(v);
ViewUtil.hideKeyboard(v);
}
});
return view;
}
public void hideKeyboard(View view) {
if (view != null) {
InputMethodManager inputMethodManager = (InputMethodManager) getActivity().getSystemService(Activity.INPUT_METHOD_SERVICE);
if (inputMethodManager != null) {
inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
}
}
@Override
public void onDestroyView() {
baseTitle.removeTextChangedListener(textWatcher);

View file

@ -78,10 +78,10 @@ import fr.free.nrw.commons.modifications.TemplateRemoveModifier;
import fr.free.nrw.commons.utils.ImageUtils;
import fr.free.nrw.commons.mwapi.MediaWikiApi;
import fr.free.nrw.commons.utils.ViewUtil;
import timber.log.Timber;
import android.support.design.widget.FloatingActionButton;
import static fr.free.nrw.commons.upload.ExistingFileAsync.Result.DUPLICATE_PROCEED;
import static fr.free.nrw.commons.upload.ExistingFileAsync.Result.NO_DUPLICATE;
import static java.lang.Long.min;
@ -121,6 +121,7 @@ public class ShareActivity
private Uri mediaUri;
private Contribution contribution;
private SimpleDraweeView backgroundImageView;
private FloatingActionButton maps_fragment;
private boolean cacheFound;
@ -144,6 +145,8 @@ public class ShareActivity
private long ShortAnimationDuration;
private FloatingActionButton zoomInButton;
private FloatingActionButton zoomOutButton;
private FloatingActionButton mainFab;
private boolean isFABOpen = false;
/**
@ -283,6 +286,24 @@ public class ShareActivity
if (mediaUri != null) {
backgroundImageView.setImageURI(mediaUri);
}
mainFab = (FloatingActionButton) findViewById(R.id.main_fab);
/*
* called when upper arrow floating button
*/
mainFab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(!isFABOpen){
showFABMenu();
}else{
closeFABMenu();
}
}
});
zoomInButton = (FloatingActionButton) findViewById(R.id.media_upload_zoom_in);
try {
zoomInButton.setOnClickListener(new View.OnClickListener() {
@ -357,7 +378,74 @@ public class ShareActivity
.commitAllowingStateLoss();
}
uploadController.prepareService();
maps_fragment = (FloatingActionButton) findViewById(R.id.media_map);
maps_fragment.setVisibility(View.VISIBLE);
if( imageObj == null || imageObj.imageCoordsExists != true){
maps_fragment.setVisibility(View.INVISIBLE);
}
maps_fragment.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if( imageObj != null && imageObj.imageCoordsExists == true) {
Uri gmmIntentUri = Uri.parse("google.streetview:cbll=" + imageObj.getDecLatitude() + "," + imageObj.getDecLongitude());
Intent mapIntent = new Intent(Intent.ACTION_VIEW, gmmIntentUri);
mapIntent.setPackage("com.google.android.apps.maps");
startActivity(mapIntent);
}
}
});
}
/*
* Function to display the zoom and map FAB
*/
private void showFABMenu(){
isFABOpen=true;
if( imageObj != null && imageObj.imageCoordsExists == true)
maps_fragment.setVisibility(View.VISIBLE);
zoomInButton.setVisibility(View.VISIBLE);
mainFab.animate().rotationBy(180);
maps_fragment.animate().translationY(-getResources().getDimension(R.dimen.second_fab));
zoomInButton.animate().translationY(-getResources().getDimension(R.dimen.first_fab));
}
/*
* function to close the zoom and map FAB
*/
private void closeFABMenu(){
isFABOpen=false;
mainFab.animate().rotationBy(-180);
maps_fragment.animate().translationY(0);
zoomInButton.animate().translationY(0).setListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {
}
@Override
public void onAnimationEnd(Animator animator) {
if(!isFABOpen){
maps_fragment.setVisibility(View.GONE);
zoomInButton.setVisibility(View.GONE);
}
}
@Override
public void onAnimationCancel(Animator animator) {
}
@Override
public void onAnimationRepeat(Animator animator) {
}
});
}
@Override
public void onRequestPermissionsResult(int requestCode,
@ -460,6 +548,9 @@ public class ShareActivity
detectUnwantedPicturesAsync.execute();
}
/*
* to display permission snackbar in share activity
*/
private Snackbar requestPermissionUsingSnackBar(String rationale,
final String[] perms,
final int code) {
@ -692,7 +783,9 @@ public class ShareActivity
return super.onOptionsItemSelected(item);
}
// Get SHA1 of file from input stream
/*
* Get SHA1 of file from input stream
*/
private String getSHA1(InputStream is) {
MessageDigest digest;
@ -729,13 +822,18 @@ public class ShareActivity
}
}
/*
* function to provide pinch zoom
*/
private void zoomImageFromThumb(final View thumbView, Uri imageuri ) {
// If there's an animation in progress, cancel it
// immediately and proceed with this one.
if (CurrentAnimator != null) {
CurrentAnimator.cancel();
}
hideKeyboard(ShareActivity.this);
ViewUtil.hideKeyboard(ShareActivity.this.findViewById(R.id.titleEdit | R.id.descEdit));
closeFABMenu();
mainFab.setVisibility(View.GONE);
InputStream input = null;
Bitmap scaled = null;
try {
@ -865,7 +963,7 @@ public class ShareActivity
CurrentAnimator.cancel();
}
zoomOutButton.setVisibility(View.GONE);
zoomInButton.setVisibility(View.VISIBLE);
mainFab.setVisibility(View.VISIBLE);
// Animate the four positioning/sizing properties in parallel,
// back to their original values.
@ -905,12 +1003,5 @@ public class ShareActivity
});
}
public static void hideKeyboard(Activity activity) {
View view = activity.findViewById(R.id.titleEdit | R.id.descEdit);
if (view != null) {
InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
}
}

View file

@ -1,8 +1,6 @@
package fr.free.nrw.commons.upload;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color;
@ -11,12 +9,10 @@ import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.v4.view.ViewCompat;
import android.support.v7.app.AlertDialog;
import android.text.Editable;
import android.text.Html;
import android.text.TextWatcher;
import android.text.method.LinkMovementMethod;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@ -24,7 +20,6 @@ import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
@ -47,9 +42,9 @@ import fr.free.nrw.commons.R;
import fr.free.nrw.commons.Utils;
import fr.free.nrw.commons.di.CommonsDaggerSupportFragment;
import fr.free.nrw.commons.settings.Prefs;
import fr.free.nrw.commons.utils.ViewUtil;
import timber.log.Timber;
import static android.view.MotionEvent.ACTION_DOWN;
import static android.view.MotionEvent.ACTION_UP;
public class SingleUploadFragment extends CommonsDaggerSupportFragment {
@ -168,13 +163,13 @@ public class SingleUploadFragment extends CommonsDaggerSupportFragment {
titleEdit.setOnFocusChangeListener((v, hasFocus) -> {
if (!hasFocus) {
hideKeyboard(v);
ViewUtil.hideKeyboard(v);
}
});
descEdit.setOnFocusChangeListener((v, hasFocus) -> {
if(!hasFocus){
hideKeyboard(v);
ViewUtil.hideKeyboard(v);
}
});
@ -183,15 +178,6 @@ public class SingleUploadFragment extends CommonsDaggerSupportFragment {
return rootView;
}
public void hideKeyboard(View view) {
if (view != null) {
InputMethodManager inputMethodManager = (InputMethodManager) getActivity().getSystemService(Activity.INPUT_METHOD_SERVICE);
if (inputMethodManager != null) {
inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
}
}
@Override
public void onDestroyView() {
titleEdit.removeTextChangedListener(textWatcher);
@ -305,7 +291,7 @@ public class SingleUploadFragment extends CommonsDaggerSupportFragment {
// FIXME: Stops the keyboard from being shown 'stale' while moving out of this fragment into the next
View target = getActivity().getCurrentFocus();
hideKeyboard(target);
ViewUtil.hideKeyboard(target);
}
@NonNull

View file

@ -0,0 +1,15 @@
package fr.free.nrw.commons.utils;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import fr.free.nrw.commons.category.QueryContinue;
public class ContinueUtils {
public static QueryContinue getQueryContinue(Node document) {
Element continueElement = (Element) document;
return new QueryContinue(continueElement.getAttribute("continue"),
continueElement.getAttribute("gcmcontinue"));
}
}

View file

@ -5,10 +5,15 @@ import android.content.Context;
import android.support.design.widget.Snackbar;
import android.view.Display;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Toast;
public class ViewUtil {
public static final String SHOWCASE_VIEW_ID_1 = "SHOWCASE_VIEW_ID_1";
public static final String SHOWCASE_VIEW_ID_2 = "SHOWCASE_VIEW_ID_2";
public static final String SHOWCASE_VIEW_ID_3 = "SHOWCASE_VIEW_ID_3";
public static void showSnackbar(View view, int messageResourceId) {
Snackbar.make(view, messageResourceId, Snackbar.LENGTH_SHORT).show();
}
@ -27,4 +32,14 @@ public class ViewUtil {
}
}
public static void hideKeyboard(View view){
if (view != null) {
InputMethodManager manager = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
view.clearFocus();
if (manager != null) {
manager.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
}
}
}

View file

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M7.41,15.41L12,10.83l4.59,4.58L18,14l-6,-6 -6,6z"/>
</vector>

View file

@ -1,5 +1,5 @@
<vector android:alpha="0.84" android:height="32dp"
<vector android:alpha="0.84" android:height="24dp"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="32dp" xmlns:android="http://schemas.android.com/apk/res/android">
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#ffffffff" android:pathData="M18,16.08c-0.76,0 -1.44,0.3 -1.96,0.77L8.91,12.7c0.05,-0.23 0.09,-0.46 0.09,-0.7s-0.04,-0.47 -0.09,-0.7l7.05,-4.11c0.54,0.5 1.25,0.81 2.04,0.81 1.66,0 3,-1.34 3,-3s-1.34,-3 -3,-3 -3,1.34 -3,3c0,0.24 0.04,0.47 0.09,0.7L8.04,9.81C7.5,9.31 6.79,9 6,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3c0.79,0 1.5,-0.31 2.04,-0.81l7.12,4.16c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.61 1.31,2.92 2.92,2.92 1.61,0 2.92,-1.31 2.92,-2.92s-1.31,-2.92 -2.92,-2.92z"/>
</vector>

View file

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
@ -16,20 +15,12 @@
android:layout_height="wrap_content" />
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/featuredFragmentContainer"
android:id="@+id/fragmentContainer"
android:orientation="horizontal"
android:layout_below="@id/toolbar">
<fragment
android:id="@+id/featuedListFragment"
android:name="fr.free.nrw.commons.featured.FeaturedImagesListFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout="@layout/fragment_contributions" />
</FrameLayout>
</RelativeLayout>

View file

@ -41,8 +41,6 @@
</FrameLayout>
<android.support.design.widget.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@ -50,8 +48,21 @@
android:layout_alignParentBottom="true"
android:layout_marginRight="@dimen/standard_gap"
android:layout_marginBottom="@dimen/standard_gap"
app:backgroundTint="@color/button_blue"
app:srcCompat="@drawable/ic_keyboard_arrow_up_black_24dp"
android:id="@+id/main_fab"/>
<android.support.design.widget.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:visibility="gone"
android:layout_marginRight="@dimen/standard_gap"
android:src="@drawable/ic_zoom_in_white_24dp"
android:layout_above="@+id/main_fab"
android:id="@+id/media_upload_zoom_in"/>
<android.support.design.widget.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@ -61,7 +72,19 @@
android:layout_marginRight="@dimen/standard_gap"
android:layout_marginBottom="@dimen/standard_gap"
android:src="@drawable/ic_zoom_out_white_24dp"
android:layout_above="@+id/main_fab"
android:id="@+id/media_upload_zoom_out"/>
<android.support.design.widget.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_above="@+id/media_upload_zoom_in"
android:visibility="gone"
android:layout_marginRight="@dimen/standard_gap"
app:srcCompat="@drawable/ic_map_white_24dp"
android:id="@+id/media_map"/>
</RelativeLayout>
<android.support.design.widget.NavigationView

View file

@ -1,20 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/mainBackground"
>
android:background="?attr/mainBackground">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/waiting_first_sync"
android:id="@+id/waitingMessage"
android:id="@+id/statusMessage"
android:layout_gravity="center"
android:visibility="gone"
tools:visibility="visible"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
/>
<ProgressBar
@ -22,11 +23,11 @@
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:visibility="gone"
android:id="@+id/loadingFeaturedImagesProgressBar"
android:id="@+id/loadingImagesProgressBar"
/>
<GridView
android:id="@+id/featuredImagesList"
android:id="@+id/categoryImagesList"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:stretchMode="columnWidth"

View file

@ -9,7 +9,7 @@
>
<TextView
android:id="@+id/featuredImagesSequenceNumber"
android:id="@+id/categoryImagesSequenceNumber"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="98sp"
@ -19,7 +19,7 @@
/>
<fr.free.nrw.commons.MediaWikiImageView
android:id="@+id/featuredImageView"
android:id="@+id/categoryImageView"
android:layout_width="match_parent"
android:layout_height="240dp"
/>
@ -33,7 +33,7 @@
android:padding="@dimen/small_gap"
>
<ProgressBar
android:id="@+id/featuredProgress"
android:id="@+id/categoryProgress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/ProgressBar"
@ -43,7 +43,7 @@
/>
<TextView
android:id="@+id/featuredImageTitle"
android:id="@+id/categoryImageTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FFFFFFFF"
@ -53,7 +53,7 @@
/>
<TextView
android:id="@+id/featuredImageAuthor"
android:id="@+id/categoryImageAuthor"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FFFFFFFF"

View file

@ -7,7 +7,7 @@
<item
android:id="@+id/share_app_icon"
android:title="@string/refresh_button"
android:title="@string/share_app_title"
android:icon="@drawable/ic_share_black_24dp"
android:orderInCategory="1"
app:showAsAction="ifRoom"

View file

@ -145,4 +145,5 @@
<string name="notifications_welcome">مرحبا بكم في ويكيمديا كومنز، %1$s! نحن سعداء لأنك هنا.</string>
<string name="notifications_talk_page_message">%1$s رسالة على صفحة الحديث</string>
<string name="notifications_mention">%1$s ذكر لك على %2$s.</string>
<string name="share_app_title">شارك التطبيق</string>
</resources>

View file

@ -259,4 +259,8 @@
<string name="internet_established">ইন্টারনেট উপলব্ধ</string>
<string name="no_notifications">কোন বিজ্ঞপ্তি পাওয়া যায়নি</string>
<string name="retry">পুনঃচেষ্টা করুন</string>
<string name="showcase_view_got_it_button">বুঝেছি!</string>
<string name="no_images_found">কোন চিত্র পাওয়া যায়নি!</string>
<string name="image_uploaded_by">আপলোড করেছেন: %1$s</string>
<string name="error_fetching_nearby_places">কাছাকাছি স্থানগুলি আনতে ত্রুটি।</string>
</resources>

View file

@ -154,6 +154,7 @@
<string name="welcome_copyright_subtext">Vermeide urheberrechtlich geschütztes Material, das du im Internet gefunden hast wie Bilder von Postern, Buchcovern etc.</string>
<string name="welcome_final_text">Verstanden?</string>
<string name="welcome_final_button_text">Ja!</string>
<string name="welcome_help_button_text"/>
<string name="detail_panel_cats_label">Kategorien</string>
<string name="detail_panel_cats_loading">Lade …</string>
<string name="detail_panel_cats_none">Keine ausgewählt</string>
@ -268,4 +269,14 @@
<string name="about_translate_proceed">Fortfahren</string>
<string name="about_translate_cancel">Abbrechen</string>
<string name="retry">Erneut versuchen</string>
<string name="showcase_view_got_it_button">Verstanden!</string>
<string name="showcase_view_whole_nearby_activity">Dies sind die Orte in deiner Nähe, die Bilder zur Illustration ihrer Wikipedia-Artikel benötigen.</string>
<string name="showcase_view_list_icon">Das Antippen dieser Schaltfläche zeigt eine Liste mit diesen Orten</string>
<string name="showcase_view_plus_fab">Du kannst ein Bild für einen beliebigen Ort von deiner Galerie oder Kamera hochladen</string>
<string name="no_images_found">Keine Bilder gefunden!</string>
<string name="error_loading_images">Beim Laden der Bilder ist ein Fehler aufgetreten.</string>
<string name="image_uploaded_by">Hochgeladen von: %1$s</string>
<string name="share_app_title">App teilen</string>
<string name="share_coordinates_not_present">Während der Bildauswahl wurden keine Koordinaten angegeben</string>
<string name="error_fetching_nearby_places">Fehler beim Abrufen der Orte in der Nähe.</string>
</resources>

View file

@ -9,11 +9,15 @@
* Mirzali
-->
<resources>
<string name="preference_category_appearance">Asayış</string>
<string name="preference_category_general">Bıngeh</string>
<string name="preference_category_location">Lokasyon</string>
<string name="app_name">Commons</string>
<string name="menu_settings">Eyari</string>
<string name="username">Namey karberi</string>
<string name="password">Parola</string>
<string name="login">Cı kewe</string>
<string name="forgot_password">Parola, xo vira kerde?</string>
<string name="signup">Qeyd be</string>
<string name="logging_in_title">Cıkewtış</string>
<string name="logging_in_message">Kerem kerên, bıpawên...</string>
@ -58,6 +62,8 @@
<string name="menu_upload_single">Bar ke</string>
<string name="categories_search_text_hint">Kategoriyan dı cı geyr</string>
<string name="menu_save_categories">Star ke</string>
<string name="refresh_button">Newe ke</string>
<string name="display_list_button">Liste</string>
<plurals name="contributions_subtitle">
<item quantity="zero">\@string/contributions_subtitle_zero</item>
<item quantity="one">Yew barbiyayış</item>
@ -83,7 +89,7 @@
<string name="menu_feedback">Peyd rışten bırış (E-posta ra)</string>
<string name="no_email_client">E-posta eyar nêbi</string>
<string name="provider_categories">Karıyaye Kategoriyê peyêni</string>
<string name="menu_retry_upload">Fına</string>
<string name="menu_retry_upload">Anciya bıcerrebne</string>
<string name="menu_cancel_upload">Bıtexelne</string>
<string name="menu_download">Ron</string>
<string name="preference_license" fuzzy="true">Lisans</string>
@ -129,4 +135,7 @@
<string name="navigation_item_home">Keye</string>
<string name="navigation_item_upload">Bar ke</string>
<string name="navigation_item_logout">Veciyayış</string>
<string name="about_translate_cancel">Bıtexelne</string>
<string name="retry">Anciya bıcerrebne</string>
<string name="showcase_view_got_it_button">Mı fehm kerd!</string>
</resources>

View file

@ -158,6 +158,7 @@
<string name="welcome_copyright_subtext">Αποφύγετε προστατευμένο υλικό που βρήκατε από το Internet, καθώς και εικόνες, αφίσες, εξώφυλλα βιβλίων, κλπ.</string>
<string name="welcome_final_text">Τι λες, μπορείς;</string>
<string name="welcome_final_button_text">Ναι!</string>
<string name="welcome_help_button_text"/>
<string name="detail_panel_cats_label">Κατηγορίες</string>
<string name="detail_panel_cats_loading">Φόρτωση…</string>
<string name="detail_panel_cats_none">Καμία επιλεγμένη</string>
@ -272,4 +273,14 @@
<string name="about_translate_proceed">Συνέχεια</string>
<string name="about_translate_cancel">Ακύρωση</string>
<string name="retry">Ξαναπροσπαθήστε</string>
<string name="showcase_view_got_it_button">Κατάλαβα!</string>
<string name="showcase_view_whole_nearby_activity">Αυτά είναι τα μέρη κοντά σας που χρειάζονται φωτογραφίες για να εικονογραφηθούν τα λήμματά τους στη Βικιπαίδεια</string>
<string name="showcase_view_list_icon">Πατώντας αυτό το κουμπί φέρνει μια λίστα αυτών των μερών</string>
<string name="showcase_view_plus_fab">Μπορείτε να ανεβάσετε μια εικόνα για οποιοδήποτε μέρος από την γκαλερί ή την κάμερά σας</string>
<string name="no_images_found">Δεν βρέθηκαν εικόνες!</string>
<string name="error_loading_images">Συνέβη σφάλμα κατά το ανέβασμα των εικόνων.</string>
<string name="image_uploaded_by">Ανέβηκε από: %1$s</string>
<string name="share_app_title">Κοινοποίηση εφαρμογής</string>
<string name="share_coordinates_not_present">Οι συντεταγμένες δεν ορίστηκαν κατά την διάρκεια της επιλογής εικόνας</string>
<string name="error_fetching_nearby_places">Σφάλμα κατά την εύρεση κοντινών μερών.</string>
</resources>

View file

@ -267,4 +267,13 @@
<string name="about_translate_message">Selecciona el idioma en que quieres enviar traducciones</string>
<string name="about_translate_cancel">Cancelar</string>
<string name="retry">Reintentar</string>
<string name="showcase_view_got_it_button">Entendido</string>
<string name="showcase_view_whole_nearby_activity">Estos sitios cercanos a ti necesitan imágenes para ilustrar sus artículos de Wikipedia</string>
<string name="showcase_view_plus_fab">Puedes cargar una imagen para cualquier sitio desde la galería o la cámara</string>
<string name="no_images_found">No se encontró ninguna imagen.</string>
<string name="error_loading_images">Se produjo un error al cargar las imágenes.</string>
<string name="image_uploaded_by">Cargada por: %1$s</string>
<string name="share_app_title">Compartir aplicación</string>
<string name="share_coordinates_not_present">No se especificaron las coordenadas al seleccionar la imagen</string>
<string name="error_fetching_nearby_places">Error al recuperar los lugares cercanos.</string>
</resources>

View file

@ -8,11 +8,17 @@
* Theklan
-->
<resources>
<string name="preference_category_appearance">Itxura</string>
<string name="preference_category_general">Orokorra</string>
<string name="preference_category_feedback">Feedback</string>
<string name="preference_category_location">Kokapena</string>
<string name="app_name">Commons</string>
<string name="bullet"></string>
<string name="menu_settings">Hobespenak</string>
<string name="username">Erabiltzaile izena</string>
<string name="password">Pasahitza</string>
<string name="login">Saioa hasi</string>
<string name="forgot_password">Pasahitza ahaztu duzu?</string>
<string name="signup">Eman izena</string>
<string name="logging_in_title">Saioa hasten</string>
<string name="logging_in_message">Mesedez itxaron…</string>
@ -54,22 +60,23 @@
<string name="categories_search_text_hint">Kategoriak bilatu</string>
<string name="menu_save_categories">Gorde</string>
<string name="refresh_button">Eguneratu</string>
<string name="display_list_button">Zerrenda</string>
<string name="enable_gps">GPSa gaitu</string>
<string name="contributions_subtitle_zero">Oraindik ez da ezer igo</string>
<plurals name="contributions_subtitle" fuzzy="true">
<item quantity="zero">Oraindik igoerarik ez</item>
<plurals name="contributions_subtitle">
<item quantity="zero">\@string/contributions_subtitle_zero</item>
<item quantity="one">igoera 1</item>
<item quantity="other">%1$d igoera</item>
</plurals>
<string name="categories_not_found">Ez da kategoriak aukritu %1$s izenarekin</string>
<string name="categories_skip_explanation" fuzzy="true">Gehitu kategoriak zure argazkiak Wikimedia Commonsen aurkitzen errazagoak izan daitezen.</string>
<string name="categories_skip_explanation">Gehitu kategoriak zure argazkiak Wikimedia Commonsen aurkitzen errazagoak izan daitezen.\nHasi idazten kategoriak gehitzeko.</string>
<string name="categories_activity_title">Kategoriak</string>
<string name="title_activity_settings">Hobespenak</string>
<string name="title_activity_signup">Eman izena</string>
<string name="menu_about">Honi buruz</string>
<string name="about_license" fuzzy="true">Open Source softwarea &lt;a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\"&gt;Apache v2 Lizentziaren&lt;/a&gt; pean egina. Wikimedia Commons eta bere logoa Wikimedia Fundazioaren marka erregistratuak dira eta Wikimedia Fundazioaren baimenarekin erabiltzen dira. Ez gaude Wikimedia Fundaziora afiliatuta.</string>
<string name="about_improve" fuzzy="true">GitHub-eko &lt;a href=\"https://github.com/commons-app/apps-android-commons\"&gt;Iturria&lt;/a&gt; eta &lt;a href=\"https://commons-app.github.io/\"&gt;webgunea&lt;/a&gt;. &lt;a href=\"https://github.com/commons-app/apps-android-commons/issues\"&gt;GitHub-eko gai&lt;/a&gt; berria sortu erroreen berri emateko.</string>
<string name="about_privacy_policy" fuzzy="true">&lt;a href=\"https://wikimediafoundation.org/wiki/Privacy_policy\"&gt;Pribatutasun politika&lt;/a&gt;</string>
<string name="about_privacy_policy">&lt;u&gt;Pribatutasun politika&lt;/u&gt;</string>
<string name="title_activity_about">Honi buruz</string>
<string name="menu_feedback">Bidali zure iritzia (e-posta bidez)</string>
<string name="no_email_client">Posta bezerorik ez da instalatu</string>
@ -81,7 +88,7 @@
<string name="share_license_summary">Irudi hau %1$s lizentziapean egongo da</string>
<string name="media_upload_policy">Irudi hau bidaltzen, nire lan propioa dela aitortzen dut, copyrighta duten materiala edo selfiak ez duela, eta beste motatakoak &lt;a href=\"https://commons.wikimedia.org/wiki/Commons:Policies_and_guidelines\"&gt;Wikimedia Ohikoaren arauak&lt;/a&gt;</string>
<string name="menu_download">Jaitsi</string>
<string name="preference_license" fuzzy="true">Lizentzia</string>
<string name="preference_license">Berezko lizentzia</string>
<string name="use_previous">Aurreko izenburu/deskribapena erabili</string>
<string name="allow_gps">Oraingo kokapena automatikoki lortu</string>
<string name="preference_theme">Gau modua</string>

View file

@ -5,6 +5,7 @@
* Happy13241
* Jean-Frédéric
* KATRINE1992
* Melissadeba95
* Metroitendo
* Nicolas Raoul
* Orikrin1998
@ -279,4 +280,14 @@
<string name="about_translate_proceed">Continuer</string>
<string name="about_translate_cancel">Annuler</string>
<string name="retry">Réessayer</string>
<string name="showcase_view_got_it_button">Cest bon!</string>
<string name="showcase_view_whole_nearby_activity">Il y a des lieux autour de vous qui demandent des images pour illustrer leurs articles Wikipédia</string>
<string name="showcase_view_list_icon">En cliquant sur ce bouton vous afficherez une liste de ces endroits</string>
<string name="showcase_view_plus_fab">Vous pouvez téléverser une photo de n\'importe quel endroit de votre gallerie ou de votre appareil photo</string>
<string name="no_images_found">Aucune images trouvée.</string>
<string name="error_loading_images">Une erreur s\'est produite pendant le chargement des images.</string>
<string name="image_uploaded_by">Importé par:%1$s</string>
<string name="share_app_title">Partager les applications</string>
<string name="share_coordinates_not_present">Les coordonnées n\'ont pas été spécifiées pendant la sélection de l\'image</string>
<string name="error_fetching_nearby_places">Erreur durant l\'exploration du voisinage.</string>
</resources>

View file

@ -90,6 +90,7 @@
<string name="categories_activity_title">Categorías</string>
<string name="title_activity_settings">Configuracións</string>
<string name="title_activity_signup">Rexistrarse</string>
<string name="title_activity_featured_images">Imaxes destacadas</string>
<string name="menu_about">Acerca de</string>
<string name="about_license">A aplicación Wikimedia Commons é unha aplicación de código aberto creada e mantida polos cesionarios e voluntarios da comunidade de Wikimedia. A Fundación Wikimedia non está involucrada na creación, desenvolvemento ou mantemento da aplicación.</string>
<string name="about_improve">Crear unha nova &lt;a href=\"https://github.com/commons-app/apps-android-commons/issues\"&gt;incidencia&lt;/a&gt; para informar de problemas e suxestións.</string>
@ -175,6 +176,8 @@
<string name="media_detail_media_title">Título do ficheiro multimedia</string>
<string name="media_detail_description">Descrición</string>
<string name="media_detail_description_explanation">Aquí vai a descrición do ficheiro multimedia. Potencialmente, pode ser bastante longo, e necesitará agruparse en múltiples liñas. De tódolos xeitos esperamos que se vexa ben.</string>
<string name="media_detail_author">Autor</string>
<string name="media_detail_author_explanation">O nome de usuario do autor da imaxe destacada vai aquí.</string>
<string name="media_detail_uploaded_date">Data de suba</string>
<string name="media_detail_license">Licenza</string>
<string name="media_detail_coordinates">Coordenadas</string>
@ -217,6 +220,7 @@
<string name="navigation_item_logout">Saír</string>
<string name="navigation_item_info">Titorial</string>
<string name="navigation_item_notification">Notificacións</string>
<string name="navigation_item_featured_images">Destacados</string>
<string name="nearby_needs_permissions">Os sitios situados preto non poden visualizarse sen permisos de localización</string>
<string name="no_description_found">non se atopou descrición</string>
<string name="nearby_info_menu_commons_article">Páxina do ficheiro en Commons</string>

View file

@ -13,6 +13,7 @@
* ViDam
-->
<resources>
<string name="preference_category_appearance">Megjelenés</string>
<string name="preference_category_general">Általános</string>
<string name="preference_category_feedback">Visszajelzés</string>
<string name="preference_category_location">Helyszín</string>
@ -145,6 +146,7 @@
<string name="tutorial_2_subtext_3">Híres emberek (a polgármestered, olimpikonok, akikkel találkoztál)</string>
<string name="tutorial_3_text">Kérjük, NE tölts fel:</string>
<string name="tutorial_3_subtext">- Szelfiket vagy képeket a barátaidról\n- Internetröl letöltött képeket\n- Kereskedelmi alkalmazások képernyőképeit</string>
<string name="tutorial_3_subtext_2">Az Internetről letöltött képek</string>
<string name="tutorial_4_text">Példa feltöltés:</string>
<string name="tutorial_4_subtext">- Cím: Sydney-i Operaház\n- Leírás: A Sydney-i Operaház az öböl túlpartjáról\n- Kategóriák: Sydney Opera House from the west, Sydney Opera House remote views</string>
<string name="tutorial_4_subtext_1">Cím: Sydney-i Operaház</string>
@ -191,6 +193,7 @@
<string name="commons_logo">Commons Logo</string>
<string name="commons_website">Commons weboldal</string>
<string name="commons_facebook">Commons Facebook-oldal</string>
<string name="commons_github">Commons Github forráskód</string>
<string name="background_image">Háttérkép</string>
<string name="no_image_found">Nem található kép</string>
<string name="upload_image">Kép feltöltése</string>
@ -223,6 +226,8 @@
<string name="error_while_cache">Hiba a képek gyorsítótárazásakor</string>
<string name="title_info">Egy egyedi, leíró cím a fájlnak, ami fájlnévként fog szolgálni. Egyszerű nyelvezetet használhatsz szóközökkel. Ne tedd bele a kiterjesztést.</string>
<string name="description_info">Kérlek a lehető legteljesebb módon írd le a fájlt: hol készült, mit ábrázol, mi a kontextus? Kérlek add meg az objektumokat vagy személyeket a képen, valamint a nehezen kitalálható információkat (például a kép készítésének dátumát, ha az egy tájkép). Amennyiben a média valami szokatlant ábrázol, kérlek fejtsd ki, hogy mi teszi szokatlanná.</string>
<string name="upload_image_too_dark">Ez a fénykép túl sötét, biztos fel akarod tölteni? A Wikimédia Commons csak enciklopédikus értékkel bíró képeket tart meg.</string>
<string name="upload_image_blurry">Ez a fénykép homályos, biztos fel akarod tölteni? A Wikimédia Commons csak enciklopédikus értékkel bíró képeket tart meg.</string>
<string name="give_permission">Engedély adása</string>
<string name="use_external_storage">Külső tárhely használata</string>
<string name="use_external_storage_summary">Az alkalmazáson belüli kamerával készült képek mentése az eszközre</string>
@ -238,6 +243,7 @@
<string name="nearby_location_not_available">A hely nem érhető el.</string>
<string name="location_permission_rationale_nearby">Közeli helyek listájának megtekintéséhez engedély szükséges</string>
<string name="notifications_welcome">Üdvözlünk a Wikimedia Commonson, %1$s! Örülünk, hogy itt vagy.</string>
<string name="notifications_talk_page_message">%1$s üzenetet hagyott a vitalapodon</string>
<string name="notifications_thank_you_edit">Köszönjük a szerkesztésedet!</string>
<string name="nearby_wikidata">WIKIDATA</string>
<string name="nearby_wikipedia">WIKIPÉDIA</string>
@ -249,6 +255,8 @@
<string name="internet_established">Internet elérhető</string>
<string name="no_notifications">Nincs értesítés</string>
<string name="about_translate_title">Nyelvek</string>
<string name="about_translate_proceed">Folytatás</string>
<string name="about_translate_cancel">Mégse</string>
<string name="retry">Újra</string>
<string name="share_app_title">Alkalmazás megosztása</string>
</resources>

View file

@ -223,4 +223,11 @@
<string name="about_translate_title">Lingue</string>
<string name="about_translate_cancel">Annulla</string>
<string name="retry">Riprova</string>
<string name="showcase_view_got_it_button">Capito!</string>
<string name="showcase_view_whole_nearby_activity">Questi sono i luoghi vicino a te che necessitano di immagini per illustrare le loro voci di Wikipedia</string>
<string name="showcase_view_plus_fab">Puoi caricare un\'immagine per ogni luogo dalla tua galleria o fotocamera</string>
<string name="no_images_found">Nessuna immagine trovata!</string>
<string name="error_loading_images">Si è verificato un errore durante il caricamento delle immagini.</string>
<string name="image_uploaded_by">Caricato da: %1$s</string>
<string name="share_app_title">Condividi applicazione</string>
</resources>

View file

@ -273,4 +273,14 @@
<string name="about_translate_proceed">המשך</string>
<string name="about_translate_cancel">ביטול</string>
<string name="retry">לנסות שוב</string>
<string name="showcase_view_got_it_button">הבנתי!</string>
<string name="showcase_view_whole_nearby_activity">אלה המקומות בסביבתך שזקוקים לתמונות כדי להמחיש את הערכים שלהם בוויקיפדיה</string>
<string name="showcase_view_list_icon">ניתן ללחוץ על כפתור זה כדי להציג רשימה של המקומות האלה</string>
<string name="showcase_view_plus_fab">באפשרותך להעלות תמונה של כל מקום מהגלריה או מהמצלמה שלך</string>
<string name="no_images_found">לא נמצאו תמונות!</string>
<string name="error_loading_images">אירעה שגיאה בטעינת התמונות.</string>
<string name="image_uploaded_by">הועלתה על־ידי: %1$s</string>
<string name="share_app_title">שיתוף היישום</string>
<string name="share_coordinates_not_present">לא צוינו קואורדינטות בעת בחירת התמונה</string>
<string name="error_fetching_nearby_places">שגיאה באחזור המקומות בסביבתך.</string>
</resources>

View file

@ -12,13 +12,18 @@
* Yusuke1109
-->
<resources>
<string name="preference_category_appearance">表示</string>
<string name="preference_category_general">全般</string>
<string name="preference_category_feedback">フィードバック</string>
<string name="preference_category_location">場所</string>
<string name="app_name">コモンズ</string>
<string name="bullet"></string>
<string name="menu_settings">設定</string>
<string name="username">利用者名</string>
<string name="password">パスワード</string>
<string name="login_credential">コモンズのベータ版アカウントにログイン</string>
<string name="login">ログイン</string>
<string name="forgot_password">パスワードを忘れた場合</string>
<string name="signup">利用者登録</string>
<string name="logging_in_title">ログイン中</string>
<string name="logging_in_message">お待ちください…</string>
@ -49,6 +54,7 @@
<string name="menu_share">共有</string>
<string name="menu_open_in_browser">ブラウザーで表示</string>
<string name="share_title_hint">タイトル</string>
<string name="add_title_toast">ファイル名をつけてください</string>
<string name="share_description_hint">説明</string>
<string name="login_failed_network">ログインできません - ネットワークのエラーです</string>
<string name="login_failed_username">ログインできません - 利用者名を確認してください</string>
@ -64,6 +70,7 @@
<string name="categories_search_text_hint">カテゴリを検索</string>
<string name="menu_save_categories">保存</string>
<string name="refresh_button">更新</string>
<string name="display_list_button">一覧</string>
<string name="gps_disabled">お使いのデバイスではGPSが無効になっています。有効にしますか?</string>
<string name="enable_gps">GPSを有効にする</string>
<string name="contributions_subtitle_zero">まだ何もアップロードされていません。</string>
@ -82,6 +89,7 @@
<string name="categories_activity_title">カテゴリ</string>
<string name="title_activity_settings">設定</string>
<string name="title_activity_signup">利用者登録</string>
<string name="title_activity_featured_images">秀逸な画像</string>
<string name="menu_about">このアプリについて</string>
<string name="about_license">ウィキメディア・コモンズ・アプリはウィキメディア・コミュニティの助成金受給者とボランティアによって製作・メンテナンスされているオープンソースソフトウェアです。ウィキメディア財団はこのアプリの製作・開発・メンテナンスに関与していません。</string>
<string name="about_improve">バグとアイディアは &lt;a href=\"https://github.com/commons-app/apps-android-commons/issues\"&gt;Github&lt;/a&gt; へ。</string>
@ -96,6 +104,7 @@
<string name="menu_retry_upload">再試行</string>
<string name="menu_cancel_upload">キャンセル</string>
<string name="share_license_summary">この画像が %1$s ライセンスでアップロードされます。</string>
<string name="media_upload_policy">この画像の投稿に当たり、私はこれが自分自身の作品であり、著作権のあるコンテンツや自撮りは含まれていないと宣言します。</string>
<string name="menu_download">ダウンロード</string>
<string name="preference_license">既定のライセンス</string>
<string name="use_previous">前回のタイトルと記述を使用</string>
@ -126,11 +135,19 @@
<string name="tutorial_1_text">ウィキメディア・コモンズにはウィキペディアで使用する画像のほぼすべてが保管されています。</string>
<string name="tutorial_1_subtext">あなたの画像は世界中の人々が学習する助けになります!</string>
<string name="tutorial_2_text">アップロードする画像はあなたご本人が撮影したものかあなたが単独で制作したものに限定します。</string>
<string name="tutorial_2_subtext" fuzzy="true">- 自然物 (動植物、山)\n- 道具 (自転車、駅)\n- 著名人 (市区村長・都道府県知事、自分が会ったオリンピック選手)</string>
<string name="tutorial_2_subtext">自然物 (動植物、山)\n• 道具 (自転車、駅)\n• 著名人 (市区村長・都道府県知事、自分が会ったオリンピック選手)</string>
<string name="tutorial_2_subtext_1">自然物 (動植物、山)</string>
<string name="tutorial_2_subtext_2">道具 (自転車、駅)</string>
<string name="tutorial_2_subtext_3">著名人 (市区村長・都道府県知事、自分が会ったオリンピック選手)</string>
<string name="tutorial_3_text">アップロードが《禁止》のもの:</string>
<string name="tutorial_3_subtext">- あなたの友人の自撮り写真や画像\n- インターネットからダウンロードした画像\n- 著作権のあるアプリのスクリーンショット</string>
<string name="tutorial_3_subtext_1">自撮りもしくは友達を撮影した写真</string>
<string name="tutorial_3_subtext_2">ウェブからダウンロードした画像</string>
<string name="tutorial_3_subtext_3">独自のアプリケーションのスクリーンショット</string>
<string name="tutorial_4_text">アップロードの例:</string>
<string name="tutorial_4_subtext">- 題名: シドニー・オペラハウス\n- 説明: 湾の向こうから見たシドニー・オペラハウス\n- カテゴリ: 西側から見たシドニー・オペラハウス、遠くから見たシドニー・オペラハウス</string>
<string name="tutorial_4_subtext_1">題名: シドニーのオペラハウス</string>
<string name="tutorial_4_subtext_2">説明: シドニーのオペラハウス。湾を挟んで撮影。</string>
<string name="welcome_wikipedia_text">画像を投稿してください。ウィキペディアの記事に彩りを!</string>
<string name="welcome_wikipedia_subtext">ウィキペディアの画像はウィキメディア・コモンズに保管されています。</string>
<string name="welcome_copyright_text">あなたの画像は世界中の人々が学習する助けになります</string>
@ -143,11 +160,11 @@
<string name="detail_description_empty">説明はありません。</string>
<string name="detail_license_empty">不明なライセンス</string>
<string name="menu_refresh">更新</string>
<string name="read_storage_permission_rationale" fuzzy="true">必要な権限:外部ストレージを読み込みます。これがなければアプリは機能しません。</string>
<string name="write_storage_permission_rationale" fuzzy="true">必要な権限:外部ストレージを作成します。これがなければアプリは機能しません。</string>
<string name="location_permission_rationale">オプションの権限:カテゴリ候補の現在の位置を取得する</string>
<string name="read_storage_permission_rationale">必要な権限:外部ストレージを読み込みます。これがなければアプリはギャラリーを開けません。</string>
<string name="write_storage_permission_rationale">必要な権限:外部ストレージに入力します。これがないとアプリはカメラにアクセスできません。</string>
<string name="location_permission_rationale">オプションの権限:カテゴリ候補のため現在の位置を取得する</string>
<string name="ok">承認</string>
<string name="title_activity_nearby">周りの場所</string>
<string name="title_activity_nearby">近くの場所</string>
<string name="no_nearby">付近の場所が見つかりません</string>
<string name="warning">警告</string>
<string name="file_exists">このファイルが既にコモンズにあります。本当にアップロードしますか?</string>
@ -158,6 +175,7 @@
<string name="media_detail_description">記述</string>
<string name="media_detail_description_explanation">ここにメディアの説明が入ります。かなり長文になる場合には数行にわたることがあります。それでも見栄えがよいと願っています。</string>
<string name="media_detail_author">作者</string>
<string name="media_detail_author_explanation">秀逸な画像の作者名を記入します。</string>
<string name="media_detail_uploaded_date">アップロード日時</string>
<string name="media_detail_license">ライセンス</string>
<string name="media_detail_coordinates">緯度経度</string>
@ -174,14 +192,19 @@
<string name="commons_logo">コモンズの商標</string>
<string name="commons_website">コモンズのウェブサイト</string>
<string name="commons_facebook">コモンズのフェイスブックページ</string>
<string name="commons_github">コモンズのGithubソースコード</string>
<string name="background_image">背景画像</string>
<string name="mediaimage_failed">メディアイメージが失敗しました</string>
<string name="no_image_found">画像がありません</string>
<string name="upload_image">画像をアップロード</string>
<string name="welcome_image_mount_zao">蔵王連峰</string>
<string name="welcome_image_llamas">リャマ</string>
<string name="welcome_image_rainbow_bridge">レインボーブリッジ</string>
<string name="welcome_image_tulip">チューリップ</string>
<string name="welcome_image_no_selfies">自撮りはアップロードできません</string>
<string name="welcome_image_proprietary">独自の著作権がある画像</string>
<string name="welcome_image_welcome_wikipedia">ウィキペディアへようこそ</string>
<string name="welcome_image_welcome_copyright">著作権について</string>
<string name="welcome_image_sydney_opera_house">シドニーオペラハウス</string>
<string name="cancel">キャンセル</string>
<string name="navigation_drawer_open">開く</string>
@ -195,28 +218,62 @@
<string name="navigation_item_logout">ログアウト</string>
<string name="navigation_item_info">チュートリアル</string>
<string name="navigation_item_notification">通知</string>
<string name="nearby_needs_permissions">場所の権限がないと、近くの場所を表示できません</string>
<string name="navigation_item_featured_images">秀逸</string>
<string name="nearby_needs_permissions">場所の権限がないため、近くの場所を表示できません</string>
<string name="no_description_found">説明がありません</string>
<string name="nearby_info_menu_commons_article">コモンズのファイルページ</string>
<string name="nearby_info_menu_wikidata_article">ウィキデータ項目</string>
<string name="nearby_info_menu_wikipedia_article">ウィキペディアの記事</string>
<string name="error_while_cache">画像をキャッシュする際のエラー</string>
<string name="title_info">ファイル固有の説明的な表題。ファイル名として使われます。平易な言葉を使い、空白を入れることができます。拡張子は含めないでください。</string>
<string name="description_info">可能な限りメディアを説明してください:どこで撮られましたか?それは何を示していますか?文脈とは何ですか?物や人を説明してください。容易に推測できない情報、例えば風景の場合の時刻を明らかにする。メディアに珍しいことがある場合は、何が珍しいのかを説明してください。</string>
<string name="give_permission">権限を取得</string>
<string name="upload_image_too_dark">この画像は暗すぎますがアップロードしますか? ウィキメディア・コモンズは百科事典に適した画像のみ受け付けます。</string>
<string name="upload_image_blurry">ピントが合っていませんが、アップロードしますか? ウィキメディア・コモンズは百科事典に適した画像のみ受け付けます。</string>
<string name="give_permission">権限を付与</string>
<string name="use_external_storage">外部ストレージを使用</string>
<string name="use_external_storage_summary">アプリ内のカメラで撮影した写真を端末に保存する</string>
<string name="login_to_your_account">自分のアカウントにログイン</string>
<string name="send_log_file">ログファイルを送信する</string>
<string name="send_log_file_description">メールで開発者にログファイルを送信する</string>
<string name="no_web_browser">URLを開くブラウザーが見つかりません</string>
<string name="null_url">エラーが発生しました。URL が見つかりません</string>
<string name="nominate_deletion">削除の提案</string>
<string name="nominated_for_deletion">この画像の削除が提案されています。</string>
<string name="view_browser">ブラウザーで表示</string>
<string name="nearby_location_has_not_changed">場所は変更されていません。</string>
<string name="nearby_location_not_available">位置が無効です。</string>
<string name="location_permission_rationale_nearby">近くの場所を表示するには権限が必要です</string>
<string name="get_directions">道順を調べる</string>
<string name="read_article">記事を読む</string>
<string name="notifications_welcome">ウィキメディアコモンズにようこそ、%1$さん! このサイトへ来てくれてありがとうございます。</string>
<string name="notifications_talk_page_message">%1$さんからアナタのとーくぺ^字にメッセージが届いています</string>
<string name="notifications_thank_you_edit">編集をしてくれてありがとうございます</string>
<string name="notifications_mention">%1$さんが%2$であなたに言及しています。</string>
<string name="toggle_view_button">表示の切り替え</string>
<string name="nearby_directions">道順</string>
<string name="nearby_wikidata">ウィキデータ</string>
<string name="nearby_wikipedia">ウィキペディア</string>
<string name="nearby_commons">コモンズ</string>
<string name="about_rate_us">&lt;u&gt;評価する&lt;/u&gt;</string>
<string name="about_faq">&lt;u&gt;FAQ&lt;/u&gt;</string>
<string name="welcome_skip_button">チュートリアルをスキップする</string>
<string name="no_internet">インターネットに接続していません</string>
<string name="internet_established">インターネットに接続しました</string>
<string name="error_notifications">通知の取得に失敗しました</string>
<string name="no_notifications">通知はありません</string>
<string name="about_translate">&lt;u&gt;翻訳&lt;/u&gt;</string>
<string name="about_translate_title">言語</string>
<string name="about_translate_message">どの言語に編集するか選択</string>
<string name="about_translate_proceed">次へ</string>
<string name="about_translate_cancel">キャンセル</string>
<string name="retry">再試行</string>
<string name="retry">やり直す</string>
<string name="showcase_view_got_it_button">了解</string>
<string name="showcase_view_whole_nearby_activity">近くでウィキペディアの記事に使う写真がない場所はこちら</string>
<string name="showcase_view_list_icon">このボタンをタップするとリストを表示します</string>
<string name="showcase_view_plus_fab">場所の写真をアップロードするには、ギャラリーから選ぶことも撮影することもできます</string>
<string name="no_images_found">画像がありません</string>
<string name="error_loading_images">画像の読み込み中にエラーが発生しました</string>
<string name="image_uploaded_by">アップロードした人: %1$</string>
<string name="share_app_title">アプリをシェアする</string>
<string name="share_coordinates_not_present">画像の選択中に位置情報を特定できませんでした</string>
</resources>

View file

@ -266,4 +266,14 @@
<string name="about_translate_proceed">진행</string>
<string name="about_translate_cancel">취소</string>
<string name="retry">다시 시도</string>
<string name="showcase_view_got_it_button">알겠습니다!</string>
<string name="showcase_view_whole_nearby_activity">이들은 위키백과 글에 사진을 넣을 필요가 있는 당신 주위의 장소들입니다</string>
<string name="showcase_view_list_icon">이 버튼을 탭하면 이 장소들의 목록을 가져옵니다</string>
<string name="showcase_view_plus_fab">갤러리나 카메라 어느 곳이든 사진을 올릴 수 있습니다</string>
<string name="no_images_found">그림이 없습니다!</string>
<string name="error_loading_images">그림을 불러오는 동안 오류가 발생했습니다.</string>
<string name="image_uploaded_by">올린이: %1$s</string>
<string name="share_app_title">앱 공유</string>
<string name="share_coordinates_not_present">그림 선택 중에 좌표가 지정되지 않았습니다</string>
<string name="error_fetching_nearby_places">주변 장소를 가져오는데 오류가 있습니다.</string>
</resources>

View file

@ -240,4 +240,8 @@
<string name="about_translate_proceed">Virufueren</string>
<string name="about_translate_cancel">Ofbriechen</string>
<string name="retry">Nach eng Kéier probéieren</string>
<string name="showcase_view_got_it_button">Verstanen!</string>
<string name="no_images_found">Keng Biller fonnt!</string>
<string name="error_loading_images">Feeler beim Eropluede vu Biller.</string>
<string name="image_uploaded_by">Eropgeluede vum: %1$s</string>
</resources>

View file

@ -109,4 +109,5 @@
<string name="about_translate_title">Valodas</string>
<string name="about_translate_proceed">Turpināt</string>
<string name="about_translate_cancel">Atcelt</string>
<string name="showcase_view_got_it_button">Sapratu!</string>
</resources>

View file

@ -263,4 +263,14 @@
<string name="about_translate_proceed">Продолжи</string>
<string name="about_translate_cancel">Откажи</string>
<string name="retry">Пробај пак</string>
<string name="showcase_view_got_it_button">Јасно!</string>
<string name="showcase_view_whole_nearby_activity">Ова се места во ваша близинана кои им требаат слики за илустрирање на нивните статии на Википедија</string>
<string name="showcase_view_list_icon">Ако допрете на копчево ќе добиете список на тие места</string>
<string name="showcase_view_plus_fab">Можете да подигнете слика за било кое од местата од вашата галерија или камера</string>
<string name="no_images_found">Не пронајдов ниедна слика!</string>
<string name="error_loading_images">Се појави грешка при вчитувањето на сликите.</string>
<string name="image_uploaded_by">Подигач: %1$s</string>
<string name="share_app_title">Сподели прилог</string>
<string name="share_coordinates_not_present">Не беа укажани координати при изборот на сликата</string>
<string name="error_fetching_nearby_places">Грешка при добивањето на околните места.</string>
</resources>

View file

@ -5,15 +5,23 @@
* Santhosh.thottingal
-->
<resources>
<string name="app_name" fuzzy="true">വിക്കിമീഡിയ കോമൺസ്</string>
<string name="preference_category_appearance">ദൃശ്യരൂപം</string>
<string name="preference_category_general">സാർവത്രികം</string>
<string name="preference_category_feedback">പ്രതികരണം</string>
<string name="preference_category_location">സ്ഥലം</string>
<string name="app_name">കോമൺസ്</string>
<string name="menu_settings">സജ്ജീകരണങ്ങൾ</string>
<string name="username">ഉപയോക്തൃനാമം</string>
<string name="password">രഹസ്യവാക്ക്</string>
<string name="login_credential">താങ്കളുടെ കോമൺസ് ബീറ്റ അംഗത്വത്തിൽ പ്രവേശിക്കുക</string>
<string name="login">പ്രവേശിക്കുക</string>
<string name="forgot_password">രഹസ്യവാക്ക് മറന്നോ?</string>
<string name="signup">അംഗത്വമെടുക്കുക</string>
<string name="logging_in_title">പ്രവേശിക്കുന്നു</string>
<string name="logging_in_message">ദയവായി കാത്തിരിക്കുക…</string>
<string name="login_success">പ്രവേശനം വിജയകരം!</string>
<string name="login_failed">പ്രവേശനം പരാജയപ്പെട്ടു!</string>
<string name="upload_failed">പ്രമാണം കണ്ടെത്താനായില്ല. ദയവായി മറ്റൊരു പ്രമാണം നോക്കുക.</string>
<string name="authentication_failed">സാധുതാനിർണ്ണയം പരാജയപ്പെട്ടു!</string>
<string name="uploading_started">അപ്‌ലോഡ് തുടങ്ങി!</string>
<string name="upload_completed_notification_title">%1$s അപ്‌ലോഡ് ചെയ്തിരിക്കുന്നു!</string>
@ -23,27 +31,30 @@
<string name="upload_progress_notification_title_finishing">%1$s അപ്‌ലോഡിങ് പൂർത്തിയാക്കുന്നു</string>
<string name="upload_failed_notification_title">%1$s അപ്‌ലോഡിങ് പരാജയപ്പെട്ടു</string>
<string name="upload_failed_notification_subtitle">കാണാനായി ടാപ് ചെയ്യുക</string>
<plurals name="uploads_pending_notification_indicator" fuzzy="true">
<item quantity="one">1 പ്രമാണം അപ്‌ലോഡ് ചെയ്യുന്നു</item>
<plurals name="uploads_pending_notification_indicator">
<item quantity="one">ഒരു പ്രമാണം അപ്‌ലോഡ് ചെയ്യുന്നു</item>
<item quantity="other">%1$d പ്രമാണങ്ങൾ അപ്‌ലോഡ് ചെയ്യുന്നു</item>
</plurals>
<string name="title_activity_contributions" fuzzy="true">എന്റെ അപ്‌ലോഡുകൾ</string>
<string name="title_activity_contributions">എന്റെ സമീപകാല അപ്‌ലോഡുകൾ</string>
<string name="contribution_state_queued">നിരയായി വെച്ചു</string>
<string name="contribution_state_failed">പരാജയപ്പെട്ടു</string>
<string name="contribution_state_in_progress">%1$d%% പൂർണ്ണം</string>
<string name="contribution_state_starting">അപ്‌ലോഡ് ചെയ്തുകൊണ്ടിരിക്കുന്നു</string>
<string name="menu_from_gallery">ചിത്രശാല</string>
<string name="menu_from_camera">ചിത്രം എടുക്കുക</string>
<string name="menu_nearby">സമീപസ്ഥം</string>
<string name="provider_contributions">എന്റെ അപ്‌ലോഡുകൾ</string>
<string name="menu_share">പങ്ക് വെയ്ക്കുക</string>
<string name="menu_open_in_browser">ബ്രൗസറിൽ കാണുക</string>
<string name="share_title_hint">തലക്കെട്ട്</string>
<string name="add_title_toast">ഈ പ്രമാണത്തിന് ഒരു തലക്കെട്ട് നൽകുക.</string>
<string name="share_description_hint">വിവരണം</string>
<string name="login_failed_network">പ്രവേശിക്കാനായില്ല - നെറ്റ്‌വർക്ക് പരാജയപ്പെട്ടു</string>
<string name="login_failed_username">പ്രവേശിക്കാനായില്ല - ദയവായി താങ്കളുടെ ഉപയോക്തൃനാമം പരിശോധിക്കുക</string>
<string name="login_failed_password">പ്രവേശിക്കാനായില്ല - ദയവായി താങ്കളുടെ രഹസ്യവാക്ക് പരിശോധിക്കുക</string>
<string name="login_failed_throttled" fuzzy="true">നിരവധി വിജയകരമല്ലാത്ത ശ്രമങ്ങൾ നടന്നിരിക്കുന്നു. വീണ്ടും ശ്രമിക്കുന്നതിനു മുമ്പ് ഏതാനം മിനിറ്റുകൾ വിശ്രമിക്കുക</string>
<string name="login_failed_throttled">നിരവധി വിജയകരമല്ലാത്ത ശ്രമങ്ങൾ നടന്നിരിക്കുന്നു. വീണ്ടും ശ്രമിക്കുന്നതിനു മുമ്പ് ഏതാനം മിനിറ്റുകൾ വിശ്രമിക്കുക.</string>
<string name="login_failed_blocked">ക്ഷമിക്കുക, ഈ ഉപയോക്താവ് കോമൺസിൽ നിന്ന് തടയപ്പെട്ടിരിക്കുകയാണ്</string>
<string name="login_failed_2fa_needed">താങ്കളുടെ ദ്വി-ഘടക സാധൂകരണ കോഡ് നൽകുക.</string>
<string name="login_failed_generic">പ്രവേശനം പരാജയപ്പെട്ടു</string>
<string name="share_upload_button">അപ്‌ലോഡ്</string>
<string name="multiple_share_base_title">ഈ ഗണത്തിന് പേരിടുക</string>
@ -51,6 +62,11 @@
<string name="menu_upload_single">അപ്‌ലോഡ്</string>
<string name="categories_search_text_hint">വർഗ്ഗങ്ങളിൽ തിരയുക</string>
<string name="menu_save_categories">സേവ് ചെയ്യുക</string>
<string name="refresh_button">പുതുക്കുക</string>
<string name="display_list_button">പട്ടിക</string>
<string name="gps_disabled">താങ്കളുടെ ഉപകരണത്തിൽ ജി.പി.എസ്. പ്രവർത്തനരഹിതമാണ്. അത് പ്രവർത്തനസജ്ജമാക്കണോ?</string>
<string name="enable_gps">ജി.പി.എസ്. സജ്ജമാക്കുക</string>
<string name="contributions_subtitle_zero">ഇതുവരെ അപ്‌ലോഡുകൾ ഒന്നുമില്ല</string>
<plurals name="contributions_subtitle" fuzzy="true">
<item quantity="zero">ഒരു അപ്‌ലോഡും ചെയ്തില്ല</item>
<item quantity="one">ഒരു അപ്‌ലോഡ്</item>
@ -68,6 +84,8 @@
<string name="categories_skip_explanation" fuzzy="true">താങ്കളുടെ ചിത്രങ്ങൾ വിക്കിമീഡിയ കോമൺസിൽ കൂടുതൽ എളുപ്പത്തിൽ കണ്ടെത്തപ്പെടാനായി വർഗ്ഗങ്ങൾ ചേർക്കുക.\n\nവർഗ്ഗങ്ങൾ ചേർക്കാനായി ടൈപ്പ് ചെയ്ത് തുടങ്ങുക.\nഈ ഘട്ടം ഒഴിവാക്കാൻ ടാപ് ചെയ്യുക (അല്ലെങ്കിൽ പിന്നോട്ട് പോവുക).</string>
<string name="categories_activity_title">വർഗ്ഗങ്ങൾ</string>
<string name="title_activity_settings">സജ്ജീകരണങ്ങൾ</string>
<string name="title_activity_signup">അംഗത്വമെടുക്കുക</string>
<string name="title_activity_featured_images">തിരഞ്ഞെടുത്ത ചിത്രങ്ങൾ</string>
<string name="menu_about">വിവരണം</string>
<string name="about_license" fuzzy="true">&lt;a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\"&gt;അപാച്ചേ അനുമതിപത്രം പതിപ്പ് 2&lt;/a&gt; പ്രകാരം പുറത്തിറക്കപ്പെട്ട ഓപ്പൺ സോഴ്സ് സോഫ്റ്റ്‌വേർ</string>
<string name="about_improve" fuzzy="true">സ്രോതസ്സ് രൂപം &lt;a href=\"https://github.com/commons-app/apps-android-commons\"&gt;ജിറ്റ്ഹബിൽ&lt;/a&gt; ലഭ്യമാണ്.\nപ്രശ്നങ്ങൾ &lt;a href=\" https://github.com/commons-app/apps-android-commons/issues\"&gt;ബഗ്സില്ലയിൽ&lt;/a&gt; അറിയിക്കുക.</string>
@ -81,9 +99,11 @@
<string name="menu_cancel_upload">റദ്ദാക്കുക</string>
<string name="share_license_summary">ചിത്രം %1$s പ്രകാരം അനുമതി നൽകപ്പെടുന്നതാണ്</string>
<string name="menu_download">ഡൗൺലോഡ്</string>
<string name="preference_license" fuzzy="true">അനുമതി</string>
<string name="license_name_cc_by_sa" fuzzy="true">സി.സി. ആട്രിബ്യൂഷൻ-ഷെയർ‌എലൈക് 3.0</string>
<string name="license_name_cc_by" fuzzy="true">സി.സി. ആട്രിബ്യൂഷൻ 3.0</string>
<string name="preference_license">സ്വതേയുള്ള ഉപയോഗാനുമതി</string>
<string name="license_name_cc_by_sa_four">ആട്രിബ്യൂഷൻ-ഷെയർ‌എലൈക് 4.0</string>
<string name="license_name_cc_by_four">ആട്രിബ്യൂഷൻ 4.0</string>
<string name="license_name_cc_by_sa">ആട്രിബ്യൂഷൻ-ഷെയർ‌എലൈക് 3.0</string>
<string name="license_name_cc_by">ആട്രിബ്യൂഷൻ 3.0</string>
<string name="license_name_cc0">സി.സി.0</string>
<string name="license_name_cc_by_sa_3_0">സി.സി. ബൈ-എസ്.എ. 3.0</string>
<string name="license_name_cc_by_sa_3_0_at">സി.സി. ബൈ-എസ്.എ. 3.0 (ഓസ്ട്രിയ)</string>
@ -97,6 +117,8 @@
<string name="license_name_cc_by_sa_3_0_pl">സി.സി. ബൈ-എസ്.എ. 3.0 (പോളണ്ട്)</string>
<string name="license_name_cc_by_sa_3_0_ro">സി.സി. ബൈ-എസ്.എ. 3.0 (റൊമേനിയ)</string>
<string name="license_name_cc_by_3_0">സി.സി. ബൈ 3.0</string>
<string name="license_name_cc_by_sa_4_0">സി.സി. ബൈ-എസ്.എ. 4.0</string>
<string name="license_name_cc_by_4_0">സി.സി. ബൈ 4.0</string>
<string name="license_name_cc_zero">സി.സി. സീറോ</string>
<string name="welcome_wikipedia_text">താങ്കളെടുക്കുന്ന ചിത്രങ്ങൾ സംഭാവന ചെയ്യുക. വിക്കിപീഡിയ ലേഖനങ്ങൾ ജീവസ്സുറ്റതാക്കിത്തീർക്കുക!</string>
<string name="welcome_wikipedia_subtext">വിക്കിപീഡിയയിലുള്ള ചിത്രങ്ങൾ വിക്കിമീഡിയ കോമൺസിൽ നിന്നാണ്</string>
@ -105,9 +127,63 @@
<string name="welcome_final_text">മനസ്സിലായോ?</string>
<string name="welcome_final_button_text">ശരി!</string>
<string name="detail_panel_cats_label">വർഗ്ഗങ്ങൾ</string>
<string name="detail_panel_cats_loading" fuzzy="true">ശേഖരിക്കുന്നു…</string>
<string name="detail_panel_cats_loading">ശേഖരിക്കുന്നു…</string>
<string name="detail_panel_cats_none">ഒന്നും തിരഞ്ഞെടുത്തിട്ടില്ല</string>
<string name="detail_description_empty">വിവരണമൊന്നുമില്ല</string>
<string name="detail_license_empty">അജ്ഞാതമായ അനുമതി</string>
<string name="menu_refresh">പുതുക്കുക</string>
<string name="ok">ശരി</string>
<string name="title_activity_nearby">സമീപ സ്ഥലങ്ങൾ</string>
<string name="warning">മുന്നറിയിപ്പ്</string>
<string name="file_exists">ഈ പ്രമാണം കോമൺസിൽ നിലവിലുണ്ട്. തുടരണം എന്ന് താങ്കൾക്കുറപ്പാണോ?</string>
<string name="yes">അതെ</string>
<string name="no">അല്ല</string>
<string name="media_detail_title">ശീർഷകം</string>
<string name="media_detail_media_title">മീഡിയയുടെ തലക്കെട്ട്</string>
<string name="media_detail_description">വിവരണം</string>
<string name="media_detail_author">സ്രഷ്ടാവ്</string>
<string name="media_detail_uploaded_date">അപ്‌ലോഡ് ചെയ്ത തീയതി</string>
<string name="media_detail_license">ഉപയോഗാനുമതി</string>
<string name="media_detail_coordinates">നിർദ്ദേശാങ്കങ്ങൾ</string>
<string name="media_detail_coordinates_empty">ഒന്നും നൽകിയിട്ടില്ല</string>
<string name="commons_logo">കോമൺസ് ലോഗോ</string>
<string name="commons_website">കോമൺസ് വെബ്‌സൈറ്റ്</string>
<string name="background_image">പശ്ചാത്തല ചിത്രം</string>
<string name="upload_image">ചിത്രം അപ്‌ലോഡ് ചെയ്യുക</string>
<string name="welcome_image_mount_zao">സാവോ പർവ്വതം</string>
<string name="welcome_image_llamas">ലാമകൾ</string>
<string name="welcome_image_rainbow_bridge">മഴവിൽ പാലം</string>
<string name="welcome_image_tulip">തുലിപ്</string>
<string name="welcome_image_no_selfies">സെൽഫികൾ വേണ്ട</string>
<string name="welcome_image_proprietary">പകർപ്പവകാശ സംരക്ഷിത ചിത്രം</string>
<string name="welcome_image_sydney_opera_house">സിഡ്നി ഓപെറാ ഹൗസ്</string>
<string name="cancel">റദ്ദാക്കുക</string>
<string name="navigation_drawer_open">തുറക്കുക</string>
<string name="navigation_drawer_close">അടയ്ക്കുക</string>
<string name="navigation_item_home">പ്രധാനം</string>
<string name="navigation_item_upload">അപ്‌ലോഡ്</string>
<string name="navigation_item_nearby">സമീപസ്ഥം</string>
<string name="navigation_item_about">വിവരണം</string>
<string name="navigation_item_settings">സജ്ജീകരണങ്ങൾ</string>
<string name="navigation_item_feedback">പ്രതികരണം</string>
<string name="navigation_item_logout">ലോഗൗട്ട്</string>
<string name="navigation_item_info">സഹായം</string>
<string name="navigation_item_notification">അറിയിപ്പുകൾ</string>
<string name="navigation_item_featured_images">തിരഞ്ഞെടുക്കപ്പെട്ടത്</string>
<string name="no_description_found">വിവരണങ്ങൾ ഒന്നും കണ്ടെത്തിയില്ല</string>
<string name="nearby_info_menu_commons_article">കോമൺസ് പ്രമാണ താൾ</string>
<string name="nearby_info_menu_wikidata_article">വിക്കിഡേറ്റാ ഇനം</string>
<string name="nearby_info_menu_wikipedia_article">വിക്കിപീഡിയ ലേഖനം</string>
<string name="give_permission">അനുമതി നൽകുക</string>
<string name="login_to_your_account">താങ്കളുടെ അംഗത്വത്തിൽ പ്രവേശിക്കുക</string>
<string name="view_browser">ബ്രൗസറിൽ കാണുക</string>
<string name="nearby_wikidata">വിക്കിഡേറ്റാ</string>
<string name="nearby_wikipedia">വിക്കിപീഡിയ</string>
<string name="nearby_commons">കോമൺസ്</string>
<string name="about_faq">&lt;u&gt;പതിവുചോദ്യങ്ങൾ&lt;/u&gt;</string>
<string name="about_translate">&lt;u&gt;പരിഭാഷപ്പെടുത്തുക&lt;/u&gt;</string>
<string name="about_translate_title">ഭാഷകൾ</string>
<string name="about_translate_proceed">തുടരുക</string>
<string name="about_translate_cancel">റദ്ദാക്കുക</string>
<string name="retry">വീണ്ടും ശ്രമിക്കുക</string>
</resources>

View file

@ -227,4 +227,6 @@
<string name="no_notifications">Nie znaleziono powiadomień</string>
<string name="about_translate_title">Języki</string>
<string name="about_translate_cancel">Anuluj</string>
<string name="no_images_found">Nie znaleziono grafik!</string>
<string name="error_loading_images">Wystąpił błąd podczas ładowania grafik.</string>
</resources>

View file

@ -263,4 +263,14 @@
<string name="about_translate_proceed">Andé anans</string>
<string name="about_translate_cancel">Anulé</string>
<string name="retry">Prové torna</string>
<string name="showcase_view_got_it_button">Fàit!</string>
<string name="showcase_view_whole_nearby_activity">A-i é dij pòst davzin a chiel ch\'a l\'han da manca ëd plance për ilustré ij sò artìcoj su Wikipedia</string>
<string name="showcase_view_list_icon">Sgnacand su \'s boton a comparirà na lista ëd si pòst</string>
<string name="showcase_view_plus_fab">A peul carié na fòto da \'n pòst qualsëssìa ëd soa galarìa o màchina fòto</string>
<string name="no_images_found">Gnun-e plance trovà!</string>
<string name="error_loading_images">A-i é staje n\'eror durant ël cariament ëd le plance.</string>
<string name="image_uploaded_by">Carià da: %1$s</string>
<string name="share_app_title">Partagé j\'aplicassion</string>
<string name="share_coordinates_not_present">Le coordinà a son nen ëstàite spessificà durant la selession ëd la plancia</string>
<string name="error_fetching_nearby_places">Eror durant l\'esplorassion dj\'anviron.</string>
</resources>

View file

@ -275,4 +275,14 @@
<string name="about_translate_proceed">Avançar</string>
<string name="about_translate_cancel">Cancelar</string>
<string name="retry">Tentar novamente</string>
<string name="showcase_view_got_it_button">Entendido!</string>
<string name="showcase_view_whole_nearby_activity">Estes são os lugares perto de você que precisam de fotografias para ilustrar os respetivos artigos na Wikipédia</string>
<string name="showcase_view_list_icon">Tocar neste botão fará surgir uma lista destes lugares</string>
<string name="showcase_view_plus_fab">Pode carregar uma fotografia para qualquer dos lugares, da sua galeria ou câmara</string>
<string name="no_images_found">Não foi encontrada nenhuma imagem!</string>
<string name="error_loading_images">Ocorreu um erro durante o carregamento das imagens.</string>
<string name="image_uploaded_by">Carregada por: %1$s</string>
<string name="share_app_title">Compartilhar o aplicativo</string>
<string name="share_coordinates_not_present">Não foram especificadas coordenadas durante a seleção da imagem</string>
<string name="error_fetching_nearby_places">Erro ao buscar lugares próximos.</string>
</resources>

View file

@ -16,12 +16,12 @@
<string name="preference_category_general">Geral</string>
<string name="preference_category_feedback">Comentários</string>
<string name="preference_category_location">Localização</string>
<string name="app_name">Wikimedia Commons</string>
<string name="app_name">Commons</string>
<string name="bullet"></string>
<string name="menu_settings">Configurações</string>
<string name="username">Nome de utilizador(a)</string>
<string name="username">Nome de utilizador</string>
<string name="password">Palavra-passe</string>
<string name="login_credential">Entre com a sua conta do Commons Beta</string>
<string name="login_credential">Entre com a sua conta da wiki Commons Beta</string>
<string name="login">Iniciar sessão</string>
<string name="forgot_password">Esqueceu-se da palavra-passe?</string>
<string name="signup">Registar-se</string>
@ -118,7 +118,7 @@
<string name="preference_theme_summary">Utilizar tema escuro</string>
<string name="license_name_cc_by_sa_four">Atribuição-CompartilhaIgual 4.0</string>
<string name="license_name_cc_by_four">Atribuição 4.0</string>
<string name="license_name_cc_by_sa"> Atribuição Compartilhamento pela mesma Licença</string>
<string name="license_name_cc_by_sa"> AtribuiçãoCompartilhaIgual 3.0</string>
<string name="license_name_cc_by">Atribuição 3.0</string>
<string name="license_name_cc0">CC0</string>
<string name="license_name_cc_by_sa_3_0">CC BY-SA 3.0</string>
@ -136,7 +136,7 @@
<string name="license_name_cc_by_sa_4_0">CC-BY-SA 4.0</string>
<string name="license_name_cc_by_4_0">CC BY 4.0</string>
<string name="license_name_cc_zero">CC Zero</string>
<string name="tutorial_1_text">Wikimedia Commons armazena a maioria das imagens que são usadas na Wikipédia.</string>
<string name="tutorial_1_text">A wiki Wikimedia Commons aloja a maioria das imagens que são usadas na Wikipédia.</string>
<string name="tutorial_1_subtext">As suas imagens ajudam a educar pessoas em todo o mundo!</string>
<string name="tutorial_2_text">Por favor, carregue apenas imagens tiradas ou criadas exclusivamente por si:</string>
<string name="tutorial_2_subtext">Objetos naturais (flores, animais, montanhas)\n• Objetos úteis (bicicletas, estações de comboio)\n• Pessoas famosas (o seu presidente da câmara, atletas olímpicos que conheça)</string>
@ -159,6 +159,7 @@
<string name="welcome_copyright_subtext">Evite materiais protegidos por direitos de autor que tenham sido encontrados na Internet, bem como imagens de cartazes, capas de livros, etc.</string>
<string name="welcome_final_text">Acha que conseguiu?</string>
<string name="welcome_final_button_text">Sim!</string>
<string name="welcome_help_button_text"/>
<string name="detail_panel_cats_label">Categorias</string>
<string name="detail_panel_cats_loading">A carregar…</string>
<string name="detail_panel_cats_none">Nenhuma selecionada</string>
@ -273,4 +274,14 @@
<string name="about_translate_proceed">Avançar</string>
<string name="about_translate_cancel">Cancelar</string>
<string name="retry">Tentar novamente</string>
<string name="showcase_view_got_it_button">Entendido!</string>
<string name="showcase_view_whole_nearby_activity">Estes são os lugares perto de si que precisam de fotografias para ilustrar os respetivos artigos na Wikipédia</string>
<string name="showcase_view_list_icon">Tocar neste botão fará surgir uma lista destes lugares</string>
<string name="showcase_view_plus_fab">Pode carregar uma fotografia para qualquer dos lugares, da sua galeria ou câmara</string>
<string name="no_images_found">Não foi encontrada nenhuma imagem!</string>
<string name="error_loading_images">Ocorreu um erro durante o carregamento das imagens.</string>
<string name="image_uploaded_by">Carregada por: %1$s</string>
<string name="share_app_title">Partilhar aplicação</string>
<string name="share_coordinates_not_present">Não foram especificadas coordenadas durante a seleção da imagem</string>
<string name="error_fetching_nearby_places">Erro ao localizar locais próximos.</string>
</resources>

View file

@ -99,6 +99,7 @@
<string name="welcome_copyright_subtext">Message explaining what kind of images not to submit.</string>
<string name="welcome_final_text">Message asking user if they understand what kinds of images to upload.</string>
<string name="welcome_final_button_text">Button text for confirming the user understands what kinds of images to upload.\n{{Identical|Yes}}</string>
<string name="welcome_help_button_text">\'\'This message is empty, and it\'s probably invalid. See bug report: https://github.com/commons-app/apps-android-commons/issues/1333 .\'\'</string>
<string name="detail_panel_cats_label">Label for categories list in media detail panel.\n{{Identical|Category}}</string>
<string name="detail_panel_cats_loading">Placeholder for categories list in media detail panel, while loading from network.\n{{Identical|Loading}}</string>
<string name="detail_panel_cats_none">Placeholder for categories list in media detail panel, if no categories found.\n{{Identical|None selected}}</string>

View file

@ -170,6 +170,7 @@
<string name="welcome_copyright_subtext">Избегайте материалов, защищённых авторским правом, например, найденных в Интернете, изображений плакатов, книжных обложек и т.п.</string>
<string name="welcome_final_text">Вам это понятно?</string>
<string name="welcome_final_button_text">Да!</string>
<string name="welcome_help_button_text">*</string>
<string name="detail_panel_cats_label">Категории</string>
<string name="detail_panel_cats_loading">Загрузка…</string>
<string name="detail_panel_cats_none">Ничего не выбрано</string>
@ -284,4 +285,13 @@
<string name="about_translate_proceed">Выполняется</string>
<string name="about_translate_cancel">Отмена</string>
<string name="retry">Повторить</string>
<string name="showcase_view_got_it_button">Понятно!</string>
<string name="showcase_view_whole_nearby_activity">Это места поблизости, статьи о которых нуждаются в иллюстрациях</string>
<string name="showcase_view_list_icon">Нажатие этой кнопки сгенерирует список таких мест</string>
<string name="showcase_view_plus_fab">Вы можете загрузить изображение для любого из этих мест, сделав снимок камерой или выбрав уже существующее изображение из галереи</string>
<string name="no_images_found">Изображений не найдено!</string>
<string name="error_loading_images">Произошла ошибка при загрузке изображений.</string>
<string name="image_uploaded_by">Загружено участником %1$s</string>
<string name="share_app_title">Поделиться приложением</string>
<string name="share_coordinates_not_present">Во время выбора изображения не были указаны координаты</string>
</resources>

View file

@ -129,4 +129,5 @@
<string name="about_translate_proceed">اڳوں تے تھیوو</string>
<string name="about_translate_cancel">منسوخ</string>
<string name="retry">ولدا کوشش کرو</string>
<string name="showcase_view_got_it_button">گھن گھندا</string>
</resources>

View file

@ -90,9 +90,9 @@
<string name="categories_activity_title">Kategorier</string>
<string name="title_activity_settings">Inställningar</string>
<string name="title_activity_signup">Registrera</string>
<string name="title_activity_featured_images">Utvalda bild</string>
<string name="title_activity_featured_images">Utvalda bilder</string>
<string name="menu_about">Om</string>
<string name="about_license">Wikimedia Commons är en app med öppen källkod som skapas och underhålls av frivilliga från Wikimedias gemenskap. Wikimedia Foundation är inte involverad i skapandet, utvecklingen eller underhållet av appen.</string>
<string name="about_license">Wikimedia Commons-appen är en app med öppen källkod som skapas och underhålls av frivilliga från Wikimedias gemenskap. Wikimedia Foundation är inte involverad i skapandet, utvecklingen eller underhållet av appen.</string>
<string name="about_improve">Skapa ett nytt &lt;a href=\"https://github.com/commons-app/apps-android-commons/issues\"&gt;ärende på GitHub&lt;/a&gt; för att rapportera buggar och förslag.</string>
<string name="about_privacy_policy">&lt;u&gt;Integritetspolicy&lt;/u&gt;</string>
<string name="about_credits">&lt;u&gt;Erkännande&lt;/u&gt;</string>
@ -105,7 +105,7 @@
<string name="menu_retry_upload">Försök igen</string>
<string name="menu_cancel_upload">Avbryt</string>
<string name="share_license_summary">Denna bild kommer att licensieras under %1$s</string>
<string name="media_upload_policy">Genom att skicka in denna bild intygar jag att detta är mitt eget verk, som inte innehåller upphovsrättsskyddat material eller selfies samt annars följer &lt;a href=\"https://commons.wikimedia.org/wiki/Commons:Policies_and_guidelines\"&gt;Wikimedia Commons-policys&lt;/a&gt;.</string>
<string name="media_upload_policy">Genom att skicka in denna bild intygar jag att detta är mitt eget verk, som inte innehåller upphovsrättsskyddat material eller selfies samt följer &lt;a href=\"https://commons.wikimedia.org/wiki/Commons:Policies_and_guidelines\"&gt;Wikimedia Commons-policys&lt;/a&gt;.</string>
<string name="menu_download">Ladda ned</string>
<string name="preference_license">Standardlicens</string>
<string name="use_previous">Använd föregående titel/beskrivning</string>
@ -135,7 +135,7 @@
<string name="license_name_cc_zero">CC Zero</string>
<string name="tutorial_1_text">Wikimedia Commons lagrar de flesta bilderna som används på Wikipedia.</string>
<string name="tutorial_1_subtext">Dina bilder hjälper till att utbilda\nmänniskor runt hela världen!</string>
<string name="tutorial_2_text">Ladda upp bilder som endast du har tagit eller skapat:</string>
<string name="tutorial_2_text">Ladda endast upp bilder som du har tagit eller skapat själv:</string>
<string name="tutorial_2_subtext">Naturliga föremål (blommor, djur, berg)\n• Användbara föremål (cyklar, tågstationer)\n• Berömda personer (din borgmästare, olympiska atleter du har träffat)</string>
<string name="tutorial_2_subtext_1">Naturliga föremål (blommor, djur, berg)</string>
<string name="tutorial_2_subtext_2">Användbar föremål (cyklar, tågstationer)</string>
@ -156,14 +156,15 @@
<string name="welcome_copyright_subtext">Undvik upphovsrättsskyddat material som du hittar på Internet, samt bilder av affischer, bokomslag, etc.</string>
<string name="welcome_final_text">Tror du att du förstår?</string>
<string name="welcome_final_button_text">Ja!</string>
<string name="welcome_help_button_text"/>
<string name="detail_panel_cats_label">Kategorier</string>
<string name="detail_panel_cats_loading">Läser in…</string>
<string name="detail_panel_cats_none">Ingen markerad</string>
<string name="detail_description_empty">Ingen beskrivning</string>
<string name="detail_license_empty">Okänd licens</string>
<string name="menu_refresh">Uppdatera</string>
<string name="read_storage_permission_rationale">Nödvändig behörighet: Läsa extern lagring. Appen kan inte komma åt ditt galleri utan detta.</string>
<string name="write_storage_permission_rationale">Nödvändig behörighet: Skriva till extern lagring. Appen kan inte komma åt din kamera utan detta.</string>
<string name="read_storage_permission_rationale">Nödvändig behörighet: Läs extern lagring. Appen kan inte komma åt ditt galleri utan detta.</string>
<string name="write_storage_permission_rationale">Nödvändig behörighet: Skriv till extern lagring. Appen kan inte komma åt din kamera utan detta.</string>
<string name="location_permission_rationale">Valfri behörighet: Hämta aktuell plats för kategoriförslag</string>
<string name="ok">OK</string>
<string name="title_activity_nearby">Platser i närheten</string>
@ -270,4 +271,13 @@
<string name="about_translate_proceed">Fortsätt</string>
<string name="about_translate_cancel">Avbryt</string>
<string name="retry">Försök igen</string>
<string name="showcase_view_got_it_button">Uppfattat!</string>
<string name="showcase_view_whole_nearby_activity">Detta är platserna nära dig som behöver bilder för att illustrera deras Wikipedia-artiklar</string>
<string name="showcase_view_list_icon">Klicka på den här knappen för att få upp en lista med dessa platser</string>
<string name="showcase_view_plus_fab">Du kan ladda upp en bild från vilken plats som helst från ditt galleri eller kamera</string>
<string name="no_images_found">Inga bilder hittades!</string>
<string name="error_loading_images">Ett fel uppstod vid inläsning av bilder.</string>
<string name="image_uploaded_by">Uppladdad av: %1$s</string>
<string name="share_app_title">Dela app</string>
<string name="share_coordinates_not_present">Koordinater specificerades inte vid bildvalet</string>
</resources>

View file

@ -271,4 +271,13 @@
<string name="about_translate_proceed">İlerle</string>
<string name="about_translate_cancel">Vazgeç</string>
<string name="retry">Tekrar Deneyin</string>
<string name="showcase_view_got_it_button">Anladım!</string>
<string name="showcase_view_whole_nearby_activity">Vikipedi maddelerine eklemek için fotoğrafa ihtiyaç duyan size yakın yerler</string>
<string name="showcase_view_list_icon">Bu tuşa dokunmak bu yerlerin bir listesini getirir</string>
<string name="showcase_view_plus_fab">Galerinizden veya kameranızla herhangi bir yer için resim yükleyebilirsiniz.</string>
<string name="no_images_found">Resim bulunamadı!</string>
<string name="error_loading_images">Resimler yüklenirken hata oluştu.</string>
<string name="image_uploaded_by">Yükleyen: %1$s</string>
<string name="share_app_title">Uygulamayı Paylaş</string>
<string name="share_coordinates_not_present">Koordinatlar görüntü seçimi sırasında belirlenmedi</string>
</resources>

View file

@ -32,7 +32,7 @@
<string name="authentication_failed">未能核對身分!</string>
<string name="uploading_started">開始上傳!</string>
<string name="upload_completed_notification_title">已上傳%1$s</string>
<string name="upload_completed_notification_text">點選檢視您上傳的項目</string>
<string name="upload_completed_notification_text">輕觸來檢視您上傳的項目</string>
<string name="upload_progress_notification_title_start">開始上傳%1$s</string>
<string name="upload_progress_notification_title_in_progress">正在上傳%1$s</string>
<string name="upload_progress_notification_title_finishing">即將完成上傳 %1$s</string>
@ -271,4 +271,14 @@
<string name="about_translate_proceed">已進行</string>
<string name="about_translate_cancel">取消</string>
<string name="retry">重試</string>
<string name="showcase_view_got_it_button">了解!</string>
<string name="showcase_view_whole_nearby_activity">這些是在您的附近,並且需要圖片來圖解有關它們的維基百科條目之地點</string>
<string name="showcase_view_list_icon">輕觸此按鈕來帶出這些地點的清單</string>
<string name="showcase_view_plus_fab">您可從您的圖庫或相機,來上傳任何地點的圖片</string>
<string name="no_images_found">找不到圖片!</string>
<string name="error_loading_images">當載入圖片時發生錯誤。</string>
<string name="image_uploaded_by">由:%1$s 上傳</string>
<string name="share_app_title">分享應用程式</string>
<string name="share_coordinates_not_present">當選擇圖片時未指定座標</string>
<string name="error_fetching_nearby_places">索取附近地點時出錯。</string>
</resources>

View file

@ -269,4 +269,14 @@
<string name="about_translate_proceed">已处理</string>
<string name="about_translate_cancel">取消</string>
<string name="retry">重试</string>
<string name="showcase_view_got_it_button">明白了!</string>
<string name="showcase_view_whole_nearby_activity">这些是您附近需要图片以阐明维基百科条目的地方</string>
<string name="showcase_view_list_icon">点按此按钮会出现这些地点的列表</string>
<string name="showcase_view_plus_fab">您可以从您的图库或照相机中上传任意地点的图片</string>
<string name="no_images_found">找不到图片!</string>
<string name="error_loading_images">加载图片时出错。</string>
<string name="image_uploaded_by">由%1$s上传</string>
<string name="share_app_title">分享应用</string>
<string name="share_coordinates_not_present">图片选择时,坐标并未指定</string>
<string name="error_fetching_nearby_places">检索附近地点时出错。</string>
</resources>

View file

@ -23,4 +23,6 @@
<dimen name="subheading_text_size">20sp</dimen>
<dimen name="normal_text">16sp</dimen>
<dimen name="description_text_size">14sp</dimen>
<dimen name="first_fab">15dp</dimen>
<dimen name="second_fab">25dp</dimen>
</resources>

View file

@ -270,4 +270,18 @@
<string name="about_translate_proceed">Proceed</string>
<string name="about_translate_cancel">Cancel</string>
<string name="retry">Retry</string>
<string name="showcase_view_got_it_button">Got it!</string>
<string name="showcase_view_whole_nearby_activity">These are the places near you that need pictures to illustrate their Wikipedia articles</string>
<string name="showcase_view_list_icon">Tapping this button brings up a list of these places</string>
<string name="showcase_view_plus_fab">You can upload a picture for any place from your gallery or camera</string>
<string name="no_images_found">No images found!</string>
<string name="error_loading_images">Error occurred while loading images.</string>
<string name="image_uploaded_by">Uploaded by: %1$s</string>
<string name="share_app_title">Share App</string>
<string name="share_coordinates_not_present">Coordinates were not specified during image selection</string>
<string name="error_fetching_nearby_places">Error fetching nearby places.</string>
</resources>

View file

@ -3,6 +3,7 @@ package fr.free.nrw.commons
import android.content.Context
import android.content.SharedPreferences
import android.support.v4.util.LruCache
import com.google.gson.Gson
import com.nhaarman.mockito_kotlin.mock
import com.squareup.leakcanary.RefWatcher
import fr.free.nrw.commons.auth.AccountUtil
@ -36,6 +37,7 @@ class MockCommonsApplicationModule(appContext: Context) : CommonsApplicationModu
val accountUtil: AccountUtil = mock()
val appSharedPreferences: SharedPreferences = mock()
val defaultSharedPreferences: SharedPreferences = mock()
val categorySharedPreferences: SharedPreferences = mock()
val otherSharedPreferences: SharedPreferences = mock()
val uploadController: UploadController = mock()
val mockSessionManager: SessionManager = mock()
@ -45,6 +47,7 @@ class MockCommonsApplicationModule(appContext: Context) : CommonsApplicationModu
val mockDbOpenHelper: DBOpenHelper = mock()
val nearbyPlaces: NearbyPlaces = mock()
val lruCache: LruCache<String, String> = mock()
val gson: Gson = Gson()
override fun providesAccountUtil(context: Context): AccountUtil = accountUtil
@ -58,7 +61,7 @@ class MockCommonsApplicationModule(appContext: Context) : CommonsApplicationModu
override fun providesSessionManager(context: Context, mediaWikiApi: MediaWikiApi, sharedPreferences: SharedPreferences): SessionManager = mockSessionManager
override fun provideMediaWikiApi(context: Context, sharedPreferences: SharedPreferences): MediaWikiApi = mediaWikiApi
override fun provideMediaWikiApi(context: Context, sharedPreferences: SharedPreferences, categorySharedPreferences: SharedPreferences, gson: Gson): MediaWikiApi = mediaWikiApi
override fun provideLocationServiceManager(context: Context): LocationServiceManager = locationServiceManager

View file

@ -3,6 +3,7 @@ package fr.free.nrw.commons.mwapi
import android.content.SharedPreferences
import android.os.Build
import android.preference.PreferenceManager
import com.google.gson.Gson
import fr.free.nrw.commons.BuildConfig
import fr.free.nrw.commons.TestCommonsApplication
import okhttp3.mockwebserver.MockResponse
@ -26,12 +27,14 @@ class ApacheHttpClientMediaWikiApiTest {
private lateinit var testObject: ApacheHttpClientMediaWikiApi
private lateinit var server: MockWebServer
private lateinit var sharedPreferences: SharedPreferences
private lateinit var categoryPreferences: SharedPreferences
@Before
fun setUp() {
server = MockWebServer()
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(RuntimeEnvironment.application)
testObject = ApacheHttpClientMediaWikiApi(RuntimeEnvironment.application, "http://" + server.hostName + ":" + server.port + "/", sharedPreferences)
categoryPreferences = PreferenceManager.getDefaultSharedPreferences(RuntimeEnvironment.application)
testObject = ApacheHttpClientMediaWikiApi(RuntimeEnvironment.application, "http://" + server.hostName + ":" + server.port + "/", sharedPreferences, categoryPreferences, Gson())
testObject.setWikiMediaToolforgeUrl("http://" + server.hostName + ":" + server.port + "/")
}