Skip to content

Commit b102663

Browse files
authored
Merge branch 'master' into exif
2 parents e25b497 + 74df6ac commit b102663

40 files changed

+864
-205
lines changed

CHANGELOG.md

+7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# Wikimedia Commons for Android
22

3+
## v2.11.0
4+
- Refactored upload process, explore/media details, and peer review to use MVP architecture
5+
- Refactored all AsyncTasks to use RxAndroid
6+
- Partial migration to Retrofit
7+
- Allow users to remove EXIF tags from their uploads if desired
8+
- Multiple crash and bug fixes
9+
310
## v2.10.2
411
- Fixed remaining issues with date image taken
512
- Fixed database crash

app/build.gradle

+2-2
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,8 @@ android {
105105

106106
defaultConfig {
107107
applicationId 'fr.free.nrw.commons'
108-
versionCode 243
109-
versionName '2.10.2'
108+
versionCode 475
109+
versionName '2.11.0'
110110
setProperty("archivesBaseName", "app-commons-v$versionName-" + getBranchName())
111111

112112
minSdkVersion 19

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

+49-2
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,21 @@ public CategoriesModel(MediaWikiApi mwApi,
4848
*/
4949
public Comparator<CategoryItem> sortBySimilarity(final String filter) {
5050
Comparator<String> stringSimilarityComparator = StringSortingUtils.sortBySimilarity(filter);
51-
return (firstItem, secondItem) -> stringSimilarityComparator
52-
.compare(firstItem.getName(), secondItem.getName());
51+
return (firstItem, secondItem) -> {
52+
//if the category is selected, it should get precedence
53+
if (null != firstItem && firstItem.isSelected()) {
54+
if (null != secondItem && secondItem.isSelected()) {
55+
return stringSimilarityComparator
56+
.compare(firstItem.getName(), secondItem.getName());
57+
}
58+
return -1;
59+
}
60+
if (null != secondItem && secondItem.isSelected()) {
61+
return 1;
62+
}
63+
return stringSimilarityComparator
64+
.compare(firstItem.getName(), secondItem.getName());
65+
};
5366
}
5467

5568
/**
@@ -255,4 +268,38 @@ public void cleanUp() {
255268
this.categoriesCache.clear();
256269
this.selectedCategories.clear();
257270
}
271+
272+
/**
273+
* Search for categories
274+
*/
275+
public Observable<CategoryItem> searchCategories(String query, List<String> imageTitleList) {
276+
if (TextUtils.isEmpty(query)) {
277+
return gpsCategories()
278+
.concatWith(titleCategories(imageTitleList))
279+
.concatWith(recentCategories());
280+
}
281+
282+
return mwApi
283+
.searchCategories(query, SEARCH_CATS_LIMIT)
284+
.map(s -> new CategoryItem(s, false));
285+
}
286+
287+
/**
288+
* Returns default categories
289+
*/
290+
public Observable<CategoryItem> getDefaultCategories(List<String> titleList) {
291+
Observable<CategoryItem> directCategories = directCategories();
292+
if (hasDirectCategories()) {
293+
Timber.d("Image has direct Categories");
294+
return directCategories
295+
.concatWith(gpsCategories())
296+
.concatWith(titleCategories(titleList))
297+
.concatWith(recentCategories());
298+
} else {
299+
Timber.d("Image has no direct Categories");
300+
return gpsCategories()
301+
.concatWith(titleCategories(titleList))
302+
.concatWith(recentCategories());
303+
}
304+
}
258305
}

app/src/main/java/fr/free/nrw/commons/nearby/NearbyFragment.java

+11
Original file line numberDiff line numberDiff line change
@@ -705,6 +705,17 @@ public void onPause() {
705705
}
706706
}
707707

708+
709+
/**
710+
* Centers the map in nearby fragment to a given place
711+
* @param place is new center of the map
712+
*/
713+
public void centerMapToPlace(Place place) {
714+
if (nearbyMapFragment != null) {
715+
nearbyMapFragment.centerMapToPlace(place);
716+
}
717+
}
718+
708719
public boolean isBottomSheetExpanded() { return bottomSheetBehavior.getState() == BottomSheetBehavior.STATE_EXPANDED;
709720
}
710721
}

app/src/main/java/fr/free/nrw/commons/nearby/NearbyMapFragment.java

