Skip to content

Refactor uploads #2981

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Jun 13, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ dependencies {
testImplementation 'androidx.test:core:1.2.0'
testImplementation 'com.nhaarman:mockito-kotlin:1.5.0'
testImplementation 'com.squareup.okhttp3:mockwebserver:3.10.0'
testImplementation "org.powermock:powermock-module-junit4:2.0.0-beta.5"
testImplementation "org.powermock:powermock-api-mockito2:2.0.0-beta.5"

// Android testing
androidTestImplementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$KOTLIN_VERSION"
Expand Down
7 changes: 5 additions & 2 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,13 @@
</activity>
<activity android:name=".WelcomeActivity" />

<activity android:name=".upload.UploadActivity"
<activity
android:name=".upload.UploadActivity"
android:configChanges="orientation|screenSize|keyboard"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:configChanges="orientation|screenSize|keyboard">
android:windowSoftInputMode="adjustResize"
>
<intent-filter android:label="@string/intent_share_upload_label">
<action android:name="android.intent.action.SEND" />

Expand Down
4 changes: 2 additions & 2 deletions app/src/main/java/fr/free/nrw/commons/BasePresenter.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
/**
* Base presenter, enforcing contracts to atach and detach view
*/
public interface BasePresenter {
public interface BasePresenter<T> {
/**
* Until a view is attached, it is open to listen events from the presenter
*/
void onAttachView(MvpView view);
void onAttachView(T view);

/**
* Detaching a view makes sure that the view no more receives events from the presenter
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/java/fr/free/nrw/commons/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,16 @@

import org.wikipedia.dataclient.WikiSite;
import org.wikipedia.page.PageTitle;
import fr.free.nrw.commons.location.LatLng;
import fr.free.nrw.commons.utils.ViewUtil;

import java.util.Locale;
import java.util.regex.Pattern;

import androidx.annotation.NonNull;
import androidx.browser.customtabs.CustomTabsIntent;
import androidx.core.content.ContextCompat;
import fr.free.nrw.commons.location.LatLng;
import fr.free.nrw.commons.settings.Prefs;
import fr.free.nrw.commons.utils.ViewUtil;
import timber.log.Timber;

import static android.widget.Toast.LENGTH_SHORT;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
* success and error
*/
@Singleton
public class CampaignsPresenter implements BasePresenter {
public class CampaignsPresenter implements BasePresenter<ICampaignsView> {
private final OkHttpJsonApiClient okHttpJsonApiClient;

private ICampaignsView view;
Expand All @@ -40,8 +40,9 @@ public CampaignsPresenter(OkHttpJsonApiClient okHttpJsonApiClient) {
this.okHttpJsonApiClient = okHttpJsonApiClient;
}

@Override public void onAttachView(MvpView view) {
this.view = (ICampaignsView) view;
@Override
public void onAttachView(ICampaignsView view) {
this.view = view;
}

@Override public void onDetachView() {
Expand Down
156 changes: 95 additions & 61 deletions app/src/main/java/fr/free/nrw/commons/category/CategoriesModel.java
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
package fr.free.nrw.commons.category;

import android.text.TextUtils;

import fr.free.nrw.commons.kvstore.JsonKvStore;
import fr.free.nrw.commons.mwapi.MediaWikiApi;
import fr.free.nrw.commons.upload.GpsCategoryModel;
import fr.free.nrw.commons.utils.StringSortingUtils;
import io.reactivex.Observable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import javax.inject.Inject;
import javax.inject.Named;

import fr.free.nrw.commons.kvstore.JsonKvStore;
import fr.free.nrw.commons.mwapi.MediaWikiApi;
import fr.free.nrw.commons.upload.GpsCategoryModel;
import fr.free.nrw.commons.utils.StringSortingUtils;
import io.reactivex.Observable;
import timber.log.Timber;

public class CategoriesModel implements CategoryClickedListener {
/**
* The model class for categories in upload
*/
public class CategoriesModel{
private static final int SEARCH_CATS_LIMIT = 25;

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

//region Misc. utility methods
/**
* Sorts CategoryItem by similarity
* @param filter
* @return
*/
public Comparator<CategoryItem> sortBySimilarity(final String filter) {
Comparator<String> stringSimilarityComparator = StringSortingUtils.sortBySimilarity(filter);
return (firstItem, secondItem) -> stringSimilarityComparator
.compare(firstItem.getName(), secondItem.getName());
}

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

/**
* Updates category count in category dao
* @param item
*/
public void updateCategoryCount(CategoryItem item) {
Category category = categoryDao.find(item.getName());

Expand All @@ -78,29 +91,27 @@ public void updateCategoryCount(CategoryItem item) {
category.incTimesUsed();
categoryDao.save(category);
}
//endregion

//region Category Caching
public void cacheAll(HashMap<String, ArrayList<String>> categories) {
categoriesCache.putAll(categories);
}

public HashMap<String, ArrayList<String>> getCategoriesCache() {
return categoriesCache;
}

boolean cacheContainsKey(String term) {
return categoriesCache.containsKey(term);
}
//endregion

//region Category searching
/**
* Regional category search
* @param term
* @param imageTitleList
* @return
*/
public Observable<CategoryItem> searchAll(String term, List<String> imageTitleList) {
//If user hasn't typed anything in yet, get GPS and recent items
//If query text is empty, show him category based on gps and title and recent searches
if (TextUtils.isEmpty(term)) {
return gpsCategories()
.concatWith(titleCategories(imageTitleList))
.concatWith(recentCategories());
Observable<CategoryItem> categoryItemObservable = gpsCategories()
.concatWith(titleCategories(imageTitleList));
if (hasDirectCategories()) {
categoryItemObservable.concatWith(directCategories().concatWith(recentCategories()));
}
return categoryItemObservable;
}

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

public Observable<CategoryItem> searchCategories(String term, List<String> imageTitleList) {
//If user hasn't typed anything in yet, get GPS and recent items
if (TextUtils.isEmpty(term)) {
return gpsCategories()
.concatWith(titleCategories(imageTitleList))
.concatWith(recentCategories());
}

return mwApi
.searchCategories(term, SEARCH_CATS_LIMIT)
.map(s -> new CategoryItem(s, false));
}

/**
* Returns cached categories
* @param term
* @return
*/
private ArrayList<String> getCachedCategories(String term) {
return categoriesCache.get(term);
}

public Observable<CategoryItem> defaultCategories(List<String> titleList) {
Observable<CategoryItem> directCat = directCategories();
if (hasDirectCategories()) {
Timber.d("Image has direct Cat");
return directCat
.concatWith(gpsCategories())
.concatWith(titleCategories(titleList))
.concatWith(recentCategories());
} else {
Timber.d("Image has no direct Cat");
return gpsCategories()
.concatWith(titleCategories(titleList))
.concatWith(recentCategories());
}
}

/**
* Returns if we have a category in DirectKV Store
* @return
*/
private boolean hasDirectCategories() {
return !directKvStore.getString("Category", "").equals("");
}

/**
* Returns categories in DirectKVStore
* @return
*/
private Observable<CategoryItem> directCategories() {
String directCategory = directKvStore.getString("Category", "");
List<String> categoryList = new ArrayList<>();
Expand All @@ -164,30 +160,49 @@ private Observable<CategoryItem> directCategories() {
return Observable.fromIterable(categoryList).map(name -> new CategoryItem(name, false));
}

/**
* Returns GPS categories
* @return
*/
Observable<CategoryItem> gpsCategories() {
return Observable.fromIterable(gpsCategoryModel.getCategoryList())
.map(name -> new CategoryItem(name, false));
}

/**
* Returns title based categories
* @param titleList
* @return
*/
private Observable<CategoryItem> titleCategories(List<String> titleList) {
return Observable.fromIterable(titleList)
.concatMap(this::getTitleCategories);
}

/**
* Return category for single title
* @param title
* @return
*/
private Observable<CategoryItem> getTitleCategories(String title) {
return mwApi.searchTitles(title, SEARCH_CATS_LIMIT)
.map(name -> new CategoryItem(name, false));
}

/**
* Returns recent categories
* @return
*/
private Observable<CategoryItem> recentCategories() {
return Observable.fromIterable(categoryDao.recentCategories(SEARCH_CATS_LIMIT))
.map(s -> new CategoryItem(s, false));
}
//endregion

//region Category Selection
@Override
public void categoryClicked(CategoryItem item) {
/**
* Handles category item selection
* @param item
*/
public void onCategoryItemClicked(CategoryItem item) {
if (item.isSelected()) {
selectCategory(item);
updateCategoryCount(item);
Expand All @@ -196,29 +211,48 @@ public void categoryClicked(CategoryItem item) {
}
}

/**
* Select's category
* @param item
*/
public void selectCategory(CategoryItem item) {
selectedCategories.add(item);
}

/**
* Unselect Category
* @param item
*/
public void unselectCategory(CategoryItem item) {
selectedCategories.remove(item);
}

public int selectedCategoriesCount() {
return selectedCategories.size();
}

/**
* Get Selected Categories
* @return
*/
public List<CategoryItem> getSelectedCategories() {
return selectedCategories;
}

/**
* Get Categories String List
* @return
*/
public List<String> getCategoryStringList() {
List<String> output = new ArrayList<>();
for (CategoryItem item : selectedCategories) {
output.add(item.getName());
}
return output;
}
//endregion

/**
* Cleanup the existing in memory cache's
*/
public void cleanUp() {
this.categoriesCache.clear();
this.selectedCategories.clear();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public CategoryItem[] newArray(int i) {
}
};

CategoryItem(String name, boolean selected) {
public CategoryItem(String name, boolean selected) {
this.name = name;
this.selected = selected;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ ContentValues toContentValues(Contribution contribution) {
cv.put(Table.COLUMN_UPLOADED, contribution.getDateUploaded().getTime());
}
cv.put(Table.COLUMN_LENGTH, contribution.getDataLength());
//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
//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
cv.put(Table.COLUMN_TIMESTAMP, contribution.getDateCreated()==null?System.currentTimeMillis():contribution.getDateCreated().getTime());
cv.put(Table.COLUMN_STATE, contribution.getState());
cv.put(Table.COLUMN_TRANSFERRED, contribution.getTransferred());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import fr.free.nrw.commons.review.ReviewController;
import fr.free.nrw.commons.settings.SettingsFragment;
import fr.free.nrw.commons.upload.FileProcessor;
import fr.free.nrw.commons.upload.UploadModule;
import fr.free.nrw.commons.widget.PicOfDayAppWidget;


Expand All @@ -27,7 +28,7 @@
ActivityBuilderModule.class,
FragmentBuilderModule.class,
ServiceBuilderModule.class,
ContentProviderBuilderModule.class
ContentProviderBuilderModule.class, UploadModule.class
})
public interface CommonsApplicationComponent extends AndroidInjector<ApplicationlessInjection> {
void inject(CommonsApplication application);
Expand Down
Loading