Skip to content

Commit 7a5dc77

Browse files
ashishkumar468maskaravivek
authored andcommitted
Refactor uploads (commons-app#2981)
* Feature/refractor uploads [WIP] (commons-app#2887) * Fix duplicate param information (commons-app#2515) * Bug fix issue commons-app#2476 (commons-app#2526) * Added wikidataEntityID in all db versions, handled db.execSql via method runQuery * Versioning and changelog for v2.10.2 (commons-app#2531) * Update changelog.md * Versioning for v2.10.2 * Update changelog.md * Bugfix/issue 2580 (commons-app#2584) * Corrected string placedholders in certain string files * Corrected string placedholders in certain string files[Bug fix commons-app#2580] * Bug Fix commons-app#2585 (commons-app#2647) * Bug Fix commons-app#2585 * Added null checks on view in SearchImageFragment when updating views from external sources * Disposed the disposables in SearchActivity and SearchImageFragment when no longer in active lifecycle * use FragmentUtils to verify fragment active state * Bug Fix issue commons-app#2648 (commons-app#2678) * Bug Fix issue commons-app#2648 * Handled external storage permission before file download * * Removed redudant check for permission in MediaDetailPagerFragment (Dexter already does that) * Removed duplicate code in PermissionUtil$checkPermissionsAndPerformAction, used the existing function with conditional extra parameters * string name typo correction * BugFix issue commons-app#2652 (commons-app#2706) * Addded null check on bookmark before operating on it * BugFix issue commons-app#2711 (commons-app#2712) * Added null checks in OkHttpJsonApiClient$searchImages MwQueryResponse * BugFix commons-app#2718 (commons-app#2719) * Handled null auth cookies * Fix commons-app#2791: NPE when nominating for deletion and leaving screen (commons-app#2792) * Bug Fix issue commons-app#2789 (commons-app#2790) * Handled Illegal State Exception for non existent appropriate view parents in ViewUtils$showShortSnackbar * BugFix commons-app#2720 (commons-app#2831) BugFix deprecated licenes commons-app#2720 * ui fixes, wip, upload * *Issue commons-app#2886, BugFix commons-app#2832[wip] * updated UploadActivity code * modified ui * Updated UploadPresenterTest * * updated interfaces names to follow names suffixed with Contract * added test cases * card view elevation * view pager disabled swipe * bug fix, duplicate image * used existing non-swipable view pager * Avoid image view resize with keyboard, added adjustPan and stateVisible as softinputMode for UploadActivity * retain UploadBaseFragment instances on orientation changes * * Added test cases for UploadMediaPresenter * Injected io and main thread schedulers * categories presenter test cased wip * Added CategoriesPresenter test * * Added the logic to show open map (with to be uploaded image's coordinates while uploading image) * codacy suggested changes * added java docs * Added travis_wait fot android-wait-for-emulator * ranamed interface onResponseCallback to Callback * * Added api to delete picture in UploadModel * cleanUp in UploadModel. once upload has been initiated * Removed unused methods from UploadModel and the corresponding test class * * Added tests for UploadPresenter * Travis suggested changes * Addded copy previous title and description * * Made the upload add descriptions visible when keyboard visible * add description request focus only when user manually requests it * Added JavaDocs, review suggested changes * Fix dagger injection * use DialogUtil to show info in descriptions * use activity context for DialogUtil * Minor changes * Bug fix, reduced the add description edit text clickable bound (commons-app#2973) * Bugfix/uploads (commons-app#3000) * merged with master * BugFix IllegalStateException * setRetainState(true), not required with FragmentStatePagerAdapter * Increase the ViewPager's Offscreen Limit, we want all the fragments to be active * BugFix, clear selected categoris for previous upload session * Clear Selected Categories * Addded JavaDocs for CategoriesModel * Code Formatting in app/src/main/java/fr/free/nrw/commons/upload/UploadModel.java * Added class level JavaDoc UploadRemoteDataSource * Added class level JavaDoc for UploadRepository * Added JavaDocs for ThumbnailsAdapter * Added JavaDocs for MediaLicensePresenter, CategoriesPresenter * Removed null check on category query * Show default catgeories based on image title and gps location when category text empty * Allow search for empty category search * Attached image scale listener to upload media image * Bug fix, reduced the add description edit text clickable bound * Fix memory leak (commons-app#3001) * Bugfix/uploads (commons-app#3002) * merged with master * BugFix IllegalStateException * setRetainState(true), not required with FragmentStatePagerAdapter * Increase the ViewPager's Offscreen Limit, we want all the fragments to be active * BugFix, clear selected categoris for previous upload session * Clear Selected Categories * Addded JavaDocs for CategoriesModel * Code Formatting in app/src/main/java/fr/free/nrw/commons/upload/UploadModel.java * Added class level JavaDoc UploadRemoteDataSource * Added class level JavaDoc for UploadRepository * Added JavaDocs for ThumbnailsAdapter * Added JavaDocs for MediaLicensePresenter, CategoriesPresenter * Removed null check on category query * Show default catgeories based on image title and gps location when category text empty * Allow search for empty category search * Attached image scale listener to upload media image * Bug fix, reduced the add description edit text clickable bound * Added tooltip in Title in UploadMediaFragment * BugFix recent categories * Updated test methods * Bugfix/uploads (commons-app#3011) * merged with master * BugFix IllegalStateException * setRetainState(true), not required with FragmentStatePagerAdapter * Increase the ViewPager's Offscreen Limit, we want all the fragments to be active * BugFix, clear selected categoris for previous upload session * Clear Selected Categories * Addded JavaDocs for CategoriesModel * Code Formatting in app/src/main/java/fr/free/nrw/commons/upload/UploadModel.java * Added class level JavaDoc UploadRemoteDataSource * Added class level JavaDoc for UploadRepository * Added JavaDocs for ThumbnailsAdapter * Added JavaDocs for MediaLicensePresenter, CategoriesPresenter * Removed null check on category query * Show default catgeories based on image title and gps location when category text empty * Allow search for empty category search * Attached image scale listener to upload media image * Bug fix, reduced the add description edit text clickable bound * Added tooltip in Title in UploadMediaFragment * BugFix recent categories * Updated test methods * Avoid memory leak, free the adpater in MediaLicenseFragment.onDestroyView * bugfix/uploads (commons-app#3012) * merged with master * BugFix IllegalStateException * setRetainState(true), not required with FragmentStatePagerAdapter * Increase the ViewPager's Offscreen Limit, we want all the fragments to be active * BugFix, clear selected categoris for previous upload session * Clear Selected Categories * Addded JavaDocs for CategoriesModel * Code Formatting in app/src/main/java/fr/free/nrw/commons/upload/UploadModel.java * Added class level JavaDoc UploadRemoteDataSource * Added class level JavaDoc for UploadRepository * Added JavaDocs for ThumbnailsAdapter * Added JavaDocs for MediaLicensePresenter, CategoriesPresenter * Removed null check on category query * Show default catgeories based on image title and gps location when category text empty * Allow search for empty category search * Attached image scale listener to upload media image * Bug fix, reduced the add description edit text clickable bound * Added tooltip in Title in UploadMediaFragment * BugFix recent categories * Updated test methods * Avoid memory leak, free the adpater in MediaLicenseFragment.onDestroyView * BugFix Illegal State Exception in ViewpPagerAdapter * Remove irrelevant comment * merge conflict with strings (commons-app#3016)
1 parent 04b051b commit 7a5dc77

File tree

68 files changed

+3742
-2075
lines changed

Some content is hidden

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

68 files changed

+3742
-2075
lines changed

app/build.gradle

+2
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ dependencies {
6565
testImplementation 'androidx.test:core:1.2.0'
6666
testImplementation 'com.nhaarman:mockito-kotlin:1.5.0'
6767
testImplementation 'com.squareup.okhttp3:mockwebserver:3.10.0'
68+
testImplementation "org.powermock:powermock-module-junit4:2.0.0-beta.5"
69+
testImplementation "org.powermock:powermock-api-mockito2:2.0.0-beta.5"
6870

6971
// Android testing
7072
androidTestImplementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$KOTLIN_VERSION"

app/src/main/AndroidManifest.xml

+5-2
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,13 @@
5050
</activity>
5151
<activity android:name=".WelcomeActivity" />
5252

53-
<activity android:name=".upload.UploadActivity"
53+
<activity
54+
android:name=".upload.UploadActivity"
55+
android:configChanges="orientation|screenSize|keyboard"
5456
android:icon="@mipmap/ic_launcher"
5557
android:label="@string/app_name"
56-
android:configChanges="orientation|screenSize|keyboard">
58+
android:windowSoftInputMode="adjustResize"
59+
>
5760
<intent-filter android:label="@string/intent_share_upload_label">
5861
<action android:name="android.intent.action.SEND" />
5962

app/src/main/java/fr/free/nrw/commons/BasePresenter.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
/**
44
* Base presenter, enforcing contracts to atach and detach view
55
*/
6-
public interface BasePresenter {
6+
public interface BasePresenter<T> {
77
/**
88
* Until a view is attached, it is open to listen events from the presenter
99
*/
10-
void onAttachView(MvpView view);
10+
void onAttachView(T view);
1111

1212
/**
1313
* Detaching a view makes sure that the view no more receives events from the presenter

app/src/main/java/fr/free/nrw/commons/Utils.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,16 @@
1111

1212
import org.wikipedia.dataclient.WikiSite;
1313
import org.wikipedia.page.PageTitle;
14+
import fr.free.nrw.commons.location.LatLng;
15+
import fr.free.nrw.commons.utils.ViewUtil;
1416

1517
import java.util.Locale;
1618
import java.util.regex.Pattern;
1719

1820
import androidx.annotation.NonNull;
1921
import androidx.browser.customtabs.CustomTabsIntent;
2022
import androidx.core.content.ContextCompat;
21-
import fr.free.nrw.commons.location.LatLng;
2223
import fr.free.nrw.commons.settings.Prefs;
23-
import fr.free.nrw.commons.utils.ViewUtil;
2424
import timber.log.Timber;
2525

2626
import static android.widget.Toast.LENGTH_SHORT;

app/src/main/java/fr/free/nrw/commons/campaigns/CampaignsPresenter.java

+4-3
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
* success and error
2929
*/
3030
@Singleton
31-
public class CampaignsPresenter implements BasePresenter {
31+
public class CampaignsPresenter implements BasePresenter<ICampaignsView> {
3232
private final OkHttpJsonApiClient okHttpJsonApiClient;
3333

3434
private ICampaignsView view;
@@ -40,8 +40,9 @@ public CampaignsPresenter(OkHttpJsonApiClient okHttpJsonApiClient) {
4040
this.okHttpJsonApiClient = okHttpJsonApiClient;
4141
}
4242

43-
@Override public void onAttachView(MvpView view) {
44-
this.view = (ICampaignsView) view;
43+
@Override
44+
public void onAttachView(ICampaignsView view) {
45+
this.view = view;
4546
}
4647

4748
@Override public void onDetachView() {
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,25 @@
11
package fr.free.nrw.commons.category;
22

33
import android.text.TextUtils;
4-
4+
import fr.free.nrw.commons.kvstore.JsonKvStore;
5+
import fr.free.nrw.commons.mwapi.MediaWikiApi;
6+
import fr.free.nrw.commons.upload.GpsCategoryModel;
7+
import fr.free.nrw.commons.utils.StringSortingUtils;
8+
import io.reactivex.Observable;
59
import java.util.ArrayList;
610
import java.util.Calendar;
711
import java.util.Comparator;
812
import java.util.Date;
913
import java.util.HashMap;
1014
import java.util.List;
11-
1215
import javax.inject.Inject;
1316
import javax.inject.Named;
14-
15-
import fr.free.nrw.commons.kvstore.JsonKvStore;
16-
import fr.free.nrw.commons.mwapi.MediaWikiApi;
17-
import fr.free.nrw.commons.upload.GpsCategoryModel;
18-
import fr.free.nrw.commons.utils.StringSortingUtils;
19-
import io.reactivex.Observable;
2017
import timber.log.Timber;
2118

22-
public class CategoriesModel implements CategoryClickedListener {
19+
/**
20+
* The model class for categories in upload
21+
*/
22+
public class CategoriesModel{
2323
private static final int SEARCH_CATS_LIMIT = 25;
2424

2525
private final MediaWikiApi mwApi;
@@ -41,13 +41,22 @@ public CategoriesModel(MediaWikiApi mwApi,
4141
this.selectedCategories = new ArrayList<>();
4242
}
4343

44-
//region Misc. utility methods
44+
/**
45+
* Sorts CategoryItem by similarity
46+
* @param filter
47+
* @return
48+
*/
4549
public Comparator<CategoryItem> sortBySimilarity(final String filter) {
4650
Comparator<String> stringSimilarityComparator = StringSortingUtils.sortBySimilarity(filter);
4751
return (firstItem, secondItem) -> stringSimilarityComparator
4852
.compare(firstItem.getName(), secondItem.getName());
4953
}
5054

55+
/**
56+
* Returns if the item contains an year
57+
* @param item
58+
* @return
59+
*/
5160
public boolean containsYear(String item) {
5261
//Check for current and previous year to exclude these categories from removal
5362
Calendar now = Calendar.getInstance();
@@ -67,6 +76,10 @@ public boolean containsYear(String item) {
6776
|| (item.matches(".*0s.*") && !item.matches(".*(200|201)0s.*")));
6877
}
6978

79+
/**
80+
* Updates category count in category dao
81+
* @param item
82+
*/
7083
public void updateCategoryCount(CategoryItem item) {
7184
Category category = categoryDao.find(item.getName());
7285

@@ -78,29 +91,27 @@ public void updateCategoryCount(CategoryItem item) {
7891
category.incTimesUsed();
7992
categoryDao.save(category);
8093
}
81-
//endregion
82-
83-
//region Category Caching
84-
public void cacheAll(HashMap<String, ArrayList<String>> categories) {
85-
categoriesCache.putAll(categories);
86-
}
87-
88-
public HashMap<String, ArrayList<String>> getCategoriesCache() {
89-
return categoriesCache;
90-
}
9194

9295
boolean cacheContainsKey(String term) {
9396
return categoriesCache.containsKey(term);
9497
}
9598
//endregion
9699

97-
//region Category searching
100+
/**
101+
* Regional category search
102+
* @param term
103+
* @param imageTitleList
104+
* @return
105+
*/
98106
public Observable<CategoryItem> searchAll(String term, List<String> imageTitleList) {
99-
//If user hasn't typed anything in yet, get GPS and recent items
107+
//If query text is empty, show him category based on gps and title and recent searches
100108
if (TextUtils.isEmpty(term)) {
101-
return gpsCategories()
102-
.concatWith(titleCategories(imageTitleList))
103-
.concatWith(recentCategories());
109+
Observable<CategoryItem> categoryItemObservable = gpsCategories()
110+
.concatWith(titleCategories(imageTitleList));
111+
if (hasDirectCategories()) {
112+
categoryItemObservable.concatWith(directCategories().concatWith(recentCategories()));
113+
}
114+
return categoryItemObservable;
104115
}
105116

106117
//if user types in something that is in cache, return cached category
@@ -115,43 +126,28 @@ public Observable<CategoryItem> searchAll(String term, List<String> imageTitleLi
115126
.map(name -> new CategoryItem(name, false));
116127
}
117128

118-
public Observable<CategoryItem> searchCategories(String term, List<String> imageTitleList) {
119-
//If user hasn't typed anything in yet, get GPS and recent items
120-
if (TextUtils.isEmpty(term)) {
121-
return gpsCategories()
122-
.concatWith(titleCategories(imageTitleList))
123-
.concatWith(recentCategories());
124-
}
125-
126-
return mwApi
127-
.searchCategories(term, SEARCH_CATS_LIMIT)
128-
.map(s -> new CategoryItem(s, false));
129-
}
130129

130+
/**
131+
* Returns cached categories
132+
* @param term
133+
* @return
134+
*/
131135
private ArrayList<String> getCachedCategories(String term) {
132136
return categoriesCache.get(term);
133137
}
134138

135-
public Observable<CategoryItem> defaultCategories(List<String> titleList) {
136-
Observable<CategoryItem> directCat = directCategories();
137-
if (hasDirectCategories()) {
138-
Timber.d("Image has direct Cat");
139-
return directCat
140-
.concatWith(gpsCategories())
141-
.concatWith(titleCategories(titleList))
142-
.concatWith(recentCategories());
143-
} else {
144-
Timber.d("Image has no direct Cat");
145-
return gpsCategories()
146-
.concatWith(titleCategories(titleList))
147-
.concatWith(recentCategories());
148-
}
149-
}
150-
139+
/**
140+
* Returns if we have a category in DirectKV Store
141+
* @return
142+
*/
151143
private boolean hasDirectCategories() {
152144
return !directKvStore.getString("Category", "").equals("");
153145
}
154146

147+
/**
148+
* Returns categories in DirectKVStore
149+
* @return
150+
*/
155151
private Observable<CategoryItem> directCategories() {
156152
String directCategory = directKvStore.getString("Category", "");
157153
List<String> categoryList = new ArrayList<>();
@@ -164,30 +160,49 @@ private Observable<CategoryItem> directCategories() {
164160
return Observable.fromIterable(categoryList).map(name -> new CategoryItem(name, false));
165161
}
166162

163+
/**
164+
* Returns GPS categories
165+
* @return
166+
*/
167167
Observable<CategoryItem> gpsCategories() {
168168
return Observable.fromIterable(gpsCategoryModel.getCategoryList())
169169
.map(name -> new CategoryItem(name, false));
170170
}
171171

172+
/**
173+
* Returns title based categories
174+
* @param titleList
175+
* @return
176+
*/
172177
private Observable<CategoryItem> titleCategories(List<String> titleList) {
173178
return Observable.fromIterable(titleList)
174179
.concatMap(this::getTitleCategories);
175180
}
176181

182+
/**
183+
* Return category for single title
184+
* @param title
185+
* @return
186+
*/
177187
private Observable<CategoryItem> getTitleCategories(String title) {
178188
return mwApi.searchTitles(title, SEARCH_CATS_LIMIT)
179189
.map(name -> new CategoryItem(name, false));
180190
}
181191

192+
/**
193+
* Returns recent categories
194+
* @return
195+
*/
182196
private Observable<CategoryItem> recentCategories() {
183197
return Observable.fromIterable(categoryDao.recentCategories(SEARCH_CATS_LIMIT))
184198
.map(s -> new CategoryItem(s, false));
185199
}
186-
//endregion
187200

188-
//region Category Selection
189-
@Override
190-
public void categoryClicked(CategoryItem item) {
201+
/**
202+
* Handles category item selection
203+
* @param item
204+
*/
205+
public void onCategoryItemClicked(CategoryItem item) {
191206
if (item.isSelected()) {
192207
selectCategory(item);
193208
updateCategoryCount(item);
@@ -196,29 +211,48 @@ public void categoryClicked(CategoryItem item) {
196211
}
197212
}
198213

214+
/**
215+
* Select's category
216+
* @param item
217+
*/
199218
public void selectCategory(CategoryItem item) {
200219
selectedCategories.add(item);
201220
}
202221

222+
/**
223+
* Unselect Category
224+
* @param item
225+
*/
203226
public void unselectCategory(CategoryItem item) {
204227
selectedCategories.remove(item);
205228
}
206229

207-
public int selectedCategoriesCount() {
208-
return selectedCategories.size();
209-
}
210230

231+
/**
232+
* Get Selected Categories
233+
* @return
234+
*/
211235
public List<CategoryItem> getSelectedCategories() {
212236
return selectedCategories;
213237
}
214238

239+
/**
240+
* Get Categories String List
241+
* @return
242+
*/
215243
public List<String> getCategoryStringList() {
216244
List<String> output = new ArrayList<>();
217245
for (CategoryItem item : selectedCategories) {
218246
output.add(item.getName());
219247
}
220248
return output;
221249
}
222-
//endregion
223250

251+
/**
252+
* Cleanup the existing in memory cache's
253+
*/
254+
public void cleanUp() {
255+
this.categoriesCache.clear();
256+
this.selectedCategories.clear();
257+
}
224258
}

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public CategoryItem[] newArray(int i) {
1919
}
2020
};
2121

22-
CategoryItem(String name, boolean selected) {
22+
public CategoryItem(String name, boolean selected) {
2323
this.name = name;
2424
this.selected = selected;
2525
}

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ ContentValues toContentValues(Contribution contribution) {
100100
cv.put(Table.COLUMN_UPLOADED, contribution.getDateUploaded().getTime());
101101
}
102102
cv.put(Table.COLUMN_LENGTH, contribution.getDataLength());
103-
//This was always meant to store the date created..If somehow date created is not fetched while actually saving the contribution, lets save today's date
103+
//This was always meant to store the date created..If somehow date created is not fetched while actually saving the contribution, lets saveValue today's date
104104
cv.put(Table.COLUMN_TIMESTAMP, contribution.getDateCreated()==null?System.currentTimeMillis():contribution.getDateCreated().getTime());
105105
cv.put(Table.COLUMN_STATE, contribution.getState());
106106
cv.put(Table.COLUMN_TRANSFERRED, contribution.getTransferred());

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import fr.free.nrw.commons.review.ReviewController;
1616
import fr.free.nrw.commons.settings.SettingsFragment;
1717
import fr.free.nrw.commons.upload.FileProcessor;
18+
import fr.free.nrw.commons.upload.UploadModule;
1819
import fr.free.nrw.commons.widget.PicOfDayAppWidget;
1920

2021

@@ -27,7 +28,7 @@
2728
ActivityBuilderModule.class,
2829
FragmentBuilderModule.class,
2930
ServiceBuilderModule.class,
30-
ContentProviderBuilderModule.class
31+
ContentProviderBuilderModule.class, UploadModule.class
3132
})
3233
public interface CommonsApplicationComponent extends AndroidInjector<ApplicationlessInjection> {
3334
void inject(CommonsApplication application);

0 commit comments

Comments
 (0)