Merge remote-tracking branch 'refs/remotes/commons-app/master'

This commit is contained in:
misaochan 2018-04-23 17:39:14 +10:00
commit 649da00c7f
278 changed files with 4540 additions and 2090 deletions

View file

@ -1,5 +1,15 @@
# Wikimedia Commons for Android
## v2.7.0
- New Nearby Places UI with direct uploads (and associated category suggestions)
- Added two-factor authentication login
- Added Notifications activity to display user talk messages
- Added real-time location tracking in Nearby
- Added "rate us", "translate", and FB link in About
- Improvements to UI of navigation drawer, tutorial, media details view, login activity and Settings
- Added option to nominate picture for deletion in media details view
- Too many bug and crash fixes to mention!
## v2.6.7
- Added null checks to prevent frequent crashes in ModificationsSyncAdapter

View file

@ -1 +1,19 @@
Please see our guidelines in the wiki: https://github.com/commons-app/apps-android-commons/wiki/Volunteers-welcome%21
Thanks for considering to contribute to this project! A few guidelines for
people who want to contribute their code to this software are documented in
[this project's Wiki](https://github.com/commons-app/apps-android-commons/wiki/Contributing-Guidelines).
If you're not sure where to start head on to [this wiki page](https://github.com/commons-app/apps-android-commons/wiki/Volunteers-welcome!).
Here's a gist of the guidelines,
# Make separate commits for logically separate changes
# Describe your changes well in the commit message
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)
# Make sure the Wiki pages don't become stale by updating them (if needed)

10
CREDITS
View file

@ -30,6 +30,16 @@ their contribution to the product.
* Bruke Mekuria Mulugeta
* Paul Hawke
* Vishan Seru
* Abhishek Poonia
* Ayushi Negi
* Harisanker Pradeep
* Hassan Ismaeel
* Jatin Rao
* Meghna Gupta
* S Balakrishnan
* Suchit Kar
* Tanvi Dadu
* Ujjwal Agrawal
3rd party open source libraries used:
* Butterknife

View file

