mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-27 04:43:54 +01:00
Migrate network tasks to RxJava
This commit is contained in:
parent
84a5f0a221
commit
b7215c580f
3 changed files with 133 additions and 133 deletions
|
|
@ -23,7 +23,6 @@ import com.jakewharton.rxbinding2.view.RxView;
|
||||||
import com.jakewharton.rxbinding2.widget.RxTextView;
|
import com.jakewharton.rxbinding2.widget.RxTextView;
|
||||||
import com.pedrogomez.renderers.RVRendererAdapter;
|
import com.pedrogomez.renderers.RVRendererAdapter;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
@ -36,10 +35,8 @@ import butterknife.ButterKnife;
|
||||||
import fr.free.nrw.commons.CommonsApplication;
|
import fr.free.nrw.commons.CommonsApplication;
|
||||||
import fr.free.nrw.commons.R;
|
import fr.free.nrw.commons.R;
|
||||||
import fr.free.nrw.commons.data.Category;
|
import fr.free.nrw.commons.data.Category;
|
||||||
import fr.free.nrw.commons.mwapi.MediaWikiApi;
|
|
||||||
import fr.free.nrw.commons.upload.MwVolleyApi;
|
import fr.free.nrw.commons.upload.MwVolleyApi;
|
||||||
import io.reactivex.Observable;
|
import io.reactivex.Observable;
|
||||||
import io.reactivex.Single;
|
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
import io.reactivex.schedulers.Schedulers;
|
import io.reactivex.schedulers.Schedulers;
|
||||||
import timber.log.Timber;
|
import timber.log.Timber;
|
||||||
|
|
@ -194,7 +191,7 @@ public class CategorizationFragment extends Fragment {
|
||||||
rootView.requestFocus();
|
rootView.requestFocus();
|
||||||
rootView.setOnKeyListener((v, keyCode, event) -> {
|
rootView.setOnKeyListener((v, keyCode, event) -> {
|
||||||
if (event.getAction() == ACTION_UP && keyCode == KEYCODE_BACK) {
|
if (event.getAction() == ACTION_UP && keyCode == KEYCODE_BACK) {
|
||||||
backButtonDialog();
|
showBackButtonDialog();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -224,25 +221,12 @@ public class CategorizationFragment extends Fragment {
|
||||||
public boolean onOptionsItemSelected(MenuItem menuItem) {
|
public boolean onOptionsItemSelected(MenuItem menuItem) {
|
||||||
switch (menuItem.getItemId()) {
|
switch (menuItem.getItemId()) {
|
||||||
case R.id.menu_save_categories:
|
case R.id.menu_save_categories:
|
||||||
//If no categories selected, display warning to user
|
if (selectedCategories.size() > 0) {
|
||||||
if (selectedCategories.size() == 0) {
|
//Some categories selected, proceed to submission
|
||||||
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));
|
onCategoriesSaveHandler.onCategoriesSave(getStringList(selectedCategories));
|
||||||
})
|
|
||||||
.create()
|
|
||||||
.show();
|
|
||||||
} else {
|
} else {
|
||||||
//Proceed to submission
|
//No categories selected, prompt the user to select some
|
||||||
onCategoriesSaveHandler.onCategoriesSave(getStringList(selectedCategories));
|
showConfirmationDialog();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
|
|
@ -271,7 +255,7 @@ public class CategorizationFragment extends Fragment {
|
||||||
return Observable.fromIterable(
|
return Observable.fromIterable(
|
||||||
MwVolleyApi.GpsCatExists.getGpsCatExists() ?
|
MwVolleyApi.GpsCatExists.getGpsCatExists() ?
|
||||||
MwVolleyApi.getGpsCat() : new ArrayList<>())
|
MwVolleyApi.getGpsCat() : new ArrayList<>())
|
||||||
.map(s -> new CategoryItem(s, false));
|
.map(name -> new CategoryItem(name, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Observable<CategoryItem> titleCategories() {
|
private Observable<CategoryItem> titleCategories() {
|
||||||
|
|
@ -279,10 +263,9 @@ public class CategorizationFragment extends Fragment {
|
||||||
SharedPreferences titleDesc = PreferenceManager.getDefaultSharedPreferences(getActivity());
|
SharedPreferences titleDesc = PreferenceManager.getDefaultSharedPreferences(getActivity());
|
||||||
String title = titleDesc.getString("Title", "");
|
String title = titleDesc.getString("Title", "");
|
||||||
|
|
||||||
return Observable.just(title)
|
return CommonsApplication.getInstance().getMWApi()
|
||||||
.observeOn(Schedulers.io())
|
.searchTitles(title, SEARCH_CATS_LIMIT)
|
||||||
.flatMapIterable(s -> titleCatQuery(s))
|
.map(name -> new CategoryItem(name, false));
|
||||||
.map(s -> new CategoryItem(s, false));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Observable<CategoryItem> recentCategories() {
|
private Observable<CategoryItem> recentCategories() {
|
||||||
|
|
@ -291,62 +274,35 @@ public class CategorizationFragment extends Fragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Observable<CategoryItem> search(String term) {
|
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 user hasn't typed anything in yet, get GPS and recent items
|
||||||
if (TextUtils.isEmpty(s)) {
|
if (TextUtils.isEmpty(term)) {
|
||||||
return new ArrayList<String>();
|
return Observable.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
//if user types in something that is in cache, return cached category
|
//if user types in something that is in cache, return cached category
|
||||||
if (categoriesCache.containsKey(s)) {
|
if (categoriesCache.containsKey(term)) {
|
||||||
return categoriesCache.get(s);
|
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
|
//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
|
return CommonsApplication.getInstance().getMWApi()
|
||||||
MediaWikiApi api = CommonsApplication.getInstance().getMWApi();
|
.allCategories(term, SEARCH_CATS_LIMIT)
|
||||||
List<String> categories = new ArrayList<>();
|
.map(name -> new CategoryItem(name, false));
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Observable<CategoryItem> search2(String term) {
|
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 user hasn't typed anything in yet, get GPS and recent items
|
||||||
if (TextUtils.isEmpty(s)) {
|
if (TextUtils.isEmpty(term)) {
|
||||||
return new ArrayList<String>();
|
return Observable.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
MediaWikiApi api = CommonsApplication.getInstance().getMWApi();
|
return CommonsApplication.getInstance().getMWApi()
|
||||||
|
.searchCategories(term, SEARCH_CATS_LIMIT)
|
||||||
//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)
|
|
||||||
.map(s -> new CategoryItem(s, false));
|
.map(s -> new CategoryItem(s, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean containsYear(String items) {
|
private boolean containsYear(String items) {
|
||||||
|
|
||||||
//Check for current and previous year to exclude these categories from removal
|
//Check for current and previous year to exclude these categories from removal
|
||||||
Calendar now = Calendar.getInstance();
|
Calendar now = Calendar.getInstance();
|
||||||
int year = now.get(Calendar.YEAR);
|
int year = now.get(Calendar.YEAR);
|
||||||
|
|
@ -356,7 +312,6 @@ public class CategorizationFragment extends Fragment {
|
||||||
String prevYearInString = String.valueOf(prevYear);
|
String prevYearInString = String.valueOf(prevYear);
|
||||||
Timber.d("Previous year: %s", prevYearInString);
|
Timber.d("Previous year: %s", prevYearInString);
|
||||||
|
|
||||||
|
|
||||||
//Check if s contains a 4-digit word anywhere within the string (.* is wildcard)
|
//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 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)
|
//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();
|
return selectedCategories.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void backButtonDialog() {
|
public void showBackButtonDialog() {
|
||||||
new AlertDialog.Builder(getActivity())
|
new AlertDialog.Builder(getActivity())
|
||||||
.setMessage("Are you sure you want to go back? The image will not "
|
.setMessage("Are you sure you want to go back? The image will not "
|
||||||
+ "have any categories saved.")
|
+ "have any categories saved.")
|
||||||
|
|
@ -380,4 +335,21 @@ public class CategorizationFragment extends Fragment {
|
||||||
.create()
|
.create()
|
||||||
.show();
|
.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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ import fr.free.nrw.commons.BuildConfig;
|
||||||
import fr.free.nrw.commons.PageTitle;
|
import fr.free.nrw.commons.PageTitle;
|
||||||
import fr.free.nrw.commons.Utils;
|
import fr.free.nrw.commons.Utils;
|
||||||
import in.yuvi.http.fluent.Http;
|
import in.yuvi.http.fluent.Http;
|
||||||
|
import io.reactivex.Observable;
|
||||||
import io.reactivex.Single;
|
import io.reactivex.Single;
|
||||||
import timber.log.Timber;
|
import timber.log.Timber;
|
||||||
|
|
||||||
|
|
@ -205,8 +206,11 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NonNull
|
@NonNull
|
||||||
public List<String> searchCategories(int searchCatsLimit, String filterValue) throws IOException {
|
public Observable<String> searchCategories(String filterValue, int searchCatsLimit) {
|
||||||
List<ApiResult> categoryNodes = api.action("query")
|
return Single.fromCallable(() -> {
|
||||||
|
List<ApiResult> categoryNodes = null;
|
||||||
|
try {
|
||||||
|
categoryNodes = api.action("query")
|
||||||
.param("format", "xml")
|
.param("format", "xml")
|
||||||
.param("list", "search")
|
.param("list", "search")
|
||||||
.param("srwhat", "text")
|
.param("srwhat", "text")
|
||||||
|
|
@ -215,9 +219,12 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
|
||||||
.param("srsearch", filterValue)
|
.param("srsearch", filterValue)
|
||||||
.get()
|
.get()
|
||||||
.getNodes("/api/query/search/p/@title");
|
.getNodes("/api/query/search/p/@title");
|
||||||
|
} catch (IOException e) {
|
||||||
|
Timber.e("Failed to obtain searchCategories", e);
|
||||||
|
}
|
||||||
|
|
||||||
if (categoryNodes == null) {
|
if (categoryNodes == null) {
|
||||||
return Collections.emptyList();
|
return new ArrayList<String>();
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> categories = new ArrayList<>();
|
List<String> categories = new ArrayList<>();
|
||||||
|
|
@ -228,20 +235,28 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
|
||||||
}
|
}
|
||||||
|
|
||||||
return categories;
|
return categories;
|
||||||
|
})
|
||||||
|
.flatMapObservable(list -> Observable.fromIterable(list));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NonNull
|
@NonNull
|
||||||
public List<String> allCategories(int searchCatsLimit, String filterValue) throws IOException {
|
public Observable<String> allCategories(String filterValue, int searchCatsLimit) {
|
||||||
ArrayList<ApiResult> categoryNodes = api.action("query")
|
return Single.fromCallable(() -> {
|
||||||
|
ArrayList<ApiResult> categoryNodes = null;
|
||||||
|
try {
|
||||||
|
categoryNodes = api.action("query")
|
||||||
.param("list", "allcategories")
|
.param("list", "allcategories")
|
||||||
.param("acprefix", filterValue)
|
.param("acprefix", filterValue)
|
||||||
.param("aclimit", searchCatsLimit)
|
.param("aclimit", searchCatsLimit)
|
||||||
.get()
|
.get()
|
||||||
.getNodes("/api/query/allcategories/c");
|
.getNodes("/api/query/allcategories/c");
|
||||||
|
} catch (IOException e) {
|
||||||
|
Timber.e("Failed to obtain allCategories", e);
|
||||||
|
}
|
||||||
|
|
||||||
if (categoryNodes == null) {
|
if (categoryNodes == null) {
|
||||||
return Collections.emptyList();
|
return new ArrayList<String>();
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> categories = new ArrayList<>();
|
List<String> categories = new ArrayList<>();
|
||||||
|
|
@ -250,12 +265,18 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
|
||||||
}
|
}
|
||||||
|
|
||||||
return categories;
|
return categories;
|
||||||
|
})
|
||||||
|
.flatMapObservable(list -> Observable.fromIterable(list));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NonNull
|
@NonNull
|
||||||
public List<String> searchTitles(int searchCatsLimit, String title) throws IOException {
|
public Observable<String> searchTitles(String title, int searchCatsLimit) {
|
||||||
ArrayList<ApiResult> categoryNodes = api.action("query")
|
return Single.fromCallable(() -> {
|
||||||
|
ArrayList<ApiResult> categoryNodes = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
categoryNodes = api.action("query")
|
||||||
.param("format", "xml")
|
.param("format", "xml")
|
||||||
.param("list", "search")
|
.param("list", "search")
|
||||||
.param("srwhat", "text")
|
.param("srwhat", "text")
|
||||||
|
|
@ -264,6 +285,10 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
|
||||||
.param("srsearch", title)
|
.param("srsearch", title)
|
||||||
.get()
|
.get()
|
||||||
.getNodes("/api/query/search/p/@title");
|
.getNodes("/api/query/search/p/@title");
|
||||||
|
} catch (IOException e) {
|
||||||
|
Timber.e("Failed to obtain searchTitles", e);
|
||||||
|
return new ArrayList();
|
||||||
|
}
|
||||||
|
|
||||||
if (categoryNodes == null) {
|
if (categoryNodes == null) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
|
|
@ -277,6 +302,8 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
|
||||||
}
|
}
|
||||||
|
|
||||||
return titleCategories;
|
return titleCategories;
|
||||||
|
})
|
||||||
|
.flatMapObservable(list -> Observable.fromIterable(list));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import io.reactivex.Observable;
|
||||||
import io.reactivex.Single;
|
import io.reactivex.Single;
|
||||||
|
|
||||||
public interface MediaWikiApi {
|
public interface MediaWikiApi {
|
||||||
|
|
@ -38,13 +39,13 @@ public interface MediaWikiApi {
|
||||||
MediaResult fetchMediaByFilename(String filename) throws IOException;
|
MediaResult fetchMediaByFilename(String filename) throws IOException;
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
List<String> searchCategories(int searchCatsLimit, String filterValue) throws IOException;
|
Observable<String> searchCategories(String filterValue, int searchCatsLimit);
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
List<String> allCategories(int searchCatsLimit, String filter) throws IOException;
|
Observable<String> allCategories(String filter, int searchCatsLimit);
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
List<String> searchTitles(int searchCatsLimit, String title) throws IOException;
|
Observable<String> searchTitles(String title, int searchCatsLimit);
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
String revisionsByFilename(String filename) throws IOException;
|
String revisionsByFilename(String filename) throws IOException;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue