Skip to content

Commit 60b1eb1

Browse files
ashishkumar468neslihanturan
authored andcommitted
Feature/refactor contributions (commons-app#3046)
* * Refactored ContributionsListFragment to use RecyclerView * Added ContributionsPresenter * Extracted out the cursor to presenter * Probable fix for commons-app#3028 * Improved the logic for cache in ContributionViewHolder * Some more refactoring * While displaying images in ContributionsList, check if status is not completed && local uri exists, use that uri to show image * typo correction in LocalDataSource * Fixed formatting in ContributionsPresenter * retain adapter position when orientation changes * retain child position with its id * Made ContributionViewHolder not implement ViewHolder * Code formatting, review suggested changes * initialise the rv layout managers only when needed * added test cases for ContributionPresenter * removed not needed semi colon * added more java docs and code formatting
1 parent 108e28c commit 60b1eb1

22 files changed

+810
-588
lines changed

app/src/main/java/fr/free/nrw/commons/bookmarks/BookmarksActivity.java

-27
Original file line numberDiff line numberDiff line change
@@ -135,31 +135,4 @@ public int getTotalMediaCount() {
135135
}
136136
return adapter.getMediaAdapter().getCount();
137137
}
138-
139-
/**
140-
* This method is never called but it was in MediaDetailProvider Interface
141-
* so it needs to be overrided.
142-
*/
143-
@Override
144-
public void notifyDatasetChanged() {
145-
146-
}
147-
148-
/**
149-
* This method is never called but it was in MediaDetailProvider Interface
150-
* so it needs to be overrided.
151-
*/
152-
@Override
153-
public void registerDataSetObserver(DataSetObserver observer) {
154-
155-
}
156-
157-
/**
158-
* This method is never called but it was in MediaDetailProvider Interface
159-
* so it needs to be overrided.
160-
*/
161-
@Override
162-
public void unregisterDataSetObserver(DataSetObserver observer) {
163-
164-
}
165138
}

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

-26
Original file line numberDiff line numberDiff line change
@@ -173,32 +173,6 @@ public int getTotalMediaCount() {
173173
return categoryImagesListFragment.getAdapter().getCount();
174174
}
175175

176-
/**
177-
* This method is never called but it was in MediaDetailProvider Interface
178-
* so it needs to be overrided.
179-
*/
180-
@Override
181-
public void notifyDatasetChanged() {
182-
183-
}
184-
185-
/**
186-
* This method is never called but it was in MediaDetailProvider Interface
187-
* so it needs to be overrided.
188-
*/
189-
@Override
190-
public void registerDataSetObserver(DataSetObserver observer) {
191-
}
192-
193-
/**
194-
* This method is never called but it was in MediaDetailProvider Interface
195-
* so it needs to be overrided.
196-
*/
197-
@Override
198-
public void unregisterDataSetObserver(DataSetObserver observer) {
199-
200-
}
201-
202176
/**
203177
* This method inflates the menu in the toolbar
204178
*/

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

-27
Original file line numberDiff line numberDiff line change
@@ -180,33 +180,6 @@ public int getTotalMediaCount() {
180180
return categoryImagesListFragment.getAdapter().getCount();
181181
}
182182

183-
/**
184-
* This method is never called but it was in MediaDetailProvider Interface
185-
* so it needs to be overrided.
186-
*/
187-
@Override
188-
public void notifyDatasetChanged() {
189-
190-
}
191-
192-
/**
193-
* This method is never called but it was in MediaDetailProvider Interface
194-
* so it needs to be overrided.
195-
*/
196-
@Override
197-
public void registerDataSetObserver(DataSetObserver observer) {
198-
199-
}
200-
201-
/**
202-
* This method is never called but it was in MediaDetailProvider Interface
203-
* so it needs to be overrided.
204-
*/
205-
@Override
206-
public void unregisterDataSetObserver(DataSetObserver observer) {
207-
208-
}
209-
210183
/**
211184
* This method inflates the menu in the toolbar
212185
*/

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

