diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a72b3cc65..31d3e41f2 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -82,6 +82,10 @@ + diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListFragment.java b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListFragment.java index 7f93599f3..1c62a48bb 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListFragment.java @@ -30,6 +30,7 @@ import fr.free.nrw.commons.AboutActivity; import fr.free.nrw.commons.CommonsApplication; import fr.free.nrw.commons.R; import fr.free.nrw.commons.SettingsActivity; +import fr.free.nrw.commons.nearby.NearbyActivity; import fr.free.nrw.commons.upload.UploadService; public class ContributionsListFragment extends Fragment { @@ -142,15 +143,28 @@ public class ContributionsListFragment extends Fragment { feedbackIntent.setType("message/rfc822"); feedbackIntent.putExtra(Intent.EXTRA_EMAIL, new String[] { CommonsApplication.FEEDBACK_EMAIL }); feedbackIntent.putExtra(Intent.EXTRA_SUBJECT, String.format(CommonsApplication.FEEDBACK_EMAIL_SUBJECT, CommonsApplication.APPLICATION_VERSION)); - try { startActivity(feedbackIntent); } catch (ActivityNotFoundException e) { Toast.makeText(getActivity(), R.string.no_email_client, Toast.LENGTH_SHORT).show(); } - return true; + case R.id.menu_nearby: + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + if (ContextCompat.checkSelfPermission(this.getActivity(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { + //See http://stackoverflow.com/questions/33169455/onrequestpermissionsresult-not-being-called-in-dialog-fragment + requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 2); + return false; + } else { + Intent nearbyIntent = new Intent(getActivity(), NearbyActivity.class); + startActivity(nearbyIntent); + } + } + else { + Intent nearbyIntent = new Intent(getActivity(), NearbyActivity.class); + startActivity(nearbyIntent); + } case R.id.menu_refresh: ((SourceRefresher)getActivity()).refreshSource(); return true; @@ -169,6 +183,14 @@ public class ContributionsListFragment extends Fragment { controller.startGalleryPick(); } } + // 2 = Location allowed when 'nearby places' selected + case 2: { + if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + Log.d("ContributionsList", "Location permission granted"); + Intent nearbyIntent = new Intent(getActivity(), NearbyActivity.class); + startActivity(nearbyIntent); + } + } } } diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/LatLng.java b/app/src/main/java/fr/free/nrw/commons/nearby/LatLng.java new file mode 100644 index 000000000..96b36cfba --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/nearby/LatLng.java @@ -0,0 +1,43 @@ +package fr.free.nrw.commons.nearby; + +import android.os.Parcel; + +public class LatLng { + + public final double latitude; + public final double longitude; + + LatLng(double latitude, double longitude) { + if(-180.0D <= longitude && longitude < 180.0D) { + this.longitude = longitude; + } else { + this.longitude = ((longitude - 180.0D) % 360.0D + 360.0D) % 360.0D - 180.0D; + } + this.latitude = Math.max(-90.0D, Math.min(90.0D, latitude)); + } + + public int hashCode() { + boolean var1 = true; + byte var2 = 1; + long var3 = Double.doubleToLongBits(this.latitude); + int var5 = 31 * var2 + (int)(var3 ^ var3 >>> 32); + var3 = Double.doubleToLongBits(this.longitude); + var5 = 31 * var5 + (int)(var3 ^ var3 >>> 32); + return var5; + } + + public boolean equals(Object o) { + if(this == o) { + return true; + } else if(!(o instanceof LatLng)) { + return false; + } else { + LatLng var2 = (LatLng)o; + return Double.doubleToLongBits(this.latitude) == Double.doubleToLongBits(var2.latitude) && Double.doubleToLongBits(this.longitude) == Double.doubleToLongBits(var2.longitude); + } + } + + public String toString() { + return "lat/lng: (" + this.latitude + "," + this.longitude + ")"; + } +} diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyActivity.java b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyActivity.java new file mode 100644 index 000000000..a06d98eea --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyActivity.java @@ -0,0 +1,121 @@ +package fr.free.nrw.commons.nearby; + +import android.content.Context; +import android.location.Criteria; +import android.location.Location; +import android.location.LocationListener; +import android.location.LocationManager; +import android.os.Bundle; +import android.support.v4.app.ActivityCompat; +import android.support.v4.app.FragmentTransaction; +import android.support.v7.app.AppCompatActivity; +import android.util.Log; + +import fr.free.nrw.commons.R; + +public class NearbyActivity extends AppCompatActivity { + + private MyLocationListener myLocationListener; + private LocationManager locationManager; + private String provider; + private Criteria criteria; + private LatLng mLatestLocation; + + private double currentLatitude, currentLongitude; + //private String gpsCoords; + + private static final String TAG = "NearbyActivity"; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_nearby); + if (getSupportActionBar() != null) { + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + } + registerLocationManager(); + + // Begin the transaction + FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); + NearbyListFragment fragment = new NearbyListFragment(); + ft.add(R.id.container, fragment); + ft.commit(); + } + + @Override + protected void onResume(){ + super.onResume(); + } + + protected LatLng getmLatestLocation() { + return mLatestLocation; + } + /** + * Registers a LocationManager to listen for current location + */ + protected void registerLocationManager() { + locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE); + criteria = new Criteria(); + provider = locationManager.getBestProvider(criteria, true); + myLocationListener = new MyLocationListener(); + + try { + locationManager.requestLocationUpdates(provider, 400, 1, myLocationListener); + Location location = locationManager.getLastKnownLocation(provider); + //Location works, just need to 'send' GPS coords via emulator extended controls if testing on emulator + Log.d(TAG, "Checking for location..."); + if (location != null) { + myLocationListener.onLocationChanged(location); + } + } catch (IllegalArgumentException e) { + Log.e(TAG, "Illegal argument exception", e); + } catch (SecurityException e) { + Log.e(TAG, "Security exception", e); + } + } + + protected void unregisterLocationManager() { + try { + locationManager.removeUpdates(myLocationListener); + } catch (SecurityException e) { + Log.e(TAG, "Security exception", e); + } + } + + /** + * Listen for user's location when it changes + */ + private class MyLocationListener implements LocationListener { + + @Override + public void onLocationChanged(Location location) { + currentLatitude = location.getLatitude(); + currentLongitude = location.getLongitude(); + Log.d(TAG, "Latitude: " + String.valueOf(currentLatitude) + " Longitude: " + String.valueOf(currentLongitude)); + + mLatestLocation = new LatLng(currentLatitude, currentLongitude); + } + + @Override + public void onStatusChanged(String provider, int status, Bundle extras) { + Log.d(TAG, provider + "'s status changed to " + status); + } + + @Override + public void onProviderEnabled(String provider) { + Log.d(TAG, "Provider " + provider + " enabled"); + } + + @Override + public void onProviderDisabled(String provider) { + Log.d(TAG, "Provider " + provider + " disabled"); + } + } + + @Override + protected void onDestroy(){ + super.onDestroy(); + + unregisterLocationManager(); + } +} diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyListFragment.java b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyListFragment.java new file mode 100644 index 000000000..78a5d01af --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyListFragment.java @@ -0,0 +1,268 @@ +package fr.free.nrw.commons.nearby; + + +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.AsyncTask; +import android.os.Bundle; +import android.support.v4.app.ListFragment; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Adapter; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.ListAdapter; +import android.widget.ListView; +import android.widget.ProgressBar; +import android.widget.TextView; +import android.widget.Toast; + +import java.text.NumberFormat; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import fr.free.nrw.commons.R; + +public class NearbyListFragment extends ListFragment { + + private int mImageSize; + private boolean mItemClicked; + private NearbyAdapter mAdapter; + + private List places; + private LatLng mLatestLocation; + private ProgressBar progressBar; + + private static final String TAG = "NearbyListFragment"; + + public NearbyListFragment() { + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + + Log.d(TAG, "NearbyListFragment created"); + View view = inflater.inflate(R.layout.fragment_nearby, container, false); + return view; + } + + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + + progressBar = (ProgressBar) view.findViewById(R.id.progressBar); + progressBar.setMax(10); + progressBar.setVisibility(View.VISIBLE); + progressBar.setProgress(0); + + mLatestLocation = ((NearbyActivity) getActivity()).getmLatestLocation(); + + getNearbyPlaces nearbyList = new getNearbyPlaces(); + nearbyList.execute(); + + Log.d(TAG, "Adapter set to ListView"); + + } + + private List loadAttractionsFromLocation(final LatLng curLatLng) { + + List places = NearbyPlaces.get(); + if (curLatLng != null) { + Log.d(TAG, "Sorting places by distance..."); + Collections.sort(places, + new Comparator() { + @Override + public int compare(Place lhs, Place rhs) { + double lhsDistance = computeDistanceBetween( + lhs.location, curLatLng); + double rhsDistance = computeDistanceBetween( + rhs.location, curLatLng); + return (int) (lhsDistance - rhsDistance); + } + } + ); + } + + for(int i = 0; i < 500; i++) { + Place place = places.get(i); + String distance = formatDistanceBetween(mLatestLocation, place.location); + System.out.println("Sorted " + place.name + " at " + distance + " away."); + place.setDistance(distance); + } + return places; + } + + private class getNearbyPlaces extends AsyncTask> { + @Override + protected void onPreExecute() { + super.onPreExecute(); + } + + @Override + protected void onProgressUpdate(Integer... values) { + super.onProgressUpdate(values); + progressBar.setProgress(values[0]); + } + + @Override + protected List doInBackground(Void... params) { + places = loadAttractionsFromLocation(mLatestLocation); + return places; + } + + @Override + protected void onPostExecute(List result) { + super.onPostExecute(result); + + mAdapter = new NearbyAdapter(getActivity(), places); + + progressBar.setVisibility(View.GONE); + + ListView listview = (ListView) getView().findViewById(R.id.listview); + listview.setAdapter(mAdapter); + + listview.setOnItemClickListener(new AdapterView.OnItemClickListener() { + public void onItemClick(AdapterView parent, View view, int position, long id) { + + + Place place = places.get(position); + LatLng placeLatLng = place.location; + + double latitude = placeLatLng.latitude; + double longitude = placeLatLng.longitude; + + Log.d(TAG, "Item at position " + position + " has coords: Lat: " + latitude + " Long: " + longitude); + + //Open map app at given position + Uri gmmIntentUri = Uri.parse("geo:0,0?q=" + latitude + "," + longitude); + Intent mapIntent = new Intent(Intent.ACTION_VIEW, gmmIntentUri); + + if (mapIntent.resolveActivity(getActivity().getPackageManager()) != null) { + startActivity(mapIntent); + } + } + }); + mAdapter.notifyDataSetChanged(); + } + } + + private class NearbyAdapter extends ArrayAdapter { + + public List placesList; + private Context mContext; + + public NearbyAdapter(Context context, List places) { + super(context, R.layout.item_place, places); + mContext = context; + placesList = places; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + // Get the data item for this position + Place place = (Place) getItem(position); + Log.d(TAG, "Place " + place.name); + + // Check if an existing view is being reused, otherwise inflate the view + if (convertView == null) { + convertView = LayoutInflater.from(getContext()).inflate(R.layout.item_place, parent, false); + } + + // Lookup view for data population + TextView tvName = (TextView) convertView.findViewById(R.id.tvName); + TextView tvDesc = (TextView) convertView.findViewById(R.id.tvDesc); + TextView distance = (TextView) convertView.findViewById(R.id.distance); + ImageView icon = (ImageView) convertView.findViewById(R.id.icon); + + String quotelessName = place.name.replaceAll("^\"|\"$", ""); + + // Populate the data into the template view using the data object + tvName.setText(quotelessName); + tvDesc.setText(place.description); + distance.setText(place.distance); + + //Types of desc: landmark, city, edu, event, mountain, isle + switch(place.description) { + case "landmark": + icon.setImageResource(R.drawable.icon_landmark); + break; + case "city": + icon.setImageResource(R.drawable.icon_city); + break; + case "edu": + icon.setImageResource(R.drawable.icon_edu); + break; + case "event": + icon.setImageResource(R.drawable.icon_event); + break; + case "mountain": + icon.setImageResource(R.drawable.icon_mountain); + break; + case "isle": + icon.setImageResource(R.drawable.icon_isle); + break; + default: + icon.setImageResource(R.drawable.empty_photo); + } + + // Return the completed view to render on screen + return convertView; + } + + @Override + public long getItemId(int position) { + return position; + } + } + + private String formatDistanceBetween(LatLng point1, LatLng point2) { + if (point1 == null || point2 == null) { + return null; + } + + NumberFormat numberFormat = NumberFormat.getNumberInstance(); + double distance = Math.round(computeDistanceBetween(point1, point2)); + + // Adjust to KM if M goes over 1000 (see javadoc of method for note + // on only supporting metric) + if (distance >= 1000) { + numberFormat.setMaximumFractionDigits(1); + return numberFormat.format(distance / 1000) + "km"; + } + return numberFormat.format(distance) + "m"; + } + + private static double computeDistanceBetween(LatLng from, LatLng to) { + return computeAngleBetween(from, to) * 6371009.0D; + } + + private static double computeAngleBetween(LatLng from, LatLng to) { + return distanceRadians(Math.toRadians(from.latitude), Math.toRadians(from.longitude), Math.toRadians(to.latitude), Math.toRadians(to.longitude)); + } + + + private static double distanceRadians(double lat1, double lng1, double lat2, double lng2) { + return arcHav(havDistance(lat1, lat2, lng1 - lng2)); + } + + private static double arcHav(double x) { + return 2.0D * Math.asin(Math.sqrt(x)); + } + + private static double havDistance(double lat1, double lat2, double dLng) { + return hav(lat1 - lat2) + hav(dLng) * Math.cos(lat1) * Math.cos(lat2); + } + + private static double hav(double x) { + double sinHalf = Math.sin(x * 0.5D); + return sinHalf * sinHalf; + } + +} diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyPlaces.java b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyPlaces.java new file mode 100644 index 000000000..0e7c3e1ed --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyPlaces.java @@ -0,0 +1,80 @@ +package fr.free.nrw.commons.nearby; + +import android.net.Uri; +import android.os.StrictMode; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +public class NearbyPlaces { + + static List places = null; + + public static List get() { + if(places != null) { + return places; + } + else { + try { + places = new ArrayList(); + StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); + StrictMode.setThreadPolicy(policy); + + URL file = new URL("https://tools.wmflabs.org/wiki-needs-pictures/data/data.csv"); + + BufferedReader in = new BufferedReader(new InputStreamReader(file.openStream())); + + boolean firstLine = true; + String line; + + while ((line = in.readLine()) != null) { + line = in.readLine(); + + // Skip CSV header. + if (firstLine) { + firstLine = false; + continue; + } + + System.out.println(line); + String[] fields = line.split(","); + String name = fields[0]; + + double latitude; + double longitude; + try { + latitude = Double.parseDouble(fields[1]); + } catch (NumberFormatException e) { + latitude = 0; + } + try { + longitude = Double.parseDouble(fields[2]); + } catch (NumberFormatException e) { + longitude = 0; + } + + String type = fields[3]; + String image; + + places.add(new Place( + name, + type, // list + type, // details + null, + new LatLng(latitude, longitude) + )); + } + in.close(); + + } catch (IOException e) { + e.printStackTrace(); + } + } + return places; + } + +} diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/Place.java b/app/src/main/java/fr/free/nrw/commons/nearby/Place.java new file mode 100644 index 000000000..beadd0f85 --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/nearby/Place.java @@ -0,0 +1,33 @@ +package fr.free.nrw.commons.nearby; + +import android.graphics.Bitmap; +import android.net.Uri; + +public class Place { + + public String name; + public String description; + public String longDescription; + public Uri secondaryImageUrl; + public LatLng location; + + public Bitmap image; + public Bitmap secondaryImage; + public String distance; + + public Place() {} + + public Place(String name, String description, String longDescription, + Uri secondaryImageUrl, LatLng location) { + this.name = name; + this.description = description; + this.longDescription = longDescription; + this.secondaryImageUrl = secondaryImageUrl; + this.location = location; + } + + public void setDistance(String distance) { + this.distance = distance; + } + +} diff --git a/app/src/main/java/fr/free/nrw/commons/upload/GPSExtractor.java b/app/src/main/java/fr/free/nrw/commons/upload/GPSExtractor.java index 8445092ff..4313e106c 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/GPSExtractor.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/GPSExtractor.java @@ -80,8 +80,8 @@ public class GPSExtractor { } /** - * Extracts geolocation of image from EXIF data. - * @return coordinates of image as string (needs to be passed as a String in API query) + * Extracts geolocation (either of image from EXIF data, or of user) + * @return coordinates as string (needs to be passed as a String in API query) */ @Nullable public String getCoords(boolean useGPS) { @@ -103,6 +103,7 @@ public class GPSExtractor { return null; } + //If image has no EXIF data and user has enabled GPS setting, get user's location if (exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE) == null && useGPS) { registerLocationManager(); @@ -122,6 +123,7 @@ public class GPSExtractor { } else if (exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE) == null) { return null; } else { + //If image has EXIF data, extract image coords imageCoordsExists = true; Log.d(TAG, "EXIF data has location info"); @@ -142,6 +144,9 @@ public class GPSExtractor { } } + /** + * Listen for user's location when it changes + */ private class MyLocationListener implements LocationListener { @Override diff --git a/app/src/main/res/drawable/empty_photo.png b/app/src/main/res/drawable/empty_photo.png new file mode 100644 index 000000000..da1478a51 Binary files /dev/null and b/app/src/main/res/drawable/empty_photo.png differ diff --git a/app/src/main/res/drawable/icon_city.png b/app/src/main/res/drawable/icon_city.png new file mode 100644 index 000000000..22004c3ec Binary files /dev/null and b/app/src/main/res/drawable/icon_city.png differ diff --git a/app/src/main/res/drawable/icon_edu.png b/app/src/main/res/drawable/icon_edu.png new file mode 100644 index 000000000..f94c9403a Binary files /dev/null and b/app/src/main/res/drawable/icon_edu.png differ diff --git a/app/src/main/res/drawable/icon_event.png b/app/src/main/res/drawable/icon_event.png new file mode 100644 index 000000000..03d0e1f4c Binary files /dev/null and b/app/src/main/res/drawable/icon_event.png differ diff --git a/app/src/main/res/drawable/icon_isle.png b/app/src/main/res/drawable/icon_isle.png new file mode 100644 index 000000000..6fdf75baa Binary files /dev/null and b/app/src/main/res/drawable/icon_isle.png differ diff --git a/app/src/main/res/drawable/icon_landmark.png b/app/src/main/res/drawable/icon_landmark.png new file mode 100644 index 000000000..9024b3fda Binary files /dev/null and b/app/src/main/res/drawable/icon_landmark.png differ diff --git a/app/src/main/res/drawable/icon_mountain.png b/app/src/main/res/drawable/icon_mountain.png new file mode 100644 index 000000000..ded8e2970 Binary files /dev/null and b/app/src/main/res/drawable/icon_mountain.png differ diff --git a/app/src/main/res/drawable/icon_war.jpg b/app/src/main/res/drawable/icon_war.jpg new file mode 100644 index 000000000..bf74779e7 Binary files /dev/null and b/app/src/main/res/drawable/icon_war.jpg differ diff --git a/app/src/main/res/layout/activity_campaigns.xml b/app/src/main/res/layout/activity_campaigns.xml new file mode 100644 index 000000000..cfac7c79b --- /dev/null +++ b/app/src/main/res/layout/activity_campaigns.xml @@ -0,0 +1,13 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_nearby.xml b/app/src/main/res/layout/activity_nearby.xml new file mode 100644 index 000000000..daa243281 --- /dev/null +++ b/app/src/main/res/layout/activity_nearby.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_campaigns.xml b/app/src/main/res/layout/fragment_campaigns.xml new file mode 100644 index 000000000..3ff614f0e --- /dev/null +++ b/app/src/main/res/layout/fragment_campaigns.xml @@ -0,0 +1,18 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_nearby.xml b/app/src/main/res/layout/fragment_nearby.xml new file mode 100644 index 000000000..ef9ff565c --- /dev/null +++ b/app/src/main/res/layout/fragment_nearby.xml @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/app/src/main/res/layout/item_place.xml b/app/src/main/res/layout/item_place.xml new file mode 100644 index 000000000..9f052786e --- /dev/null +++ b/app/src/main/res/layout/item_place.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/layout_campaign_item.xml b/app/src/main/res/layout/layout_campaign_item.xml new file mode 100644 index 000000000..79c0355dd --- /dev/null +++ b/app/src/main/res/layout/layout_campaign_item.xml @@ -0,0 +1,12 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/fragment_contributions_list.xml b/app/src/main/res/menu/fragment_contributions_list.xml index c4ff771b7..3805a7730 100644 --- a/app/src/main/res/menu/fragment_contributions_list.xml +++ b/app/src/main/res/menu/fragment_contributions_list.xml @@ -27,6 +27,11 @@ app:showAsAction="never" android:icon="@android:drawable/ic_menu_send" /> + + + + #90000000 + #22000000 + #ddd + + \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 47c822467..bd62460f7 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -2,4 +2,7 @@ 16dp 16dp + 120dp + 4dp + 8dp diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0d2edb1bd..d64578557 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -33,6 +33,7 @@ Uploading From Gallery Take photo + Nearby My uploads Share @@ -154,4 +155,6 @@ Optional permission: Get current location for category suggestions OK Back + + Nearby Places diff --git a/app/src/main/res/xml/campaigns_sync_adapter.xml b/app/src/main/res/xml/campaigns_sync_adapter.xml new file mode 100644 index 000000000..1da828c50 --- /dev/null +++ b/app/src/main/res/xml/campaigns_sync_adapter.xml @@ -0,0 +1,9 @@ + + + diff --git a/disable-campaigns.patch b/disable-campaigns.patch new file mode 100644 index 000000000..586abe1d5 --- /dev/null +++ b/disable-campaigns.patch @@ -0,0 +1,51 @@ +diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml +index 5ad1c77..50b16ff 100644 +--- a/app/src/main/AndroidManifest.xml ++++ b/app/src/main/AndroidManifest.xml +@@ -82,14 +82,6 @@ + android:label="@string/title_activity_settings" + /> + +- +- +- +- +- +- + + + +@@ -106,17 +98,6 @@ + android:resource="@xml/authenticator" /> + + +- +- +- +- +- +- + +@@ -148,13 +129,6 @@ + android:exported="false"> + + +- +-