@ -11,18 +11,19 @@ dependencies {
implementation 'fr.avianey.com.viewpagerindicator:library:2.4.1.1@aar'
implementation 'in.yuvi:http.fluent:1.3'
implementation 'com.android.volley:volley:1.0.0'
implementation 'ch.acra:acra:4.7.0'
implementation 'ch.acra:acra:4.9.2'
implementation 'org.mediawiki:api:1.3'
implementation 'commons-codec:commons-codec:1.10'
implementation 'com.github.pedrovgs:renderers:3.3.3'
implementation 'com.google.code.gson:gson:2.8.1'
implementation 'com.jakewharton.timber:timber:4.5.1'
implementation 'info.debatty:java-string-similarity:0.24'
implementation 'com.borjabravo:readmoretextview:2.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
implementation ('com.mapbox.mapboxsdk:mapbox-android-sdk:5.4.1@aar'){
transitive=true
}
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"
@ -41,8 +42,6 @@ dependencies {
// explicitly depend on RxJava's latest version for bug fixes and new features.
implementation 'com.android.support:multidex:1.0.3'
testImplementation "org.robolectric:multidex:3.4.2"
implementation 'io.reactivex.rxjava2:rxjava:2.1.2'
implementation 'com.jakewharton.rxbinding2:rxbinding:2.0.0'
implementation 'com.jakewharton.rxbinding2:rxbinding-support-v4:2.0.0'
@ -54,33 +53,25 @@ dependencies {
implementation "com.google.dagger:dagger:$DAGGER_VERSION"
implementation "com.google.dagger:dagger-android-support:$DAGGER_VERSION"
kapt "com.google.dagger:dagger-android-processor:$DAGGER_VERSION"
kapt "com.google.dagger:dagger-compiler:$DAGGER_VERSION"
testImplementation "org.robolectric:multidex:3.4.2"
testImplementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
androidTestImplementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
testImplementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
testImplementation 'junit:junit:4.12'
testImplementation 'org.robolectric:robolectric:3.7.1'
testImplementation 'org.mockito:mockito-all:1.10.19'
testImplementation 'com.nhaarman:mockito-kotlin:1.5.0'
testImplementation 'com.squareup.okhttp3:mockwebserver:3.8.1'
androidTestImplementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
androidTestImplementation 'com.squareup.okhttp3:mockwebserver:3.8.1'
androidTestImplementation "com.android.support:support-annotations:$SUPPORT_LIB_VERSION"
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2-alpha1'
debugImplementation "com.squareup.leakcanary:leakcanary-android:$LEAK_CANARY"
releaseImplementation "com.squareup.leakcanary:leakcanary-android-no-op:$LEAK_CANARY"
testImplementation "com.squareup.leakcanary:leakcanary-android-no-op:$LEAK_CANARY"
implementation "com.google.dagger:dagger:$DAGGER_VERSION"
implementation "com.google.dagger:dagger-android-support:$DAGGER_VERSION"
kapt "com.google.dagger:dagger-compiler:$DAGGER_VERSION"
kapt "com.google.dagger:dagger-android-processor:$DAGGER_VERSION"
implementation 'com.borjabravo:readmoretextview:2.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
}
android {
@ -91,8 +82,8 @@ android {
defaultConfig {
applicationId 'fr.free.nrw.commons'
versionCode 82
versionName '2.6.7'
versionCode 83
versionName '2.7.0'
setProperty("archivesBaseName", "app-commons-v$versionName-" + getBranchName())
minSdkVersion project.minSdkVersion

View file

@ -91,6 +91,10 @@
android:name=".notification.NotificationActivity"
android:label="@string/navigation_item_notification" />
<activity
android:name=".featured.FeaturedImagesActivity"
android:label="@string/title_activity_featured_images" />
<service android:name=".upload.UploadService" />
<service

View file

@ -6,11 +6,15 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.text.Html;
import android.text.SpannableString;
import android.text.style.UnderlineSpan;
import android.util.Log;
import android.support.customtabs.CustomTabsIntent;
import android.support.v4.content.ContextCompat;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
@ -62,6 +66,18 @@ public class AboutActivity extends NavigationBaseActivity {
content.setSpan(new UnderlineSpan(), 0, content.length(), 0);
faqText.setText(content);
versionText.setText(BuildConfig.VERSION_NAME);
TextView rate_us = findViewById(R.id.about_rate_us);
TextView privacy_policy = findViewById(R.id.about_privacy_policy);
TextView translate = findViewById(R.id.about_translate);
TextView credits = findViewById(R.id.about_credits);
TextView faq = findViewById(R.id.about_faq);
rate_us.setText(Html.fromHtml(getString(R.string.about_rate_us)));
privacy_policy.setText(Html.fromHtml(getString(R.string.about_privacy_policy)));
translate.setText(Html.fromHtml(getString(R.string.about_translate)));
credits.setText(Html.fromHtml(getString(R.string.about_credits)));
faq.setText(Html.fromHtml(getString(R.string.about_faq)));
initDrawer();
}
@ -108,6 +124,28 @@ public class AboutActivity extends NavigationBaseActivity {
Utils.handleWebUrl(this,Uri.parse("https://github.com/commons-app/apps-android-commons/wiki/Frequently-Asked-Questions\\"));
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_about, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.share_app_icon:
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.setType("text/plain");
startActivity(Intent.createChooser(sendIntent, "Share app via..."));
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@OnClick(R.id.about_translate)
public void launchTranslate(View view) {
final ArrayAdapter<String> languageAdapter = new ArrayAdapter<String>(AboutActivity.this,

View file

@ -54,9 +54,11 @@ public class CommonsApplication extends MultiDexApplication {
public static final String FEEDBACK_EMAIL = "commons-app-android@googlegroups.com";
public static final String FEEDBACK_EMAIL_SUBJECT = "Commons Android App (%s) Feedback";
public static final String LOGS_PRIVATE_EMAIL = "commons-app-android-private@googlegroups.com";
public static final String FEEDBACK_EMAIL_SUBJECT = "Commons Android App (%s) Feedback";
public static final String LOGS_PRIVATE_EMAIL_SUBJECT = "Commons Android App (%s) Logs";
private RefWatcher refWatcher;

View file

@ -280,8 +280,11 @@ public class CategorizationFragment extends CommonsDaggerSupportFragment {
private Observable<CategoryItem> directCategories() {
String directCategory = directPrefs.getString("Category", "");
// Strip newlines to prevent blank categories, and to tidy existing categories
directCategory = directCategory.replace("\n", "");
List<String> categoryList = new ArrayList<>();
Timber.d("Direct category found: " + directCategory);
Timber.d("Direct category found: " + "'" + directCategory + "'");
if (!directCategory.equals("")) {
hasDirectCategories = true;

View file

@ -105,6 +105,7 @@ public class CategoryDao {
return items;
}
@NonNull
Category fromCursor(Cursor cursor) {
// Hardcoding column positions!
return new Category(

View file

@ -7,6 +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.nearby.NearbyActivity;
import fr.free.nrw.commons.notification.NotificationActivity;
import fr.free.nrw.commons.settings.SettingsActivity;
@ -46,4 +47,7 @@ public abstract class ActivityBuilderModule {
@ContributesAndroidInjector
abstract NotificationActivity bindNotificationActivity();
@ContributesAndroidInjector
abstract FeaturedImagesActivity bindFeaturedImagesActivity();
}

View file

@ -4,6 +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.media.MediaDetailFragment;
import fr.free.nrw.commons.media.MediaDetailPagerFragment;
import fr.free.nrw.commons.nearby.NearbyListFragment;
@ -47,4 +48,7 @@ public abstract class FragmentBuilderModule {
@ContributesAndroidInjector
abstract SingleUploadFragment bindSingleUploadFragment();
@ContributesAndroidInjector
abstract FeaturedImagesListFragment bindFeaturedImagesListFragment();
}

View file

@ -0,0 +1,44 @@
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

@ -0,0 +1,114 @@
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

@ -0,0 +1,57 @@
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;
/**
* Created by root on 09.01.2018.
*/
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

@ -0,0 +1,50 @@
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

@ -50,14 +50,16 @@ import static android.widget.Toast.LENGTH_SHORT;
public class MediaDetailFragment extends CommonsDaggerSupportFragment {
private boolean editable;
private boolean isFeaturedMedia;
private MediaDetailPagerFragment.MediaDetailProvider detailProvider;
private int index;
public static MediaDetailFragment forMedia(int index, boolean editable) {
public static MediaDetailFragment forMedia(int index, boolean editable, boolean isFeaturedMedia) {
MediaDetailFragment mf = new MediaDetailFragment();
Bundle state = new Bundle();
state.putBoolean("editable", editable);
state.putBoolean("isFeaturedMedia", isFeaturedMedia);
state.putInt("index", index);
state.putInt("listIndex", 0);
state.putInt("listTop", 0);
@ -79,12 +81,14 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment {
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;
private ArrayList<String> categoryNames;
@ -101,6 +105,7 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment {
super.onSaveInstanceState(outState);
outState.putInt("index", index);
outState.putBoolean("editable", editable);
outState.putBoolean("isFeaturedMedia", isFeaturedMedia);
getScrollPosition();
outState.putInt("listTop", initialListTop);
@ -116,13 +121,16 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment {
if (savedInstanceState != null) {
editable = savedInstanceState.getBoolean("editable");
isFeaturedMedia = savedInstanceState.getBoolean("isFeaturedMedia");
index = savedInstanceState.getInt("index");
initialListTop = savedInstanceState.getInt("listTop");
} else {
editable = getArguments().getBoolean("editable");
isFeaturedMedia = getArguments().getBoolean("isFeaturedMedia");
index = getArguments().getInt("index");
initialListTop = 0;
}
categoryNames = new ArrayList<>();
categoryNames.add(getString(R.string.detail_panel_cats_loading));
@ -135,6 +143,7 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment {
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);
@ -142,6 +151,13 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment {
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);
if (isFeaturedMedia){
authorLayout.setVisibility(View.VISIBLE);
} else {
authorLayout.setVisibility(View.GONE);
}
licenseList = new LicenseList(getActivity());
@ -304,9 +320,10 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment {
coordinates.setOnClickListener(v -> openMap(media.getCoordinates()));
}
if (delete.getVisibility() == View.VISIBLE) {
enableDeleteButton(true);
delete.setOnClickListener(v -> {
delete.setEnabled(false);
delete.setTextColor(getResources().getColor(R.color.deleteButtonLight));
AlertDialog.Builder alert = new AlertDialog.Builder(getActivity());
alert.setMessage("Why should this file be deleted?");
final EditText input = new EditText(getActivity());
@ -317,6 +334,7 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment {
String reason = input.getText().toString();
DeleteTask deleteTask = new DeleteTask(getActivity(), media, reason);
deleteTask.execute();
enableDeleteButton(false);
}
});
alert.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
@ -358,6 +376,15 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment {
}
}
private void enableDeleteButton(boolean visibility) {
delete.setEnabled(visibility);
if(visibility) {
delete.setTextColor(getResources().getColor(R.color.primaryTextColor));
} else {
delete.setTextColor(getResources().getColor(R.color.deleteButtonLight));
}
}
private void rebuildCatList() {
categoryContainer.removeAllViews();
// @fixme add the category items

View file

@ -55,14 +55,16 @@ public class MediaDetailPagerFragment extends CommonsDaggerSupportFragment imple
private ViewPager pager;
private Boolean editable;
private boolean isFeaturedImage;
public MediaDetailPagerFragment() {
this(false);
this(false, false);
}
@SuppressLint("ValidFragment")
public MediaDetailPagerFragment(Boolean editable) {
public MediaDetailPagerFragment(Boolean editable, boolean isFeaturedImage) {
this.editable = editable;
this.isFeaturedImage = isFeaturedImage;
}
@Override
@ -96,6 +98,7 @@ public class MediaDetailPagerFragment extends CommonsDaggerSupportFragment imple
super.onSaveInstanceState(outState);
outState.putInt("current-page", pager.getCurrentItem());
outState.putBoolean("editable", editable);
outState.putBoolean("isFeaturedImage", isFeaturedImage);
}
@Override
@ -103,6 +106,7 @@ public class MediaDetailPagerFragment extends CommonsDaggerSupportFragment imple
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
editable = savedInstanceState.getBoolean("editable");
isFeaturedImage = savedInstanceState.getBoolean("isFeaturedImage");
}
setHasOptionsMenu(true);
}
@ -291,7 +295,7 @@ public class MediaDetailPagerFragment extends CommonsDaggerSupportFragment imple
// See bug https://code.google.com/p/android/issues/detail?id=27526
pager.postDelayed(() -> getActivity().supportInvalidateOptionsMenu(), 5);
}
return MediaDetailFragment.forMedia(i, editable);
return MediaDetailFragment.forMedia(i, editable, isFeaturedImage);
}
@Override

View file

@ -8,6 +8,7 @@ import android.support.v7.app.AlertDialog;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.contributions.ContributionController;
import timber.log.Timber;
import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
@ -23,46 +24,25 @@ class DirectUpload {
this.controller = controller;
}
void initiateCameraUpload() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(fragment.getActivity(), WRITE_EXTERNAL_STORAGE) != PERMISSION_GRANTED) {
if (fragment.getActivity().shouldShowRequestPermissionRationale(WRITE_EXTERNAL_STORAGE)) {
new AlertDialog.Builder(fragment.getActivity())
.setMessage(fragment.getActivity().getString(R.string.write_storage_permission_rationale))
.setPositiveButton("OK", (dialog, which) -> {
fragment.getActivity().requestPermissions(new String[]{WRITE_EXTERNAL_STORAGE}, 3);
dialog.dismiss();
})
.setNegativeButton("Cancel", null)
.create()
.show();
} else {
fragment.getActivity().requestPermissions(new String[]{WRITE_EXTERNAL_STORAGE}, 3);
}
} else {
controller.startCameraCapture();
}
} else {
controller.startCameraCapture();
}
}
// These permission requests will be handled by the Fragments.
// Do not use requestCode 1 as it will conflict with NearbyActivity's requestCodes
void initiateGalleryUpload() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(fragment.getActivity(), READ_EXTERNAL_STORAGE) != PERMISSION_GRANTED) {
if (fragment.getActivity().shouldShowRequestPermissionRationale(READ_EXTERNAL_STORAGE)) {
if (fragment.shouldShowRequestPermissionRationale(READ_EXTERNAL_STORAGE)) {
new AlertDialog.Builder(fragment.getActivity())
.setMessage(fragment.getActivity().getString(R.string.read_storage_permission_rationale))
.setPositiveButton("OK", (dialog, which) -> {
fragment.getActivity().requestPermissions(new String[]{READ_EXTERNAL_STORAGE}, 1);
Timber.d("Requesting permissions for read external storage");
fragment.requestPermissions(new String[]{READ_EXTERNAL_STORAGE}, 4);
dialog.dismiss();
})
.setNegativeButton("Cancel", null)
.create()
.show();
} else {
fragment.getActivity().requestPermissions(new String[]{READ_EXTERNAL_STORAGE},
1);
fragment.requestPermissions(new String[]{READ_EXTERNAL_STORAGE},
4);
}
} else {
controller.startGalleryPick();
@ -72,4 +52,28 @@ class DirectUpload {
controller.startGalleryPick();
}
}
void initiateCameraUpload() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(fragment.getActivity(), WRITE_EXTERNAL_STORAGE) != PERMISSION_GRANTED) {
if (fragment.shouldShowRequestPermissionRationale(WRITE_EXTERNAL_STORAGE)) {
new AlertDialog.Builder(fragment.getActivity())
.setMessage(fragment.getActivity().getString(R.string.write_storage_permission_rationale))
.setPositiveButton("OK", (dialog, which) -> {
fragment.requestPermissions(new String[]{WRITE_EXTERNAL_STORAGE}, 5);
dialog.dismiss();
})
.setNegativeButton("Cancel", null)
.create()
.show();
} else {
fragment.requestPermissions(new String[]{WRITE_EXTERNAL_STORAGE}, 5);
}
} else {
controller.startCameraCapture();
}
} else {
controller.startCameraCapture();
}
}
}

View file

@ -10,17 +10,14 @@ import android.os.Build;
import android.os.Bundle;
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.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
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;
@ -31,7 +28,6 @@ import javax.inject.Inject;
import butterknife.BindView;
import butterknife.ButterKnife;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.location.LatLng;
import fr.free.nrw.commons.location.LocationServiceManager;
@ -39,13 +35,11 @@ import fr.free.nrw.commons.location.LocationUpdateListener;
import fr.free.nrw.commons.theme.NavigationBaseActivity;
import fr.free.nrw.commons.utils.NetworkUtils;
import fr.free.nrw.commons.utils.UriSerializer;
import fr.free.nrw.commons.utils.ViewUtil;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import timber.log.Timber;
@ -68,7 +62,7 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
@Inject
NearbyController nearbyController;
private LatLng curLatLang;
private LatLng curLatLng;
private Bundle bundle;
private Disposable placesDisposable;
private boolean lockNearbyView; //Determines if the nearby places needs to be refreshed
@ -136,11 +130,17 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
case R.id.action_display_list:
bottomSheetBehaviorForDetails.setState(BottomSheetBehavior.STATE_HIDDEN);
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
if(bottomSheetBehavior.getState()==BottomSheetBehavior.STATE_COLLAPSED || bottomSheetBehavior.getState()==BottomSheetBehavior.STATE_HIDDEN){
bottomSheetBehaviorForDetails.setState(BottomSheetBehavior.STATE_HIDDEN);
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}else if(bottomSheetBehavior.getState()==BottomSheetBehavior.STATE_EXPANDED){
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
}
return true;
default:
return super.onOptionsItemSelected(item);
@ -165,6 +165,11 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
showLocationPermissionDeniedErrorDialog();
}
}
break;
default:
// This is needed to allow the request codes from the Fragments to be routed appropriately
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
@ -262,8 +267,6 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
@Override
protected void onStop() {
super.onStop();
locationManager.removeLocationListener(this);
locationManager.unregisterLocationManager();
}
@Override
@ -292,8 +295,13 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
// to the retained fragment object to perform its own cleanup.
removeMapFragment();
removeListFragment();
unregisterReceiver(broadcastReceiver);
}
unregisterReceiver(broadcastReceiver);
broadcastReceiver = null;
locationManager.removeLocationListener(this);
locationManager.unregisterLocationManager();
}
private void addNetworkBroadcastReceiver() {
@ -334,12 +342,12 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
locationManager.registerLocationManager();
LatLng lastLocation = locationManager.getLastLocation();
if (curLatLang != null && curLatLang.equals(lastLocation)) { //refresh view only if location has changed
if (curLatLng != null && curLatLng.equals(lastLocation)) { //refresh view only if location has changed
return;
}
curLatLang = lastLocation;
curLatLng = lastLocation;
if (curLatLang == null) {
if (curLatLng == null) {
Timber.d("Skipping update of nearby places as location is unavailable");
return;
}
@ -348,7 +356,7 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
.equals(LocationServiceManager.LocationChangeType.LOCATION_SIGNIFICANTLY_CHANGED)) {
progressBar.setVisibility(View.VISIBLE);
placesDisposable = Observable.fromCallable(() -> nearbyController
.loadAttractionsFromLocation(curLatLang))
.loadAttractionsFromLocation(curLatLng))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::populatePlaces);
@ -357,7 +365,7 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
Gson gson = new GsonBuilder()
.registerTypeAdapter(Uri.class, new UriSerializer())
.create();
String gsonCurLatLng = gson.toJson(curLatLang);
String gsonCurLatLng = gson.toJson(curLatLng);
bundle.putString("CurLatLng", gsonCurLatLng);
updateMapFragment(true);
}
@ -370,7 +378,7 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
.registerTypeAdapter(Uri.class, new UriSerializer())
.create();
String gsonPlaceList = gson.toJson(placeList);
String gsonCurLatLng = gson.toJson(curLatLang);
String gsonCurLatLng = gson.toJson(curLatLng);
String gsonBoundaryCoordinates = gson.toJson(boundaryCoordinates);
if (placeList.size() == 0) {
@ -422,6 +430,7 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
if (nearbyMapFragment != null) {
android.support.v4.app.FragmentManager fm = getSupportFragmentManager();
fm.beginTransaction().remove(nearbyMapFragment).commit();
nearbyMapFragment = null;
}
}
@ -433,6 +442,7 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
if (nearbyListFragment != null) {
android.support.v4.app.FragmentManager fm = getSupportFragmentManager();
fm.beginTransaction().remove(nearbyListFragment).commit();
nearbyListFragment = null;
}
}
@ -447,34 +457,34 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
NearbyMapFragment nearbyMapFragment = getMapFragment();
if (nearbyMapFragment != null && curLatLang != null) {
if (nearbyMapFragment != null && curLatLng != null) {
hideProgressBar(); // In case it is visible (this happens, not an impossible case)
/*
* If we are close to nearby places boundaries, we need a significant update to
* get new nearby places. Check order is south, north, west, east
* */
if (nearbyMapFragment.boundaryCoordinates != null
&& (curLatLang.getLatitude() <= nearbyMapFragment.boundaryCoordinates[0].getLatitude()
|| curLatLang.getLatitude() >= nearbyMapFragment.boundaryCoordinates[1].getLatitude()
|| curLatLang.getLongitude() <= nearbyMapFragment.boundaryCoordinates[2].getLongitude()
|| curLatLang.getLongitude() >= nearbyMapFragment.boundaryCoordinates[3].getLongitude())) {
&& (curLatLng.getLatitude() <= nearbyMapFragment.boundaryCoordinates[0].getLatitude()
|| curLatLng.getLatitude() >= nearbyMapFragment.boundaryCoordinates[1].getLatitude()
|| curLatLng.getLongitude() <= nearbyMapFragment.boundaryCoordinates[2].getLongitude()
|| curLatLng.getLongitude() >= nearbyMapFragment.boundaryCoordinates[3].getLongitude())) {
// populate places
placesDisposable = Observable.fromCallable(() -> nearbyController
.loadAttractionsFromLocation(curLatLang))
.loadAttractionsFromLocation(curLatLng))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::populatePlaces);
nearbyMapFragment.setArguments(bundle);
nearbyMapFragment.setBundleForUpdtes(bundle);
nearbyMapFragment.updateMapSignificantly();
updateListFragment();
return;
}
if (isSlightUpdate) {
nearbyMapFragment.setArguments(bundle);
nearbyMapFragment.setBundleForUpdtes(bundle);
nearbyMapFragment.updateMapSlightly();
} else {
nearbyMapFragment.setArguments(bundle);
nearbyMapFragment.setBundleForUpdtes(bundle);
nearbyMapFragment.updateMapSignificantly();
updateListFragment();
}
@ -488,7 +498,7 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
}
private void updateListFragment() {
nearbyListFragment.setArguments(bundle);
nearbyListFragment.setBundleForUpdates(bundle);
nearbyListFragment.updateNearbyListSignificantly();
}

View file

@ -54,41 +54,47 @@ public class NearbyController {
}
List<Place> places = nearbyPlaces.getFromWikidataQuery(curLatLng, Locale.getDefault().getLanguage());
LatLng[] boundaryCoordinates = {places.get(0).location, // south
places.get(0).location, // north
places.get(0).location, // west
places.get(0).location};// east, init with a random location
if (places.size() > 0) {
LatLng[] boundaryCoordinates = {places.get(0).location, // south
places.get(0).location, // north
places.get(0).location, // west
places.get(0).location};// east, init with a random location
if (curLatLng != null) {
Timber.d("Sorting places by distance...");
final Map<Place, Double> distances = new HashMap<>();
for (Place place: places) {
distances.put(place, computeDistanceBetween(place.location, curLatLng));
// Find boundaries with basic find max approach
if (place.location.getLatitude() < boundaryCoordinates[0].getLatitude()) {
boundaryCoordinates[0] = place.location;
}
if (place.location.getLatitude() > boundaryCoordinates[1].getLatitude()) {
boundaryCoordinates[1] = place.location;
}
if (place.location.getLongitude() < boundaryCoordinates[2].getLongitude()) {
boundaryCoordinates[2] = place.location;
}
if (place.location.getLongitude() > boundaryCoordinates[3].getLongitude()) {
boundaryCoordinates[3] = place.location;
}
}
Collections.sort(places,
(lhs, rhs) -> {
double lhsDistance = distances.get(lhs);
double rhsDistance = distances.get(rhs);
return (int) (lhsDistance - rhsDistance);
if (curLatLng != null) {
Timber.d("Sorting places by distance...");
final Map<Place, Double> distances = new HashMap<>();
for (Place place : places) {
distances.put(place, computeDistanceBetween(place.location, curLatLng));
// Find boundaries with basic find max approach
if (place.location.getLatitude() < boundaryCoordinates[0].getLatitude()) {
boundaryCoordinates[0] = place.location;
}
);
if (place.location.getLatitude() > boundaryCoordinates[1].getLatitude()) {
boundaryCoordinates[1] = place.location;
}
if (place.location.getLongitude() < boundaryCoordinates[2].getLongitude()) {
boundaryCoordinates[2] = place.location;
}
if (place.location.getLongitude() > boundaryCoordinates[3].getLongitude()) {
boundaryCoordinates[3] = place.location;
}
}
Collections.sort(places,
(lhs, rhs) -> {
double lhsDistance = distances.get(lhs);
double rhsDistance = distances.get(rhs);
return (int) (lhsDistance - rhsDistance);
}
);
}
nearbyPlacesInfo.placeList = places;
nearbyPlacesInfo.boundaryCoordinates = boundaryCoordinates;
return nearbyPlacesInfo;
}
else {
return null;
}
nearbyPlacesInfo.placeList = places;
nearbyPlacesInfo.boundaryCoordinates = boundaryCoordinates;
return nearbyPlacesInfo;
}
/**

View file

@ -33,6 +33,8 @@ import static android.app.Activity.RESULT_OK;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
public class NearbyListFragment extends DaggerFragment {
private Bundle bundleForUpdates; // Carry information from activity about changed nearby places and current location
private static final Type LIST_TYPE = new TypeToken<List<Place>>() {
}.getType();
private static final Type CUR_LAT_LNG_TYPE = new TypeToken<LatLng>() {
@ -80,8 +82,7 @@ public class NearbyListFragment extends DaggerFragment {
}
public void updateNearbyListSignificantly() {
Bundle bundle = this.getArguments();
adapterFactory.updateAdapterData(getPlaceListFromBundle(bundle),
adapterFactory.updateAdapterData(getPlaceListFromBundle(bundleForUpdates),
(RVRendererAdapter<Place>) recyclerView.getAdapter());
}
@ -106,8 +107,8 @@ public class NearbyListFragment extends DaggerFragment {
Timber.d("onRequestPermissionsResult: req code = " + " perm = " + permissions + " grant =" + grantResults);
switch (requestCode) {
// 1 = "Read external storage" allowed when gallery selected
case 1: {
// 4 = "Read external storage" allowed when gallery selected
case 4: {
if (grantResults.length > 0 && grantResults[0] == PERMISSION_GRANTED) {
Timber.d("Call controller.startGalleryPick()");
controller.startGalleryPick();
@ -115,8 +116,8 @@ public class NearbyListFragment extends DaggerFragment {
}
break;
// 3 = "Write external storage" allowed when camera selected
case 3: {
// 5 = "Write external storage" allowed when camera selected
case 5: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Timber.d("Call controller.startCameraCapture()");
controller.startCameraCapture();
@ -140,4 +141,8 @@ public class NearbyListFragment extends DaggerFragment {
}
}
public void setBundleForUpdates(Bundle bundleForUpdates) {
this.bundleForUpdates = bundleForUpdates;
}
}

View file

@ -53,8 +53,10 @@ import javax.inject.Named;
import dagger.android.support.DaggerFragment;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.Utils;
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 static android.app.Activity.RESULT_OK;
@ -97,6 +99,7 @@ public class NearbyMapFragment extends DaggerFragment {
private Animation fab_open;
private Animation rotate_forward;
private ContributionController controller;
private DirectUpload directUpload;
private Place place;
private Marker selected;
@ -105,7 +108,10 @@ public class NearbyMapFragment extends DaggerFragment {
private PolygonOptions currentLocationPolygonOptions;
private boolean isBottomListSheetExpanded;
private final double CAMERA_TARGET_SHIFT_FACTOR = 0.06;
private final double CAMERA_TARGET_SHIFT_FACTOR_PORTRAIT = 0.06;
private final double CAMERA_TARGET_SHIFT_FACTOR_LANDSCAPE = 0.04;
private Bundle bundleForUpdtes;// Carry information from activity about changed nearby places and current location
@Inject
@Named("prefs")
@ -120,6 +126,10 @@ public class NearbyMapFragment extends DaggerFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
controller = new ContributionController(this);
directUpload = new DirectUpload(this, controller);
Bundle bundle = this.getArguments();
Gson gson = new GsonBuilder()
.registerTypeAdapter(Uri.class, new UriDeserializer())
@ -184,14 +194,12 @@ public class NearbyMapFragment extends DaggerFragment {
}
public void updateMapSlightly() {
// Get arguments from bundle for new location
Bundle bundle = this.getArguments();
if (mapboxMap != null) {
Gson gson = new GsonBuilder()
.registerTypeAdapter(Uri.class, new UriDeserializer())
.create();
if (bundle != null) {
String gsonLatLng = bundle.getString("CurLatLng");
if (bundleForUpdtes != null) {
String gsonLatLng = bundleForUpdtes.getString("CurLatLng");
Type curLatLngType = new TypeToken<fr.free.nrw.commons.location.LatLng>() {}.getType();
curLatLng = gson.fromJson(gsonLatLng, curLatLngType);
}
@ -201,17 +209,15 @@ public class NearbyMapFragment extends DaggerFragment {
}
public void updateMapSignificantly() {
Bundle bundle = this.getArguments();
if (mapboxMap != null) {
if (bundle != null) {
if (bundleForUpdtes != null) {
Gson gson = new GsonBuilder()
.registerTypeAdapter(Uri.class, new UriDeserializer())
.create();
String gsonPlaceList = bundle.getString("PlaceList");
String gsonLatLng = bundle.getString("CurLatLng");
String gsonBoundaryCoordinates = bundle.getString("BoundaryCoord");
String gsonPlaceList = bundleForUpdtes.getString("PlaceList");
String gsonLatLng = bundleForUpdtes.getString("CurLatLng");
String gsonBoundaryCoordinates = bundleForUpdtes.getString("BoundaryCoord");
Type listType = new TypeToken<List<Place>>() {}.getType();
List<Place> placeList = gson.fromJson(gsonPlaceList, listType);
Type curLatLngType = new TypeToken<fr.free.nrw.commons.location.LatLng>() {}.getType();
@ -253,13 +259,28 @@ public class NearbyMapFragment extends DaggerFragment {
}
// Make camera to follow user on location change
CameraPosition position = new CameraPosition.Builder()
.target(isBottomListSheetExpanded ?
new LatLng(curMapBoxLatLng.getLatitude()- CAMERA_TARGET_SHIFT_FACTOR,
curMapBoxLatLng.getLongitude())
: curMapBoxLatLng ) // Sets the new camera position
.zoom(mapboxMap.getCameraPosition().zoom) // Same zoom level
.build();
CameraPosition position ;
if(ViewUtil.isPortrait(getActivity())){
position = new CameraPosition.Builder()
.target(isBottomListSheetExpanded ?
new LatLng(curMapBoxLatLng.getLatitude()- CAMERA_TARGET_SHIFT_FACTOR_PORTRAIT,
curMapBoxLatLng.getLongitude())
: curMapBoxLatLng ) // Sets the new camera position
.zoom(isBottomListSheetExpanded ?
11 // zoom level is fixed to 11 when bottom sheet is expanded
:mapboxMap.getCameraPosition().zoom) // Same zoom level
.build();
}else {
position = new CameraPosition.Builder()
.target(isBottomListSheetExpanded ?
new LatLng(curMapBoxLatLng.getLatitude()- CAMERA_TARGET_SHIFT_FACTOR_LANDSCAPE,
curMapBoxLatLng.getLongitude())
: curMapBoxLatLng ) // Sets the new camera position
.zoom(isBottomListSheetExpanded ?
11 // zoom level is fixed to 11 when bottom sheet is expanded
:mapboxMap.getCameraPosition().zoom) // Same zoom level
.build();
}
mapboxMap.animateCamera(CameraUpdateFactory
.newCameraPosition(position), 1000);
@ -273,12 +294,21 @@ public class NearbyMapFragment extends DaggerFragment {
if (mapboxMap != null && curLatLng != null) {
if (isBottomListSheetExpanded) {
// Make camera to follow user on location change
position = new CameraPosition.Builder()
.target(new LatLng(curLatLng.getLatitude() - CAMERA_TARGET_SHIFT_FACTOR,
curLatLng.getLongitude())) // Sets the new camera target above
// current to make it visible when sheet is expanded
.zoom(11) // Same zoom level
.build();
if(ViewUtil.isPortrait(getActivity())) {
position = new CameraPosition.Builder()
.target(new LatLng(curLatLng.getLatitude() - CAMERA_TARGET_SHIFT_FACTOR_PORTRAIT,
curLatLng.getLongitude())) // Sets the new camera target above
// current to make it visible when sheet is expanded
.zoom(11) // Fixed zoom level
.build();
} else {
position = new CameraPosition.Builder()
.target(new LatLng(curLatLng.getLatitude() - CAMERA_TARGET_SHIFT_FACTOR_LANDSCAPE,
curLatLng.getLongitude())) // Sets the new camera target above
// current to make it visible when sheet is expanded
.zoom(11) // Fixed zoom level
.build();
}
} else {
// Make camera to follow user on location change
@ -344,10 +374,29 @@ public class NearbyMapFragment extends DaggerFragment {
fabRecenter.setOnClickListener(view -> {
if (curLatLng != null) {
mapView.getMapAsync(mapboxMap -> {
CameraPosition position = new CameraPosition.Builder()
.target(new LatLng(curLatLng.getLatitude(), curLatLng.getLongitude())) // Sets the new camera position
.zoom(11) // Sets the zoom
.build(); // Creates a CameraPosition from the builder
CameraPosition position;
if(ViewUtil.isPortrait(getActivity())){
position = new CameraPosition.Builder()
.target(isBottomListSheetExpanded ?
new LatLng(curLatLng.getLatitude()- CAMERA_TARGET_SHIFT_FACTOR_PORTRAIT,
curLatLng.getLongitude())
: new LatLng(curLatLng.getLatitude(), curLatLng.getLongitude(), 0)) // Sets the new camera position
.zoom(isBottomListSheetExpanded ?
11 // zoom level is fixed to 11 when bottom sheet is expanded
:mapboxMap.getCameraPosition().zoom) // Same zoom level
.build();
}else {
position = new CameraPosition.Builder()
.target(isBottomListSheetExpanded ?
new LatLng(curLatLng.getLatitude()- CAMERA_TARGET_SHIFT_FACTOR_LANDSCAPE,
curLatLng.getLongitude())
: new LatLng(curLatLng.getLatitude(), curLatLng.getLongitude(), 0)) // Sets the new camera position
.zoom(isBottomListSheetExpanded ?
11 // zoom level is fixed to 11 when bottom sheet is expanded
:mapboxMap.getCameraPosition().zoom) // Same zoom level
.build();
}
mapboxMap.animateCamera(CameraUpdateFactory
.newCameraPosition(position), 1000);
@ -406,6 +455,8 @@ public class NearbyMapFragment extends DaggerFragment {
private void setupMapView(Bundle savedInstanceState) {
MapboxMapOptions options = new MapboxMapOptions()
.compassGravity(Gravity.BOTTOM | Gravity.LEFT)
.compassMargins(new int[]{12, 0, 0, 24})
.styleUrl(Style.OUTDOORS)
.logoEnabled(false)
.attributionEnabled(false)
@ -534,7 +585,9 @@ public class NearbyMapFragment extends DaggerFragment {
transparentView.setAlpha(0);
closeFabs(isFabOpen);
hideFAB();
this.getView().requestFocus();
if (this.getView() != null) {
this.getView().requestFocus();
}
break;
}
}
@ -613,7 +666,7 @@ public class NearbyMapFragment extends DaggerFragment {
directionsButton.setOnClickListener(view -> {
//Open map app at given position
Intent mapIntent = new Intent(Intent.ACTION_VIEW, place.location.getGmmIntentUri());
Intent mapIntent = new Intent(Intent.ACTION_VIEW, this.place.location.getGmmIntentUri());
if (mapIntent.resolveActivity(getActivity().getPackageManager()) != null) {
startActivity(mapIntent);
}
@ -633,9 +686,6 @@ public class NearbyMapFragment extends DaggerFragment {
fabCamera.setOnClickListener(view -> {
if (fabCamera.isShown()) {
Timber.d("Camera button tapped. Image title: " + place.getName() + "Image desc: " + place.getLongDescription());
controller = new ContributionController(this);
DirectUpload directUpload = new DirectUpload(this, controller);
storeSharedPrefs();
directUpload.initiateCameraUpload();
}
@ -644,9 +694,6 @@ public class NearbyMapFragment extends DaggerFragment {
fabGallery.setOnClickListener(view -> {
if (fabGallery.isShown()) {
Timber.d("Gallery button tapped. Image title: " + place.getName() + "Image desc: " + place.getLongDescription());
controller = new ContributionController(this);
DirectUpload directUpload = new DirectUpload(this, controller);
storeSharedPrefs();
directUpload.initiateGalleryUpload();
}
@ -665,9 +712,10 @@ public class NearbyMapFragment extends DaggerFragment {
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
Timber.d("onRequestPermissionsResult: req code = " + " perm = " + permissions + " grant =" + grantResults);
// Do not use requestCode 1 as it will conflict with NearbyActivity's requestCodes
switch (requestCode) {
// 1 = "Read external storage" allowed when gallery selected
case 1: {
// 4 = "Read external storage" allowed when gallery selected
case 4: {
if (grantResults.length > 0 && grantResults[0] == PERMISSION_GRANTED) {
Timber.d("Call controller.startGalleryPick()");
controller.startGalleryPick();
@ -675,8 +723,8 @@ public class NearbyMapFragment extends DaggerFragment {
}
break;
// 3 = "Write external storage" allowed when camera selected
case 3: {
// 5 = "Write external storage" allowed when camera selected
case 5: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Timber.d("Call controller.startCameraCapture()");
controller.startCameraCapture();
@ -700,8 +748,7 @@ public class NearbyMapFragment extends DaggerFragment {
}
private void openWebView(Uri link) {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, link);
startActivity(browserIntent);
Utils.handleWebUrl(getContext(), link);
}
private void animateFAB(boolean isFabOpen) {
@ -724,7 +771,7 @@ public class NearbyMapFragment extends DaggerFragment {
}
}
private void closeFabs ( boolean isFabOpen){
private void closeFabs ( boolean isFabOpen){
if (isFabOpen) {
fabPlus.startAnimation(rotate_backward);
fabCamera.startAnimation(fab_close);
@ -735,6 +782,11 @@ public class NearbyMapFragment extends DaggerFragment {
}
}
public void setBundleForUpdtes(Bundle bundleForUpdtes) {
this.bundleForUpdtes = bundleForUpdtes;
}
@Override
public void onStart() {
if (mapView != null) {
@ -776,6 +828,9 @@ public class NearbyMapFragment extends DaggerFragment {
if (mapView != null) {
mapView.onDestroy();
}
selected = null;
currentLocationMarker = null;
super.onDestroyView();
}

View file

@ -27,6 +27,7 @@ import butterknife.BindView;
import butterknife.ButterKnife;
import fr.free.nrw.commons.CommonsApplication;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.Utils;
import fr.free.nrw.commons.contributions.ContributionController;
import fr.free.nrw.commons.di.ApplicationlessInjection;
import timber.log.Timber;
@ -200,8 +201,7 @@ public class PlaceRenderer extends Renderer<Place> {
}
private void openWebView(Uri link) {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, link);
view.getContext().startActivity(browserIntent);
Utils.handleWebUrl(getContext(), link);
}
private boolean showMenu() {

View file

@ -6,6 +6,7 @@ import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.design.widget.Snackbar;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
@ -15,6 +16,7 @@ import android.widget.RelativeLayout;
import com.pedrogomez.renderers.RVRendererAdapter;
import java.lang.ref.WeakReference;
import java.util.Collections;
import java.util.List;
@ -25,6 +27,7 @@ import butterknife.ButterKnife;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.Utils;
import fr.free.nrw.commons.theme.NavigationBaseActivity;
import fr.free.nrw.commons.utils.NetworkUtils;
import fr.free.nrw.commons.utils.ViewUtil;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
@ -62,9 +65,23 @@ public class NotificationActivity extends NavigationBaseActivity {
recyclerView.setLayoutManager(new LinearLayoutManager(this));
DividerItemDecoration itemDecor = new DividerItemDecoration(recyclerView.getContext(), DividerItemDecoration.VERTICAL);
recyclerView.addItemDecoration(itemDecor);
addNotifications();
refresh();
}
private void refresh() {
if (!NetworkUtils.isInternetConnectionEstablished(this)) {
progressBar.setVisibility(View.GONE);
Snackbar.make(relativeLayout , R.string.no_internet, Snackbar.LENGTH_INDEFINITE)
.setAction(R.string.retry, view -> {
refresh();
}).show();
}else {
progressBar.setVisibility(View.VISIBLE);
addNotifications();
}
}
@SuppressLint("CheckResult")
private void addNotifications() {
Timber.d("Add notifications");
@ -124,4 +141,4 @@ public class NotificationActivity extends NavigationBaseActivity {
.commit();
mNotificationWorkerFragment.setNotificationList(notificationList);
}
}
}

View file

@ -47,8 +47,8 @@ public class NotificationRenderer extends Renderer<Notification> {
@Override
public void render() {
Notification notification = getContent();
StringBuilder str = new StringBuilder(notification.notificationText.trim());
str.append(" ");
String str = notification.notificationText.trim();
str = str.concat(" ");
title.setText(str);
time.setText(notification.date);
switch (notification.notificationType) {

View file

@ -151,8 +151,9 @@ public class SettingsFragment extends PreferenceFragment {
emailSelectorIntent.setData(Uri.parse("mailto:"));
//initialize the emailIntent
final Intent emailIntent = new Intent(Intent.ACTION_SEND);
emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[]{CommonsApplication.FEEDBACK_EMAIL});
emailIntent.putExtra(Intent.EXTRA_SUBJECT, String.format(CommonsApplication.FEEDBACK_EMAIL_SUBJECT, BuildConfig.VERSION_NAME));
// Logs must be sent to the PRIVATE email. Please do not modify this without good reason!
emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[]{CommonsApplication.LOGS_PRIVATE_EMAIL});
emailIntent.putExtra(Intent.EXTRA_SUBJECT, String.format(CommonsApplication.LOGS_PRIVATE_EMAIL_SUBJECT, BuildConfig.VERSION_NAME));
emailIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
emailIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
emailIntent.setSelector( emailSelectorIntent );

View file

@ -28,6 +28,7 @@ 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.nearby.NearbyActivity;
import fr.free.nrw.commons.notification.NotificationActivity;
import fr.free.nrw.commons.settings.SettingsActivity;
@ -154,6 +155,10 @@ public abstract class NavigationBaseActivity extends BaseActivity
drawerLayout.closeDrawer(navigationView);
NotificationActivity.startYourself(this);
return true;
case R.id.action_featured_images:
drawerLayout.closeDrawer(navigationView);
startActivityWithFlags(this, FeaturedImagesActivity.class, Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
return true;
default:
Timber.e("Unknown option [%s] selected from the navigation menu", itemId);
return false;

View file

@ -1,12 +1,18 @@
package fr.free.nrw.commons.upload;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.BitmapRegionDecoder;
import android.net.Uri;
import android.os.AsyncTask;
import android.support.v7.app.AlertDialog;
import java.io.IOException;
import java.lang.ref.WeakReference;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.contributions.ContributionsActivity;
import fr.free.nrw.commons.utils.ImageUtils;
import timber.log.Timber;
@ -21,16 +27,13 @@ import timber.log.Timber;
public class DetectUnwantedPicturesAsync extends AsyncTask<Void, Void, ImageUtils.Result> {
interface Callback {
void onResult(ImageUtils.Result result);
}
private final Callback callback;
private final String imageMediaFilePath;
public final WeakReference<Activity> activityWeakReference;
DetectUnwantedPicturesAsync(String imageMediaFilePath, Callback callback) {
this.callback = callback;
DetectUnwantedPicturesAsync(WeakReference<Activity> activityWeakReference, String imageMediaFilePath) {
//this.callback = callback;
this.imageMediaFilePath = imageMediaFilePath;
this.activityWeakReference = activityWeakReference;
}
@Override
@ -53,7 +56,29 @@ public class DetectUnwantedPicturesAsync extends AsyncTask<Void, Void, ImageUtil
@Override
protected void onPostExecute(ImageUtils.Result result) {
super.onPostExecute(result);
//callback to UI so that it can take necessary decision based on the result obtained
callback.onResult(result);
Activity activity = activityWeakReference.get();
if (result != ImageUtils.Result.IMAGE_OK) {
//show appropriate error message
String errorMessage = result == ImageUtils.Result.IMAGE_DARK ? activity.getString(R.string.upload_image_too_dark) : activity.getString(R.string.upload_image_blurry);
AlertDialog.Builder errorDialogBuilder = new AlertDialog.Builder(activity);
errorDialogBuilder.setMessage(errorMessage);
errorDialogBuilder.setTitle(activity.getString(R.string.warning));
errorDialogBuilder.setPositiveButton(activity.getString(R.string.no), (dialogInterface, i) -> {
//user does not wish to upload the picture, take them back to ContributionsActivity
Intent intent = new Intent(activity, ContributionsActivity.class);
dialogInterface.dismiss();
activity.startActivity(intent);
});
errorDialogBuilder.setNegativeButton(activity.getString(R.string.yes), (dialogInterface, i) -> {
//user wishes to go ahead with the upload of this picture, just dismiss this dialog
dialogInterface.dismiss();
});
AlertDialog errorDialog = errorDialogBuilder.create();
if (!activity.isFinishing()) {
errorDialog.show();
}
}
}
}

View file

@ -237,7 +237,7 @@ public class MultipleShareActivity extends AuthenticatedActivity
private void showDetail(int i) {
if (mediaDetails == null || !mediaDetails.isVisible()) {
mediaDetails = new MediaDetailPagerFragment(true);
mediaDetails = new MediaDetailPagerFragment(true, false);
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.uploadsFragmentContainer, mediaDetails)

View file

@ -415,31 +415,9 @@ public class ShareActivity
private void performUnwantedPictureDetectionProcess() {
String imageMediaFilePath = FileUtils.getPath(this,mediaUri);
DetectUnwantedPicturesAsync detectUnwantedPicturesAsync = new DetectUnwantedPicturesAsync(imageMediaFilePath, result -> {
if (result != ImageUtils.Result.IMAGE_OK) {
//show appropriate error message
String errorMessage = result == ImageUtils.Result.IMAGE_DARK ? getString(R.string.upload_image_too_dark) : getString(R.string.upload_image_blurry);
AlertDialog.Builder errorDialogBuilder = new AlertDialog.Builder(this);
errorDialogBuilder.setMessage(errorMessage);
errorDialogBuilder.setTitle(getString(R.string.warning));
errorDialogBuilder.setPositiveButton(getString(R.string.no), (dialogInterface, i) -> {
//user does not wish to upload the picture, take them back to ContributionsActivity
Intent intent = new Intent(ShareActivity.this, ContributionsActivity.class);
dialogInterface.dismiss();
startActivity(intent);
});
errorDialogBuilder.setNegativeButton(getString(R.string.yes), (dialogInterface, i) -> {
//user wishes to go ahead with the upload of this picture, just dismiss this dialog
dialogInterface.dismiss();
});
AlertDialog errorDialog = errorDialogBuilder.create();
if (!isFinishing()) {
errorDialog.show();
}
}
});
DetectUnwantedPicturesAsync detectUnwantedPicturesAsync
= new DetectUnwantedPicturesAsync(new WeakReference<Activity>(this)
, imageMediaFilePath);
detectUnwantedPicturesAsync.execute();
}

View file

@ -14,7 +14,9 @@ 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.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
@ -225,18 +227,6 @@ public class SingleUploadFragment extends CommonsDaggerSupportFragment {
.commit();
}
@OnTouch(R.id.share_license_summary)
boolean showLicence(View view, MotionEvent motionEvent) {
if (motionEvent.getActionMasked() == ACTION_DOWN) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(Uri.parse(licenseUrlFor(license)));
startActivity(intent);
return true;
} else {
return false;
}
}
@OnClick(R.id.titleDescButton)
void setTitleDescButton() {
@ -294,8 +284,10 @@ public class SingleUploadFragment extends CommonsDaggerSupportFragment {
@SuppressLint("StringFormatInvalid")
private void setLicenseSummary(String license) {
licenseSummaryView.setText(getString(R.string.share_license_summary, getString(Utils.licenseNameFor(license))));
}
String licenseHyperLink = "<a href='" + licenseUrlFor(license)+"'>"+ getString(Utils.licenseNameFor(license)) + "</a><br>";
licenseSummaryView.setMovementMethod(LinkMovementMethod.getInstance());
licenseSummaryView.setText(Html.fromHtml(getString(R.string.share_license_summary, licenseHyperLink)));
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {

View file

@ -9,7 +9,7 @@ public class NetworkUtils {
public static boolean isInternetConnectionEstablished(Context context) {
ConnectivityManager cm =
(ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
(ConnectivityManager)context.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
return activeNetwork != null &&

View file

@ -1,7 +1,9 @@
package fr.free.nrw.commons.utils;
import android.app.Activity;
import android.content.Context;
import android.support.design.widget.Snackbar;
import android.view.Display;
import android.view.View;
import android.widget.Toast;
@ -16,4 +18,13 @@ public class ViewUtil {
Toast.LENGTH_LONG).show();
}
public static boolean isPortrait(Context context) {
Display orientation = ((Activity)context).getWindowManager().getDefaultDisplay();
if(orientation.getWidth() < orientation.getHeight()){
return true;
} else {
return false;
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

View file

@ -0,0 +1,5 @@
<vector android:alpha="0.84" android:height="32dp"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="32dp" 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

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M12,17.27L18.18,21l-1.64,-7.03L22,9.24l-7.19,-0.61L12,2 9.19,8.63 2,9.24l5.46,4.73L5.82,21z"/>
</vector>

View file

@ -111,7 +111,7 @@
android:layout_marginTop="@dimen/standard_gap"
android:gravity="center"
android:textColor="@color/primaryColor"
android:text="@string/about_rate_us" />
/>
<TextView
android:id="@+id/about_privacy_policy"
@ -121,7 +121,7 @@
android:layout_marginTop="@dimen/standard_gap"
android:textColor="@color/primaryColor"
android:gravity="center"
android:text="@string/about_privacy_policy" />
/>
<TextView
android:id="@+id/about_translate"
@ -131,7 +131,7 @@
android:textColor="@color/primaryColor"
android:layout_marginTop="@dimen/standard_gap"
android:gravity="center"
android:text="@string/about_translate" />
/>
<TextView
android:id="@+id/about_credits"
@ -141,7 +141,7 @@
android:textColor="@color/primaryColor"
android:layout_marginTop="@dimen/standard_gap"
android:gravity="center"
android:text="@string/about_credits" />
/>
<TextView
android:id="@+id/about_faq"
@ -153,15 +153,6 @@
android:gravity="center"
/>
<TextView
android:id="@+id/about_uploads_to"
style="?android:textAppearanceSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/large_gap"
android:alpha="0.2"
android:gravity="center" />
</LinearLayout>
</RelativeLayout>
</ScrollView>

View file

@ -0,0 +1,44 @@
<?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"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<include
android:id="@+id/toolbar"
layout="@layout/toolbar"
android:layout_width="match_parent"
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: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>
<android.support.design.widget.NavigationView
android:id="@+id/navigation_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="@layout/drawer_header"
app:menu="@menu/drawer"/>
</android.support.v4.widget.DrawerLayout>

View file

@ -14,6 +14,7 @@
android:id="@+id/welcomePagerIndicator"
android:layout_height="@dimen/half_standard_height"
android:layout_width="match_parent"
android:layout_gravity="bottom" />
android:layout_gravity="bottom"
android:padding="5dp" />
</FrameLayout>

View file

@ -37,8 +37,11 @@
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp" />
android:textSize="16sp"
android:layout_marginRight="50dp"
android:maxLines="2"
android:ellipsize="end"
/>
<TextView
android:id="@+id/category"
android:layout_width="wrap_content"
@ -189,4 +192,4 @@
android:textSize="16sp" />
</LinearLayout>
</LinearLayout>

View file

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
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:layout_gravity="center"
android:visibility="gone"
android:layout_centerHorizontal="true"
/>
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:visibility="gone"
android:id="@+id/loadingFeaturedImagesProgressBar"
/>
<GridView
android:id="@+id/featuredImagesList"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:stretchMode="columnWidth"
android:columnWidth="240dp"
android:numColumns="auto_fit"
android:listSelector="@null"
android:fadingEdge="none"
android:fastScrollEnabled="true"
/>
</RelativeLayout>

View file

@ -80,6 +80,39 @@
android:textSize="@dimen/description_text_size" />
</LinearLayout>
<fr.free.nrw.commons.media.MediaDetailSpacer
android:layout_width="match_parent"
android:layout_height="@dimen/small_gap" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/authorLinearLayout"
android:background="?attr/subBackground"
android:orientation="vertical"
android:padding="@dimen/standard_gap">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/tiny_gap"
android:text="@string/media_detail_author"
android:textColor="@android:color/white"
android:textSize="@dimen/normal_text"
android:textStyle="bold" />
<TextView
android:id="@+id/mediaDetailAuthor"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:background="?attr/subBackground"
android:padding="@dimen/small_gap"
android:text="@string/media_detail_author_explanation"
android:textColor="@android:color/white"
android:textSize="@dimen/description_text_size" />
</LinearLayout>
<fr.free.nrw.commons.media.MediaDetailSpacer
android:layout_width="match_parent"
android:layout_height="@dimen/small_gap" />

View file

@ -74,6 +74,8 @@
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/standard_gap"
android:gravity="center"
android:clickable="true"
android:textColorLink="@color/button_blue"
android:text="@string/share_license_summary" />
<fr.free.nrw.commons.ui.widget.HtmlTextView

View file

@ -51,5 +51,6 @@
app:colorClickableText="#969494"
android:textAppearance="@style/TextAppearance.AppCompat.Body2"
tools:text="@string/placeholder_place_name"
android:padding="12dp"
/>
</RelativeLayout>

View file

@ -0,0 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="2dp"
android:paddingBottom="0dp"
>
<TextView
android:id="@+id/featuredImagesSequenceNumber"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="98sp"
android:textColor="#33FFFFFF"
android:typeface="serif"
android:layout_gravity="end|bottom"
/>
<fr.free.nrw.commons.MediaWikiImageView
android:id="@+id/featuredImageView"
android:layout_width="match_parent"
android:layout_height="240dp"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center|bottom"
android:background="#AA000000"
android:orientation="vertical"
android:padding="@dimen/small_gap"
>
<ProgressBar
android:id="@+id/featuredProgress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/ProgressBar"
android:indeterminateOnly="false"
android:max="100"
android:visibility="gone"
/>
<TextView
android:id="@+id/featuredImageTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FFFFFFFF"
style="?android:textAppearanceLarge"
android:maxLines="1"
android:ellipsize="end"
/>
<TextView
android:id="@+id/featuredImageAuthor"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FFFFFFFF"
style="?android:textAppearanceMedium"
android:maxLines="1"
android:ellipsize="end"
/>
</LinearLayout>
</FrameLayout>

View file

@ -9,4 +9,5 @@
android:minHeight="?attr/actionBarSize"
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
android:background="?attr/colorPrimaryDark">
</android.support.v7.widget.Toolbar>

View file

@ -9,6 +9,12 @@
android:id="@+id/action_nearby"
android:icon="@drawable/ic_location_black_24dp"
android:title="@string/navigation_item_nearby" />
<item
android:id="@+id/action_featured_images"
android:icon="@drawable/ic_star_black_24dp"
android:title="@string/navigation_item_featured_images"/>
</group>
<group android:id="@+id/drawer_account">
<item

View file

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity"
>
<item
android:id="@+id/share_app_icon"
android:title="@string/refresh_button"
android:icon="@drawable/ic_share_black_24dp"
android:orderInCategory="1"
app:showAsAction="ifRoom"
/>
</menu>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Андрей
-->
<resources>
<string name="crash_dialog_title">Аиҧҟьара</string>
<string name="crash_dialog_ok_toast">Иҭабуп!</string>

View file

@ -1,4 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Envlh
* Андрей
-->
<resources>
<string name="menu_settings">Архиарақәа</string>
<string name="username">Ахархәаҩ ихьӡ</string>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Naudefj
-->
<resources>
<string name="crash_dialog_title">Commons het omgeval</string>
<string name="crash_dialog_text">Oeps. Er is iets misgegaan.</string>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Akamycoco
-->
<resources>
<string name="crash_dialog_ok_toast">kukay</string>
</resources>

View file

@ -1,4 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Ali1
* Mido
-->
<resources>
<string name="crash_dialog_title">لقد تعطل كومنز</string>
<string name="crash_dialog_text">عفوا. حدث خطأ!</string>

View file

@ -1,4 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Ali1
* Antime
* Azouz.anis
* ButterflyOfFire
* Claw eg
* Meno25
* Mido
* Monrokhoury
* Mr. Ibrahem
* OsamaK
* ترجمان05
* محمد أحمد عبد الفتاح
* مشعل الحربي
-->
<resources>
<string name="preference_category_general">عام</string>
<string name="app_name">كومنز</string>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Man2fly2002
-->
<resources>
<string name="crash_dialog_ok_toast">ܬܘܕܝ ܠܟ!</string>
</resources>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Xuacu
-->
<resources>
<string name="crash_dialog_title">Commons colgóse</string>
<string name="crash_dialog_text">Vaya. ¡Daqué funcionó mal!</string>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Xuacu
-->
<resources>
<string name="preference_category_appearance">Aspeutu</string>
<string name="preference_category_general">Xeneral</string>
@ -59,6 +62,7 @@
<string name="categories_search_text_hint">Guetar categoríes</string>
<string name="menu_save_categories">Guardar</string>
<string name="refresh_button">Refrescar</string>
<string name="display_list_button">Llista</string>
<string name="gps_disabled">El GPS ta desactiváu nel preséu. ¿Quiés activalu?</string>
<string name="enable_gps">Activar GPS</string>
<string name="contributions_subtitle_zero">Inda nun hai xubes</string>
@ -151,8 +155,8 @@
<string name="detail_description_empty">Ensin descripción</string>
<string name="detail_license_empty">Llicencia desconocida</string>
<string name="menu_refresh">Refrescar</string>
<string name="read_storage_permission_rationale">Permisu riquíu: llectura d\'almacenamientu esternu. L\'aplicación nun puede funcionar ensin él.</string>
<string name="write_storage_permission_rationale">Permisu riquíu: escritura d\'almacenamientu esternu. L\'aplicación nun puede funcionar ensin él.</string>
<string name="read_storage_permission_rationale">Permisu riquíu: llectura d\'almacenamientu esternu. L\'aplicación nun puede entrar na to galería ensin él.</string>
<string name="write_storage_permission_rationale">Permisu necesariu: Escritura n\'almacenamientu esternu. L\'aplicación nun puede aportar a la cámara ensin él.</string>
<string name="location_permission_rationale">Permisu opcional: llograr l\'allugamientu actual pa suxerir categoríes</string>
<string name="ok">Aceutar</string>
<string name="title_activity_nearby">Llugares cercanos</string>
@ -211,6 +215,7 @@
<string name="no_description_found">nun s\'atoparon descripciones</string>
<string name="nearby_info_menu_commons_article">Páxina del ficheru en Commons</string>
<string name="nearby_info_menu_wikidata_article">Elementu de WikiData</string>
<string name="nearby_info_menu_wikipedia_article">Artículu de Wikipedia</string>
<string name="error_while_cache">Error al poner les fotos na caché</string>
<string name="title_info">Un títulu descriptivu únicu pal ficheru, que sirvirá para da-y nome al ficheru. Se pue usar llinguax normal con espacios. Nun amiestes la estensión del ficheru</string>
<string name="description_info">Por favor, describi l\'elementu multimedia tantu como sía posible: ¿ónde se tomó?, ¿qué amuesa?, ¿cuál ye\'l contestu? Por favor, describi los oxetos o persones. Revela la información que nun pueda aldovinase de mou cenciellu, por casu el momentu del día si ye un paisaxe. Si\'l mediu amuesa daqué desacostumao, esplica qué lo fai raro.</string>
@ -224,6 +229,9 @@
<string name="send_log_file_description">Unviar ficheru de rexistru a los desendolcadores per corréu electrónicu</string>
<string name="no_web_browser">Nun s\'alcontró un restolador p\'abrir la URL</string>
<string name="null_url">¡Error! Nun s\'alcontró la URL</string>
<string name="nominate_deletion">Marcada pa desaniciar</string>
<string name="nominated_for_deletion">Esta imaxe marcóse pa desaniciar.</string>
<string name="view_browser">Ver nel restolador</string>
<string name="nearby_location_has_not_changed">L\'allugamientu nun camudó.</string>
<string name="nearby_location_not_available">L\'allugamientu nun ta disponible.</string>
<string name="location_permission_rationale_nearby">Ríquese permisu p\'amosar una llista de llugares cercanos</string>
@ -234,6 +242,21 @@
<string name="notifications_thank_you_edit">Gracies por facer una edición</string>
<string name="notifications_mention">%1$s te mentó en %2$s.</string>
<string name="toggle_view_button">Alternar vista</string>
<string name="about_faq">Entrugues más frecuentes</string>
<string name="nearby_directions">CÓMO LLEGAR</string>
<string name="nearby_wikidata">WIKIDATA</string>
<string name="nearby_wikipedia">WIKIPEDIA</string>
<string name="nearby_commons">COMMONS</string>
<string name="about_rate_us">&lt;u&gt;Puntúanos&lt;/u&gt;</string>
<string name="about_faq">&lt;u&gt;EMF&lt;/u&gt;</string>
<string name="welcome_skip_button">Saltar el tutorial</string>
<string name="no_internet">Internet nun ta disponible</string>
<string name="internet_established">Internet ta disponible</string>
<string name="error_notifications">Error al llograr les notificaciones</string>
<string name="no_notifications">Nun s\'alcontraron notificaciones</string>
<string name="about_translate">&lt;u&gt;Traducir&lt;/u&gt;</string>
<string name="about_translate_title">Llingües</string>
<string name="about_translate_message">Escueye l\'idioma pal que quies unviar traducciones</string>
<string name="about_translate_proceed">Siguir</string>
<string name="about_translate_cancel">Encaboxar</string>
<string name="retry">Retentar</string>
</resources>

View file

@ -1,4 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Dağlı95
* Khan27
-->
<resources>
<string name="crash_dialog_title">Nasazlıq</string>
<string name="crash_dialog_text">Uups. Nəsə düzgün çalışmır!</string>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Mousa
-->
<resources>
<string name="crash_dialog_title">کامانز ایشدن دوشدو</string>
<string name="crash_dialog_text">اوخ. بیر خطا قاباغا گلدی!</string>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Kareyac
-->
<resources>
<string name="crash_dialog_ok_toast">Дзякуем!</string>
</resources>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Thakurji
-->
<resources>
<string name="crash_dialog_title">Commons crash hoe gais</string>
<string name="crash_dialog_text">Oops, Koi chij wrong hoe gais</string>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Wikibilim
-->
<resources>
<string name="crash_dialog_ok_toast">Рақмет!</string>
</resources>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Servien
-->
<resources>
<string name="crash_dialog_title">Commons is vasteleupen</string>
<string name="crash_dialog_text">Oeps. Der gung iets mis.</string>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Joetaras
-->
<resources>
<string name="crash_dialog_title">Commons ha sckattate</string>
<string name="crash_dialog_text">Mudu. Quacchecose ha sciute male!</string>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Zoranzoki21
-->
<resources>
<string name="crash_dialog_title">Ostava se srušila</string>
<string name="crash_dialog_text">Ups! Nešto je pošlo naopako.</string>

View file

@ -1,4 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Ego and his own
* Milicevic01
* Zoranzoki21
-->
<resources>
<string name="app_name">Ostava</string>
<string name="menu_settings">Podešavanja</string>
@ -134,8 +139,8 @@
<string name="detail_description_empty">Nema opisa</string>
<string name="detail_license_empty">Nepoznata licenca</string>
<string name="menu_refresh">Osveži</string>
<string name="read_storage_permission_rationale">Potrebna dozvola: Provera spoljašnje memorije. Aplikacija bez ovoga ne može da funkcioniše.</string>
<string name="write_storage_permission_rationale">Neophodna dozvola: Pisanje spoljašnjeg skladišta. Aplikacija ne može da funkcioniše bez ovoga.</string>
<string name="read_storage_permission_rationale" fuzzy="true">Potrebna dozvola: Provera spoljašnje memorije. Aplikacija bez ovoga ne može da funkcioniše.</string>
<string name="write_storage_permission_rationale" fuzzy="true">Neophodna dozvola: Pisanje spoljašnjeg skladišta. Aplikacija ne može da funkcioniše bez ovoga.</string>
<string name="location_permission_rationale">Opciona dozvola: Preuzmi trenutnu lokaciju za predloge kategorija</string>
<string name="ok">U redu</string>
<string name="title_activity_nearby">Mesta u blizini</string>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Ibrahim
-->
<resources>
<string name="crash_dialog_ok_toast">Ташаккур!</string>
</resources>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Рустам Нурыев
-->
<resources>
<string name="crash_dialog_ok_toast">Рәхмәт!</string>
</resources>

View file

@ -1,4 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Lizalizaufa
* Sagan
* Рустам Нурыев
-->
<resources>
<string name="preference_category_appearance">Тышҡы күренеш</string>
<string name="preference_category_general">Ғәҙәти</string>
@ -149,8 +154,8 @@
<string name="detail_description_empty">Һүрәтләүе юҡ</string>
<string name="detail_license_empty">Билдәһеҙ лицензия</string>
<string name="menu_refresh">Яңыртып алыу</string>
<string name="read_storage_permission_rationale">Кәрәкле рөхсәт: тышҡы һаҡлағыстан алып уҡыу. Ҡушымта шунһыҙ эшләмәйәсәк.</string>
<string name="write_storage_permission_rationale">Кәрәкле рөхсәт: тышҡы һаҡлағысҡа яҙыу. Ҡушымта шунһыҙ эшләмәйәсәк.</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="title_activity_nearby">Яҡындағы урындар</string>
<string name="no_nearby">Яҡындағы урындар табылманы</string>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Geopoet
-->
<resources>
<string name="crash_dialog_title">Kagrugaringan nagkagarabá</string>
<string name="crash_dialog_text">Oops. May bagay an napasala!</string>

View file

@ -1,4 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* DCLXVI
* Vodnokon4e
-->
<resources>
<string name="crash_dialog_title">Неуспех с Общомедия</string>
<string name="crash_dialog_text">Опа. Нещо се обърка!</string>

View file

@ -1,4 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* DCLXVI
* MegaAlex
* StanProg
* Vodnokon4e
* АдмиралАнимЕ
-->
<resources>
<string name="app_name">Общомедия</string>
<string name="menu_settings">Настройки</string>

View file

@ -1,4 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Aftabuzzaman
* Bellayet
* Sankarshan
-->
<resources>
<string name="crash_dialog_title">কমন্স ক্র্যাশ করেছে</string>
<string name="crash_dialog_text">ওহ, কিছু একটা ত্রুটি হয়েছে!</string>

View file

@ -1,4 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Aftabuzzaman
* Bellayet
* Elias Ahmmad
* Leemon2010
* Mohammed Galib Hasan
* Muktogayn
* Rasal Lia
* Sankarshan
* Tauhid16
-->
<resources>
<string name="preference_category_appearance">অবয়ব</string>
<string name="preference_category_general">সাধারণ</string>
@ -59,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>
@ -80,6 +92,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;গিটহাব ইস্যু&lt;/a&gt; তৈরি করুন।</string>
@ -150,8 +163,8 @@
<string name="detail_description_empty">বিবরণ নেই</string>
<string name="detail_license_empty">অজানা লাইসেন্স</string>
<string name="menu_refresh">পুনঃসতেজ</string>
<string name="read_storage_permission_rationale">প্রয়োজনীয় অনুমতি: বহিঃস্ত সঞ্চয়স্থান পড়া। এটি ছাড়া অ্যাপ কাজ করবে না।</string>
<string name="write_storage_permission_rationale">অনুমতি প্রয়োজন: অালাদাভাবে সংযুক্ত স্টোরেজ লিখুন। এটি ছাড়া অ্যাপটি চলতে পারেনা।</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="ok">ঠিক আছে</string>
<string name="title_activity_nearby">কাছাকাছি স্থান</string>
@ -164,6 +177,7 @@
<string name="media_detail_media_title">মিডিয়ার শিরোনাম</string>
<string name="media_detail_description">বিবরণ</string>
<string name="media_detail_description_explanation">মিডিয়ার বিবরণ এখানে যাবে। এই মোটামুটি দীর্ঘ হতে পারে এবং একাধিক লাইনে লিখতে হতে পারে। আমরা আশা করি এটি দেখতে সুন্দর হবে।</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>
@ -206,10 +220,12 @@
<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="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>
@ -222,6 +238,8 @@
<string name="send_log_file">লগ ফাইল পাঠান</string>
<string name="send_log_file_description">ইমেইলের মাধ্যমে উন্নয়নকারীর কাছে লগ ফাইল পাঠান</string>
<string name="null_url">ত্রুটি! ইউআরএল পাওয়া যায়নি</string>
<string name="nominate_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>
@ -231,6 +249,14 @@
<string name="notifications_talk_page_message">%1$s আপনার আলাপ পাতায় একটি বার্তা দিয়েছেন</string>
<string name="notifications_thank_you_edit">একটি সম্পাদনা করার জন্য আপনাকে ধন্যবাদ</string>
<string name="notifications_mention">%1$s আপনাকে %2$s-এ উল্লেখ করেছেন।</string>
<string name="about_faq">প্রায়শই জিজ্ঞাসিত প্রশ্নসমূহ</string>
<string name="nearby_directions">দিকনির্দেশ</string>
<string name="nearby_wikidata">উইকিউপাত্ত</string>
<string name="nearby_wikipedia">উইকিপিডিয়া</string>
<string name="nearby_commons">কমন্স</string>
<string name="about_faq" fuzzy="true">প্রায়শই জিজ্ঞাসিত প্রশ্নসমূহ</string>
<string name="welcome_skip_button">টিউটোরিয়াল এড়ান</string>
<string name="no_internet">ইন্টারনেট অনুপলব্ধ</string>
<string name="internet_established">ইন্টারনেট উপলব্ধ</string>
<string name="no_notifications">কোন বিজ্ঞপ্তি পাওয়া যায়নি</string>
<string name="retry">পুনঃচেষ্টা করুন</string>
</resources>

View file

@ -1,4 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Fohanno
* Gwenn-Ael
-->
<resources>
<string name="crash_dialog_title">Commons zo aet er c\'hleuz</string>
<string name="crash_dialog_text">Hopala ! Un dra bennak a-dreuz zo bet !</string>

View file

@ -1,4 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Dishual
* Fohanno
* Fulup
* Gwenn-Ael
* Y-M D
-->
<resources>
<string name="preference_category_appearance">Neuz</string>
<string name="preference_category_general">Hollek</string>
@ -146,8 +153,8 @@
<string name="detail_description_empty">Deskrivadur ebet</string>
<string name="detail_license_empty">Aotre-implijout dizanv</string>
<string name="menu_refresh">Freskaat</string>
<string name="read_storage_permission_rationale">Aotre rekis : lenn ur stokañ diavaez. Hep se, n\'hall ket an arload mont en-dro.</string>
<string name="write_storage_permission_rationale">Aotre ret ; skrivañ war al lec\'h stokañ diavaez. Ne c\'hall ket an arload mont en-dro hep an dra-se.</string>
<string name="read_storage_permission_rationale" fuzzy="true">Aotre rekis : lenn ur stokañ diavaez. Hep se, n\'hall ket an arload mont en-dro.</string>
<string name="write_storage_permission_rationale" fuzzy="true">Aotre ret ; skrivañ war al lec\'h stokañ diavaez. Ne c\'hall ket an arload mont en-dro hep an dra-se.</string>
<string name="location_permission_rationale">Aotre diret : kaout al lec\'hiadur red evit kinnig rummadoù</string>
<string name="ok">Mat eo</string>
<string name="title_activity_nearby">Lec\'hioù nes</string>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Srdjan m
-->
<resources>
<string name="crash_dialog_title">Commons se srušio</string>
<string name="crash_dialog_text">Ups. Nešto je pošlo po zlu!</string>

View file

@ -1,4 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* CERminator
* DzWiki
* Srdjan m
-->
<resources>
<string name="app_name">Commons</string>
<string name="menu_settings">Postavke</string>
@ -133,7 +138,7 @@
<string name="detail_description_empty">Nema opisa</string>
<string name="detail_license_empty">Nepoznata licenca</string>
<string name="menu_refresh">Osvježi</string>
<string name="read_storage_permission_rationale">Potrebna dozvola: Čitanje vanjske memorije. Aplikacija ne može raditi bez ovog.</string>
<string name="read_storage_permission_rationale" fuzzy="true">Potrebna dozvola: Čitanje vanjske memorije. Aplikacija ne može raditi bez ovog.</string>
<string name="location_permission_rationale">Neobavezna dozvola: Dobavljanje trenutne lokacije za predlaganje kategorija</string>
<string name="ok">U redu</string>
<string name="title_activity_nearby">Mjesta u blizini</string>

View file

@ -1,4 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Toniher
* XVEC
-->
<resources>
<string name="crash_dialog_title">El Commons s\'ha penjat</string>
<string name="crash_dialog_text">Uups ! Quelcom ha anat malament !</string>

View file

@ -1,4 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Alvaro Vidal-Abarca
* Fitoschido
* Kippelboy
* MarionaDSR
* Pintor Smeargle
* Pitort
* Toniher
* XVEC
-->
<resources>
<string name="preference_category_appearance">Aparença</string>
<string name="preference_category_location">Ubicació</string>
@ -181,5 +191,5 @@
<string name="read_article">LLEGIU LARTICLE</string>
<string name="notifications_thank_you_edit">Gràcies per fer una modificació</string>
<string name="notifications_mention" fuzzy="true">%1$s us ha mencionat a %2$s.</string>
<string name="about_faq">Preguntes freqüents</string>
<string name="about_faq" fuzzy="true">Preguntes freqüents</string>
</resources>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Умар
-->
<resources>
<string name="crash_dialog_ok_toast">Баркалла!</string>
</resources>

View file

@ -1,6 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Chmee2
* Ilimanaq29
* Patriccck
-->
<resources>
<string name="crash_dialog_title">Commons spadly</string>
<string name="crash_dialog_title">Aplikace Commons spadla</string>
<string name="crash_dialog_text">Něco se pokazilo!</string>
<string name="crash_dialog_comment_prompt">Řekněte nám, co jste dělali a dejte nám to vědět e-mailem. Pomůže sjednat nápravu!</string>
<string name="crash_dialog_ok_toast">Děkujeme vám!</string>

View file

@ -1,4 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Aktron
* Chmee2
* Dvorapa
* Frettie
* Ilimanaq29
* Jkjk
* Leanes
* Matěj Suchánek
* Mormegil
* Patriccck
* Spotter
* Vojtěch Dostál
* Walter Klosse
-->
<resources>
<string name="preference_category_appearance">Vzhled</string>
<string name="preference_category_general">Obecné</string>
@ -59,6 +74,7 @@
<string name="categories_search_text_hint">Hledání kategorií</string>
<string name="menu_save_categories">Uložit</string>
<string name="refresh_button">Obnovit</string>
<string name="display_list_button">Seznam</string>
<string name="gps_disabled">GPS ve vašem zařízení není povoleno. Chtěli byste ho spustit?</string>
<string name="enable_gps">Spustit GPS</string>
<string name="contributions_subtitle_zero">Žádné nahrané soubory</string>
@ -151,8 +167,8 @@
<string name="detail_description_empty">Bez popisu</string>
<string name="detail_license_empty">Neznámá licence</string>
<string name="menu_refresh">Obnovit</string>
<string name="read_storage_permission_rationale">Požadováno oprávnění ke čtení externího úložiště. Aplikace bez toho nemůže pracovat.</string>
<string name="write_storage_permission_rationale">Požadováno oprávnění k zápisu do externího úložiště. Aplikace bez toho nemůže pracovat.</string>
<string name="read_storage_permission_rationale">Požadované oprávnění: Čtení externího úložiště. Bez něj nemůže aplikace číst vaši galerii.</string>
<string name="write_storage_permission_rationale">Požadované oprávnění: Zapisování do externího úložiště. Bez něj nemůže aplikace používat vaši kameru.</string>
<string name="location_permission_rationale">Volitelně: Umožněte aplikaci, aby získávala aktuální polohu a nabízela na jejím základě kategorie</string>
<string name="ok">OK</string>
<string name="title_activity_nearby">Místa v okolí</string>
@ -211,6 +227,7 @@
<string name="no_description_found">nebyl nalezen žádný popisek</string>
<string name="nearby_info_menu_commons_article">Stránka souboru na Commons</string>
<string name="nearby_info_menu_wikidata_article">Položka Wikidat</string>
<string name="nearby_info_menu_wikipedia_article">Článek na Wikipedii</string>
<string name="error_while_cache">Chyba při meziukládání obrázků</string>
<string name="title_info">Unikátní a popisný název pro daný soubor, který bude sloužit jako název souboru. Můžete použít běžný psaný jazyk s mezerami; nezahrnujte koncovku souboru.</string>
<string name="description_info">Popište prosím obrázek, jak jen to je možné: Kde byl pořízen? Co znázorňuje? Jaký je kontext obrázku? Popisujte prosím významné předměty nebo osoby na obrázku a nezapomeňte na informace, které není možné snadno odhadnout ze samotného obrázku, jako je například denní doba, pokud jde o krajinu. Pokud je na obrázku něco neobvyklého, popište, co to dělá neobvyklým.</string>
@ -225,6 +242,8 @@
<string name="no_web_browser">Nebyl nalezen žádný webový prohlížeč k otevření URL</string>
<string name="null_url">Chyba! URL nenalezeno</string>
<string name="nominate_deletion">Navrhnout na smazání</string>
<string name="nominated_for_deletion">Tento obrázek byl nominován na smazání.</string>
<string name="nominated_see_more" fuzzy="true"/>
<string name="view_browser">Zobrazit v prohlížeči</string>
<string name="nearby_location_has_not_changed">Vaše umístění se nezměnilo.</string>
<string name="nearby_location_not_available">Umístění není dostupné.</string>
@ -236,6 +255,21 @@
<string name="notifications_thank_you_edit">Děkujeme za vaši editaci</string>
<string name="notifications_mention">%1$s vás zmínil na %2$s.</string>
<string name="toggle_view_button">Přepnout pohled</string>
<string name="about_faq">Často kladené dotazy</string>
<string name="nearby_directions">POKYNY</string>
<string name="nearby_wikidata">WIKIDATA</string>
<string name="nearby_wikipedia">WIKIPEDIE</string>
<string name="nearby_commons">COMMONS</string>
<string name="about_rate_us">&lt;u&gt;Ohodnoť nás&lt;/u&gt;</string>
<string name="about_faq">&lt;u&gt;Často kladené otázky&lt;/u&gt;</string>
<string name="welcome_skip_button">Přeskočit úvod</string>
<string name="no_internet">Internet je nedostupný</string>
<string name="internet_established">Internet je dostupný</string>
<string name="error_notifications">Při načítání oznámení došlo k chybě</string>
<string name="no_notifications">Nebyly nalezeny žádné oznámení</string>
<string name="about_translate">&lt;u&gt;Přeložit&lt;/u&gt;</string>
<string name="about_translate_title">Jazyky</string>
<string name="about_translate_message">Vyberte jazyk, pro který chcete odeslat překlady</string>
<string name="about_translate_proceed">Pokračovat</string>
<string name="about_translate_cancel">Zrušit</string>
<string name="retry">Zkusit znovu</string>
</resources>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Kaszeba
-->
<resources>
<string name="crash_dialog_title">Pókôza sã fela Commons.</string>
<string name="crash_dialog_text">Wejle! Cos je lëchò pòszłé!</string>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Kaszeba
-->
<resources>
<string name="app_name">Commons</string>
<string name="menu_settings">Nastôwë</string>

View file

@ -1,4 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Lloffiwr
* Robin Owain
-->
<resources>
<string name="crash_dialog_title">Aeth rhywbeth o\'i le yn Comin</string>
<string name="crash_dialog_text">Wwwwps. Aeth rhywbeth o\'i le!</string>

View file

@ -1,4 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Cymrodor
* Lloffiwr
* Robin Owain
-->
<resources>
<string name="app_name">Comin Wicimedia</string>
<string name="menu_settings">Gosodiadau</string>

View file

@ -1,4 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Christian List
* Jsmakaayb
-->
<resources>
<string name="crash_dialog_title">Commons gik ned</string>
<string name="crash_dialog_text">Ups. Noget gik galt!</string>

View file

@ -1,4 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Christian List
* Envlh
* Joedalton
* Jsmakaayb
* Luckas
* Overlaet
-->
<resources>
<string name="preference_category_appearance">Udseende</string>
<string name="preference_category_general">Generelt</string>
@ -151,8 +159,8 @@
<string name="detail_description_empty">Ingen beskrivelse</string>
<string name="detail_license_empty">Ukendt licens</string>
<string name="menu_refresh">Opdater</string>
<string name="read_storage_permission_rationale">Krævet tilladelse: Læs eksternt lager. Programmet kan ikke fungere uden denne tilladelse.</string>
<string name="write_storage_permission_rationale">Krævet tilladelse: Skriv til eksternt lager. Program kan ikke fungere uden denne funktion.</string>
<string name="read_storage_permission_rationale" fuzzy="true">Krævet tilladelse: Læs eksternt lager. Programmet kan ikke fungere uden denne tilladelse.</string>
<string name="write_storage_permission_rationale" fuzzy="true">Krævet tilladelse: Skriv til eksternt lager. Program kan ikke fungere uden denne funktion.</string>
<string name="location_permission_rationale">Valgfri tilladelse: Hent nuværende position for kategoriforslag</string>
<string name="ok">O.k.</string>
<string name="title_activity_nearby">Steder i nærheden</string>
@ -236,6 +244,6 @@
<string name="notifications_thank_you_edit">Tak fordi du lavede en redigering</string>
<string name="notifications_mention">%1$s nævnte dig på %2$s.</string>
<string name="toggle_view_button">Skift visning</string>
<string name="about_faq">Ofte stillede spørgsmål</string>
<string name="about_faq" fuzzy="true">Ofte stillede spørgsmål</string>
<string name="welcome_skip_button">Udelad øvelse</string>
</resources>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Metalhead64
-->
<resources>
<string name="crash_dialog_title">Commons ist abgestürzt</string>
<string name="crash_dialog_text">Huch! Etwas ist schiefgelaufen.</string>

View file

@ -1,4 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Envlh
* Inkowik
* Kghbln
* Metalhead64
* Sujan
-->
<resources>
<string name="preference_category_appearance">Erscheinung</string>
<string name="preference_category_general">Allgemein</string>
@ -81,6 +88,7 @@
<string name="categories_activity_title">Kategorien</string>
<string name="title_activity_settings">Einstellungen</string>
<string name="title_activity_signup">Registrieren</string>
<string name="title_activity_featured_images">Vorgestellte Bilder</string>
<string name="menu_about">Über</string>
<string name="about_license">Die Wikimedia-Commons-App ist eine Open-Source-App, entwickelt und gewartet von Freiwilligen der Wikimedia-Gemeinschaft. Die Wikimedia Foundation ist nicht bei der Erstellung, Entwicklung oder Wartung der App beteiligt.</string>
<string name="about_improve">Einen neuen &lt;a href=\"https://github.com/commons-app/apps-android-commons/issues\"&gt;GitHub-Eintrag&lt;/a&gt; für Fehlerberichte und Vorschläge erstellen.</string>
@ -152,8 +160,8 @@
<string name="detail_description_empty">Keine Beschreibung</string>
<string name="detail_license_empty">Unbekannte Lizenz</string>
<string name="menu_refresh">Aktualisieren</string>
<string name="read_storage_permission_rationale">Erforderliche Berechtigung: Externen Speicher lesen. Die App funktioniert ohne diese Berechtigung nicht.</string>
<string name="write_storage_permission_rationale">Erforderliche Berechtigung: Externen Speicher beschreiben. Die App kann ohne dies nicht funktionieren.</string>
<string name="read_storage_permission_rationale">Erforderliche Berechtigung: Externen Speicher lesen. Die App kann ohne diese Berechtigung nicht auf deine Galerie zugreifen.</string>
<string name="write_storage_permission_rationale">Erforderliche Berechtigung: Externen Speicher beschreiben. Die App kann ohne diese Berechtigung nicht auf deine Kamera zugreifen.</string>
<string name="location_permission_rationale">Optionale Berechtigung: Ruft den aktuellen Standort für Kategorievorschläge ab</string>
<string name="ok">Okay</string>
<string name="title_activity_nearby">Orte in der Nähe</string>
@ -166,6 +174,8 @@
<string name="media_detail_media_title">Titel des Mediums</string>
<string name="media_detail_description">Beschreibung</string>
<string name="media_detail_description_explanation">Hier folgt die Beschreibung des Mediums. Diese kann möglicherweise ziemlich lang sein und erfordert dann einen Umbruch auf mehreren Zeilen. Wir hoffen, dass sie dennoch gut aussieht.</string>
<string name="media_detail_author">Autor</string>
<string name="media_detail_author_explanation">Hier steht der Benutzername des Autors des vorgestellten Bildes.</string>
<string name="media_detail_uploaded_date">Hochgeladen am</string>
<string name="media_detail_license">Lizenz</string>
<string name="media_detail_coordinates">Koordinaten</string>
@ -208,6 +218,7 @@
<string name="navigation_item_logout">Abmelden</string>
<string name="navigation_item_info">Anleitung</string>
<string name="navigation_item_notification">Benachrichtigungen</string>
<string name="navigation_item_featured_images">Vorgestellt</string>
<string name="nearby_needs_permissions">Orte in der Nähe können ohne Berechtigung zur Standortbestimmung nicht ermittelt werden</string>
<string name="no_description_found">Keine Beschreibung gefunden</string>
<string name="nearby_info_menu_commons_article">Commons-Dateiseite</string>
@ -227,6 +238,8 @@
<string name="no_web_browser">Zum Öffnen der URL wurde kein Webbrowser gefunden</string>
<string name="null_url">Fehler! URL nicht gefunden</string>
<string name="nominate_deletion">Zur Löschung vorschlagen</string>
<string name="nominated_for_deletion">Dieses Bild wurde zur Löschung vorgeschlagen.</string>
<string name="nominated_see_more"/>
<string name="view_browser">Im Browser ansehen</string>
<string name="nearby_location_has_not_changed">Der Standort hat sich nicht geändert.</string>
<string name="nearby_location_not_available">Der Standort ist nicht verfügbar.</string>
@ -242,7 +255,17 @@
<string name="nearby_wikidata">WIKIDATA</string>
<string name="nearby_wikipedia">WIKIPEDIA</string>
<string name="nearby_commons">COMMONS</string>
<string name="about_rate_us"/>
<string name="about_faq">Häufig gestellte Fragen</string>
<string name="about_rate_us">&lt;u&gt;Bewerte uns&lt;/u&gt;</string>
<string name="about_faq">&lt;u&gt;Häufig gestellte Fragen&lt;/u&gt;</string>
<string name="welcome_skip_button">Tutorial überspringen</string>
<string name="no_internet">Internet nicht verfügbar</string>
<string name="internet_established">Internet verfügbar</string>
<string name="error_notifications">Fehler beim Abruf der Benachrichtigungen</string>
<string name="no_notifications">Keine Benachrichtigungen gefunden</string>
<string name="about_translate">&lt;u&gt;Übersetzen&lt;/u&gt;</string>
<string name="about_translate_title">Sprachen</string>
<string name="about_translate_message">Wähle die Sprache aus, für die du Übersetzungen durchführen möchtest.</string>
<string name="about_translate_proceed">Fortfahren</string>
<string name="about_translate_cancel">Abbrechen</string>
<string name="retry">Erneut versuchen</string>
</resources>

View file

@ -1,7 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* 1917 Ekim Devrimi
* Gorizon
* Marmase
* Mirzali
-->
<resources>
<string name="crash_dialog_title">Commons lığiya</string>
<string name="crash_dialog_text">Oops. Thebayo nigurweyino!</string>
<string name="crash_dialog_comment_prompt">Şıma se kerd bı, marê vacê. Dıma e-posta ra bırışê marê. Ney timar kerdışi de marê beno desteg!</string>
<string name="crash_dialog_ok_toast">Teşekur kena</string>
<string name="crash_dialog_ok_toast">Teşekur kenan!</string>
</resources>

View file

@ -1,4 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* 1917 Ekim Devrimi
* Envlh
* Gambollar
* Gorizon
* Gırd
* Marmase
* Mirzali
-->
<resources>
<string name="app_name">Commons</string>
<string name="menu_settings">Eyari</string>
@ -26,7 +35,7 @@
</plurals>
<string name="title_activity_contributions">Barkerdışê mınê peyêni</string>
<string name="contribution_state_queued">Ratneya</string>
<string name="contribution_state_failed">Nêbı</string>
<string name="contribution_state_failed">Ebe ser nêkewt</string>
<string name="contribution_state_in_progress">%1$d%% temamya</string>
<string name="contribution_state_starting">Bar beno</string>
<string name="menu_from_gallery">Galeri ra</string>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Nirajan pant
-->
<resources>
<string name="crash_dialog_text">हैत्मरा। केइचीज गलत भयो।</string>
<string name="crash_dialog_ok_toast">धन्यवाद!</string>

View file

@ -1,4 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Auslaender
* Evropi
* Geraki
-->
<resources>
<string name="crash_dialog_title">Τα Commons παρουσίασαν σφάλμα</string>
<string name="crash_dialog_text">Ωχ. Κάτι πήγε στραβά!</string>

View file

@ -1,4 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Astralnet
* Evropi
* Geraki
* Glavkos
* KATRINE1992
* ManosHacker
* Nikosgranturismogt
* Nikosguard
* Tgkarounos
-->
<resources>
<string name="preference_category_appearance">Εμφάνιση</string>
<string name="preference_category_general">Γενικά</string>
@ -81,6 +92,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">Λογισμικό ανοικτού κωδικού που κυκλοφορεί υπό την &lt;a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\"&gt;Άδεια Apache v2&lt;/a&gt;. Το Wikimedia Commons και το λογότυπο είναι εμπορικά σήματα του Ιδρύματος Wikimedia και χρησιμοποιούνται με άδεια από το Ίδρυμα Wikimedia. Δεν συμμετέχουμε στην δημιουργία, ανάπτυξη ή συντήρηση του Ιδρύματος Wikimedia.</string>
<string name="about_improve">Δημιουργήστε ένα νέο &lt;a href=\"https://github.com/commons-app/apps-android-commons/issues\"&gt;GitHub θέμα&lt;/a&gt; για αναφορές σφαλμάτων και προτάσεις.</string>
@ -152,8 +164,8 @@
<string name="detail_description_empty">Καμία περιγραφή</string>
<string name="detail_license_empty">Άγνωστη άδεια</string>
<string name="menu_refresh">Ανανέωση</string>
<string name="read_storage_permission_rationale">Απαιτούμενη άδεια: Ανάγνωση εξωτερικής αποθήκευσης. Η εφαρμογή δεν μπορεί να λειτουργήσει χωρίς αυτή.</string>
<string name="write_storage_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>
@ -166,6 +178,8 @@
<string name="media_detail_media_title">Τίτλος πολυμέσου</string>
<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>
@ -208,6 +222,7 @@
<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="nearby_needs_permissions">Οι κοντινές τοποθεσίες δεν μπορούν να προβληθούν δίχως τις άδειες τοποθεσίας</string>
<string name="no_description_found">δεν βρέθηκε περιγραφή</string>
<string name="nearby_info_menu_commons_article">Σελίδα φακέλλου κοινής χρήσης</string>
@ -227,6 +242,8 @@
<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="nominated_see_more"/>
<string name="view_browser">Προβολή στον περιηγητή</string>
<string name="nearby_location_has_not_changed">Ο εντοπισμός δεν έχει αλλάξει.</string>
<string name="nearby_location_not_available">Ο τόπος δεν είναι διαθέσιμος.</string>
@ -242,7 +259,17 @@
<string name="nearby_wikidata">Βικιδεδομένα</string>
<string name="nearby_wikipedia">Βικιπαίδεια</string>
<string name="nearby_commons">Κοινά</string>
<string name="about_rate_us"/>
<string name="about_faq">Συχνές ερωτήσεις</string>
<string name="about_rate_us">&lt;u&gt;Βαθμολογήστε μας&lt;/u&gt;</string>
<string name="about_faq">&lt;u&gt;Συχνές ερωτήσεις&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>
</resources>

View file

@ -1,4 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Fitoschido
* Jduranboger
* Vivaelcelta
-->
<resources>
<string name="crash_dialog_title">Commons falló</string>
<string name="crash_dialog_text">Vaya. ¡Algo salió mal!</string>

View file

@ -1,4 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* 2axterix2
* Benfutbol10
* Fitoschido
* Jduranboger
* Luisangelrg
* Macofe
* MarionaDSR
* Miguel2706
* Vivaelcelta
-->
<resources>
<string name="preference_category_appearance">Apariencia</string>
<string name="preference_category_general">Generales</string>
@ -59,6 +70,7 @@
<string name="categories_search_text_hint">Buscar categorías</string>
<string name="menu_save_categories">Guardar</string>
<string name="refresh_button">Actualizar</string>
<string name="display_list_button">Lista</string>
<string name="gps_disabled">El GPS está desactivado en tu dispositivo. ¿Quieres activarlo?</string>
<string name="enable_gps">Activar GPS</string>
<string name="contributions_subtitle_zero">No hay subidas aún</string>
@ -80,6 +92,7 @@
<string name="categories_activity_title">Categorías</string>
<string name="title_activity_settings">Ajustes</string>
<string name="title_activity_signup">Regístrate</string>
<string name="title_activity_featured_images">Imágenes en destaque</string>
<string name="menu_about">Acerca de</string>
<string name="about_license">La aplicación de código abierto Wikimedia Commons fue creada por, y recibe mantenimiento de, cesionarios y voluntarios de la comunidad de Wikimedia. La Fundación Wikimedia no está involucrada en la creación, el desarrollo ni el mantenimiento de la aplicación.</string>
<string name="about_improve">Notifica de problemas y sugerencias en &lt;a href=\"https://github.com/commons-app/apps-android-commons/issues\"&gt;GitHub&lt;/a&gt;.</string>
@ -125,7 +138,7 @@
<string name="tutorial_1_text">Wikimedia Commons aloja la mayoría de las imágenes utilizadas en Wikipedia.</string>
<string name="tutorial_1_subtext">¡Tus imágenes ayudan a instruir a personas de todo el mundo!</string>
<string name="tutorial_2_text">Carga únicamente imágenes capturadas o creadas por ti.</string>
<string name="tutorial_2_subtext" fuzzy="true">- Objetos naturales (flores, animales, montañas)\n- Objetos útiles (bicicletas, estaciones de tren)\n- Personas famosas (tu alcalde, algún atleta olímpico que conociste)</string>
<string name="tutorial_2_subtext">Objetos naturales (flores, animales, montañas)\n• Objetos útiles (bicicletas, estaciones de tren)\n• Personas famosas (tu alcalde, algún atleta olímpico que conociste)</string>
<string name="tutorial_2_subtext_1">Naturaleza (flores, animales, montañas)</string>
<string name="tutorial_2_subtext_2">Objetos utilitarios (bicicletas, estaciones de tren)</string>
<string name="tutorial_2_subtext_3">Gente famosa (tu regente, algún atleta que hayas conocido…)</string>
@ -138,6 +151,7 @@
<string name="tutorial_4_subtext">- Título: Casa de la Ópera de Sídney\n- Descripción: Casa de la Ópera de Sídney vista desde el otro lado de la bahía\n- Categorías: Casa de la Ópera de Sídney desde el oeste, Vistas a distancia de la Casa de la Ópera de Sídney</string>
<string name="tutorial_4_subtext_1">Título: Ópera de Sídney</string>
<string name="tutorial_4_subtext_2">Descripción: La Ópera de Sídney, vista desde el otro lado de la bahía</string>
<string name="tutorial_4_subtext_3">Categorías: Ópera de Sídney desde el oeste, Vistas a distancia de la Ópera de Sídney</string>
<string name="welcome_wikipedia_text">Contribuye con tus imágenes.\n¡Ayuda a que los artículos de Wikipedia tengan vida!</string>
<string name="welcome_wikipedia_subtext">Las imágenes en Wikipedia proceden de\nWikimedia Commons.</string>
<string name="welcome_copyright_text">Tus imágenes ayudan a educar a la gente\nalrededor del mundo.</string>
@ -150,8 +164,8 @@
<string name="detail_description_empty">Sin descripción</string>
<string name="detail_license_empty">Licencia desconocida</string>
<string name="menu_refresh">Actualizar</string>
<string name="read_storage_permission_rationale">Permiso obligatorio: lectura de almacenamiento externo. La aplicación no puede funcionar sin él.</string>
<string name="write_storage_permission_rationale">Permiso necesario: Escribir en almacenamiento externo. La aplicación no puede funcionar sin él.</string>
<string name="read_storage_permission_rationale">Permiso obligatorio: lectura de almacenamiento externo. La aplicación no puede acceder a la galería sin él.</string>
<string name="write_storage_permission_rationale">Permiso necesario: Escribir en almacenamiento externo. La aplicación no puede acceder a la cámara sin él.</string>
<string name="location_permission_rationale">Permiso opcional: obtener la ubicación actual para sugerir categorías</string>
<string name="ok">Aceptar</string>
<string name="title_activity_nearby">Lugares cercanos</string>
@ -164,6 +178,7 @@
<string name="media_detail_media_title">Título del multimedia</string>
<string name="media_detail_description">Descripción</string>
<string name="media_detail_description_explanation">Aquí va la descripción del archivo multimedia. Esta puede ser muy extensa, en cuyo caso deberá ajustarse en varios renglones. No obstante, esperamos que se vea bien.</string>
<string name="media_detail_author">Autor</string>
<string name="media_detail_uploaded_date">Fecha de subida</string>
<string name="media_detail_license">Licencia</string>
<string name="media_detail_coordinates">Coordenadas</string>
@ -206,10 +221,12 @@
<string name="navigation_item_logout">Salir</string>
<string name="navigation_item_info">Tutorial</string>
<string name="navigation_item_notification">Notificaciones</string>
<string name="navigation_item_featured_images">En destaque</string>
<string name="nearby_needs_permissions">Los sitios cercanos no pueden mostrarse sin los permisos de ubicación</string>
<string name="no_description_found">no se encontró ninguna descripción</string>
<string name="nearby_info_menu_commons_article">Página del archivo en Commons</string>
<string name="nearby_info_menu_wikidata_article">Elemento de Wikidata</string>
<string name="nearby_info_menu_wikipedia_article">Artículo de Wikipedia</string>
<string name="error_while_cache">Error al almacenar imágenes en la antememoria</string>
<string name="title_info">Un título único descriptivo para el archivo, que servirá como un nombre de archivo. Puede usar un lenguaje claro con espacios. No incluya la extensión del archivo.</string>
<string name="description_info">Por favor, describa el elemento multimedia tanto como sea posible: ¿dónde fue tomado?, ¿qué muestra?, ¿cuál es el contexto? Por favor, describa los objetos o personas. Ofrezca la información que no puede ser inferida tan fácilmente, por ejemplo el momento del día si es un paisaje. Si el medio muestra algo inusual, explique qué lo hace insual.</string>
@ -224,6 +241,7 @@
<string name="no_web_browser">No se encontró ningún navegador con el que abrir el URL</string>
<string name="null_url">Error: no se encontró el URL</string>
<string name="nominate_deletion">Nominar para borrado</string>
<string name="nominated_for_deletion">Se ha nominado esta imagen para su borrado.</string>
<string name="view_browser">Ver en navegador</string>
<string name="nearby_location_has_not_changed">La ubicación no ha cambiado.</string>
<string name="nearby_location_not_available">La ubicación no está disponible.</string>
@ -234,5 +252,19 @@
<string name="notifications_talk_page_message">%1$s dejó un mensaje en tu página de discusión</string>
<string name="notifications_thank_you_edit">Gracias por realizar una edición</string>
<string name="notifications_mention">%1$s te ha mencionado en %2$s.</string>
<string name="about_faq">Preguntas frecuentes</string>
<string name="nearby_directions">CÓMO LLEGAR</string>
<string name="nearby_wikidata">WIKIDATA</string>
<string name="nearby_wikipedia">WIKIPEDIA</string>
<string name="nearby_commons">COMMONS</string>
<string name="about_faq">&lt;u&gt;Preguntas frecuentes&lt;/u&gt;</string>
<string name="welcome_skip_button">Omitir tutorial</string>
<string name="no_internet">Internet no disponible</string>
<string name="internet_established">Internet disponible</string>
<string name="error_notifications">Error al recuperar las notificaciones</string>
<string name="no_notifications">No se encontró ninguna notificación</string>
<string name="about_translate">&lt;u&gt;Traducir&lt;/u&gt;</string>
<string name="about_translate_title">Idiomas</string>
<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>
</resources>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Theklan
-->
<resources>
<string name="crash_dialog_title">Commons apurtu da</string>
<string name="crash_dialog_text">Uiii. Zerbait gaizki dabil!</string>

View file

@ -1,4 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* An13sa
* Fitoschido
* Mikel Ibaiba
* Sator
* Subi
* Theklan
-->
<resources>
<string name="app_name">Commons</string>
<string name="menu_settings">Hobespenak</string>

Some files were not shown because too many files have changed in this diff Show more