+52-39
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,34 @@
11
package fr.free.nrw.commons.contributions;
22

3-
import android.content.Context;
3+
import android.net.Uri;
44
import android.view.View;
55
import android.widget.LinearLayout;
66
import android.widget.ProgressBar;
77
import android.widget.TextView;
8-
98
import androidx.collection.LruCache;
10-
11-
import com.facebook.drawee.view.SimpleDraweeView;
12-
13-
import org.apache.commons.lang3.StringUtils;
14-
15-
import javax.inject.Inject;
16-
import javax.inject.Named;
17-
9+
import androidx.recyclerview.widget.RecyclerView;
1810
import butterknife.BindView;
1911
import butterknife.ButterKnife;
2012
import butterknife.OnClick;
13+
import com.facebook.drawee.view.SimpleDraweeView;
2114
import fr.free.nrw.commons.MediaDataExtractor;
2215
import fr.free.nrw.commons.R;
23-
import fr.free.nrw.commons.ViewHolder;
16+
import fr.free.nrw.commons.contributions.ContributionsListAdapter.Callback;
2417
import fr.free.nrw.commons.contributions.model.DisplayableContribution;
2518
import fr.free.nrw.commons.di.ApplicationlessInjection;
19+
import fr.free.nrw.commons.upload.FileUtils;
2620
import io.reactivex.android.schedulers.AndroidSchedulers;
2721
import io.reactivex.disposables.CompositeDisposable;
2822
import io.reactivex.disposables.Disposable;
2923
import io.reactivex.schedulers.Schedulers;
24+
import javax.inject.Inject;
25+
import javax.inject.Named;
26+
import org.apache.commons.lang3.StringUtils;
3027
import timber.log.Timber;
3128

