mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 20:33:53 +01:00
commit
1ebdb33f80
19 changed files with 550 additions and 172 deletions
10
CHANGELOG.md
10
CHANGELOG.md
|
|
@ -1,5 +1,15 @@
|
||||||
# Wikimedia Commons for Android
|
# Wikimedia Commons for Android
|
||||||
|
|
||||||
|
## v2.9.0
|
||||||
|
- New main screen UI with Nearby tab
|
||||||
|
- New upload UI and flow
|
||||||
|
- Multiple uploads
|
||||||
|
- Send Log File revamp
|
||||||
|
- Fixed issues with wrong "image taken" date
|
||||||
|
- Fixed default zoom level in Nearby map
|
||||||
|
- Incremented target SDK to 27, with corresponding notification channel fix
|
||||||
|
- Removed several redundant libraries to reduce bloat
|
||||||
|
|
||||||
## v2.8.5
|
## v2.8.5
|
||||||
- Fixed issues with sporadic upload failures due to wrong mimeType
|
- Fixed issues with sporadic upload failures due to wrong mimeType
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -89,8 +89,8 @@ android {
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId 'fr.free.nrw.commons'
|
applicationId 'fr.free.nrw.commons'
|
||||||
versionCode 92
|
versionCode 94
|
||||||
versionName '2.8.5'
|
versionName '2.9.0'
|
||||||
setProperty("archivesBaseName", "app-commons-v$versionName-" + getBranchName())
|
setProperty("archivesBaseName", "app-commons-v$versionName-" + getBranchName())
|
||||||
|
|
||||||
minSdkVersion 15
|
minSdkVersion 15
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package fr.free.nrw.commons.contributions;
|
package fr.free.nrw.commons.contributions;
|
||||||
|
|
||||||
|
import android.Manifest;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
|
@ -20,12 +21,14 @@ import android.support.v4.content.CursorLoader;
|
||||||
import android.support.v4.content.Loader;
|
import android.support.v4.content.Loader;
|
||||||
import android.support.v4.app.LoaderManager;
|
import android.support.v4.app.LoaderManager;
|
||||||
import android.support.v4.widget.CursorAdapter;
|
import android.support.v4.widget.CursorAdapter;
|
||||||
import android.util.Log;
|
import android.support.v7.app.AlertDialog;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.Adapter;
|
import android.widget.Adapter;
|
||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
|
import android.widget.CheckBox;
|
||||||
|
import android.widget.CompoundButton;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
|
@ -50,6 +53,8 @@ import fr.free.nrw.commons.notification.NotificationController;
|
||||||
import fr.free.nrw.commons.notification.UnreadNotificationsCheckAsync;
|
import fr.free.nrw.commons.notification.UnreadNotificationsCheckAsync;
|
||||||
import fr.free.nrw.commons.settings.Prefs;
|
import fr.free.nrw.commons.settings.Prefs;
|
||||||
import fr.free.nrw.commons.upload.UploadService;
|
import fr.free.nrw.commons.upload.UploadService;
|
||||||
|
import fr.free.nrw.commons.utils.DialogUtil;
|
||||||
|
import fr.free.nrw.commons.utils.ViewUtil;
|
||||||
import io.reactivex.Observable;
|
import io.reactivex.Observable;
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
import io.reactivex.disposables.CompositeDisposable;
|
import io.reactivex.disposables.CompositeDisposable;
|
||||||
|
|
@ -102,10 +107,11 @@ public class ContributionsFragment
|
||||||
private LatLng curLatLng;
|
private LatLng curLatLng;
|
||||||
|
|
||||||
private boolean firstLocationUpdate = true;
|
private boolean firstLocationUpdate = true;
|
||||||
private LocationServiceManager locationManager;
|
public LocationServiceManager locationManager;
|
||||||
|
|
||||||
private boolean isFragmentAttachedBefore = false;
|
private boolean isFragmentAttachedBefore = false;
|
||||||
|
private View checkBoxView;
|
||||||
|
private CheckBox checkBox;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Since we will need to use parent activity on onAuthCookieAcquired, we have to wait
|
* Since we will need to use parent activity on onAuthCookieAcquired, we have to wait
|
||||||
|
|
@ -137,6 +143,18 @@ public class ContributionsFragment
|
||||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||||
View view = inflater.inflate(R.layout.fragment_contributions, container, false);
|
View view = inflater.inflate(R.layout.fragment_contributions, container, false);
|
||||||
nearbyNoificationCardView = view.findViewById(R.id.card_view_nearby);
|
nearbyNoificationCardView = view.findViewById(R.id.card_view_nearby);
|
||||||
|
checkBoxView = View.inflate(getActivity(), R.layout.nearby_permission_dialog, null);
|
||||||
|
checkBox = (CheckBox) checkBoxView.findViewById(R.id.never_ask_again);
|
||||||
|
checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||||
|
if (isChecked) {
|
||||||
|
// Do not ask for permission on activity start again
|
||||||
|
prefs.edit().putBoolean("displayLocationPermissionForCardView",false).apply();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if (savedInstanceState != null) {
|
if (savedInstanceState != null) {
|
||||||
mediaDetailPagerFragment = (MediaDetailPagerFragment)getChildFragmentManager().findFragmentByTag(MEDIA_DETAIL_PAGER_FRAGMENT_TAG);
|
mediaDetailPagerFragment = (MediaDetailPagerFragment)getChildFragmentManager().findFragmentByTag(MEDIA_DETAIL_PAGER_FRAGMENT_TAG);
|
||||||
|
|
@ -186,7 +204,9 @@ public class ContributionsFragment
|
||||||
// show nearby card view on contributions list is visible
|
// show nearby card view on contributions list is visible
|
||||||
if (nearbyNoificationCardView != null) {
|
if (nearbyNoificationCardView != null) {
|
||||||
if (prefs.getBoolean("displayNearbyCardView", true)) {
|
if (prefs.getBoolean("displayNearbyCardView", true)) {
|
||||||
nearbyNoificationCardView.setVisibility(View.VISIBLE);
|
if (nearbyNoificationCardView.cardViewVisibilityState == NearbyNoificationCardView.CardViewVisibilityState.READY) {
|
||||||
|
nearbyNoificationCardView.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
nearbyNoificationCardView.setVisibility(View.GONE);
|
nearbyNoificationCardView.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
@ -312,16 +332,24 @@ public class ContributionsFragment
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||||
|
Timber.d("onRequestPermissionsResult");
|
||||||
switch (requestCode) {
|
switch (requestCode) {
|
||||||
case LOCATION_REQUEST: {
|
case LOCATION_REQUEST: {
|
||||||
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||||
Timber.d("Location permission granted, refreshing view");
|
Timber.d("Location permission granted, refreshing view");
|
||||||
// No need to display permission request button anymore
|
// No need to display permission request button anymore
|
||||||
nearbyNoificationCardView.displayPermissionRequestButton(false);
|
|
||||||
locationManager.registerLocationManager();
|
locationManager.registerLocationManager();
|
||||||
} else {
|
} else {
|
||||||
// Still ask for permission
|
if (prefs.getBoolean("displayLocationPermissionForCardView", true)) {
|
||||||
nearbyNoificationCardView.displayPermissionRequestButton(true);
|
// Still ask for permission
|
||||||
|
DialogUtil.showAlertDialog(getActivity(),
|
||||||
|
getString(R.string.nearby_card_permission_title),
|
||||||
|
getString(R.string.nearby_card_permission_explanation),
|
||||||
|
() -> displayYouWontSeeNearbyMessage(),
|
||||||
|
() -> enableLocationPermission(),
|
||||||
|
checkBoxView,
|
||||||
|
false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -499,9 +527,10 @@ public class ContributionsFragment
|
||||||
|
|
||||||
|
|
||||||
if (prefs.getBoolean("displayNearbyCardView", true)) {
|
if (prefs.getBoolean("displayNearbyCardView", true)) {
|
||||||
nearbyNoificationCardView.cardViewVisibilityState = NearbyNoificationCardView.CardViewVisibilityState.LOADING;
|
|
||||||
nearbyNoificationCardView.setVisibility(View.VISIBLE);
|
|
||||||
checkGPS();
|
checkGPS();
|
||||||
|
if (nearbyNoificationCardView.cardViewVisibilityState == NearbyNoificationCardView.CardViewVisibilityState.READY) {
|
||||||
|
nearbyNoificationCardView.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Hide nearby notification card view if related shared preferences is false
|
// Hide nearby notification card view if related shared preferences is false
|
||||||
|
|
@ -511,7 +540,6 @@ public class ContributionsFragment
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check GPS to decide displaying request permission button or not.
|
* Check GPS to decide displaying request permission button or not.
|
||||||
*/
|
*/
|
||||||
|
|
@ -519,7 +547,15 @@ public class ContributionsFragment
|
||||||
if (!locationManager.isProviderEnabled()) {
|
if (!locationManager.isProviderEnabled()) {
|
||||||
Timber.d("GPS is not enabled");
|
Timber.d("GPS is not enabled");
|
||||||
nearbyNoificationCardView.permissionType = NearbyNoificationCardView.PermissionType.ENABLE_GPS;
|
nearbyNoificationCardView.permissionType = NearbyNoificationCardView.PermissionType.ENABLE_GPS;
|
||||||
nearbyNoificationCardView.displayPermissionRequestButton(true);
|
if (prefs.getBoolean("displayLocationPermissionForCardView", true)) {
|
||||||
|
DialogUtil.showAlertDialog(getActivity(),
|
||||||
|
getString(R.string.nearby_card_permission_title),
|
||||||
|
getString(R.string.nearby_card_permission_explanation),
|
||||||
|
() -> displayYouWontSeeNearbyMessage(),
|
||||||
|
() -> enableGPS(),
|
||||||
|
checkBoxView,
|
||||||
|
false);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Timber.d("GPS is enabled");
|
Timber.d("GPS is enabled");
|
||||||
checkLocationPermission();
|
checkLocationPermission();
|
||||||
|
|
@ -530,20 +566,57 @@ public class ContributionsFragment
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
if (locationManager.isLocationPermissionGranted()) {
|
if (locationManager.isLocationPermissionGranted()) {
|
||||||
nearbyNoificationCardView.permissionType = NearbyNoificationCardView.PermissionType.NO_PERMISSION_NEEDED;
|
nearbyNoificationCardView.permissionType = NearbyNoificationCardView.PermissionType.NO_PERMISSION_NEEDED;
|
||||||
nearbyNoificationCardView.displayPermissionRequestButton(false);
|
|
||||||
locationManager.registerLocationManager();
|
locationManager.registerLocationManager();
|
||||||
} else {
|
} else {
|
||||||
nearbyNoificationCardView.permissionType = NearbyNoificationCardView.PermissionType.ENABLE_LOCATION_PERMISSON;
|
nearbyNoificationCardView.permissionType = NearbyNoificationCardView.PermissionType.ENABLE_LOCATION_PERMISSON;
|
||||||
nearbyNoificationCardView.displayPermissionRequestButton(true);
|
// If user didn't selected Don't ask again
|
||||||
|
if (shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION)
|
||||||
|
&& prefs.getBoolean("displayLocationPermissionForCardView", true)) {
|
||||||
|
DialogUtil.showAlertDialog(getActivity(),
|
||||||
|
getString(R.string.nearby_card_permission_title),
|
||||||
|
getString(R.string.nearby_card_permission_explanation),
|
||||||
|
() -> displayYouWontSeeNearbyMessage(),
|
||||||
|
() -> enableLocationPermission(),
|
||||||
|
checkBoxView,
|
||||||
|
false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// If device is under Marshmallow, we already checked for GPS
|
// If device is under Marshmallow, we already checked for GPS
|
||||||
nearbyNoificationCardView.permissionType = NearbyNoificationCardView.PermissionType.NO_PERMISSION_NEEDED;
|
nearbyNoificationCardView.permissionType = NearbyNoificationCardView.PermissionType.NO_PERMISSION_NEEDED;
|
||||||
nearbyNoificationCardView.displayPermissionRequestButton(false);
|
|
||||||
locationManager.registerLocationManager();
|
locationManager.registerLocationManager();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void enableLocationPermission() {
|
||||||
|
if (!getActivity().isFinishing()) {
|
||||||
|
((MainActivity) getActivity()).locationManager.requestPermissions(getActivity());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void enableGPS() {
|
||||||
|
new AlertDialog.Builder(getActivity())
|
||||||
|
.setMessage(R.string.gps_disabled)
|
||||||
|
.setCancelable(false)
|
||||||
|
.setPositiveButton(R.string.enable_gps,
|
||||||
|
(dialog, id) -> {
|
||||||
|
Intent callGPSSettingIntent = new Intent(
|
||||||
|
android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
|
||||||
|
Timber.d("Loaded settings page");
|
||||||
|
((MainActivity) getActivity()).startActivityForResult(callGPSSettingIntent, 1);
|
||||||
|
})
|
||||||
|
.setNegativeButton(R.string.menu_cancel_upload, (dialog, id) -> {
|
||||||
|
dialog.cancel();
|
||||||
|
displayYouWontSeeNearbyMessage();
|
||||||
|
})
|
||||||
|
.create()
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void displayYouWontSeeNearbyMessage() {
|
||||||
|
ViewUtil.showLongToast(getActivity(), getResources().getString(R.string.unable_to_display_nearest_place));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void updateClosestNearbyCardViewInfo() {
|
private void updateClosestNearbyCardViewInfo() {
|
||||||
curLatLng = locationManager.getLastLocation();
|
curLatLng = locationManager.getLastLocation();
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ import fr.free.nrw.commons.auth.SessionManager;
|
||||||
import fr.free.nrw.commons.location.LocationServiceManager;
|
import fr.free.nrw.commons.location.LocationServiceManager;
|
||||||
import fr.free.nrw.commons.nearby.NearbyFragment;
|
import fr.free.nrw.commons.nearby.NearbyFragment;
|
||||||
import fr.free.nrw.commons.nearby.NearbyMapFragment;
|
import fr.free.nrw.commons.nearby.NearbyMapFragment;
|
||||||
|
import fr.free.nrw.commons.nearby.NearbyNoificationCardView;
|
||||||
import fr.free.nrw.commons.notification.NotificationActivity;
|
import fr.free.nrw.commons.notification.NotificationActivity;
|
||||||
import fr.free.nrw.commons.theme.NavigationBaseActivity;
|
import fr.free.nrw.commons.theme.NavigationBaseActivity;
|
||||||
import fr.free.nrw.commons.upload.UploadService;
|
import fr.free.nrw.commons.upload.UploadService;
|
||||||
|
|
@ -253,7 +254,9 @@ public class MainActivity extends AuthenticatedActivity implements FragmentManag
|
||||||
showTabs();
|
showTabs();
|
||||||
// Nearby Notification Card View was invisible when Media Details Fragment is active, make it visible again on Contrib List Fragment active, according to preferences
|
// Nearby Notification Card View was invisible when Media Details Fragment is active, make it visible again on Contrib List Fragment active, according to preferences
|
||||||
if (prefs.getBoolean("displayNearbyCardView", true)) {
|
if (prefs.getBoolean("displayNearbyCardView", true)) {
|
||||||
contributionsFragment.nearbyNoificationCardView.setVisibility(View.VISIBLE);
|
if (contributionsFragment.nearbyNoificationCardView.cardViewVisibilityState == NearbyNoificationCardView.CardViewVisibilityState.READY) {
|
||||||
|
contributionsFragment.nearbyNoificationCardView.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
contributionsFragment.nearbyNoificationCardView.setVisibility(View.GONE);
|
contributionsFragment.nearbyNoificationCardView.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
@ -468,6 +471,8 @@ public class MainActivity extends AuthenticatedActivity implements FragmentManag
|
||||||
if (grantResults.length > 0
|
if (grantResults.length > 0
|
||||||
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||||
Timber.d("Location permission given");
|
Timber.d("Location permission given");
|
||||||
|
((ContributionsFragment)contributionsActivityPagerAdapter
|
||||||
|
.getItem(0)).locationManager.registerLocationManager();
|
||||||
} else {
|
} else {
|
||||||
// If nearby fragment is visible and location permission is not given, send user back to contrib fragment
|
// If nearby fragment is visible and location permission is not given, send user back to contrib fragment
|
||||||
if (!isContributionsFragmentVisible) {
|
if (!isContributionsFragmentVisible) {
|
||||||
|
|
|
||||||
|
|
@ -157,8 +157,11 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
detailProvider = (MediaDetailPagerFragment.MediaDetailProvider) (getParentFragment().getParentFragment());
|
if (getParentFragment() != null
|
||||||
|
&& getParentFragment() instanceof MediaDetailPagerFragment) {
|
||||||
|
detailProvider =
|
||||||
|
((MediaDetailPagerFragment) getParentFragment()).getMediaDetailProvider();
|
||||||
|
}
|
||||||
if (savedInstanceState != null) {
|
if (savedInstanceState != null) {
|
||||||
editable = savedInstanceState.getBoolean("editable");
|
editable = savedInstanceState.getBoolean("editable");
|
||||||
isCategoryImage = savedInstanceState.getBoolean("isCategoryImage");
|
isCategoryImage = savedInstanceState.getBoolean("isCategoryImage");
|
||||||
|
|
@ -230,7 +233,12 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment {
|
||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
((ContributionsFragment)(getParentFragment().getParentFragment())).nearbyNoificationCardView.setVisibility(View.GONE);
|
if(getParentFragment()!=null && getParentFragment().getParentFragment()!=null) {
|
||||||
|
//Added a check because, not necessarily, the parent fragment will have a parent fragment, say
|
||||||
|
// in the case when MediaDetailPagerFragment is directly started by the CategoryImagesActivity
|
||||||
|
((ContributionsFragment) (getParentFragment().getParentFragment())).nearbyNoificationCardView
|
||||||
|
.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
media = detailProvider.getMediaAtPosition(index);
|
media = detailProvider.getMediaAtPosition(index);
|
||||||
if (media == null) {
|
if (media == null) {
|
||||||
// Ask the detail provider to ping us when we're ready
|
// Ask the detail provider to ping us when we're ready
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,7 @@ public class MediaDetailPagerFragment extends CommonsDaggerSupportFragment imple
|
||||||
private boolean isFeaturedImage;
|
private boolean isFeaturedImage;
|
||||||
MediaDetailAdapter adapter;
|
MediaDetailAdapter adapter;
|
||||||
private Bookmark bookmark;
|
private Bookmark bookmark;
|
||||||
|
private MediaDetailProvider provider;
|
||||||
|
|
||||||
public MediaDetailPagerFragment() {
|
public MediaDetailPagerFragment() {
|
||||||
this(false, false);
|
this(false, false);
|
||||||
|
|
@ -128,6 +129,23 @@ public class MediaDetailPagerFragment extends CommonsDaggerSupportFragment imple
|
||||||
isFeaturedImage = savedInstanceState.getBoolean("isFeaturedImage");
|
isFeaturedImage = savedInstanceState.getBoolean("isFeaturedImage");
|
||||||
}
|
}
|
||||||
setHasOptionsMenu(true);
|
setHasOptionsMenu(true);
|
||||||
|
initProvider();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* initialise the provider, based on from where the fragment was started, as in from an activity
|
||||||
|
* or a fragment
|
||||||
|
*/
|
||||||
|
private void initProvider() {
|
||||||
|
if (getParentFragment() != null) {
|
||||||
|
provider = (MediaDetailProvider) getParentFragment();
|
||||||
|
} else {
|
||||||
|
provider = (MediaDetailProvider) getActivity();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public MediaDetailProvider getMediaDetailProvider() {
|
||||||
|
return provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -136,7 +154,7 @@ public class MediaDetailPagerFragment extends CommonsDaggerSupportFragment imple
|
||||||
Timber.d("Returning as activity is destroyed!");
|
Timber.d("Returning as activity is destroyed!");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
MediaDetailProvider provider = (MediaDetailProvider) getParentFragment();
|
|
||||||
Media m = provider.getMediaAtPosition(pager.getCurrentItem());
|
Media m = provider.getMediaAtPosition(pager.getCurrentItem());
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
case R.id.menu_bookmark_current_image:
|
case R.id.menu_bookmark_current_image:
|
||||||
|
|
@ -346,7 +364,7 @@ public class MediaDetailPagerFragment extends CommonsDaggerSupportFragment imple
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
getParentFragment().getActivity().supportInvalidateOptionsMenu();
|
getActivity().invalidateOptionsMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -384,7 +402,7 @@ public class MediaDetailPagerFragment extends CommonsDaggerSupportFragment imple
|
||||||
Timber.d("Skipping getItem. Returning as activity is destroyed!");
|
Timber.d("Skipping getItem. Returning as activity is destroyed!");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
pager.postDelayed(() -> getParentFragment().getActivity().supportInvalidateOptionsMenu(), 5);
|
pager.postDelayed(() -> getActivity().invalidateOptionsMenu(), 5);
|
||||||
}
|
}
|
||||||
return MediaDetailFragment.forMedia(i, editable, isFeaturedImage);
|
return MediaDetailFragment.forMedia(i, editable, isFeaturedImage);
|
||||||
}
|
}
|
||||||
|
|
@ -395,7 +413,7 @@ public class MediaDetailPagerFragment extends CommonsDaggerSupportFragment imple
|
||||||
Timber.d("Skipping getCount. Returning as activity is destroyed!");
|
Timber.d("Skipping getCount. Returning as activity is destroyed!");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return ((MediaDetailProvider) getParentFragment()).getTotalMediaCount();
|
return provider.getTotalMediaCount();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -135,6 +135,8 @@ public class NearbyMapFragment extends DaggerFragment {
|
||||||
@Inject
|
@Inject
|
||||||
BookmarkLocationsDao bookmarkLocationDao;
|
BookmarkLocationsDao bookmarkLocationDao;
|
||||||
|
|
||||||
|
private static final double ZOOM_LEVEL = 14f;
|
||||||
|
|
||||||
public NearbyMapFragment() {
|
public NearbyMapFragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -304,7 +306,7 @@ public class NearbyMapFragment extends DaggerFragment {
|
||||||
curMapBoxLatLng.getLongitude())
|
curMapBoxLatLng.getLongitude())
|
||||||
: curMapBoxLatLng ) // Sets the new camera position
|
: curMapBoxLatLng ) // Sets the new camera position
|
||||||
.zoom(isBottomListSheetExpanded ?
|
.zoom(isBottomListSheetExpanded ?
|
||||||
11 // zoom level is fixed to 11 when bottom sheet is expanded
|
ZOOM_LEVEL // zoom level is fixed when bottom sheet is expanded
|
||||||
:mapboxMap.getCameraPosition().zoom) // Same zoom level
|
:mapboxMap.getCameraPosition().zoom) // Same zoom level
|
||||||
.build();
|
.build();
|
||||||
}else {
|
}else {
|
||||||
|
|
@ -314,7 +316,7 @@ public class NearbyMapFragment extends DaggerFragment {
|
||||||
curMapBoxLatLng.getLongitude())
|
curMapBoxLatLng.getLongitude())
|
||||||
: curMapBoxLatLng ) // Sets the new camera position
|
: curMapBoxLatLng ) // Sets the new camera position
|
||||||
.zoom(isBottomListSheetExpanded ?
|
.zoom(isBottomListSheetExpanded ?
|
||||||
11 // zoom level is fixed to 11 when bottom sheet is expanded
|
ZOOM_LEVEL // zoom level is fixed when bottom sheet is expanded
|
||||||
:mapboxMap.getCameraPosition().zoom) // Same zoom level
|
:mapboxMap.getCameraPosition().zoom) // Same zoom level
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
@ -325,47 +327,6 @@ public class NearbyMapFragment extends DaggerFragment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates camera position according to list sheet status. If list sheet is collapsed, camera
|
|
||||||
* focus should be in the center. If list sheet is expanded, camera focus should be visible
|
|
||||||
* on the gap between list sheet and tab layout.
|
|
||||||
* @param isBottomListSheetExpanded
|
|
||||||
*/
|
|
||||||
private void updateMapCameraAccordingToBottomSheet(boolean isBottomListSheetExpanded) {
|
|
||||||
CameraPosition position;
|
|
||||||
this.isBottomListSheetExpanded = isBottomListSheetExpanded;
|
|
||||||
if (mapboxMap != null && curLatLng != null) {
|
|
||||||
if (isBottomListSheetExpanded) {
|
|
||||||
// Make camera to follow user on location change
|
|
||||||
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
|
|
||||||
position = new CameraPosition.Builder()
|
|
||||||
.target(new LatLng(curLatLng.getLatitude(),
|
|
||||||
curLatLng.getLongitude())) // Sets the new camera target to curLatLng
|
|
||||||
.zoom(mapboxMap.getCameraPosition().zoom) // Same zoom level
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
mapboxMap.animateCamera(CameraUpdateFactory
|
|
||||||
.newCameraPosition(position), 1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initViews() {
|
private void initViews() {
|
||||||
Timber.d("initViews called");
|
Timber.d("initViews called");
|
||||||
bottomSheetList = ((NearbyFragment)getParentFragment()).view.findViewById(R.id.bottom_sheet);
|
bottomSheetList = ((NearbyFragment)getParentFragment()).view.findViewById(R.id.bottom_sheet);
|
||||||
|
|
@ -446,7 +407,7 @@ public class NearbyMapFragment extends DaggerFragment {
|
||||||
curLatLng.getLongitude())
|
curLatLng.getLongitude())
|
||||||
: new LatLng(curLatLng.getLatitude(), curLatLng.getLongitude(), 0)) // Sets the new camera position
|
: new LatLng(curLatLng.getLatitude(), curLatLng.getLongitude(), 0)) // Sets the new camera position
|
||||||
.zoom(isBottomListSheetExpanded ?
|
.zoom(isBottomListSheetExpanded ?
|
||||||
11 // zoom level is fixed to 11 when bottom sheet is expanded
|
ZOOM_LEVEL
|
||||||
:mapboxMap.getCameraPosition().zoom) // Same zoom level
|
:mapboxMap.getCameraPosition().zoom) // Same zoom level
|
||||||
.build();
|
.build();
|
||||||
}else {
|
}else {
|
||||||
|
|
@ -456,7 +417,7 @@ public class NearbyMapFragment extends DaggerFragment {
|
||||||
curLatLng.getLongitude())
|
curLatLng.getLongitude())
|
||||||
: new LatLng(curLatLng.getLatitude(), curLatLng.getLongitude(), 0)) // Sets the new camera position
|
: new LatLng(curLatLng.getLatitude(), curLatLng.getLongitude(), 0)) // Sets the new camera position
|
||||||
.zoom(isBottomListSheetExpanded ?
|
.zoom(isBottomListSheetExpanded ?
|
||||||
11 // zoom level is fixed to 11 when bottom sheet is expanded
|
ZOOM_LEVEL
|
||||||
:mapboxMap.getCameraPosition().zoom) // Same zoom level
|
:mapboxMap.getCameraPosition().zoom) // Same zoom level
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
@ -494,9 +455,6 @@ public class NearbyMapFragment extends DaggerFragment {
|
||||||
public void onStateChanged(@NonNull View bottomSheet, int newState) {
|
public void onStateChanged(@NonNull View bottomSheet, int newState) {
|
||||||
if (newState == BottomSheetBehavior.STATE_EXPANDED) {
|
if (newState == BottomSheetBehavior.STATE_EXPANDED) {
|
||||||
bottomSheetDetailsBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
|
bottomSheetDetailsBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
|
||||||
updateMapCameraAccordingToBottomSheet(true);
|
|
||||||
} else {
|
|
||||||
updateMapCameraAccordingToBottomSheet(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -526,7 +484,7 @@ public class NearbyMapFragment extends DaggerFragment {
|
||||||
.attributionEnabled(false)
|
.attributionEnabled(false)
|
||||||
.camera(new CameraPosition.Builder()
|
.camera(new CameraPosition.Builder()
|
||||||
.target(new LatLng(curLatLng.getLatitude(), curLatLng.getLongitude()))
|
.target(new LatLng(curLatLng.getLatitude(), curLatLng.getLongitude()))
|
||||||
.zoom(11)
|
.zoom(ZOOM_LEVEL)
|
||||||
.build());
|
.build());
|
||||||
|
|
||||||
if (!getParentFragment().getActivity().isFinishing()) {
|
if (!getParentFragment().getActivity().isFinishing()) {
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package fr.free.nrw.commons.nearby;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
|
import android.os.Handler;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.design.widget.CoordinatorLayout;
|
import android.support.design.widget.CoordinatorLayout;
|
||||||
|
|
@ -10,6 +11,7 @@ import android.support.design.widget.SwipeDismissBehavior;
|
||||||
import android.support.v7.app.AlertDialog;
|
import android.support.v7.app.AlertDialog;
|
||||||
import android.support.v7.widget.CardView;
|
import android.support.v7.widget.CardView;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
|
|
@ -19,6 +21,7 @@ import android.widget.RelativeLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import fr.free.nrw.commons.R;
|
import fr.free.nrw.commons.R;
|
||||||
import fr.free.nrw.commons.contributions.MainActivity;
|
import fr.free.nrw.commons.contributions.MainActivity;
|
||||||
import fr.free.nrw.commons.utils.ViewUtil;
|
import fr.free.nrw.commons.utils.ViewUtil;
|
||||||
|
|
@ -86,7 +89,7 @@ public class NearbyNoificationCardView extends CardView{
|
||||||
protected void onAttachedToWindow() {
|
protected void onAttachedToWindow() {
|
||||||
super.onAttachedToWindow();
|
super.onAttachedToWindow();
|
||||||
// If you don't setVisibility after getting layout params, then you will se an empty space in place of nerabyNotificationCardView
|
// If you don't setVisibility after getting layout params, then you will se an empty space in place of nerabyNotificationCardView
|
||||||
if (((MainActivity)context).prefs.getBoolean("displayNearbyCardView", true)) {
|
if (((MainActivity)context).prefs.getBoolean("displayNearbyCardView", true) && this.cardViewVisibilityState == NearbyNoificationCardView.CardViewVisibilityState.READY) {
|
||||||
this.setVisibility(VISIBLE);
|
this.setVisibility(VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
this.setVisibility(GONE);
|
this.setVisibility(GONE);
|
||||||
|
|
@ -183,7 +186,7 @@ public class NearbyNoificationCardView extends CardView{
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
cardViewVisibilityState = CardViewVisibilityState.LOADING;
|
cardViewVisibilityState = CardViewVisibilityState.LOADING;
|
||||||
permissionRequestButton.setVisibility(GONE);
|
/*permissionRequestButton.setVisibility(GONE);
|
||||||
contentLayout.setVisibility(VISIBLE);
|
contentLayout.setVisibility(VISIBLE);
|
||||||
// Set visibility of elements in content layout once it become visible
|
// Set visibility of elements in content layout once it become visible
|
||||||
progressBar.setVisibility(VISIBLE);
|
progressBar.setVisibility(VISIBLE);
|
||||||
|
|
@ -191,10 +194,35 @@ public class NearbyNoificationCardView extends CardView{
|
||||||
notificationDistance.setVisibility(GONE);
|
notificationDistance.setVisibility(GONE);
|
||||||
notificationIcon.setVisibility(GONE);
|
notificationIcon.setVisibility(GONE);
|
||||||
|
|
||||||
permissionRequestButton.setVisibility(GONE);
|
permissionRequestButton.setVisibility(GONE);*/
|
||||||
|
|
||||||
|
this.setVisibility(GONE);
|
||||||
|
Handler nearbyNotificationHandler = new Handler();
|
||||||
|
Runnable nearbyNotificationRunnable = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (cardViewVisibilityState != NearbyNoificationCardView.CardViewVisibilityState.READY
|
||||||
|
&& cardViewVisibilityState != NearbyNoificationCardView.CardViewVisibilityState.ASK_PERMISSION
|
||||||
|
&& cardViewVisibilityState != NearbyNoificationCardView.CardViewVisibilityState.INVISIBLE) {
|
||||||
|
// If after 30 seconds, card view is not ready
|
||||||
|
errorOcured();
|
||||||
|
} else {
|
||||||
|
suceeded();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
nearbyNotificationHandler.postDelayed(nearbyNotificationRunnable, 30000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void errorOcured() {
|
||||||
|
this.setVisibility(GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void suceeded() {
|
||||||
|
this.setVisibility(VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pass place information to views.
|
* Pass place information to views.
|
||||||
* @param isClosestNearbyPlaceFound false if there are no close place
|
* @param isClosestNearbyPlaceFound false if there are no close place
|
||||||
|
|
@ -202,6 +230,7 @@ public class NearbyNoificationCardView extends CardView{
|
||||||
*/
|
*/
|
||||||
public void updateContent(boolean isClosestNearbyPlaceFound, Place place) {
|
public void updateContent(boolean isClosestNearbyPlaceFound, Place place) {
|
||||||
Timber.d("Update nearby card notification content");
|
Timber.d("Update nearby card notification content");
|
||||||
|
this.setVisibility(VISIBLE);
|
||||||
cardViewVisibilityState = CardViewVisibilityState.READY;
|
cardViewVisibilityState = CardViewVisibilityState.READY;
|
||||||
permissionRequestButton.setVisibility(GONE);
|
permissionRequestButton.setVisibility(GONE);
|
||||||
contentLayout.setVisibility(VISIBLE);
|
contentLayout.setVisibility(VISIBLE);
|
||||||
|
|
@ -269,6 +298,7 @@ public class NearbyNoificationCardView extends CardView{
|
||||||
READY,
|
READY,
|
||||||
INVISIBLE,
|
INVISIBLE,
|
||||||
ASK_PERMISSION,
|
ASK_PERMISSION,
|
||||||
|
ERROR_OCURED
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,204 @@
|
||||||
|
package fr.free.nrw.commons.ui.widget;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.widget.EditText;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom edit text with a drawable click listener
|
||||||
|
* https://stackoverflow.com/questions/13135447/setting-onclicklistener-for-the-drawable-right-of-an-edittext
|
||||||
|
*/
|
||||||
|
@SuppressLint("AppCompatCustomView")
|
||||||
|
public class CustomEditText extends EditText {
|
||||||
|
|
||||||
|
private Drawable drawableRight;
|
||||||
|
private Drawable drawableLeft;
|
||||||
|
private Drawable drawableTop;
|
||||||
|
private Drawable drawableBottom;
|
||||||
|
|
||||||
|
int actionX, actionY;
|
||||||
|
|
||||||
|
private DrawableClickListener clickListener;
|
||||||
|
|
||||||
|
public CustomEditText(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
// this Contructure required when you are using this view in xml
|
||||||
|
}
|
||||||
|
|
||||||
|
public CustomEditText(Context context, AttributeSet attrs, int defStyle) {
|
||||||
|
super(context, attrs, defStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onDraw(Canvas canvas) {
|
||||||
|
super.onDraw(canvas);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||||
|
super.onSizeChanged(w, h, oldw, oldh);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCompoundDrawables(Drawable left, Drawable top,
|
||||||
|
Drawable right, Drawable bottom) {
|
||||||
|
if (left != null) {
|
||||||
|
drawableLeft = left;
|
||||||
|
}
|
||||||
|
if (right != null) {
|
||||||
|
drawableRight = right;
|
||||||
|
}
|
||||||
|
if (top != null) {
|
||||||
|
drawableTop = top;
|
||||||
|
}
|
||||||
|
if (bottom != null) {
|
||||||
|
drawableBottom = bottom;
|
||||||
|
}
|
||||||
|
super.setCompoundDrawables(left, top, right, bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fires the appropriate drawable click listener on touching the icon
|
||||||
|
* @param event
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean onTouchEvent(MotionEvent event) {
|
||||||
|
Rect bounds;
|
||||||
|
if (event.getAction() == MotionEvent.ACTION_DOWN) {
|
||||||
|
actionX = (int) event.getX();
|
||||||
|
actionY = (int) event.getY();
|
||||||
|
if (drawableBottom != null
|
||||||
|
&& drawableBottom.getBounds().contains(actionX, actionY)) {
|
||||||
|
clickListener.onClick(DrawableClickListener.DrawablePosition.BOTTOM);
|
||||||
|
return super.onTouchEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (drawableTop != null
|
||||||
|
&& drawableTop.getBounds().contains(actionX, actionY)) {
|
||||||
|
clickListener.onClick(DrawableClickListener.DrawablePosition.TOP);
|
||||||
|
return super.onTouchEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
// this works for left since container shares 0,0 origin with bounds
|
||||||
|
if (drawableLeft != null) {
|
||||||
|
bounds = null;
|
||||||
|
bounds = drawableLeft.getBounds();
|
||||||
|
|
||||||
|
int x, y;
|
||||||
|
int extraTapArea = (int) (13 * getResources().getDisplayMetrics().density + 0.5);
|
||||||
|
|
||||||
|
x = actionX;
|
||||||
|
y = actionY;
|
||||||
|
|
||||||
|
if (!bounds.contains(actionX, actionY)) {
|
||||||
|
/** Gives the +20 area for tapping. */
|
||||||
|
x = (int) (actionX - extraTapArea);
|
||||||
|
y = (int) (actionY - extraTapArea);
|
||||||
|
|
||||||
|
if (x <= 0)
|
||||||
|
x = actionX;
|
||||||
|
if (y <= 0)
|
||||||
|
y = actionY;
|
||||||
|
|
||||||
|
/** Creates square from the smallest value */
|
||||||
|
if (x < y) {
|
||||||
|
y = x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bounds.contains(x, y) && clickListener != null) {
|
||||||
|
clickListener
|
||||||
|
.onClick(DrawableClickListener.DrawablePosition.LEFT);
|
||||||
|
event.setAction(MotionEvent.ACTION_CANCEL);
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (drawableRight != null) {
|
||||||
|
|
||||||
|
bounds = null;
|
||||||
|
bounds = drawableRight.getBounds();
|
||||||
|
|
||||||
|
int x, y;
|
||||||
|
int extraTapArea = 13;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IF USER CLICKS JUST OUT SIDE THE RECTANGLE OF THE DRAWABLE
|
||||||
|
* THAN ADD X AND SUBTRACT THE Y WITH SOME VALUE SO THAT AFTER
|
||||||
|
* CALCULATING X AND Y CO-ORDINATE LIES INTO THE DRAWBABLE
|
||||||
|
* BOUND. - this process help to increase the tappable area of
|
||||||
|
* the rectangle.
|
||||||
|
*/
|
||||||
|
x = (int) (actionX + extraTapArea);
|
||||||
|
y = (int) (actionY - extraTapArea);
|
||||||
|
|
||||||
|
/**Since this is right drawable subtract the value of x from the width
|
||||||
|
* of view. so that width - tappedarea will result in x co-ordinate in drawable bound.
|
||||||
|
*/
|
||||||
|
x = getWidth() - x;
|
||||||
|
|
||||||
|
/*x can be negative if user taps at x co-ordinate just near the width.
|
||||||
|
* e.g views width = 300 and user taps 290. Then as per previous calculation
|
||||||
|
* 290 + 13 = 303. So subtract X from getWidth() will result in negative value.
|
||||||
|
* So to avoid this add the value previous added when x goes negative.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (x <= 0) {
|
||||||
|
x += extraTapArea;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If result after calculating for extra tappable area is negative.
|
||||||
|
* assign the original value so that after subtracting
|
||||||
|
* extratapping area value doesn't go into negative value.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (y <= 0)
|
||||||
|
y = actionY;
|
||||||
|
|
||||||
|
/**If drawble bounds contains the x and y points then move ahead.*/
|
||||||
|
if (bounds.contains(x, y) && clickListener != null) {
|
||||||
|
clickListener
|
||||||
|
.onClick(DrawableClickListener.DrawablePosition.RIGHT);
|
||||||
|
event.setAction(MotionEvent.ACTION_CANCEL);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return super.onTouchEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return super.onTouchEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void finalize() throws Throwable {
|
||||||
|
drawableRight = null;
|
||||||
|
drawableBottom = null;
|
||||||
|
drawableLeft = null;
|
||||||
|
drawableTop = null;
|
||||||
|
super.finalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attaches the drawable click listener to the custom edit text
|
||||||
|
* @param listener
|
||||||
|
*/
|
||||||
|
public void setDrawableClickListener(DrawableClickListener listener) {
|
||||||
|
this.clickListener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for drawable click listener
|
||||||
|
*/
|
||||||
|
public interface DrawableClickListener {
|
||||||
|
enum DrawablePosition {TOP, BOTTOM, LEFT, RIGHT}
|
||||||
|
void onClick(DrawablePosition target);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -4,26 +4,22 @@ import android.content.Context;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v4.view.ViewCompat;
|
|
||||||
import android.support.v7.widget.AppCompatSpinner;
|
import android.support.v7.widget.AppCompatSpinner;
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.MotionEvent;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
import android.widget.AdapterView.OnItemSelectedListener;
|
import android.widget.AdapterView.OnItemSelectedListener;
|
||||||
import android.widget.EditText;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
import butterknife.OnTouch;
|
|
||||||
import butterknife.Optional;
|
|
||||||
import fr.free.nrw.commons.R;
|
import fr.free.nrw.commons.R;
|
||||||
|
import fr.free.nrw.commons.ui.widget.CustomEditText;
|
||||||
import fr.free.nrw.commons.utils.AbstractTextWatcher;
|
import fr.free.nrw.commons.utils.AbstractTextWatcher;
|
||||||
import fr.free.nrw.commons.utils.BiMap;
|
import fr.free.nrw.commons.utils.BiMap;
|
||||||
import fr.free.nrw.commons.utils.ViewUtil;
|
import fr.free.nrw.commons.utils.ViewUtil;
|
||||||
|
|
@ -31,8 +27,6 @@ import io.reactivex.subjects.BehaviorSubject;
|
||||||
import io.reactivex.subjects.Subject;
|
import io.reactivex.subjects.Subject;
|
||||||
import timber.log.Timber;
|
import timber.log.Timber;
|
||||||
|
|
||||||
import static android.view.MotionEvent.ACTION_UP;
|
|
||||||
|
|
||||||
class DescriptionsAdapter extends RecyclerView.Adapter<DescriptionsAdapter.ViewHolder> {
|
class DescriptionsAdapter extends RecyclerView.Adapter<DescriptionsAdapter.ViewHolder> {
|
||||||
|
|
||||||
private Title title;
|
private Title title;
|
||||||
|
|
@ -119,7 +113,7 @@ class DescriptionsAdapter extends RecyclerView.Adapter<DescriptionsAdapter.ViewH
|
||||||
AppCompatSpinner spinnerDescriptionLanguages;
|
AppCompatSpinner spinnerDescriptionLanguages;
|
||||||
|
|
||||||
@BindView(R.id.description_item_edit_text)
|
@BindView(R.id.description_item_edit_text)
|
||||||
EditText descItemEditText;
|
CustomEditText descItemEditText;
|
||||||
|
|
||||||
private View view;
|
private View view;
|
||||||
|
|
||||||
|
|
@ -154,6 +148,18 @@ class DescriptionsAdapter extends RecyclerView.Adapter<DescriptionsAdapter.ViewH
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
descItemEditText.setDrawableClickListener(target -> {
|
||||||
|
switch (target) {
|
||||||
|
case RIGHT:
|
||||||
|
if (getAdapterPosition() == 0) {
|
||||||
|
callback.showAlert(R.string.media_detail_title, R.string.title_info);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Description description = descriptions.get(position - 1);
|
Description description = descriptions.get(position - 1);
|
||||||
Timber.d("Description is " + description);
|
Timber.d("Description is " + description);
|
||||||
|
|
@ -168,9 +174,7 @@ class DescriptionsAdapter extends RecyclerView.Adapter<DescriptionsAdapter.ViewH
|
||||||
descItemEditText.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null);
|
descItemEditText.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
descItemEditText.addTextChangedListener(new AbstractTextWatcher(descriptionText -> {
|
descItemEditText.addTextChangedListener(new AbstractTextWatcher(description::setDescriptionText));
|
||||||
description.setDescriptionText(descriptionText);
|
|
||||||
}));
|
|
||||||
descItemEditText.setOnFocusChangeListener((v, hasFocus) -> {
|
descItemEditText.setOnFocusChangeListener((v, hasFocus) -> {
|
||||||
if (!hasFocus) {
|
if (!hasFocus) {
|
||||||
ViewUtil.hideKeyboard(v);
|
ViewUtil.hideKeyboard(v);
|
||||||
|
|
@ -179,97 +183,77 @@ class DescriptionsAdapter extends RecyclerView.Adapter<DescriptionsAdapter.ViewH
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
SpinnerLanguagesAdapter languagesAdapter = new SpinnerLanguagesAdapter(context,
|
|
||||||
R.layout.row_item_languages_spinner, selectedLanguages);
|
|
||||||
languagesAdapter.notifyDataSetChanged();
|
|
||||||
spinnerDescriptionLanguages.setAdapter(languagesAdapter);
|
|
||||||
|
|
||||||
if (description.getSelectedLanguageIndex() == -1) {
|
descItemEditText.setDrawableClickListener(target -> {
|
||||||
if (position == 1) {
|
switch (target) {
|
||||||
int defaultLocaleIndex = languagesAdapter.getIndexOfUserDefaultLocale(context);
|
case RIGHT:
|
||||||
spinnerDescriptionLanguages.setSelection(defaultLocaleIndex);
|
if (getAdapterPosition() == 1) {
|
||||||
} else {
|
callback.showAlert(R.string.media_detail_description,
|
||||||
spinnerDescriptionLanguages.setSelection(0);
|
R.string.description_info);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
initLanguageSpinner(position, description);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracted out the function to init the language spinner with different system supported languages
|
||||||
|
* @param position
|
||||||
|
* @param description
|
||||||
|
*/
|
||||||
|
private void initLanguageSpinner(int position, Description description) {
|
||||||
|
SpinnerLanguagesAdapter languagesAdapter = new SpinnerLanguagesAdapter(context,
|
||||||
|
R.layout.row_item_languages_spinner, selectedLanguages);
|
||||||
|
languagesAdapter.notifyDataSetChanged();
|
||||||
|
spinnerDescriptionLanguages.setAdapter(languagesAdapter);
|
||||||
|
|
||||||
|
if (description.getSelectedLanguageIndex() == -1) {
|
||||||
|
if (position == 1) {
|
||||||
|
int defaultLocaleIndex = languagesAdapter.getIndexOfUserDefaultLocale(context);
|
||||||
|
spinnerDescriptionLanguages.setSelection(defaultLocaleIndex);
|
||||||
} else {
|
} else {
|
||||||
spinnerDescriptionLanguages.setSelection(description.getSelectedLanguageIndex());
|
spinnerDescriptionLanguages.setSelection(0);
|
||||||
selectedLanguages.put(spinnerDescriptionLanguages, description.getLanguageCode());
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
spinnerDescriptionLanguages.setSelection(description.getSelectedLanguageIndex());
|
||||||
|
selectedLanguages.put(spinnerDescriptionLanguages, description.getLanguageCode());
|
||||||
|
}
|
||||||
|
|
||||||
//TODO do it the butterknife way
|
//TODO do it the butterknife way
|
||||||
spinnerDescriptionLanguages.setOnItemSelectedListener(new OnItemSelectedListener() {
|
spinnerDescriptionLanguages.setOnItemSelectedListener(new OnItemSelectedListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onItemSelected(AdapterView<?> adapterView, View view, int position,
|
public void onItemSelected(AdapterView<?> adapterView, View view, int position,
|
||||||
long l) {
|
long l) {
|
||||||
description.setSelectedLanguageIndex(position);
|
description.setSelectedLanguageIndex(position);
|
||||||
String languageCode = ((SpinnerLanguagesAdapter) adapterView.getAdapter()).getLanguageCode(position);
|
String languageCode = ((SpinnerLanguagesAdapter) adapterView.getAdapter()).getLanguageCode(position);
|
||||||
description.setLanguageCode(languageCode);
|
description.setLanguageCode(languageCode);
|
||||||
selectedLanguages.remove(adapterView);
|
selectedLanguages.remove(adapterView);
|
||||||
selectedLanguages.put(adapterView, languageCode);
|
selectedLanguages.put(adapterView, languageCode);
|
||||||
((SpinnerLanguagesAdapter) adapterView.getAdapter()).selectedLangCode = languageCode;
|
((SpinnerLanguagesAdapter) adapterView.getAdapter()).selectedLangCode = languageCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onNothingSelected(AdapterView<?> adapterView) {
|
public void onNothingSelected(AdapterView<?> adapterView) {
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Optional
|
/**
|
||||||
@OnTouch(R.id.description_item_edit_text)
|
* Extracted out the method to get the icon drawable
|
||||||
boolean descriptionInfo(View view, MotionEvent motionEvent) {
|
* @return
|
||||||
//Title info is visible only for the title
|
*/
|
||||||
if (getAdapterPosition() == 0) {
|
private Drawable getInfoIcon() {
|
||||||
if (ViewCompat.getLayoutDirection(view) == ViewCompat.LAYOUT_DIRECTION_LTR) {
|
return context.getResources().getDrawable(R.drawable.mapbox_info_icon_default);
|
||||||
final int value = view.getRight() - descItemEditText
|
|
||||||
.getCompoundDrawables()[2]
|
|
||||||
.getBounds().width();
|
|
||||||
if (motionEvent.getAction() == ACTION_UP && motionEvent.getRawX() >= value) {
|
|
||||||
callback.showAlert(R.string.media_detail_title, R.string.title_info);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
final int value = descItemEditText.getLeft() + descItemEditText
|
|
||||||
.getCompoundDrawables()[0]
|
|
||||||
.getBounds().width();
|
|
||||||
if (motionEvent.getAction() == ACTION_UP && motionEvent.getRawX() <= value) {
|
|
||||||
callback.showAlert(R.string.media_detail_title, R.string.title_info);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//Description info is visible only for the first description
|
|
||||||
} else if (getAdapterPosition() == 1) {
|
|
||||||
final int value;
|
|
||||||
if (ViewCompat.getLayoutDirection(view) == ViewCompat.LAYOUT_DIRECTION_LTR) {
|
|
||||||
value = view.getRight() - descItemEditText.getCompoundDrawables()[2].getBounds().width();
|
|
||||||
if (motionEvent.getAction() == ACTION_UP && motionEvent.getRawX() >= value) {
|
|
||||||
callback.showAlert(R.string.media_detail_description,
|
|
||||||
R.string.description_info);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
value = descItemEditText.getLeft() + descItemEditText
|
|
||||||
.getCompoundDrawables()[0]
|
|
||||||
.getBounds().width();
|
|
||||||
if (motionEvent.getAction() == ACTION_UP && motionEvent.getRawX() <= value) {
|
|
||||||
callback.showAlert(R.string.media_detail_description,
|
|
||||||
R.string.description_info);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Drawable getInfoIcon() {
|
|
||||||
return context.getResources()
|
|
||||||
.getDrawable(R.drawable.mapbox_info_icon_default);
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface Callback {
|
public interface Callback {
|
||||||
void showAlert(int mediaDetailDescription, int descriptionInfo);
|
void showAlert(int mediaDetailDescription, int descriptionInfo);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -223,6 +223,9 @@ public class UploadActivity extends AuthenticatedActivity implements UploadView,
|
||||||
bottomCardSubtitle.setText(cardSubTitle);
|
bottomCardSubtitle.setText(cardSubTitle);
|
||||||
categoryTitle.setText(cardTitle);
|
categoryTitle.setText(cardTitle);
|
||||||
licenseTitle.setText(cardTitle);
|
licenseTitle.setText(cardTitle);
|
||||||
|
if (currentStep == stepCount) {
|
||||||
|
dismissKeyboard();
|
||||||
|
}
|
||||||
if(isShowingItem) {
|
if(isShowingItem) {
|
||||||
descriptionsAdapter.setItems(uploadItem.title, uploadItem.descriptions);
|
descriptionsAdapter.setItems(uploadItem.title, uploadItem.descriptions);
|
||||||
rvDescriptions.setAdapter(descriptionsAdapter);
|
rvDescriptions.setAdapter(descriptionsAdapter);
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import android.os.Build;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v4.app.DialogFragment;
|
import android.support.v4.app.DialogFragment;
|
||||||
import android.support.v4.app.FragmentActivity;
|
import android.support.v4.app.FragmentActivity;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
import fr.free.nrw.commons.R;
|
import fr.free.nrw.commons.R;
|
||||||
import timber.log.Timber;
|
import timber.log.Timber;
|
||||||
|
|
@ -160,6 +161,63 @@ public class DialogUtil {
|
||||||
showSafely(activity, dialog);
|
showSafely(activity, dialog);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Shows alert dialog with custom view
|
||||||
|
*/
|
||||||
|
public static void showAlertDialog(Activity activity,
|
||||||
|
String title,
|
||||||
|
String message,
|
||||||
|
final Runnable onPositiveBtnClick,
|
||||||
|
final Runnable onNegativeBtnClick,
|
||||||
|
View customView,
|
||||||
|
boolean cancelable) {
|
||||||
|
showAlertDialog(activity,
|
||||||
|
title,
|
||||||
|
message,
|
||||||
|
activity.getString(R.string.no),
|
||||||
|
activity.getString(R.string.yes),
|
||||||
|
onPositiveBtnClick,
|
||||||
|
onNegativeBtnClick,
|
||||||
|
customView,
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Shows alert dialog with custom view
|
||||||
|
*/
|
||||||
|
private static void showAlertDialog(Activity activity,
|
||||||
|
String title,
|
||||||
|
String message,
|
||||||
|
String positiveButtonText,
|
||||||
|
String negativeButtonText,
|
||||||
|
final Runnable onPositiveBtnClick,
|
||||||
|
final Runnable onNegativeBtnClick,
|
||||||
|
View customView,
|
||||||
|
boolean cancelable) {
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||||
|
builder.setTitle(title);
|
||||||
|
builder.setMessage(message);
|
||||||
|
builder.setView(customView);
|
||||||
|
builder.setCancelable(cancelable);
|
||||||
|
|
||||||
|
builder.setPositiveButton(positiveButtonText, (dialogInterface, i) -> {
|
||||||
|
dialogInterface.dismiss();
|
||||||
|
if (onPositiveBtnClick != null) {
|
||||||
|
onPositiveBtnClick.run();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
builder.setNegativeButton(negativeButtonText, (DialogInterface dialogInterface, int i) -> {
|
||||||
|
dialogInterface.dismiss();
|
||||||
|
if (onNegativeBtnClick != null) {
|
||||||
|
onNegativeBtnClick.run();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
AlertDialog dialog = builder.create();
|
||||||
|
showSafely(activity, dialog);
|
||||||
|
}
|
||||||
|
|
||||||
public interface Callback {
|
public interface Callback {
|
||||||
|
|
||||||
void onPositiveButtonClicked();
|
void onPositiveButtonClicked();
|
||||||
|
|
|
||||||
13
app/src/main/res/layout/nearby_permission_dialog.xml
Normal file
13
app/src/main/res/layout/nearby_permission_dialog.xml
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content" >
|
||||||
|
|
||||||
|
<CheckBox
|
||||||
|
android:id="@+id/never_ask_again"
|
||||||
|
style="?android:attr/textAppearanceMedium"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/never_ask_again"
|
||||||
|
android:layout_margin="5dp" />
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
|
|
@ -20,14 +19,16 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="8">
|
android:layout_weight="8">
|
||||||
|
|
||||||
<EditText
|
<fr.free.nrw.commons.ui.widget.CustomEditText
|
||||||
android:id="@+id/description_item_edit_text"
|
android:id="@+id/description_item_edit_text"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:drawableEnd="@drawable/mapbox_info_icon_default"
|
|
||||||
android:drawableRight="@drawable/mapbox_info_icon_default"
|
|
||||||
android:hint="@string/share_description_hint"
|
android:hint="@string/share_description_hint"
|
||||||
android:imeOptions="flagNoExtractUi"
|
android:imeOptions="flagNoExtractUi"
|
||||||
|
android:drawablePadding="4dp"
|
||||||
|
android:paddingLeft="4dp"
|
||||||
|
android:paddingRight="4dp"
|
||||||
|
android:drawableRight="@drawable/mapbox_info_icon_default"
|
||||||
android:inputType="textMultiLine" />
|
android:inputType="textMultiLine" />
|
||||||
</android.support.design.widget.TextInputLayout>
|
</android.support.design.widget.TextInputLayout>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
tools:showIn="@layout/activity_upload">
|
tools:showIn="@layout/activity_upload">
|
||||||
|
|
||||||
<android.support.design.widget.TextInputEditText
|
<fr.free.nrw.commons.ui.widget.CustomEditText
|
||||||
android:id="@+id/description_item_edit_text"
|
android:id="@+id/description_item_edit_text"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@
|
||||||
<string name="provider_contributions">การอัปโหลดของฉัน</string>
|
<string name="provider_contributions">การอัปโหลดของฉัน</string>
|
||||||
<string name="menu_share">แชร์</string>
|
<string name="menu_share">แชร์</string>
|
||||||
<string name="menu_open_in_browser">ดูในเบราว์เซอร์</string>
|
<string name="menu_open_in_browser">ดูในเบราว์เซอร์</string>
|
||||||
<string name="share_title_hint" fuzzy="true">ชื่อเรื่อง</string>
|
<string name="share_title_hint">ชื่อเรื่อง</string>
|
||||||
<string name="add_title_toast">กรุณาระบุชืิ่อเรื่องของไฟล์นี้</string>
|
<string name="add_title_toast">กรุณาระบุชืิ่อเรื่องของไฟล์นี้</string>
|
||||||
<string name="share_description_hint">คำอธิบาย</string>
|
<string name="share_description_hint">คำอธิบาย</string>
|
||||||
<string name="login_failed_network">ไม่สามารถเข้าสู่ระบบได้ - ความล้มเหลวของเครือข่าย</string>
|
<string name="login_failed_network">ไม่สามารถเข้าสู่ระบบได้ - ความล้มเหลวของเครือข่าย</string>
|
||||||
|
|
@ -63,7 +63,7 @@
|
||||||
<string name="gps_disabled">GPS ถูกปิดใช้งานในอุปกรณ์ของคุณอยู่ คุณต้องการเปิดใช้งานหรือไม่?</string>
|
<string name="gps_disabled">GPS ถูกปิดใช้งานในอุปกรณ์ของคุณอยู่ คุณต้องการเปิดใช้งานหรือไม่?</string>
|
||||||
<string name="enable_gps">เปิดใช้งาน GPS</string>
|
<string name="enable_gps">เปิดใช้งาน GPS</string>
|
||||||
<string name="contributions_subtitle_zero">ยังไม่มีการอัปโหลด</string>
|
<string name="contributions_subtitle_zero">ยังไม่มีการอัปโหลด</string>
|
||||||
<string name="contributions_subtitle" fuzzy="true">การอัปโหลด %1$d รายการ</string>
|
<string name="contributions_subtitle">การอัปโหลด %1$d รายการ</string>
|
||||||
<plurals name="starting_multiple_uploads">
|
<plurals name="starting_multiple_uploads">
|
||||||
<item quantity="one">กำลังเริ่มอัปโหลด %1$d รายการ</item>
|
<item quantity="one">กำลังเริ่มอัปโหลด %1$d รายการ</item>
|
||||||
<item quantity="other">กำลังเริ่มอัปโหลด %1$d รายการ</item>
|
<item quantity="other">กำลังเริ่มอัปโหลด %1$d รายการ</item>
|
||||||
|
|
@ -155,6 +155,7 @@
|
||||||
<string name="title_activity_nearby">สถานที่ใกล้เคียง</string>
|
<string name="title_activity_nearby">สถานที่ใกล้เคียง</string>
|
||||||
<string name="no_nearby">ไม่พบสถานที่ใกล้เคียง</string>
|
<string name="no_nearby">ไม่พบสถานที่ใกล้เคียง</string>
|
||||||
<string name="warning">คำเตือน</string>
|
<string name="warning">คำเตือน</string>
|
||||||
|
<string name="upload_image_problem_duplicate">ไฟล์นี้มีอยู่แล้วบนคอมมอนส์ คุณแน่ใจหรือว่าคุณต้องการดำเนินการต่อ?</string>
|
||||||
<string name="yes">ใช่</string>
|
<string name="yes">ใช่</string>
|
||||||
<string name="no">ไม่</string>
|
<string name="no">ไม่</string>
|
||||||
<string name="media_detail_title">ชื่อเรื่อง</string>
|
<string name="media_detail_title">ชื่อเรื่อง</string>
|
||||||
|
|
@ -212,7 +213,6 @@
|
||||||
<string name="error_while_cache">ข้อผิดพลาดขณะแคชภาพ</string>
|
<string name="error_while_cache">ข้อผิดพลาดขณะแคชภาพ</string>
|
||||||
<string name="title_info">ชื่อเรื่องที่อธิบายลักษณะเฉพาะของไฟล์ ซึ่งจะใช้เป็นชื่อไฟล์ คุณอาจใช้ภาษาธรรมดาที่มีเว้นวรรคก็ได้ อย่ารวมนามสกุลไฟล์</string>
|
<string name="title_info">ชื่อเรื่องที่อธิบายลักษณะเฉพาะของไฟล์ ซึ่งจะใช้เป็นชื่อไฟล์ คุณอาจใช้ภาษาธรรมดาที่มีเว้นวรรคก็ได้ อย่ารวมนามสกุลไฟล์</string>
|
||||||
<string name="description_info">โปรดอธิบายสื่อดังกล่าวให้มากที่สุดเท่าที่จะได้: สื่อนี้ถูกถ่ายที่ไหน? สื่อนี้แสดงถึงอะไร? บริบทคืออะไร? โปรดอธิบายถึงวัตถุหรือบุคคล เปิดเผยข้อมูลที่ไม่อาจคาดเดาได้อย่างง่ายดาย เช่น เวลาที่ถ่าย หากเป็นภาพทิวทัศน์ หากสื่อแสดงถึงสิ่งที่ไม่ธรรมดา โปรดอธิบายว่าอะไรทำให้สื่อดังกล่าวไม่ธรรมดา</string>
|
<string name="description_info">โปรดอธิบายสื่อดังกล่าวให้มากที่สุดเท่าที่จะได้: สื่อนี้ถูกถ่ายที่ไหน? สื่อนี้แสดงถึงอะไร? บริบทคืออะไร? โปรดอธิบายถึงวัตถุหรือบุคคล เปิดเผยข้อมูลที่ไม่อาจคาดเดาได้อย่างง่ายดาย เช่น เวลาที่ถ่าย หากเป็นภาพทิวทัศน์ หากสื่อแสดงถึงสิ่งที่ไม่ธรรมดา โปรดอธิบายว่าอะไรทำให้สื่อดังกล่าวไม่ธรรมดา</string>
|
||||||
<string name="upload_image_problem_duplicate">ไฟล์นี้มีอยู่แล้วบนคอมมอนส์ คุณแน่ใจหรือว่าคุณต้องการดำเนินการต่อ?</string>
|
|
||||||
<string name="upload_image_problem_dark">ภาพนี้มืดเกินไป คุณแน่ใจหรือว่าคุณต้องการอัปโหลดภาพนี้? วิกิมีเดียคอมมอนส์นั้นมีไว้สำหรับรูปภาพที่มีคุณค่าในทางสารานุกรมเท่านั้น</string>
|
<string name="upload_image_problem_dark">ภาพนี้มืดเกินไป คุณแน่ใจหรือว่าคุณต้องการอัปโหลดภาพนี้? วิกิมีเดียคอมมอนส์นั้นมีไว้สำหรับรูปภาพที่มีคุณค่าในทางสารานุกรมเท่านั้น</string>
|
||||||
<string name="upload_image_problem_blurry">ภาพนี้มัว คุณแน่ใจหรือว่าคุณต้องการอัปโหลดภาพนี้? วิกิมีเดียคอมมอนส์นั้นมีไว้สำหรับรูปภาพที่มีคุณค่าในทางสารานุกรมเท่านั้น</string>
|
<string name="upload_image_problem_blurry">ภาพนี้มัว คุณแน่ใจหรือว่าคุณต้องการอัปโหลดภาพนี้? วิกิมีเดียคอมมอนส์นั้นมีไว้สำหรับรูปภาพที่มีคุณค่าในทางสารานุกรมเท่านั้น</string>
|
||||||
<string name="give_permission">ให้สิทธิ์</string>
|
<string name="give_permission">ให้สิทธิ์</string>
|
||||||
|
|
|
||||||
|
|
@ -185,6 +185,7 @@
|
||||||
<string name="title_activity_nearby">Місця поблизу</string>
|
<string name="title_activity_nearby">Місця поблизу</string>
|
||||||
<string name="no_nearby">Не знайдено місць поблизу</string>
|
<string name="no_nearby">Не знайдено місць поблизу</string>
|
||||||
<string name="warning">Попередження</string>
|
<string name="warning">Попередження</string>
|
||||||
|
<string name="file_exists">Цей файл вже існує на Вікісховищі. Ви впевнені, що хочете продовжити?</string>
|
||||||
<string name="yes">Так</string>
|
<string name="yes">Так</string>
|
||||||
<string name="no">Ні</string>
|
<string name="no">Ні</string>
|
||||||
<string name="media_detail_title">Назва</string>
|
<string name="media_detail_title">Назва</string>
|
||||||
|
|
|
||||||
|
|
@ -425,5 +425,11 @@ Upload your first media by touching the camera or gallery icon above.</string>
|
||||||
<string name="no_go_back">No, Go Back</string>
|
<string name="no_go_back">No, Go Back</string>
|
||||||
|
|
||||||
<string name="upload_flow_all_images_in_set">(For all images in set)</string>
|
<string name="upload_flow_all_images_in_set">(For all images in set)</string>
|
||||||
|
<string name="nearby_card_permission_title">Permission Request</string>
|
||||||
|
<string name="nearby_card_permission_explanation">Would you like us to use your current location to display the nearest place that needs pictures?</string>
|
||||||
|
<string name="unable_to_display_nearest_place">Unable to display nearest place that needs pictures without location permissions</string>
|
||||||
|
<string name="never_ask_again">Never ask this again</string>
|
||||||
|
<string name="display_location_permission_title">Display location permission</string>
|
||||||
|
<string name="display_location_permission_explanation">Ask for location permission when needed for nearby notification card view feature.</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,12 @@
|
||||||
android:defaultValue="true"
|
android:defaultValue="true"
|
||||||
android:summary="@string/display_nearby_notification_summary" />
|
android:summary="@string/display_nearby_notification_summary" />
|
||||||
|
|
||||||
|
<fr.free.nrw.commons.ui.LongTitlePreferences.LongTitleSwitchPreference
|
||||||
|
android:key="displayLocationPermissionForCardView"
|
||||||
|
android:title="@string/display_location_permission_title"
|
||||||
|
android:defaultValue="true"
|
||||||
|
android:summary="@string/display_location_permission_explanation" />
|
||||||
|
|
||||||
</fr.free.nrw.commons.ui.LongTitlePreferences.LongTitlePreferenceCategory>
|
</fr.free.nrw.commons.ui.LongTitlePreferences.LongTitlePreferenceCategory>
|
||||||
|
|
||||||
<!-- The key 'allowGps' was used before and has since been removed based on the discussion at #1599.
|
<!-- The key 'allowGps' was used before and has since been removed based on the discussion at #1599.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue