Allow to load next and previous chapter for horizontal readers
This commit is contained in:
parent
a055cc07d8
commit
e6c230cbe3
8 changed files with 134 additions and 32 deletions
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,6 +53,7 @@ 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(this::getAdjacentChapters)
|
||||||
.doOnCompleted(() -> start(GET_PAGE_IMAGES)),
|
.doOnCompleted(() -> start(GET_PAGE_IMAGES)),
|
||||||
(view, pages) -> {
|
(view, pages) -> {
|
||||||
view.onPageListReady(pages);
|
view.onPageListReady(pages);
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
Reference in a new issue