32-
public class ContributionViewHolder implements ViewHolder<DisplayableContribution> {
29+
public class ContributionViewHolder extends RecyclerView.ViewHolder {
30+
31+
private final Callback callback;
3332
@BindView(R.id.contributionImage)
3433
SimpleDraweeView imageView;
3534
@BindView(R.id.contributionTitle) TextView titleView;
@@ -47,15 +46,18 @@ public class ContributionViewHolder implements ViewHolder<DisplayableContributio
4746

4847
private DisplayableContribution contribution;
4948
private CompositeDisposable compositeDisposable = new CompositeDisposable();
49+
private int position;
5050

51-
ContributionViewHolder(View parent) {
51+
ContributionViewHolder(View parent, Callback callback) {
52+
super(parent);
5253
ButterKnife.bind(this, parent);
54+
this.callback=callback;
5355
}
5456

55-
@Override
56-
public void bindModel(Context context, DisplayableContribution contribution) {
57-
ApplicationlessInjection.getInstance(context)
57+
public void init(int position, DisplayableContribution contribution) {
58+
ApplicationlessInjection.getInstance(itemView.getContext())
5859
.getCommonsApplicationComponent().inject(this);
60+
this.position=position;
5961
this.contribution = contribution;
6062
fetchAndDisplayThumbnail(contribution);
6163
titleView.setText(contribution.getDisplayTitle());
@@ -104,19 +106,39 @@ public void bindModel(Context context, DisplayableContribution contribution) {
104106
* @param contribution
105107
*/
106108
private void fetchAndDisplayThumbnail(DisplayableContribution contribution) {
107-
if (!StringUtils.isBlank(thumbnailCache.get(contribution.getFilename()))) {
108-
imageView.setImageURI(thumbnailCache.get(contribution.getFilename()));
109+
String keyForLRUCache = getKeyForLRUCache(contribution.getContentUri());
110+
String cacheUrl = thumbnailCache.get(keyForLRUCache);
111+
if (!StringUtils.isBlank(cacheUrl)) {
112+
imageView.setImageURI(cacheUrl);
109113
return;
110114
}
111-
Timber.d("Fetching thumbnail for %s", contribution.getFilename());
112-
Disposable disposable = mediaDataExtractor.getMediaFromFileName(contribution.getFilename())
113-
.subscribeOn(Schedulers.io())
114-
.observeOn(AndroidSchedulers.mainThread())
115-
.subscribe(media -> {
116-
thumbnailCache.put(contribution.getFilename(), media.getThumbUrl());
117-
imageView.setImageURI(media.getThumbUrl());
118-
});
119-
compositeDisposable.add(disposable);
115+
116+
imageView.setBackground(null);
117+
if ((contribution.getState() != Contribution.STATE_COMPLETED) && FileUtils.fileExists(
118+
contribution.getLocalUri())) {
119+
imageView.setImageURI(contribution.getLocalUri());
120+
} else {
121+
Timber.d("Fetching thumbnail for %s", contribution.getFilename());
122+
Disposable disposable = mediaDataExtractor
123+
.getMediaFromFileName(contribution.getFilename())
124+
.subscribeOn(Schedulers.io())
125+
.observeOn(AndroidSchedulers.mainThread())
126+
.subscribe(media -> {
127+
thumbnailCache.put(keyForLRUCache, media.getThumbUrl());
128+
imageView.setImageURI(media.getThumbUrl());
129+
});
130+
compositeDisposable.add(disposable);
131+
}
132+
133+
}
134+
135+
/**
136+
* Returns image key for the LRU cache, basically the id of the image, (the content uri is the ""+/id)
137+
* @param contentUri
138+
* @return
139+
*/
140+
private String getKeyForLRUCache(Uri contentUri) {
141+
return contentUri.getLastPathSegment();
120142
}
121143

122144
public void clear() {
@@ -128,28 +150,19 @@ public void clear() {
128150
*/
129151
@OnClick(R.id.retryButton)
130152
public void retryUpload() {
131-
DisplayableContribution.ContributionActions actions = contribution.getContributionActions();
132-
if (actions != null) {
133-
actions.retryUpload();
134-
}
153+
callback.retryUpload(contribution);
135154
}
136155

137156
/**
138157
* Delete a failed upload attempt
139158
*/
140159
@OnClick(R.id.cancelButton)
141160
public void deleteUpload() {
142-
DisplayableContribution.ContributionActions actions = contribution.getContributionActions();
143-
if (actions != null) {
144-
actions.deleteUpload();
145-
}
161+
callback.deleteUpload(contribution);
146162
}
147163

148164
@OnClick(R.id.contributionImage)
149165
public void imageClicked(){
150-
DisplayableContribution.ContributionActions actions = contribution.getContributionActions();
151-
if (actions != null) {
152-
actions.onClick();
153-
}
166+
callback.openMediaDetail(position);
154167
}
155168
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package fr.free.nrw.commons.contributions;
2+
3+
import android.database.Cursor;
4+
import androidx.loader.app.LoaderManager;
5+
import fr.free.nrw.commons.BasePresenter;
6+
import fr.free.nrw.commons.Media;
7+
8+
/**
9+
* The contract for Contributions View & Presenter
10+
*/
11+
public class ContributionsContract {
12+
13+
public interface View {
14+
15+
void showWelcomeTip(boolean numberOfUploads);
16+
17+
void showProgress(boolean shouldShow);
18+
19+
void showNoContributionsUI(boolean shouldShow);
20+
21+
void setUploadCount(int count);
22+
23+
void onDataSetChanged();
24+
}
25+
26+
public interface UserActionListener extends BasePresenter<ContributionsContract.View>,
27+
LoaderManager.LoaderCallbacks<Cursor> {
28+
29+
Contribution getContributionsFromCursor(Cursor cursor);
30+
31+
void deleteUpload(Contribution contribution);
32+
33+
Media getItemAtPosition(int i);
34+
}
35+
}

0 commit comments

Comments
 (0)