Minor changes
This commit is contained in:
parent
b002a125fd
commit
75236559ca
5 changed files with 80 additions and 69 deletions
|
@ -94,7 +94,7 @@ dependencies {
|
||||||
apt "com.pushtorefresh.storio:sqlite-annotations-processor:$STORIO_VERSION"
|
apt "com.pushtorefresh.storio:sqlite-annotations-processor:$STORIO_VERSION"
|
||||||
provided 'org.glassfish:javax.annotation:10.0-b28'
|
provided 'org.glassfish:javax.annotation:10.0-b28'
|
||||||
|
|
||||||
compile('com.mikepenz:materialdrawer:4.3.0@aar') {
|
compile('com.mikepenz:materialdrawer:4.4.8@aar') {
|
||||||
transitive = true
|
transitive = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -173,8 +173,9 @@ public class DatabaseHelper {
|
||||||
.withQuery(Query.builder()
|
.withQuery(Query.builder()
|
||||||
.table(ChaptersTable.TABLE)
|
.table(ChaptersTable.TABLE)
|
||||||
.where(ChaptersTable.COLUMN_MANGA_ID + "=? AND " +
|
.where(ChaptersTable.COLUMN_MANGA_ID + "=? AND " +
|
||||||
ChaptersTable.COLUMN_CHAPTER_NUMBER + ">?")
|
ChaptersTable.COLUMN_CHAPTER_NUMBER + ">? AND " +
|
||||||
.whereArgs(chapter.manga_id, chapter.chapter_number)
|
ChaptersTable.COLUMN_CHAPTER_NUMBER + "<=?")
|
||||||
|
.whereArgs(chapter.manga_id, chapter.chapter_number, chapter.chapter_number + 1)
|
||||||
.orderBy(ChaptersTable.COLUMN_CHAPTER_NUMBER)
|
.orderBy(ChaptersTable.COLUMN_CHAPTER_NUMBER)
|
||||||
.limit(1)
|
.limit(1)
|
||||||
.build())
|
.build())
|
||||||
|
@ -187,8 +188,9 @@ public class DatabaseHelper {
|
||||||
.withQuery(Query.builder()
|
.withQuery(Query.builder()
|
||||||
.table(ChaptersTable.TABLE)
|
.table(ChaptersTable.TABLE)
|
||||||
.where(ChaptersTable.COLUMN_MANGA_ID + "=? AND " +
|
.where(ChaptersTable.COLUMN_MANGA_ID + "=? AND " +
|
||||||
ChaptersTable.COLUMN_CHAPTER_NUMBER + "<?")
|
ChaptersTable.COLUMN_CHAPTER_NUMBER + "<? AND " +
|
||||||
.whereArgs(chapter.manga_id, chapter.chapter_number)
|
ChaptersTable.COLUMN_CHAPTER_NUMBER + ">=?")
|
||||||
|
.whereArgs(chapter.manga_id, chapter.chapter_number, chapter.chapter_number - 1)
|
||||||
.orderBy(ChaptersTable.COLUMN_CHAPTER_NUMBER + " DESC")
|
.orderBy(ChaptersTable.COLUMN_CHAPTER_NUMBER + " DESC")
|
||||||
.limit(1)
|
.limit(1)
|
||||||
.build())
|
.build())
|
||||||
|
|
|
@ -129,10 +129,15 @@ public class CatalogueFragment extends BaseRxFragment<CataloguePresenter> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initializeScrollListener() {
|
public void initializeScrollListener() {
|
||||||
scroll_listener = new EndlessScrollListener(getPresenter()::requestNext);
|
scroll_listener = new EndlessScrollListener(this::requestNext);
|
||||||
manga_list.setOnScrollListener(scroll_listener);
|
manga_list.setOnScrollListener(scroll_listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void requestNext() {
|
||||||
|
if (getPresenter().requestNext())
|
||||||
|
showGridProgressBar();
|
||||||
|
}
|
||||||
|
|
||||||
public void showProgressBar() {
|
public void showProgressBar() {
|
||||||
progress.setVisibility(ProgressBar.VISIBLE);
|
progress.setVisibility(ProgressBar.VISIBLE);
|
||||||
}
|
}
|
||||||
|
@ -147,6 +152,7 @@ public class CatalogueFragment extends BaseRxFragment<CataloguePresenter> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onAddPage(PageBundle<List<Manga>> page) {
|
public void onAddPage(PageBundle<List<Manga>> page) {
|
||||||
|
hideProgressBar();
|
||||||
if (page.page == 0) {
|
if (page.page == 0) {
|
||||||
adapter.getItems().clear();
|
adapter.getItems().clear();
|
||||||
scroll_listener.resetScroll();
|
scroll_listener.resetScroll();
|
||||||
|
@ -155,7 +161,7 @@ public class CatalogueFragment extends BaseRxFragment<CataloguePresenter> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getMangaIndex(Manga manga) {
|
private int getMangaIndex(Manga manga) {
|
||||||
for (int i = 0; i < adapter.getCount(); i++) {
|
for (int i = adapter.getCount() - 1; i >= 0; i--) {
|
||||||
if (manga.id == adapter.getItem(i).id) {
|
if (manga.id == adapter.getItem(i).id) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
@ -164,6 +170,9 @@ public class CatalogueFragment extends BaseRxFragment<CataloguePresenter> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private ImageView getImageView(int position) {
|
private ImageView getImageView(int position) {
|
||||||
|
if (position == -1)
|
||||||
|
return null;
|
||||||
|
|
||||||
View v = manga_list.getChildAt(position -
|
View v = manga_list.getChildAt(position -
|
||||||
manga_list.getFirstVisiblePosition());
|
manga_list.getFirstVisiblePosition());
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ import rx.Subscription;
|
||||||
import rx.android.schedulers.AndroidSchedulers;
|
import rx.android.schedulers.AndroidSchedulers;
|
||||||
import rx.schedulers.Schedulers;
|
import rx.schedulers.Schedulers;
|
||||||
import rx.subjects.PublishSubject;
|
import rx.subjects.PublishSubject;
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
public class CataloguePresenter extends BasePresenter<CatalogueFragment> {
|
public class CataloguePresenter extends BasePresenter<CatalogueFragment> {
|
||||||
|
|
||||||
|
@ -31,40 +32,55 @@ public class CataloguePresenter extends BasePresenter<CatalogueFragment> {
|
||||||
|
|
||||||
private Source selectedSource;
|
private Source selectedSource;
|
||||||
|
|
||||||
@State protected String mSearchName;
|
@State protected String searchName;
|
||||||
@State protected boolean mSearchMode;
|
@State protected boolean searchMode;
|
||||||
private final int SEARCH_TIMEOUT = 1000;
|
private final int SEARCH_TIMEOUT = 1000;
|
||||||
|
|
||||||
private int mCurrentPage;
|
private int currentPage;
|
||||||
private RxPager pager;
|
private RxPager pager;
|
||||||
private MangasPage lastMangasPage;
|
private MangasPage lastMangasPage;
|
||||||
|
|
||||||
private Subscription mQueryDebouncerSubscription;
|
private Subscription queryDebouncerSubscription;
|
||||||
private Subscription mMangaDetailFetchSubscription;
|
private PublishSubject<String> queryDebouncerSubject;
|
||||||
private PublishSubject<String> mQueryDebouncerSubject;
|
private PublishSubject<List<Manga>> mangaDetailSubject;
|
||||||
private PublishSubject<List<Manga>> mMangaDetailPublishSubject;
|
|
||||||
|
|
||||||
private static final int GET_MANGA_LIST = 1;
|
private static final int GET_MANGA_LIST = 1;
|
||||||
|
private static final int GET_MANGA_DETAIL = 2;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedState) {
|
protected void onCreate(Bundle savedState) {
|
||||||
super.onCreate(savedState);
|
super.onCreate(savedState);
|
||||||
|
|
||||||
|
mangaDetailSubject = PublishSubject.create();
|
||||||
|
|
||||||
restartableReplay(GET_MANGA_LIST,
|
restartableReplay(GET_MANGA_LIST,
|
||||||
() -> pager.pages().<PageBundle<List<Manga>>>concatMap(
|
() -> pager.pages().<PageBundle<List<Manga>>>concatMap(
|
||||||
page -> getMangaObs(page + 1)
|
page -> getMangaObs(page + 1)
|
||||||
.map(mangas -> new PageBundle<>(page, mangas))
|
.map(mangas -> new PageBundle<>(page, mangas))
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())),
|
||||||
),
|
|
||||||
(view, page) -> {
|
(view, page) -> {
|
||||||
view.hideProgressBar();
|
|
||||||
view.onAddPage(page);
|
view.onAddPage(page);
|
||||||
if (mMangaDetailPublishSubject != null)
|
if (mangaDetailSubject != null)
|
||||||
mMangaDetailPublishSubject.onNext(page.data);
|
mangaDetailSubject.onNext(page.data);
|
||||||
});
|
},
|
||||||
|
(view, error) -> Timber.e(error.fillInStackTrace(), error.getMessage()));
|
||||||
|
|
||||||
|
restartableLatestCache(GET_MANGA_DETAIL,
|
||||||
|
() -> mangaDetailSubject
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.flatMap(Observable::from)
|
||||||
|
.filter(manga -> !manga.initialized)
|
||||||
|
.window(3)
|
||||||
|
.concatMap(pack -> pack.concatMap(this::getMangaDetails))
|
||||||
|
.filter(manga -> manga.initialized)
|
||||||
|
.onBackpressureBuffer()
|
||||||
|
.observeOn(AndroidSchedulers.mainThread()),
|
||||||
|
(view, manga) -> {
|
||||||
|
view.updateImage(manga);
|
||||||
|
},
|
||||||
|
(view, error) -> Timber.e(error.fillInStackTrace(), error.getMessage()));
|
||||||
|
|
||||||
initializeSearch();
|
initializeSearch();
|
||||||
initializeMangaDetailsLoader();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -73,8 +89,8 @@ public class CataloguePresenter extends BasePresenter<CatalogueFragment> {
|
||||||
|
|
||||||
view.setToolbarTitle(selectedSource.getName());
|
view.setToolbarTitle(selectedSource.getName());
|
||||||
|
|
||||||
if (mSearchMode)
|
if (searchMode)
|
||||||
view.restoreSearch(mSearchName);
|
view.restoreSearch(searchName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startRequesting(int sourceId) {
|
public void startRequesting(int sourceId) {
|
||||||
|
@ -84,31 +100,32 @@ public class CataloguePresenter extends BasePresenter<CatalogueFragment> {
|
||||||
|
|
||||||
private void restartRequest() {
|
private void restartRequest() {
|
||||||
stop(GET_MANGA_LIST);
|
stop(GET_MANGA_LIST);
|
||||||
mCurrentPage = 1;
|
currentPage = 1;
|
||||||
pager = new RxPager();
|
pager = new RxPager();
|
||||||
if (getView() != null)
|
if (getView() != null)
|
||||||
getView().showProgressBar();
|
getView().showProgressBar();
|
||||||
|
|
||||||
|
start(GET_MANGA_DETAIL);
|
||||||
start(GET_MANGA_LIST);
|
start(GET_MANGA_LIST);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void requestNext() {
|
public boolean requestNext() {
|
||||||
pager.requestNext(++mCurrentPage);
|
if (lastMangasPage.nextPageUrl == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
pager.requestNext(++currentPage);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Observable<List<Manga>> getMangaObs(int page) {
|
private Observable<List<Manga>> getMangaObs(int page) {
|
||||||
MangasPage nextMangasPage = new MangasPage(page);
|
MangasPage nextMangasPage = new MangasPage(page);
|
||||||
if (page != 1) {
|
if (page != 1) {
|
||||||
if (lastMangasPage.nextPageUrl == null)
|
|
||||||
return Observable.empty();
|
|
||||||
nextMangasPage.url = lastMangasPage.nextPageUrl;
|
nextMangasPage.url = lastMangasPage.nextPageUrl;
|
||||||
}
|
}
|
||||||
if (getView() != null)
|
|
||||||
getView().showGridProgressBar();
|
|
||||||
|
|
||||||
Observable<MangasPage> obs;
|
Observable<MangasPage> obs;
|
||||||
if (mSearchMode)
|
if (searchMode)
|
||||||
obs = selectedSource.searchMangasFromNetwork(nextMangasPage, mSearchName);
|
obs = selectedSource.searchMangasFromNetwork(nextMangasPage, searchName);
|
||||||
else
|
else
|
||||||
obs = selectedSource.pullPopularMangasFromNetwork(nextMangasPage);
|
obs = selectedSource.pullPopularMangasFromNetwork(nextMangasPage);
|
||||||
|
|
||||||
|
@ -131,41 +148,20 @@ public class CataloguePresenter extends BasePresenter<CatalogueFragment> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initializeSearch() {
|
private void initializeSearch() {
|
||||||
if (mQueryDebouncerSubscription != null)
|
if (queryDebouncerSubscription != null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mSearchName = "";
|
searchName = "";
|
||||||
mSearchMode = false;
|
searchMode = false;
|
||||||
mQueryDebouncerSubject = PublishSubject.create();
|
queryDebouncerSubject = PublishSubject.create();
|
||||||
|
|
||||||
add(mQueryDebouncerSubscription = mQueryDebouncerSubject
|
add(queryDebouncerSubscription = queryDebouncerSubject
|
||||||
.debounce(SEARCH_TIMEOUT, TimeUnit.MILLISECONDS)
|
.debounce(SEARCH_TIMEOUT, TimeUnit.MILLISECONDS)
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(this::queryFromSearch));
|
.subscribe(this::queryFromSearch));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initializeMangaDetailsLoader() {
|
|
||||||
if (mMangaDetailFetchSubscription != null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
mMangaDetailPublishSubject = PublishSubject.create();
|
|
||||||
|
|
||||||
add(mMangaDetailFetchSubscription = mMangaDetailPublishSubject
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.flatMap(Observable::from)
|
|
||||||
.filter(manga -> !manga.initialized)
|
|
||||||
.window(3)
|
|
||||||
.concatMap(pack -> pack.concatMap(this::getMangaDetails))
|
|
||||||
.filter(manga -> manga.initialized)
|
|
||||||
.onBackpressureBuffer()
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.subscribe(manga -> {
|
|
||||||
if (getView() != null)
|
|
||||||
getView().updateImage(manga);
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Observable<Manga> getMangaDetails(final Manga manga) {
|
private Observable<Manga> getMangaDetails(final Manga manga) {
|
||||||
return selectedSource.pullMangaFromNetwork(manga.url)
|
return selectedSource.pullMangaFromNetwork(manga.url)
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
|
@ -173,6 +169,9 @@ public class CataloguePresenter extends BasePresenter<CatalogueFragment> {
|
||||||
Manga.copyFromNetwork(manga, networkManga);
|
Manga.copyFromNetwork(manga, networkManga);
|
||||||
db.insertManga(manga).executeAsBlocking();
|
db.insertManga(manga).executeAsBlocking();
|
||||||
return Observable.just(manga);
|
return Observable.just(manga);
|
||||||
|
})
|
||||||
|
.onErrorResumeNext(error -> {
|
||||||
|
return Observable.just(manga);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,25 +179,25 @@ public class CataloguePresenter extends BasePresenter<CatalogueFragment> {
|
||||||
// If the query is empty or not debounced, resolve it instantly
|
// If the query is empty or not debounced, resolve it instantly
|
||||||
if (now || query.equals(""))
|
if (now || query.equals(""))
|
||||||
queryFromSearch(query);
|
queryFromSearch(query);
|
||||||
else if (mQueryDebouncerSubject != null)
|
else if (queryDebouncerSubject != null)
|
||||||
mQueryDebouncerSubject.onNext(query);
|
queryDebouncerSubject.onNext(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void queryFromSearch(String query) {
|
private void queryFromSearch(String query) {
|
||||||
// If text didn't change, do nothing
|
// If text didn't change, do nothing
|
||||||
if (mSearchName.equals(query)) {
|
if (searchName.equals(query)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// If going to search mode
|
// If going to search mode
|
||||||
else if (mSearchName.equals("") && !query.equals("")) {
|
else if (searchName.equals("") && !query.equals("")) {
|
||||||
mSearchMode = true;
|
searchMode = true;
|
||||||
}
|
}
|
||||||
// If going to normal mode
|
// If going to normal mode
|
||||||
else if (!mSearchName.equals("") && query.equals("")) {
|
else if (!searchName.equals("") && query.equals("")) {
|
||||||
mSearchMode = false;
|
searchMode = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
mSearchName = query;
|
searchName = query;
|
||||||
restartRequest();
|
restartRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,11 +14,11 @@ import com.mikepenz.materialdrawer.model.PrimaryDrawerItem;
|
||||||
import butterknife.Bind;
|
import butterknife.Bind;
|
||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
import eu.kanade.mangafeed.R;
|
import eu.kanade.mangafeed.R;
|
||||||
import eu.kanade.mangafeed.ui.setting.SettingsActivity;
|
|
||||||
import eu.kanade.mangafeed.ui.base.activity.BaseActivity;
|
import eu.kanade.mangafeed.ui.base.activity.BaseActivity;
|
||||||
|
import eu.kanade.mangafeed.ui.catalogue.SourceFragment;
|
||||||
import eu.kanade.mangafeed.ui.download.DownloadFragment;
|
import eu.kanade.mangafeed.ui.download.DownloadFragment;
|
||||||
import eu.kanade.mangafeed.ui.library.LibraryFragment;
|
import eu.kanade.mangafeed.ui.library.LibraryFragment;
|
||||||
import eu.kanade.mangafeed.ui.catalogue.SourceFragment;
|
import eu.kanade.mangafeed.ui.setting.SettingsActivity;
|
||||||
|
|
||||||
public class MainActivity extends BaseActivity {
|
public class MainActivity extends BaseActivity {
|
||||||
|
|
||||||
|
@ -88,6 +88,7 @@ public class MainActivity extends BaseActivity {
|
||||||
)
|
)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
if (savedInstanceState == null)
|
||||||
drawer.setSelection(R.id.nav_drawer_library);
|
drawer.setSelection(R.id.nav_drawer_library);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Reference in a new issue