Allow to load next and previous chapter for horizontal readers

This commit is contained in:
inorichi 2015-11-15 21:21:12 +01:00
parent a055cc07d8
commit e6c230cbe3
8 changed files with 134 additions and 32 deletions

View file

@ -167,6 +167,34 @@ public class DatabaseHelper {
.prepare(); .prepare();
} }
public PreparedGetListOfObjects<Chapter> getNextChapter(Chapter chapter) {
return db.get()
.listOfObjects(Chapter.class)
.withQuery(Query.builder()
.table(ChaptersTable.TABLE)
.where(ChaptersTable.COLUMN_MANGA_ID + "=? AND " +
ChaptersTable.COLUMN_CHAPTER_NUMBER + ">?")
.whereArgs(chapter.manga_id, chapter.chapter_number)
.orderBy(ChaptersTable.COLUMN_CHAPTER_NUMBER)
.limit(1)
.build())
.prepare();
}
public PreparedGetListOfObjects<Chapter> getPreviousChapter(Chapter chapter) {
return db.get()
.listOfObjects(Chapter.class)
.withQuery(Query.builder()
.table(ChaptersTable.TABLE)
.where(ChaptersTable.COLUMN_MANGA_ID + "=? AND " +
ChaptersTable.COLUMN_CHAPTER_NUMBER + "<?")
.whereArgs(chapter.manga_id, chapter.chapter_number)
.orderBy(ChaptersTable.COLUMN_CHAPTER_NUMBER + " DESC")
.limit(1)
.build())
.prepare();
}
public PreparedPutObject<Chapter> insertChapter(Chapter chapter) { public PreparedPutObject<Chapter> insertChapter(Chapter chapter) {
return db.put() return db.put()
.object(chapter) .object(chapter)

View file

@ -9,15 +9,16 @@ import javax.inject.Inject;
import de.greenrobot.event.EventBus; import de.greenrobot.event.EventBus;
import eu.kanade.mangafeed.data.database.DatabaseHelper; import eu.kanade.mangafeed.data.database.DatabaseHelper;
import eu.kanade.mangafeed.data.database.models.Chapter;
import eu.kanade.mangafeed.data.database.models.Manga;
import eu.kanade.mangafeed.data.download.DownloadManager; import eu.kanade.mangafeed.data.download.DownloadManager;
import eu.kanade.mangafeed.data.preference.PreferencesHelper; import eu.kanade.mangafeed.data.preference.PreferencesHelper;
import eu.kanade.mangafeed.data.source.SourceManager; import eu.kanade.mangafeed.data.source.SourceManager;
import eu.kanade.mangafeed.data.database.models.Chapter; import eu.kanade.mangafeed.data.source.base.Source;
import eu.kanade.mangafeed.data.database.models.Manga; import eu.kanade.mangafeed.data.source.model.Page;
import eu.kanade.mangafeed.event.ChapterCountEvent; import eu.kanade.mangafeed.event.ChapterCountEvent;
import eu.kanade.mangafeed.event.DownloadChaptersEvent; import eu.kanade.mangafeed.event.DownloadChaptersEvent;
import eu.kanade.mangafeed.event.SourceMangaChapterEvent; import eu.kanade.mangafeed.event.SourceMangaChapterEvent;
import eu.kanade.mangafeed.data.source.base.Source;
import eu.kanade.mangafeed.ui.base.presenter.BasePresenter; import eu.kanade.mangafeed.ui.base.presenter.BasePresenter;
import eu.kanade.mangafeed.util.EventBusHook; import eu.kanade.mangafeed.util.EventBusHook;
import eu.kanade.mangafeed.util.PostResult; import eu.kanade.mangafeed.util.PostResult;
@ -123,6 +124,7 @@ public class ChaptersPresenter extends BasePresenter<ChaptersFragment> {
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.map(chapter -> { .map(chapter -> {
chapter.read = read; chapter.read = read;
if (!read) chapter.last_page_read = 0;
return chapter; return chapter;
}) })
.toList() .toList()
@ -153,10 +155,9 @@ public class ChaptersPresenter extends BasePresenter<ChaptersFragment> {
public void checkIsChapterDownloaded(Chapter chapter) { public void checkIsChapterDownloaded(Chapter chapter) {
File dir = downloadManager.getAbsoluteChapterDirectory(source, manga, chapter); File dir = downloadManager.getAbsoluteChapterDirectory(source, manga, chapter);
File pageList = new File(dir, DownloadManager.PAGE_LIST_FILE); List<Page> pageList = downloadManager.getSavedPageList(source, manga, chapter);
if (dir.exists() && pageList.exists() && downloadManager if (pageList != null && pageList.size() + 1 == dir.listFiles().length) {
.getSavedPageList(source, manga, chapter).size() + 1 == dir.listFiles().length) {
chapter.downloaded = Chapter.DOWNLOADED; chapter.downloaded = Chapter.DOWNLOADED;
} else { } else {
chapter.downloaded = Chapter.NOT_DOWNLOADED; chapter.downloaded = Chapter.NOT_DOWNLOADED;

View file

@ -32,7 +32,7 @@ import nucleus.factory.RequiresPresenter;
public class ReaderActivity extends BaseRxActivity<ReaderPresenter> { public class ReaderActivity extends BaseRxActivity<ReaderPresenter> {
@Bind(R.id.page_number) TextView pageNumber; @Bind(R.id.page_number) TextView pageNumber;
@Bind(R.id.viewer) FrameLayout container; @Bind(R.id.reader) FrameLayout container;
@Inject PreferencesHelper prefs; @Inject PreferencesHelper prefs;
@ -59,12 +59,15 @@ public class ReaderActivity extends BaseRxActivity<ReaderPresenter> {
if (prefs.useFullscreenSet()) if (prefs.useFullscreenSet())
enableFullScreen(); enableFullScreen();
viewer = getViewer();
enableHardwareAcceleration(); enableHardwareAcceleration();
viewer = getViewer();
} }
public void onPageListReady(List<Page> pages) { public void onPageListReady(List<Page> pages) {
if (viewer != null)
viewer.destroySubscriptions();
viewer = getViewer();
viewer.onPageListReady(pages); viewer.onPageListReady(pages);
viewer.updatePageNumber(); viewer.updatePageNumber();
} }
@ -81,11 +84,6 @@ public class ReaderActivity extends BaseRxActivity<ReaderPresenter> {
super.onPause(); super.onPause();
} }
@Override
protected void onDestroy() {
super.onDestroy();
}
public void setSelectedPage(int pageIndex) { public void setSelectedPage(int pageIndex) {
viewer.setSelectedPage(pageIndex); viewer.setSelectedPage(pageIndex);
} }

View file

@ -9,17 +9,18 @@ import javax.inject.Inject;
import de.greenrobot.event.EventBus; import de.greenrobot.event.EventBus;
import eu.kanade.mangafeed.data.database.DatabaseHelper; import eu.kanade.mangafeed.data.database.DatabaseHelper;
import eu.kanade.mangafeed.data.download.DownloadManager;
import eu.kanade.mangafeed.data.preference.PreferencesHelper;
import eu.kanade.mangafeed.data.database.models.Chapter; import eu.kanade.mangafeed.data.database.models.Chapter;
import eu.kanade.mangafeed.data.database.models.Manga; import eu.kanade.mangafeed.data.database.models.Manga;
import eu.kanade.mangafeed.data.download.DownloadManager;
import eu.kanade.mangafeed.data.preference.PreferencesHelper;
import eu.kanade.mangafeed.data.source.base.Source;
import eu.kanade.mangafeed.data.source.model.Page; import eu.kanade.mangafeed.data.source.model.Page;
import eu.kanade.mangafeed.event.SourceMangaChapterEvent; import eu.kanade.mangafeed.event.SourceMangaChapterEvent;
import eu.kanade.mangafeed.data.source.base.Source;
import eu.kanade.mangafeed.ui.base.presenter.BasePresenter; import eu.kanade.mangafeed.ui.base.presenter.BasePresenter;
import eu.kanade.mangafeed.util.EventBusHook; import eu.kanade.mangafeed.util.EventBusHook;
import icepick.State; import icepick.State;
import rx.Observable; import rx.Observable;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers; import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers; import rx.schedulers.Schedulers;
import timber.log.Timber; import timber.log.Timber;
@ -33,10 +34,15 @@ public class ReaderPresenter extends BasePresenter<ReaderActivity> {
private Source source; private Source source;
private Manga manga; private Manga manga;
private Chapter chapter; private Chapter chapter;
private Chapter nextChapter;
private Chapter previousChapter;
private List<Page> pageList; private List<Page> pageList;
private boolean isDownloaded; private boolean isDownloaded;
@State int currentPage; @State int currentPage;
private Subscription nextChapterSubscription;
private Subscription previousChapterSubscription;
private static final int GET_PAGE_LIST = 1; private static final int GET_PAGE_LIST = 1;
private static final int GET_PAGE_IMAGES = 2; private static final int GET_PAGE_IMAGES = 2;
@ -47,7 +53,8 @@ public class ReaderPresenter extends BasePresenter<ReaderActivity> {
restartableLatestCache(GET_PAGE_LIST, restartableLatestCache(GET_PAGE_LIST,
() -> getPageListObservable() () -> getPageListObservable()
.doOnNext(pages -> pageList = pages) .doOnNext(pages -> pageList = pages)
.doOnCompleted( () -> start(GET_PAGE_IMAGES) ), .doOnCompleted(this::getAdjacentChapters)
.doOnCompleted(() -> start(GET_PAGE_IMAGES)),
(view, pages) -> { (view, pages) -> {
view.onPageListReady(pages); view.onPageListReady(pages);
if (currentPage != 0) if (currentPage != 0)
@ -76,24 +83,37 @@ public class ReaderPresenter extends BasePresenter<ReaderActivity> {
@Override @Override
protected void onDestroy() { protected void onDestroy() {
if (!isDownloaded) onChapterChange();
source.savePageList(chapter.url, pageList);
saveChapterProgress();
super.onDestroy(); super.onDestroy();
} }
@EventBusHook @EventBusHook
public void onEventMainThread(SourceMangaChapterEvent event) { public void onEventMainThread(SourceMangaChapterEvent event) {
EventBus.getDefault().removeStickyEvent(event);
source = event.getSource(); source = event.getSource();
manga = event.getManga(); manga = event.getManga();
chapter = event.getChapter(); loadChapter(event.getChapter());
isDownloaded = chapter.downloaded == Chapter.DOWNLOADED; }
private void loadChapter(Chapter chapter) {
this.chapter = chapter;
isDownloaded = isChapterDownloaded(chapter);
if (chapter.last_page_read != 0 && !chapter.read) if (chapter.last_page_read != 0 && !chapter.read)
currentPage = chapter.last_page_read; currentPage = chapter.last_page_read;
else
currentPage = 0;
// Reset next and previous chapter. They have to be fetched again
nextChapter = null;
previousChapter = null;
start(GET_PAGE_LIST); start(GET_PAGE_LIST);
}
EventBus.getDefault().removeStickyEvent(SourceMangaChapterEvent.class); private void onChapterChange() {
if (!isDownloaded)
source.savePageList(chapter.url, pageList);
saveChapterProgress();
} }
private Observable<List<Page>> getPageListObservable() { private Observable<List<Page>> getPageListObservable() {
@ -117,15 +137,17 @@ public class ReaderPresenter extends BasePresenter<ReaderActivity> {
File chapterDir = downloadManager.getAbsoluteChapterDirectory(source, manga, chapter); File chapterDir = downloadManager.getAbsoluteChapterDirectory(source, manga, chapter);
pages = Observable.from(pageList) pages = Observable.from(pageList)
.flatMap(page -> downloadManager.getDownloadedImage(page, source, chapterDir)) .flatMap(page -> downloadManager.getDownloadedImage(page, source, chapterDir));
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
} }
return pages return pages
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()); .observeOn(AndroidSchedulers.mainThread());
} }
public void retryPage(Page page) {
}
public void setCurrentPage(int currentPage) { public void setCurrentPage(int currentPage) {
this.currentPage = currentPage; this.currentPage = currentPage;
} }
@ -137,4 +159,43 @@ public class ReaderPresenter extends BasePresenter<ReaderActivity> {
} }
db.insertChapter(chapter).executeAsBlocking(); db.insertChapter(chapter).executeAsBlocking();
} }
private void getAdjacentChapters() {
if (nextChapterSubscription != null)
remove(nextChapterSubscription);
add(nextChapterSubscription = db.getNextChapter(chapter).createObservable()
.flatMap(Observable::from)
.subscribeOn(Schedulers.io())
.subscribe(result -> nextChapter = result));
if (previousChapterSubscription != null)
remove(previousChapterSubscription);
add(previousChapterSubscription = db.getPreviousChapter(chapter).createObservable()
.flatMap(Observable::from)
.subscribeOn(Schedulers.io())
.subscribe(result -> previousChapter = result));
}
public boolean isChapterDownloaded(Chapter chapter) {
File dir = downloadManager.getAbsoluteChapterDirectory(source, manga, chapter);
List<Page> pageList = downloadManager.getSavedPageList(source, manga, chapter);
return pageList != null && pageList.size() + 1 == dir.listFiles().length;
}
public void loadNextChapter() {
if (nextChapter != null) {
onChapterChange();
loadChapter(nextChapter);
}
}
public void loadPreviousChapter() {
if (previousChapter != null) {
onChapterChange();
loadChapter(previousChapter);
}
}
} }

View file

@ -33,6 +33,20 @@ public abstract class BaseReader {
return getCurrentPageIndex(currentPosition); return getCurrentPageIndex(currentPosition);
} }
public void retryPage(Page page) {
activity.getPresenter().retryPage(page);
}
public void requestNextChapter() {
activity.getPresenter().setCurrentPage(getCurrentPosition());
activity.getPresenter().loadNextChapter();
}
public void requestPreviousChapter() {
activity.getPresenter().setCurrentPage(getCurrentPosition());
activity.getPresenter().loadPreviousChapter();
}
public void destroySubscriptions() {} public void destroySubscriptions() {}
public abstract int getTotalPages(); public abstract int getTotalPages();

View file

@ -12,12 +12,12 @@ public class LeftToRightReader extends HorizontalReader {
@Override @Override
public void onFirstPageOut() { public void onFirstPageOut() {
// TODO requestPreviousChapter();
} }
@Override @Override
public void onLastPageOut() { public void onLastPageOut() {
// TODO requestNextChapter();
} }
} }

View file

@ -30,12 +30,12 @@ public class RightToLeftReader extends HorizontalReader {
@Override @Override
public void onFirstPageOut() { public void onFirstPageOut() {
// TODO requestNextChapter();
} }
@Override @Override
public void onLastPageOut() { public void onLastPageOut() {
// TODO requestPreviousChapter();
} }
} }

View file

@ -4,7 +4,7 @@
android:layout_height="match_parent"> android:layout_height="match_parent">
<FrameLayout <FrameLayout
android:id="@+id/viewer" android:id="@+id/reader"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
</FrameLayout> </FrameLayout>