+21-2
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,6 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container,
225225
Timber.d("curLatLng found, setting up map view...");
226226
setupMapView(savedInstanceState);
227227
}
228-
229228
setHasOptionsMenu(false);
230229

231230
return mapView;
@@ -254,6 +253,7 @@ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
254253
});
255254
}
256255

256+
257257
/**
258258
* Updates map slightly means it doesn't updates all nearby markers around. It just updates
259259
* location tracker marker of user.
@@ -719,7 +719,6 @@ private void addNearbyMarkersToMapBoxMap(@Nullable List<NearbyBaseMarker> custom
719719
passInfoToSheet(place);
720720
bottomSheetListBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
721721
bottomSheetDetailsBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
722-
723722
}
724723
return false;
725724
});
@@ -1040,6 +1039,25 @@ public LatLng evaluate(float fraction, LatLng startValue, LatLng endValue) {
10401039
}
10411040
}
10421041

1042+
/**
1043+
* Centers the map in nearby fragment to a given place
1044+
* @param place is new center of the map
1045+
*/
1046+
public void centerMapToPlace(Place place) {
1047+
mapView.getMapAsync(mapboxMap1 -> {
1048+
CameraPosition position = new CameraPosition.Builder()
1049+
.target(isBottomListSheetExpanded ?
1050+
new LatLng(place.location.getLatitude()- CAMERA_TARGET_SHIFT_FACTOR_LANDSCAPE,
1051+
place.getLocation().getLongitude())
1052+
: new LatLng(place.getLocation().getLatitude(), place.getLocation().getLongitude(), 0)) // Sets the new camera position
1053+
.zoom(isBottomListSheetExpanded ?
1054+
ZOOM_LEVEL
1055+
:mapboxMap.getCameraPosition().zoom) // Same zoom level
1056+
.build();
1057+
mapboxMap.animateCamera(CameraUpdateFactory.newCameraPosition(position), 1000);
1058+
});
1059+
}
1060+
10431061

10441062
public void updateMarker(boolean isBookmarked, Place place) {
10451063

@@ -1077,5 +1095,6 @@ public void updateMarker(boolean isBookmarked, Place place) {
10771095

10781096
}
10791097

1098+
10801099
}
10811100

app/src/main/java/fr/free/nrw/commons/nearby/NearbyNotificationCardView.java

+13-3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
import fr.free.nrw.commons.utils.ViewUtil;
1818
import timber.log.Timber;
1919

20+
import static fr.free.nrw.commons.contributions.MainActivity.NEARBY_TAB_POSITION;
21+
2022
/**
2123
* Custom card view for nearby notification card view on main screen, above contributions list
2224
*/
@@ -66,7 +68,6 @@ private void init() {
6668

6769
progressBar = rootView.findViewById(R.id.progressBar);
6870

69-
setActionListeners();
7071
}
7172

7273
@Override
@@ -81,8 +82,16 @@ protected void onAttachedToWindow() {
8182
}
8283

8384

