Skip to content

Commit cb0b976

Browse files
author
Vivek Maskara
authored
Merge pull request commons-app#1346 from commons-app/directNearbyUploadsNew
Merge Direct nearby uploads new branch to master
2 parents fe1f0b5 + 50d9cff commit cb0b976

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+2124
-495
lines changed

app/src/main/java/fr/free/nrw/commons/category/CategorizationFragment.java

+33-5
Original file line numberDiff line numberDiff line change
@@ -73,13 +73,16 @@ public class CategorizationFragment extends CommonsDaggerSupportFragment {
7373

7474
@Inject MediaWikiApi mwApi;
7575
@Inject @Named("default_preferences") SharedPreferences prefs;
76+
@Inject @Named("prefs") SharedPreferences prefsPrefs;
77+
@Inject @Named("direct_nearby_upload_prefs") SharedPreferences directPrefs;
7678
@Inject CategoryDao categoryDao;
7779

7880
private RVRendererAdapter<CategoryItem> categoriesAdapter;
7981
private OnCategoriesSaveHandler onCategoriesSaveHandler;
8082
private HashMap<String, ArrayList<String>> categoriesCache;
8183
private List<CategoryItem> selectedCategories = new ArrayList<>();
8284
private TitleTextWatcher textWatcher = new TitleTextWatcher();
85+
private boolean hasDirectCategories = false;
8386

8487
private final CategoriesAdapterFactory adapterFactory = new CategoriesAdapterFactory(item -> {
8588
if (item.isSelected()) {
@@ -128,7 +131,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container,
128131
}
129132

130133
public void hideKeyboard(View view) {
131-
InputMethodManager inputMethodManager =(InputMethodManager)getActivity().getSystemService(Activity.INPUT_METHOD_SERVICE);
134+
InputMethodManager inputMethodManager = (InputMethodManager) getActivity().getSystemService(Activity.INPUT_METHOD_SERVICE);
132135
inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
133136
}
134137

@@ -223,7 +226,7 @@ private void updateCategoryList(String filter) {
223226
.observeOn(AndroidSchedulers.mainThread())
224227
.subscribe(
225228
s -> categoriesAdapter.add(s),
226-
Timber::e,
229+
Timber::e,
227230
() -> {
228231
categoriesAdapter.notifyDataSetChanged();
229232
categoriesSearchInProgress.setVisibility(View.GONE);
@@ -258,9 +261,34 @@ private List<String> getStringList(List<CategoryItem> input) {
258261
}
259262

260263
private Observable<CategoryItem> defaultCategories() {
261-
return gpsCategories()
262-
.concatWith(titleCategories())
263-
.concatWith(recentCategories());
264+
265+
Observable<CategoryItem> directCat = directCategories();
266+
if (hasDirectCategories) {
267+
Timber.d("Image has direct Cat");
268+
return directCat
269+
.concatWith(gpsCategories())
270+
.concatWith(titleCategories())
271+
.concatWith(recentCategories());
272+
}
273+
else {
274+
Timber.d("Image has no direct Cat");
275+
return gpsCategories()
276+
.concatWith(titleCategories())
277+
.concatWith(recentCategories());
278+
}
279+
}
280+
281+
private Observable<CategoryItem> directCategories() {
282+
String directCategory = directPrefs.getString("Category", "");
283+
List<String> categoryList = new ArrayList<>();
284+
Timber.d("Direct category found: " + directCategory);
285+
286+
if (!directCategory.equals("")) {
287+
hasDirectCategories = true;
288+
categoryList.add(directCategory);
289+
Timber.d("DirectCat does not equal emptyString. Direct Cat list has " + categoryList);
290+
}
291+
return Observable.fromIterable(categoryList).map(name -> new CategoryItem(name, false));
264292
}
265293

266294
private Observable<CategoryItem> gpsCategories() {

app/src/main/java/fr/free/nrw/commons/contributions/ContributionController.java

+22-5
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,14 @@
2525
import static fr.free.nrw.commons.contributions.Contribution.SOURCE_GALLERY;
2626
import static fr.free.nrw.commons.upload.UploadService.EXTRA_SOURCE;
2727

28-
class ContributionController {
28+
public class ContributionController {
2929

3030
private static final int SELECT_FROM_GALLERY = 1;
3131
private static final int SELECT_FROM_CAMERA = 2;
3232

3333
private Fragment fragment;
3434

35-
ContributionController(Fragment fragment) {
35+
public ContributionController(Fragment fragment) {
3636
this.fragment = fragment;
3737
}
3838

@@ -61,7 +61,7 @@ private static void requestWritePermission(Context context, Intent intent, Uri u
6161
}
6262
}
6363

64-
void startCameraCapture() {
64+
public void startCameraCapture() {
6565

6666
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
6767
lastGeneratedCaptureUri = reGenerateImageCaptureUriInCache();
@@ -70,18 +70,29 @@ void startCameraCapture() {
7070
requestWritePermission(fragment.getContext(), takePictureIntent, lastGeneratedCaptureUri);
7171

7272
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, lastGeneratedCaptureUri);
73+
if (!fragment.isAdded()) {
74+
return;
75+
}
7376
fragment.startActivityForResult(takePictureIntent, SELECT_FROM_CAMERA);
7477
}
7578

7679
public void startGalleryPick() {
7780
//FIXME: Starts gallery (opens Google Photos)
7881
Intent pickImageIntent = new Intent(ACTION_GET_CONTENT);
7982
pickImageIntent.setType("image/*");
83+
// See https://stackoverflow.com/questions/22366596/android-illegalstateexception-fragment-not-attached-to-activity-webview
84+
if (!fragment.isAdded()) {
85+
Timber.d("Fragment is not added, startActivityForResult cannot be called");
86+
return;
87+
}
88+
Timber.d("startGalleryPick() called with pickImageIntent");
89+
8090
fragment.startActivityForResult(pickImageIntent, SELECT_FROM_GALLERY);
8191
}
8292

83-
void handleImagePicked(int requestCode, Intent data) {
93+
public void handleImagePicked(int requestCode, Intent data, boolean isDirectUpload) {
8494
FragmentActivity activity = fragment.getActivity();
95+
Timber.d("handleImagePicked() called with onActivityResult()");
8596
Intent shareIntent = new Intent(activity, ShareActivity.class);
8697
shareIntent.setAction(ACTION_SEND);
8798
switch (requestCode) {
@@ -91,6 +102,9 @@ void handleImagePicked(int requestCode, Intent data) {
91102
shareIntent.setType(activity.getContentResolver().getType(imageData));
92103
shareIntent.putExtra(EXTRA_STREAM, imageData);
93104
shareIntent.putExtra(EXTRA_SOURCE, SOURCE_GALLERY);
105+
if (isDirectUpload) {
106+
shareIntent.putExtra("isDirectUpload", true);
107+
}
94108
break;
95109
case SELECT_FROM_CAMERA:
96110
//FIXME: Find out appropriate mime type
@@ -99,6 +113,10 @@ void handleImagePicked(int requestCode, Intent data) {
99113
shareIntent.setType("image/jpeg");
100114
shareIntent.putExtra(EXTRA_STREAM, lastGeneratedCaptureUri);
101115
shareIntent.putExtra(EXTRA_SOURCE, SOURCE_CAMERA);
116+
if (isDirectUpload) {
117+
shareIntent.putExtra("isDirectUpload", true);
118+
}
119+
102120
break;
103121
default:
104122
break;
@@ -122,5 +140,4 @@ void loadState(Bundle savedInstanceState) {
122140
lastGeneratedCaptureUri = savedInstanceState.getParcelable("lastGeneratedCaptureURI");
123141
}
124142
}
125-
126143
}

app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListFragment.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) {
117117
if (resultCode == RESULT_OK) {
118118
Timber.d("OnActivityResult() parameters: Req code: %d Result code: %d Data: %s",
119119
requestCode, resultCode, data);
120-
controller.handleImagePicked(requestCode, data);
120+
controller.handleImagePicked(requestCode, data, false);
121121
} else {
122122
Timber.e("OnActivityResult() parameters: Req code: %d Result code: %d Data: %s",
123123
requestCode, resultCode, data);

app/src/main/java/fr/free/nrw/commons/di/CommonsApplicationComponent.java

+3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import fr.free.nrw.commons.delete.DeleteTask;
1616
import fr.free.nrw.commons.modifications.ModificationsSyncAdapter;
1717
import fr.free.nrw.commons.settings.SettingsFragment;
18+
import fr.free.nrw.commons.nearby.PlaceRenderer;
1819

1920
@Singleton
2021
@Component(modules = {
@@ -44,6 +45,8 @@ public interface CommonsApplicationComponent extends AndroidInjector<Application
4445
@Override
4546
void inject(ApplicationlessInjection instance);
4647

48+
void inject(PlaceRenderer placeRenderer);
49+
4750
@Component.Builder
4851
@SuppressWarnings({"WeakerAccess", "unused"})
4952
interface Builder {

app/src/main/java/fr/free/nrw/commons/di/CommonsApplicationModule.java

+7-4
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ public class CommonsApplicationModule {
3333
public static final String CATEGORY_AUTHORITY = "fr.free.nrw.commons.categories.contentprovider";
3434
public static final long OK_HTTP_CACHE_SIZE = 10 * 1024 * 1024;
3535

36-
private CommonsApplication application;
3736
private Context applicationContext;
3837

3938
public CommonsApplicationModule(Context applicationContext) {
@@ -87,9 +86,13 @@ public SharedPreferences providesOtherSharedPreferences(Context context) {
8786
}
8887

8988
@Provides
90-
public UploadController providesUploadController(Context context,
91-
SessionManager sessionManager,
92-
@Named("default_preferences") SharedPreferences sharedPreferences) {
89+
@Named("direct_nearby_upload_prefs")
90+
public SharedPreferences providesDirectNearbyUploadPreferences(Context context) {
91+
return context.getSharedPreferences("direct_nearby_upload_prefs", MODE_PRIVATE);
92+
}
93+
94+
@Provides
95+
public UploadController providesUploadController(SessionManager sessionManager, @Named("default_preferences") SharedPreferences sharedPreferences, Context context) {
9396
return new UploadController(sessionManager, context, sharedPreferences);
9497
}
9598

app/src/main/java/fr/free/nrw/commons/di/FragmentBuilderModule.java

+4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import fr.free.nrw.commons.media.MediaDetailFragment;
88
import fr.free.nrw.commons.media.MediaDetailPagerFragment;
99
import fr.free.nrw.commons.nearby.NearbyListFragment;
10+
import fr.free.nrw.commons.nearby.NearbyMapFragment;
1011
import fr.free.nrw.commons.nearby.NoPermissionsFragment;
1112
import fr.free.nrw.commons.settings.SettingsFragment;
1213
import fr.free.nrw.commons.upload.MultipleUploadListFragment;
@@ -31,6 +32,9 @@ public abstract class FragmentBuilderModule {
3132
@ContributesAndroidInjector
3233
abstract NearbyListFragment bindNearbyListFragment();
3334

35+
@ContributesAndroidInjector
36+
abstract NearbyMapFragment bindNearbyMapFragment();
37+
3438
@ContributesAndroidInjector
3539
abstract NoPermissionsFragment bindNoPermissionsFragment();
3640

app/src/main/java/fr/free/nrw/commons/location/LatLng.java

+10-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package fr.free.nrw.commons.location;
22

33
import android.location.Location;
4+
import android.net.Uri;
45
import android.support.annotation.NonNull;
56

67
/**
@@ -11,15 +12,15 @@ public class LatLng {
1112
private final double latitude;
1213
private final double longitude;
1314
private final float accuracy;
14-
15+
1516
/**
1617
* Accepts latitude and longitude.
1718
* North and South values are cut off at 90°
18-
*
19+
*
1920
* @param latitude the latitude
2021
* @param longitude the longitude
2122
* @param accuracy the accuracy
22-
*
23+
*
2324
* Examples:
2425
* the Statue of Liberty is located at 40.69° N, 74.04° W
2526
* The Statue of Liberty could be constructed as LatLng(40.69, -74.04, 1.0)
@@ -43,7 +44,7 @@ public LatLng(double latitude, double longitude, float accuracy) {
4344
public static LatLng from(@NonNull Location location) {
4445
return new LatLng(location.getLatitude(), location.getLongitude(), location.getAccuracy());
4546
}
46-
47+
4748
/**
4849
* creates a hash code for the longitude and longitude
4950
*/
@@ -153,4 +154,9 @@ public double getLongitude() {
153154
public double getLatitude() {
154155
return latitude;
155156
}
157+
158+
public Uri getGmmIntentUri() {
159+
return Uri.parse("geo:0,0?q=" + latitude + "," + longitude);
160+
}
156161
}
162+

app/src/main/java/fr/free/nrw/commons/location/LocationServiceManager.java

+47-26
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import android.os.Bundle;
1111
import android.support.v4.app.ActivityCompat;
1212
import android.support.v4.content.ContextCompat;
13+
import android.util.Log;
1314

1415
import java.util.List;
1516
import java.util.concurrent.CopyOnWriteArrayList;
@@ -19,7 +20,8 @@
1920
public class LocationServiceManager implements LocationListener {
2021
public static final int LOCATION_REQUEST = 1;
2122

22-
private static final long MIN_LOCATION_UPDATE_REQUEST_TIME_IN_MILLIS = 2 * 60 * 1000;
23+
// Maybe these values can be improved for efficiency
24+
private static final long MIN_LOCATION_UPDATE_REQUEST_TIME_IN_MILLIS = 2 * 60 * 100;
2325
private static final long MIN_LOCATION_UPDATE_REQUEST_DISTANCE_IN_METERS = 10;
2426

2527
private Context context;
@@ -120,12 +122,14 @@ private boolean requestLocationUpdatesFromProvider(String locationProvider) {
120122
*
121123
* @param location the location to be tested
122124
* @param currentBestLocation the current best location
123-
* @return true if the given location is better
125+
* @return LOCATION_SIGNIFICANTLY_CHANGED if location changed significantly
126+
* LOCATION_SLIGHTLY_CHANGED if location changed slightly
124127
*/
125-
protected boolean isBetterLocation(Location location, Location currentBestLocation) {
128+
protected LocationChangeType isBetterLocation(Location location, Location currentBestLocation) {
129+
126130
if (currentBestLocation == null) {
127131
// A new location is always better than no location
128-
return true;
132+
return LocationChangeType.LOCATION_SIGNIFICANTLY_CHANGED;
129133
}
130134

131135
// Check whether the new location fix is newer or older
@@ -134,15 +138,6 @@ protected boolean isBetterLocation(Location location, Location currentBestLocati
134138
boolean isSignificantlyOlder = timeDelta < -MIN_LOCATION_UPDATE_REQUEST_TIME_IN_MILLIS;
135139
boolean isNewer = timeDelta > 0;
136140

137-
// If it's been more than two minutes since the current location, use the new location
138-
// because the user has likely moved
139-
if (isSignificantlyNewer) {
140-
return true;
141-
// If the new location is more than two minutes older, it must be worse
142-
} else if (isSignificantlyOlder) {
143-
return false;
144-
}
145-
146141
// Check whether the new location fix is more or less accurate
147142
int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
148143
boolean isLessAccurate = accuracyDelta > 0;
@@ -153,15 +148,28 @@ protected boolean isBetterLocation(Location location, Location currentBestLocati
153148
boolean isFromSameProvider = isSameProvider(location.getProvider(),
154149
currentBestLocation.getProvider());
155150

156-
// Determine location quality using a combination of timeliness and accuracy
157-
if (isMoreAccurate) {
158-
return true;
159-
} else if (isNewer && !isLessAccurate) {
160-
return true;
161-
} else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
162-
return true;
151+
float[] results = new float[5];
152+
Location.distanceBetween(
153+
currentBestLocation.getLatitude(),
154+
currentBestLocation.getLongitude(),
155+
location.getLatitude(),
156+
location.getLongitude(),
157+
results);
158+
159+
// If it's been more than two minutes since the current location, use the new location
160+
// because the user has likely moved
161+
if (isSignificantlyNewer
162+
|| isMoreAccurate
163+
|| (isNewer && !isLessAccurate)
164+
|| (isNewer && !isSignificantlyLessAccurate && isFromSameProvider)) {
165+
if (results[0] < 1000) { // Means change is smaller than 1000 meter
166+
return LocationChangeType.LOCATION_SLIGHTLY_CHANGED;
167+
} else {
168+
return LocationChangeType.LOCATION_SIGNIFICANTLY_CHANGED;
169+
}
170+
} else{
171+
return LocationChangeType.LOCATION_NOT_CHANGED;
163172
}
164-
return false;
165173
}
166174

167175
/**
@@ -208,12 +216,19 @@ public void removeLocationListener(LocationUpdateListener listener) {
208216

209217
@Override
210218
public void onLocationChanged(Location location) {
211-
if (isBetterLocation(location, lastLocation)) {
212-
lastLocation = location;
213-
for (LocationUpdateListener listener : locationListeners) {
214-
listener.onLocationChanged(LatLng.from(lastLocation));
219+
if (isBetterLocation(location, lastLocation)
220+
.equals(LocationChangeType.LOCATION_SIGNIFICANTLY_CHANGED)) {
221+
lastLocation = location;
222+
for (LocationUpdateListener listener : locationListeners) {
223+
listener.onLocationChangedSignificantly(LatLng.from(lastLocation));
224+
}
225+
} else if (isBetterLocation(location, lastLocation)
226+
.equals(LocationChangeType.LOCATION_SLIGHTLY_CHANGED)) {
227+
lastLocation = location;
228+
for (LocationUpdateListener listener : locationListeners) {
229+
listener.onLocationChangedSlightly(LatLng.from(lastLocation));
230+
}
215231
}
216-
}
217232
}
218233

219234
@Override
@@ -230,4 +245,10 @@ public void onProviderEnabled(String provider) {
230245
public void onProviderDisabled(String provider) {
231246
Timber.d("Provider %s disabled", provider);
232247
}
248+
249+
public enum LocationChangeType{
250+
LOCATION_SIGNIFICANTLY_CHANGED, //Went out of borders of nearby markers
251+
LOCATION_SLIGHTLY_CHANGED, //User might be walking or driving
252+
LOCATION_NOT_CHANGED
253+
}
233254
}

0 commit comments

Comments
 (0)