diff --git a/app/src/androidTest/java/org/bspeice/minimalbible/test/activity/downloader/BookListFragmentTest.java b/app/src/androidTest/java/org/bspeice/minimalbible/test/activity/downloader/BookListFragmentTest.java new file mode 100644 index 0000000..0a74541 --- /dev/null +++ b/app/src/androidTest/java/org/bspeice/minimalbible/test/activity/downloader/BookListFragmentTest.java @@ -0,0 +1,70 @@ +package org.bspeice.minimalbible.test.activity.downloader; + +import org.bspeice.minimalbible.MBTestCase; +import org.bspeice.minimalbible.activity.downloader.BookListFragment; +import org.crosswire.common.util.Language; +import org.crosswire.jsword.book.Book; +import org.crosswire.jsword.book.BookCategory; +import org.mockito.Mockito; + +import rx.Observable; +import rx.functions.Action1; + +import static org.mockito.Mockito.when; + +public class BookListFragmentTest extends MBTestCase { + + public void testBooksByLanguage() throws Exception { + BookCategory bibleCategory = BookCategory.BIBLE; + BookCategory dictionaryCategory = BookCategory.DICTIONARY; + Language russianLanguage = new Language("ru"); + Language englishLanguage = new Language("en"); + + final Book russianBible = Mockito.mock(Book.class); + when(russianBible.getBookCategory()).thenReturn(bibleCategory); + when(russianBible.getLanguage()).thenReturn(russianLanguage); + + final Book englishBible = Mockito.mock(Book.class); + when(englishBible.getBookCategory()).thenReturn(bibleCategory); + when(englishBible.getLanguage()).thenReturn(englishLanguage); + + final Book englishDictionary = Mockito.mock(Book.class); + when(englishDictionary.getBookCategory()).thenReturn(dictionaryCategory); + when(englishDictionary.getLanguage()).thenReturn(englishLanguage); + + Observable mockBooks = Observable.just(russianBible, englishBible, + englishDictionary); + + // Since we're not testing lifecycle here, don't worry about newInstance() + TestableBookListFragment fragment = new TestableBookListFragment(); + + fragment.booksByLanguage(mockBooks, englishLanguage, bibleCategory) + .subscribe(new Action1() { + @Override + public void call(Book book) { + assertEquals(englishBible, book); + } + }); + fragment.booksByLanguage(mockBooks, russianLanguage, bibleCategory) + .subscribe(new Action1() { + @Override + public void call(Book book) { + assertEquals(russianBible, book); + } + }); + fragment.booksByLanguage(mockBooks, englishLanguage, dictionaryCategory) + .subscribe(new Action1() { + @Override + public void call(Book book) { + assertEquals(englishDictionary, book); + } + }); + } + + public static class TestableBookListFragment extends BookListFragment { + @Override + public Observable booksByLanguage(Observable books, Language language, BookCategory category) { + return super.booksByLanguage(books, language, category); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/org/bspeice/minimalbible/activity/downloader/BookListFragment.java b/app/src/main/java/org/bspeice/minimalbible/activity/downloader/BookListFragment.java index f2a371f..fdc2023 100644 --- a/app/src/main/java/org/bspeice/minimalbible/activity/downloader/BookListFragment.java +++ b/app/src/main/java/org/bspeice/minimalbible/activity/downloader/BookListFragment.java @@ -18,6 +18,7 @@ import org.bspeice.minimalbible.Injector; import org.bspeice.minimalbible.R; import org.bspeice.minimalbible.activity.BaseFragment; import org.bspeice.minimalbible.activity.downloader.manager.RefreshManager; +import org.crosswire.common.util.Language; import org.crosswire.jsword.book.Book; import org.crosswire.jsword.book.BookCategory; import org.crosswire.jsword.book.BookComparators; @@ -30,6 +31,7 @@ import javax.inject.Inject; import butterknife.ButterKnife; import butterknife.InjectView; import butterknife.OnItemSelected; +import rx.Observable; import rx.android.schedulers.AndroidSchedulers; import rx.functions.Action1; import rx.functions.Func1; @@ -47,7 +49,7 @@ public class BookListFragment extends BaseFragment { protected ProgressDialog refreshDialog; @Inject RefreshManager refreshManager; @Inject - List availableLanguages; + List availableLanguages; @InjectView(R.id.lst_download_available) ListView downloadsAvailable; @@ -153,22 +155,9 @@ public class BookListFragment extends BaseFragment { @SuppressWarnings("unused") @OnItemSelected(R.id.spn_available_languages) public void onClick(final int position) { - refreshManager.getFlatModules() - .filter(new Func1() { - @Override - public Boolean call(Book book) { - return book.getBookCategory() == - BookCategory.fromString(BookListFragment.this.getArguments() - .getString(ARG_BOOK_CATEGORY)); - } - }) - .filter(new Func1() { - @Override - public Boolean call(Book book) { - return book.getLanguage().getName() - .equals(availableLanguages.get(position)); - } - }) + booksByLanguage(refreshManager.getFlatModules(), + availableLanguages.get(position), + BookCategory.fromString(getArguments().getString(ARG_BOOK_CATEGORY))) // Repack all the books .toSortedList(new Func2() { @Override @@ -187,6 +176,25 @@ public class BookListFragment extends BaseFragment { }); } + protected Observable booksByLanguage(Observable books, final Language language, + final BookCategory category) { + return books + .filter(new Func1() { + @Override + public Boolean call(Book book) { + return book.getBookCategory() == category; + } + }) + .filter(new Func1() { + @Override + public Boolean call(Book book) { + // Language doesn't properly implement .equals(), so use Strings + return book.getLanguage().getCode() + .equals(language.getCode()); + } + }); + } + private class DownloadDialogListener implements DialogInterface.OnClickListener { @Override diff --git a/app/src/main/java/org/bspeice/minimalbible/activity/downloader/DownloadActivityModules.java b/app/src/main/java/org/bspeice/minimalbible/activity/downloader/DownloadActivityModules.java index fd8a62d..68664ed 100644 --- a/app/src/main/java/org/bspeice/minimalbible/activity/downloader/DownloadActivityModules.java +++ b/app/src/main/java/org/bspeice/minimalbible/activity/downloader/DownloadActivityModules.java @@ -9,6 +9,7 @@ import org.bspeice.minimalbible.activity.downloader.manager.BookDownloadManager; import org.bspeice.minimalbible.activity.downloader.manager.InstalledManager; import org.bspeice.minimalbible.activity.downloader.manager.LocaleManager; import org.bspeice.minimalbible.activity.downloader.manager.RefreshManager; +import org.crosswire.common.util.Language; import org.crosswire.jsword.book.Book; import org.crosswire.jsword.book.BookCategory; import org.crosswire.jsword.book.Books; @@ -120,8 +121,7 @@ public class DownloadActivityModules { } @Provides - List availableLanguages(LocaleManager localeManager) { - final List languages = new ArrayList(); + List availableLanguages(LocaleManager localeManager) { return localeManager.getSortedLanguagesList(); } } diff --git a/app/src/main/kotlin/org/bspeice/minimalbible/activity/downloader/manager/LocaleManager.kt b/app/src/main/kotlin/org/bspeice/minimalbible/activity/downloader/manager/LocaleManager.kt index 0a26004..bae7487 100644 --- a/app/src/main/kotlin/org/bspeice/minimalbible/activity/downloader/manager/LocaleManager.kt +++ b/app/src/main/kotlin/org/bspeice/minimalbible/activity/downloader/manager/LocaleManager.kt @@ -1,23 +1,31 @@ package org.bspeice.minimalbible.activity.downloader.manager import org.crosswire.common.util.Language +import rx.Observable class LocaleManager(val rM: RefreshManager) { - val currentLanguage = Language.DEFAULT_LANG.getName() - val languageModuleMap = rM.flatModules - .map { it.getLanguage() ?: Language(Language.UNKNOWN_LANG_CODE) } - .groupBy { it.getName() } + val currentLanguage = Language.DEFAULT_LANG - val availableLanguages = languageModuleMap.map { it.getKey() } - val sortedLanguagesList: List = + val languageModuleMap = rM.flatModules + // Language doesn't have hashCode(), so we actually group by its String + .groupBy { FixedLanguage(it.getLanguage()) } + + // Cast back to the original Language implementation + val availableLanguages: Observable = languageModuleMap.map { it.getKey() } + val sortedLanguagesList = availableLanguages.toSortedList {(left, right) -> // Prioritize our current language first - if (left == currentLanguage) + if (left.getName() == currentLanguage.getName()) -1 - else if (right == currentLanguage) + else if (right.getName() == currentLanguage.getName()) 1 else - left.compareTo(right) + left.getName().compareTo(right.getName()) }.toBlocking().first() +} + +class FixedLanguage(language: Language?) : + Language(language?.getCode() ?: Language.UNKNOWN_LANG_CODE) { + override fun hashCode() = this.getName().hashCode() } \ No newline at end of file