84-
private void setActionListeners() {
85-
this.setOnClickListener(view -> ((MainActivity)getContext()).viewPager.setCurrentItem(1));
85+
private void setActionListeners(Place place) {
86+
this.setOnClickListener(view -> {
87+
MainActivity m = (MainActivity) getContext();
88+
89+
// Change to nearby tab
90+
m.viewPager.setCurrentItem(NEARBY_TAB_POSITION);
91+
92+
// Center the map to the place
93+
((NearbyFragment) m.contributionsActivityPagerAdapter.getItem(NEARBY_TAB_POSITION)).centerMapToPlace(place);
94+
});
8695
}
8796

8897
@Override public boolean onSwipe(View view) {
@@ -120,6 +129,7 @@ public void updateContent(Place place) {
120129
contentLayout.setVisibility(VISIBLE);
121130
// Make progress bar invisible once data is ready
122131
progressBar.setVisibility(GONE);
132+
setActionListeners(place);
123133
// And content views visible since they are ready
124134
notificationTitle.setVisibility(VISIBLE);
125135
notificationDistance.setVisibility(VISIBLE);

app/src/main/java/fr/free/nrw/commons/nearby/PlaceRenderer.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,12 @@ protected void hookListeners(View view) {
116116
((LinearLayoutManager) recyclerView.getLayoutManager()).scrollToPositionWithOffset(lastPosition, buttonLayout.getHeight());
117117
}
118118
}
119-
119+
if (onBookmarkClick == null) {
120+
((NearbyFragment) fragment.getParentFragment()).centerMapToPlace(place);
121+
}
120122
};
121123
view.setOnClickListener(listener);
124+
122125
view.requestFocus();
123126
view.setOnFocusChangeListener((view1, hasFocus) -> {
124127
if (!hasFocus && buttonLayout.isShown()) {

app/src/main/java/fr/free/nrw/commons/notification/NotificationActivity.java

+1
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ private void setAdapter(List<Notification> notificationList) {
225225
public void notificationClicked(Notification notification) {
226226
Timber.d("Notification clicked %s", notification.link);
227227
handleUrl(notification.link);
228+
removeNotification(notification);
228229
}
229230

230231
@Override

app/src/main/java/fr/free/nrw/commons/notification/NotificationRenderer.java

+2-29
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
import android.widget.RelativeLayout;
1010
import android.widget.TextView;
1111

12-
import com.daimajia.swipe.SwipeLayout;
1312
import com.google.android.material.animation.ArgbEvaluatorCompat;
1413
import com.pedrogomez.renderers.Renderer;
1514

@@ -32,12 +31,8 @@ public class NotificationRenderer extends Renderer<Notification> {
3231
TextView time;
3332
@BindView(R.id.icon)
3433
ImageView icon;
35-
@BindView(R.id.swipeLayout)
36-
SwipeLayout swipeLayout;
37-
@BindView(R.id.bottom)
38-
LinearLayout bottomLayout;
39-
@BindView(R.id.notification_view)
40-
RelativeLayout notificationView;
34+
/*@BindView(R.id.bottom)
35+
LinearLayout bottomLayout;*/
4136

4237
private NotificationClicked listener;
4338
private boolean isarchivedvisible = false;
@@ -53,13 +48,6 @@ void onNotificationClicked() {
5348
listener.notificationClicked(getContent());
5449
}
5550

56-
@OnClick(R.id.bottom)
57-
void onBottomLayoutClicked(){
58-
Notification notification = getContent();
59-
Timber.d("NotificationID: %s", notification.notificationId);
60-
listener.markNotificationAsRead(notification);
61-
}
62-
6351
@Override
6452
protected void setUpView(View rootView) {
6553

@@ -74,21 +62,6 @@ protected void hookListeners(View rootView) {
7462
protected View inflate(LayoutInflater layoutInflater, ViewGroup viewGroup) {
7563
View inflatedView = layoutInflater.inflate(R.layout.item_notification, viewGroup, false);
7664
ButterKnife.bind(this, inflatedView);
77-
if (isarchivedvisible) {
78-
swipeLayout.setSwipeEnabled(false);
79-
}else {
80-
swipeLayout.setSwipeEnabled(true);
81-
}
82-
swipeLayout.addDrag(SwipeLayout.DragEdge.Top, bottomLayout);
83-
swipeLayout.addRevealListener(R.id.bottom_wrapper_child1, (child, edge, fraction, distance) -> {
84-
View star = child.findViewById(R.id.star);
85-
float d = child.getHeight() / 2 - star.getHeight() / 2;
86-
star.setTranslationY(d * fraction);
87-
star.setScaleX(fraction + 0.6f);
88-
star.setScaleY(fraction + 0.6f);
89-
int c = ArgbEvaluatorCompat.getInstance().evaluate(fraction, Color.parseColor("#dddddd"), Color.parseColor("#90960a0a"));
90-
child.setBackgroundColor(c);
91-
});
9265
return inflatedView;
9366
}
9467

app/src/main/java/fr/free/nrw/commons/repository/UploadRemoteDataSource.java

+18-3
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,8 @@
1111
import fr.free.nrw.commons.upload.UploadModel.UploadItem;
1212
import io.reactivex.Observable;
1313
import io.reactivex.Single;
14-
1514
import java.util.Comparator;
1615
import java.util.List;
17-
1816
import javax.inject.Inject;
1917
import javax.inject.Singleton;
2018

@@ -167,7 +165,7 @@ public Observable<UploadItem> preProcessImage(UploadableFile uploadableFile, Pla
167165
}
168166

169167
/**
170-
* ask the UplaodModel for the image quality of the UploadItem
168+
* ask the UploadModel for the image quality of the UploadItem
171169
*
172170
* @param uploadItem
173171
* @param shouldValidateTitle
@@ -176,4 +174,21 @@ public Observable<UploadItem> preProcessImage(UploadableFile uploadableFile, Pla
176174
public Single<Integer> getImageQuality(UploadItem uploadItem, boolean shouldValidateTitle) {
177175
return uploadModel.getImageQuality(uploadItem, shouldValidateTitle);
178176
}
177+
178+
/**
179+
* Ask the CategoriesModel to search categories
180+
* @param query
181+
* @param imageTitleList
182+
* @return
183+
*/
184+
public Observable<CategoryItem> searchCategories(String query, List<String> imageTitleList) {
185+
return categoriesModel.searchCategories(query, imageTitleList);
186+
}
187+
188+
/**
189+
* Ask the CategoriesModel for default categories
190+
*/
191+
public Observable<CategoryItem> getDefaultCategories(List<String> imageTitleList) {
192+
return categoriesModel.getDefaultCategories(imageTitleList);
193+
}
179194
}

app/src/main/java/fr/free/nrw/commons/repository/UploadRepository.java

+14-2
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,8 @@
88
import fr.free.nrw.commons.upload.UploadModel.UploadItem;
99
import io.reactivex.Observable;
1010
import io.reactivex.Single;
11-
1211
import java.util.Comparator;
1312
import java.util.List;
14-
1513
import javax.inject.Inject;
1614
import javax.inject.Singleton;
1715

@@ -262,4 +260,18 @@ public String getValue(String key, String value) {
262260
public void setSelectedLicense(String licenseName) {
263261
localDataSource.setSelectedLicense(licenseName);
264262
}
263+
264+
/**
265+
* Ask the RemoteDataSource to search for categories
266+
*/
267+
public Observable<CategoryItem> searchCategories(String query, List<String> imageTitleList) {
268+
return remoteDataSource.searchCategories(query, imageTitleList);
269+
}
270+
271+
/**
272+
* Ask the RemoteDataSource to get default categories
273+
*/
274+
public Observable<CategoryItem> getDefaultCategories(List<String> imageTitleList) {
275+
return remoteDataSource.getDefaultCategories(imageTitleList);
276+
}
265277
}

app/src/main/java/fr/free/nrw/commons/settings/SettingsFragment.java

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
11
package fr.free.nrw.commons.settings;
22

33
import android.Manifest;
4-
import android.content.SharedPreferences;
54
import android.net.Uri;
65
import android.os.Bundle;
76
import android.preference.EditTextPreference;
8-
import android.preference.MultiSelectListPreference;
97
import android.preference.ListPreference;
108
import android.preference.Preference;
119
import android.preference.PreferenceFragment;
12-
import android.preference.PreferenceManager;
1310
import android.preference.SwitchPreference;
1411
import android.text.Editable;
1512
import android.text.TextWatcher;
@@ -31,6 +28,7 @@
3128
import fr.free.nrw.commons.di.ApplicationlessInjection;
3229
import fr.free.nrw.commons.kvstore.JsonKvStore;
3330
import fr.free.nrw.commons.logging.CommonsLogSender;
31+
import fr.free.nrw.commons.ui.LongTitlePreferences.LongTitleMultiSelectListPreference;
3432
import fr.free.nrw.commons.utils.PermissionUtils;
3533
import fr.free.nrw.commons.utils.ViewUtil;
3634
import fr.free.nrw.commons.upload.Language;
@@ -70,8 +68,9 @@ public void onCreate(Bundle savedInstanceState) {
7068
return true;
7169
});
7270

73-
MultiSelectListPreference multiSelectListPref = (MultiSelectListPreference) findPreference("manageExifTags");
71+
LongTitleMultiSelectListPreference multiSelectListPref = (LongTitleMultiSelectListPreference) findPreference("manageExifTags");
7472
if (multiSelectListPref != null) {
73+
defaultKvStore.putJson(Prefs.MANAGED_EXIF_TAGS, multiSelectListPref.getValues());
7574
multiSelectListPref.setOnPreferenceChangeListener((preference, newValue) -> {
7675
defaultKvStore.putJson(Prefs.MANAGED_EXIF_TAGS, newValue);
7776
return true;

0 commit comments

Comments
 (0)