Skip to content

Commit 1576212

Browse files
byerlyb20ashishkumar468
authored andcommitted
Fixes commons-app#3694 Pre-select places as depictions (commons-app#4452)
* WikidataEditService: stop automatically adding WikidataPlace as a depiction When the user initiates the upload process from Nearby and also manually adds the place as a depiction, the depiction is added twice. Since this behavior is invisible to the user, it is being removed in preparation for auto-selecting the place as a depiction on the DepictsFragment screen. * DepictsFragment: auto-select place as a depiction Pass the Place reference from UploadActivity to DepictsFragment and select the corresponding DepictedItem. Using the place id, retrieve the corresponding Entity to create and select a DepictedItem. * UploadRepository: use Place from UploadItem to obtain a DepictedItem Instead of passing a Place object from UploadActivity to DepictsFragment and then passing the Place object up the chain to obtain and select a DepictedItem, retrieve the Place object directly within UploadRepository * DepictsFragment: select Place depiction when fragment becomes visible * UploadDepictsAdapter: make adapter aware of selection state Update selection state when recycled list items are automatically selected, preventing automatically selected items from appearing as unselected until they are forced to re-bind (i.e. after scrolling) * DepictsFragment: pre-select place depictions for all UploadItems If several images are selected and set to different places, pre-select all place depictions to reinforce the intended upload workflow philosophy (i.e. all images in a set are intended to be from/of the same place). See discussion in commons-app#3694 * DepictsFragment: scroll to the top every time list is updated
1 parent 37a250a commit 1576212

File tree

7 files changed

+85
-15
lines changed

7 files changed

+85
-15
lines changed

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

+20
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,11 @@
1919
import io.reactivex.Observable;
2020
import io.reactivex.Single;
2121
import java.io.IOException;
22+
import java.util.ArrayList;
23+
import java.util.HashSet;
2224
import java.util.List;
2325
import java.util.Locale;
26+
import java.util.Set;
2427
import javax.inject.Inject;
2528
import javax.inject.Singleton;
2629

@@ -254,6 +257,23 @@ public Flowable<List<DepictedItem>> searchAllEntities(String query) {
254257
return depictModel.searchAllEntities(query);
255258
}
256259

260+
/**
261+
* Gets the depiction for each unique {@link Place} associated with an {@link UploadItem}
262+
* from {@link #getUploads()}
263+
*
264+
* @return a single that provides the depictions
265+
*/
266+
public Single<List<DepictedItem>> getPlaceDepictions() {
267+
final Set<Place> places = new HashSet<>();
268+
for (final UploadItem item : getUploads()) {
269+
final Place place = item.getPlace();
270+
if (place != null) {
271+
places.add(place);
272+
}
273+
}
274+
return depictModel.getPlaceDepictions(new ArrayList<>(places));
275+
}
276+
257277
/**
258278
* Returns nearest place matching the passed latitude and longitude
259279
* @param decLatitude

app/src/main/java/fr/free/nrw/commons/upload/depicts/DepictsContract.java

+5
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,11 @@ interface UserActionListener extends BasePresenter<View> {
6060
*/
6161
void searchForDepictions(String query);
6262

63+
/**
64+
* Selects all associated places (if any) as depictions
65+
*/
66+
void selectPlaceDepictions();
67+
6368
/**
6469
* Check if depictions were selected
6570
* from the depiction list

app/src/main/java/fr/free/nrw/commons/upload/depicts/DepictsFragment.java

+9
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,14 @@ private void initRecyclerView() {
100100
depictsRecyclerView.setAdapter(adapter);
101101
}
102102

103+
@Override
104+
protected void onBecameVisible() {
105+
super.onBecameVisible();
106+
// Select Place depiction as the fragment becomes visible to ensure that the most up to date
107+
// Place is used (i.e. if the user accepts a nearby place dialog)
108+
presenter.selectPlaceDepictions();
109+
}
110+
103111
@Override
104112
public void goToNextScreen() {
105113
callback.onNextButtonClicked(callback.getIndexInViewFlipper(this));
@@ -146,6 +154,7 @@ public void showError(Boolean value) {
146154
@Override
147155
public void setDepictsList(List<DepictedItem> depictedItemList) {
148156
adapter.setItems(depictedItemList);
157+
depictsRecyclerView.smoothScrollToPosition(0);
149158
}
150159

151160
@OnClick(R.id.depicts_next)

app/src/main/java/fr/free/nrw/commons/upload/depicts/DepictsPresenter.kt

+29
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,35 @@ class DepictsPresenter @Inject constructor(
8484
compositeDisposable.clear()
8585
}
8686

87+
/**
88+
* Selects the place depictions retrieved by the repository
89+
*/
90+
override fun selectPlaceDepictions() {
91+
compositeDisposable.add(repository.placeDepictions
92+
.subscribeOn(ioScheduler)
93+
.observeOn(mainThreadScheduler)
94+
.subscribe(::selectNewDepictions)
95+
)
96+
}
97+
98+
/**
99+
* Selects each [DepictedItem] in a given list as if they were clicked by the user by calling
100+
* [onDepictItemClicked] for each depiction and adding the depictions to [depictedItems]
101+
*/
102+
private fun selectNewDepictions(toSelect: List<DepictedItem>) {
103+
toSelect.forEach {
104+
it.isSelected = true
105+
repository.onDepictItemClicked(it)
106+
}
107+
108+
// Add the new selections to the list of depicted items so that the selections appear
109+
// immediately (i.e. without any search term queries)
110+
depictedItems.value?.toMutableList()
111+
?.let { toSelect + it }
112+
?.distinctBy(DepictedItem::id)
113+
?.let { depictedItems.value = it }
114+
}
115+
87116
override fun onPreviousButtonClicked() {
88117
view.goToPreviousScreen()
89118
}

app/src/main/java/fr/free/nrw/commons/upload/depicts/UploadDepictsAdapter.kt

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ import fr.free.nrw.commons.upload.structure.depictions.DepictedItem
66
class UploadDepictsAdapter(onDepictsClicked: (DepictedItem) -> Unit) :
77
BaseDelegateAdapter<DepictedItem>(
88
uploadDepictsDelegate(onDepictsClicked),
9-
areItemsTheSame = { oldItem, newItem -> oldItem.id == newItem.id }
9+
areItemsTheSame = { oldItem, newItem -> oldItem.id == newItem.id },
10+
areContentsTheSame = { itemA, itemB -> itemA.isSelected == itemB.isSelected}
1011
)

app/src/main/java/fr/free/nrw/commons/upload/structure/depictions/DepictModel.kt

+19-8
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package fr.free.nrw.commons.upload.structure.depictions
33
import fr.free.nrw.commons.explore.depictions.DepictsClient
44
import fr.free.nrw.commons.nearby.Place
55
import io.reactivex.Flowable
6+
import io.reactivex.Observable
67
import io.reactivex.Single
78
import io.reactivex.processors.BehaviorProcessor
89
import timber.log.Timber
@@ -27,19 +28,29 @@ class DepictModel @Inject constructor(private val depictsClient: DepictsClient)
2728
fun searchAllEntities(query: String): Flowable<List<DepictedItem>> {
2829
return if (query.isBlank())
2930
nearbyPlaces.switchMap { places: List<Place> ->
30-
depictsClient.getEntities(places.toIds())
31-
.map {
32-
it.entities()
33-
.values
34-
.mapIndexed { index, entity -> DepictedItem(entity, places[index]) }
35-
}
36-
.onErrorResumeWithEmptyList()
37-
.toFlowable()
31+
getPlaceDepictions(places).toFlowable()
3832
}
3933
else
4034
networkItems(query)
4135
}
4236

37+
/**
38+
* Provides [DepictedItem] instances via a [Single] for a given list of [Place], providing an
39+
* empty list if no places are provided or if there is an error
40+
*/
41+
fun getPlaceDepictions(places: List<Place>): Single<List<DepictedItem>> =
42+
places.toIds().let { ids ->
43+
if (ids.isNotEmpty())
44+
depictsClient.getEntities(ids)
45+
.map{
46+
it.entities()
47+
.values
48+
.mapIndexed { index, entity -> DepictedItem(entity, places[index])}
49+
}
50+
.onErrorResumeWithEmptyList()
51+
else Single.just(emptyList())
52+
}
53+
4354
private fun networkItems(query: String): Flowable<List<DepictedItem>> {
4455
return depictsClient.searchForDepictions(query, SEARCH_DEPICTS_LIMIT, 0)
4556
.onErrorResumeWithEmptyList()

app/src/main/java/fr/free/nrw/commons/wikidata/WikidataEditService.java

+1-6
Original file line numberDiff line numberDiff line change
@@ -206,12 +206,7 @@ private Observable<Boolean> captionEdits(Contribution contribution, Long fileEnt
206206
}
207207

208208
private Observable<Boolean> depictionEdits(Contribution contribution, Long fileEntityId) {
209-
final ArrayList<WikidataItem> depictedItems = new ArrayList<>(contribution.getDepictedItems());
210-
final WikidataPlace wikidataPlace = contribution.getWikidataPlace();
211-
if (wikidataPlace != null) {
212-
depictedItems.add(wikidataPlace);
213-
}
214-
return Observable.fromIterable(depictedItems)
209+
return Observable.fromIterable(contribution.getDepictedItems())
215210
.concatMap(wikidataItem -> addDepictsProperty(fileEntityId.toString(), wikidataItem));
216211
}
217212
}

0 commit comments

Comments
 (0)