Migrate network tasks to RxJava

This commit is contained in:
Mikel 2017-08-06 19:58:58 +01:00
parent 84a5f0a221
commit b7215c580f
3 changed files with 133 additions and 133 deletions

View file

@ -23,7 +23,6 @@ import com.jakewharton.rxbinding2.view.RxView;
import com.jakewharton.rxbinding2.widget.RxTextView;
import com.pedrogomez.renderers.RVRendererAdapter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
@ -36,10 +35,8 @@ import butterknife.ButterKnife;
import fr.free.nrw.commons.CommonsApplication;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.data.Category;
import fr.free.nrw.commons.mwapi.MediaWikiApi;
import fr.free.nrw.commons.upload.MwVolleyApi;
import io.reactivex.Observable;
import io.reactivex.Single;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import timber.log.Timber;
@ -194,7 +191,7 @@ public class CategorizationFragment extends Fragment {
rootView.requestFocus();
rootView.setOnKeyListener((v, keyCode, event) -> {
if (event.getAction() == ACTION_UP && keyCode == KEYCODE_BACK) {
backButtonDialog();
showBackButtonDialog();
return true;
}
return false;
@ -224,25 +221,12 @@ public class CategorizationFragment extends Fragment {
public boolean onOptionsItemSelected(MenuItem menuItem) {
switch (menuItem.getItemId()) {
case R.id.menu_save_categories:
//If no categories selected, display warning to user
if (selectedCategories.size() == 0) {
new AlertDialog.Builder(getActivity())
.setMessage("Images without categories are rarely usable. "
+ "Are you sure you want to submit without selecting "
+ "categories?")
.setTitle("No Categories Selected")
.setPositiveButton("No, go back", (dialog, id) -> {
//Exit menuItem so user can select their categories
})
.setNegativeButton("Yes, submit", (dialog, id) -> {
//Proceed to submission
onCategoriesSaveHandler.onCategoriesSave(getStringList(selectedCategories));
})
.create()
.show();
} else {
//Proceed to submission
if (selectedCategories.size() > 0) {
//Some categories selected, proceed to submission
onCategoriesSaveHandler.onCategoriesSave(getStringList(selectedCategories));
} else {
//No categories selected, prompt the user to select some
showConfirmationDialog();
}
return true;
default:
@ -271,7 +255,7 @@ public class CategorizationFragment extends Fragment {
return Observable.fromIterable(
MwVolleyApi.GpsCatExists.getGpsCatExists() ?
MwVolleyApi.getGpsCat() : new ArrayList<>())
.map(s -> new CategoryItem(s, false));
.map(name -> new CategoryItem(name, false));
}
private Observable<CategoryItem> titleCategories() {
@ -279,10 +263,9 @@ public class CategorizationFragment extends Fragment {
SharedPreferences titleDesc = PreferenceManager.getDefaultSharedPreferences(getActivity());
String title = titleDesc.getString("Title", "");
return Observable.just(title)
.observeOn(Schedulers.io())
.flatMapIterable(s -> titleCatQuery(s))
.map(s -> new CategoryItem(s, false));
return CommonsApplication.getInstance().getMWApi()
.searchTitles(title, SEARCH_CATS_LIMIT)
.map(name -> new CategoryItem(name, false));
}
private Observable<CategoryItem> recentCategories() {
@ -291,62 +274,35 @@ public class CategorizationFragment extends Fragment {
}
private Observable<CategoryItem> search(String term) {
return Single.just(term)
.map(s -> {
//If user hasn't typed anything in yet, get GPS and recent items
if (TextUtils.isEmpty(s)) {
return new ArrayList<String>();
}
//If user hasn't typed anything in yet, get GPS and recent items
if (TextUtils.isEmpty(term)) {
return Observable.empty();
}
//if user types in something that is in cache, return cached category
if (categoriesCache.containsKey(s)) {
return categoriesCache.get(s);
}
//if user types in something that is in cache, return cached category
if (categoriesCache.containsKey(term)) {
return Observable.fromIterable(categoriesCache.get(term))
.map(name -> new CategoryItem(name, false));
}
//otherwise if user has typed something in that isn't in cache, search API for matching categories
//URL: https://commons.wikimedia.org/w/api.php?action=query&list=allcategories&acprefix=filter&aclimit=25
MediaWikiApi api = CommonsApplication.getInstance().getMWApi();
List<String> categories = new ArrayList<>();
try {
categories = api.allCategories(SEARCH_CATS_LIMIT, s);
Timber.d("Prefix URL filter %s", categories);
} catch (IOException e) {
Timber.e(e, "IO Exception: ");
//Return empty arraylist
return categories;
}
Timber.d("Found categories from Prefix search, waiting for filter");
return categories;
})
.flatMapObservable(Observable::fromIterable)
.map(s -> new CategoryItem(s, false));
//otherwise if user has typed something in that isn't in cache, search API for matching categories
return CommonsApplication.getInstance().getMWApi()
.allCategories(term, SEARCH_CATS_LIMIT)
.map(name -> new CategoryItem(name, false));
}
private Observable<CategoryItem> search2(String term) {
return Single.just(term)
.map(s -> {
//If user hasn't typed anything in yet, get GPS and recent items
if (TextUtils.isEmpty(s)) {
return new ArrayList<String>();
}
//If user hasn't typed anything in yet, get GPS and recent items
if (TextUtils.isEmpty(term)) {
return Observable.empty();
}
MediaWikiApi api = CommonsApplication.getInstance().getMWApi();
//URL https://commons.wikimedia.org/w/api.php?action=query&format=xml&list=search&srwhat=text&srenablerewrites=1&srnamespace=14&srlimit=10&srsearch=
try {
return api.searchCategories(SEARCH_CATS_LIMIT, term);
} catch (IOException e) {
Timber.e(e, "IO Exception: ");
return new ArrayList<String>();
}
})
.flatMapObservable(Observable::fromIterable)
return CommonsApplication.getInstance().getMWApi()
.searchCategories(term, SEARCH_CATS_LIMIT)
.map(s -> new CategoryItem(s, false));
}
private boolean containsYear(String items) {
//Check for current and previous year to exclude these categories from removal
Calendar now = Calendar.getInstance();
int year = now.get(Calendar.YEAR);
@ -356,7 +312,6 @@ public class CategorizationFragment extends Fragment {
String prevYearInString = String.valueOf(prevYear);
Timber.d("Previous year: %s", prevYearInString);
//Check if s contains a 4-digit word anywhere within the string (.* is wildcard)
//And that s does not equal the current year or previous year
//And if it is an irrelevant category such as Media_needing_categories_as_of_16_June_2017(Issue #750)
@ -368,7 +323,7 @@ public class CategorizationFragment extends Fragment {
return selectedCategories.size();
}
public void backButtonDialog() {
public void showBackButtonDialog() {
new AlertDialog.Builder(getActivity())
.setMessage("Are you sure you want to go back? The image will not "
+ "have any categories saved.")
@ -380,4 +335,21 @@ public class CategorizationFragment extends Fragment {
.create()
.show();
}
public void showConfirmationDialog() {
new AlertDialog.Builder(getActivity())
.setMessage("Images without categories are rarely usable. "
+ "Are you sure you want to submit without selecting "
+ "categories?")
.setTitle("No Categories Selected")
.setPositiveButton("No, go back", (dialog, id) -> {
//Exit menuItem so user can select their categories
})
.setNegativeButton("Yes, submit", (dialog, id) -> {
//Proceed to submission
onCategoriesSaveHandler.onCategoriesSave(getStringList(selectedCategories));
})
.create()
.show();
}
}

View file

@ -35,6 +35,7 @@ import fr.free.nrw.commons.BuildConfig;
import fr.free.nrw.commons.PageTitle;
import fr.free.nrw.commons.Utils;
import in.yuvi.http.fluent.Http;
import io.reactivex.Observable;
import io.reactivex.Single;
import timber.log.Timber;
@ -205,78 +206,104 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
@Override
@NonNull
public List<String> searchCategories(int searchCatsLimit, String filterValue) throws IOException {
List<ApiResult> categoryNodes = api.action("query")
.param("format", "xml")
.param("list", "search")
.param("srwhat", "text")
.param("srnamespace", "14")
.param("srlimit", searchCatsLimit)
.param("srsearch", filterValue)
.get()
.getNodes("/api/query/search/p/@title");
public Observable<String> searchCategories(String filterValue, int searchCatsLimit) {
return Single.fromCallable(() -> {
List<ApiResult> categoryNodes = null;
try {
categoryNodes = api.action("query")
.param("format", "xml")
.param("list", "search")
.param("srwhat", "text")
.param("srnamespace", "14")
.param("srlimit", searchCatsLimit)
.param("srsearch", filterValue)
.get()
.getNodes("/api/query/search/p/@title");
} catch (IOException e) {
Timber.e("Failed to obtain searchCategories", e);
}
if (categoryNodes == null) {
return Collections.emptyList();
}
if (categoryNodes == null) {
return new ArrayList<String>();
}
List<String> categories = new ArrayList<>();
for (ApiResult categoryNode : categoryNodes) {
String cat = categoryNode.getDocument().getTextContent();
String catString = cat.replace("Category:", "");
categories.add(catString);
}
List<String> categories = new ArrayList<>();
for (ApiResult categoryNode : categoryNodes) {
String cat = categoryNode.getDocument().getTextContent();
String catString = cat.replace("Category:", "");
categories.add(catString);
}
return categories;
return categories;
})
.flatMapObservable(list -> Observable.fromIterable(list));
}
@Override
@NonNull
public List<String> allCategories(int searchCatsLimit, String filterValue) throws IOException {
ArrayList<ApiResult> categoryNodes = api.action("query")
.param("list", "allcategories")
.param("acprefix", filterValue)
.param("aclimit", searchCatsLimit)
.get()
.getNodes("/api/query/allcategories/c");
public Observable<String> allCategories(String filterValue, int searchCatsLimit) {
return Single.fromCallable(() -> {
ArrayList<ApiResult> categoryNodes = null;
try {
categoryNodes = api.action("query")
.param("list", "allcategories")
.param("acprefix", filterValue)
.param("aclimit", searchCatsLimit)
.get()
.getNodes("/api/query/allcategories/c");
} catch (IOException e) {
Timber.e("Failed to obtain allCategories", e);
}
if (categoryNodes == null) {
return Collections.emptyList();
}
if (categoryNodes == null) {
return new ArrayList<String>();
}
List<String> categories = new ArrayList<>();
for (ApiResult categoryNode : categoryNodes) {
categories.add(categoryNode.getDocument().getTextContent());
}
List<String> categories = new ArrayList<>();
for (ApiResult categoryNode : categoryNodes) {
categories.add(categoryNode.getDocument().getTextContent());
}
return categories;
return categories;
})
.flatMapObservable(list -> Observable.fromIterable(list));
}
@Override
@NonNull
public List<String> searchTitles(int searchCatsLimit, String title) throws IOException {
ArrayList<ApiResult> categoryNodes = api.action("query")
.param("format", "xml")
.param("list", "search")
.param("srwhat", "text")
.param("srnamespace", "14")
.param("srlimit", searchCatsLimit)
.param("srsearch", title)
.get()
.getNodes("/api/query/search/p/@title");
public Observable<String> searchTitles(String title, int searchCatsLimit) {
return Single.fromCallable(() -> {
ArrayList<ApiResult> categoryNodes = null;
if (categoryNodes == null) {
return Collections.emptyList();
}
try {
categoryNodes = api.action("query")
.param("format", "xml")
.param("list", "search")
.param("srwhat", "text")
.param("srnamespace", "14")
.param("srlimit", searchCatsLimit)
.param("srsearch", title)
.get()
.getNodes("/api/query/search/p/@title");
} catch (IOException e) {
Timber.e("Failed to obtain searchTitles", e);
return new ArrayList();
}
List<String> titleCategories = new ArrayList<>();
for (ApiResult categoryNode : categoryNodes) {
String cat = categoryNode.getDocument().getTextContent();
String catString = cat.replace("Category:", "");
titleCategories.add(catString);
}
if (categoryNodes == null) {
return Collections.emptyList();
}
return titleCategories;
List<String> titleCategories = new ArrayList<>();
for (ApiResult categoryNode : categoryNodes) {
String cat = categoryNode.getDocument().getTextContent();
String catString = cat.replace("Category:", "");
titleCategories.add(catString);
}
return titleCategories;
})
.flatMapObservable(list -> Observable.fromIterable(list));
}
@Override

View file

@ -7,6 +7,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import io.reactivex.Observable;
import io.reactivex.Single;
public interface MediaWikiApi {
@ -38,13 +39,13 @@ public interface MediaWikiApi {
MediaResult fetchMediaByFilename(String filename) throws IOException;
@NonNull
List<String> searchCategories(int searchCatsLimit, String filterValue) throws IOException;
Observable<String> searchCategories(String filterValue, int searchCatsLimit);
@NonNull
List<String> allCategories(int searchCatsLimit, String filter) throws IOException;
Observable<String> allCategories(String filter, int searchCatsLimit);
@NonNull
List<String> searchTitles(int searchCatsLimit, String title) throws IOException;
Observable<String> searchTitles(String title, int searchCatsLimit);
@Nullable
String revisionsByFilename(String filename) throws IOException;