ReaderPresenter.java 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. package eu.kanade.mangafeed.ui.reader;
  2. import android.os.Bundle;
  3. import java.io.File;
  4. import java.util.List;
  5. import javax.inject.Inject;
  6. import de.greenrobot.event.EventBus;
  7. import eu.kanade.mangafeed.data.database.DatabaseHelper;
  8. import eu.kanade.mangafeed.data.database.models.Chapter;
  9. import eu.kanade.mangafeed.data.database.models.Manga;
  10. import eu.kanade.mangafeed.data.download.DownloadManager;
  11. import eu.kanade.mangafeed.data.preference.PreferencesHelper;
  12. import eu.kanade.mangafeed.data.source.base.Source;
  13. import eu.kanade.mangafeed.data.source.model.Page;
  14. import eu.kanade.mangafeed.event.SourceMangaChapterEvent;
  15. import eu.kanade.mangafeed.ui.base.presenter.BasePresenter;
  16. import eu.kanade.mangafeed.util.EventBusHook;
  17. import icepick.State;
  18. import rx.Observable;
  19. import rx.Subscription;
  20. import rx.android.schedulers.AndroidSchedulers;
  21. import rx.schedulers.Schedulers;
  22. import timber.log.Timber;
  23. public class ReaderPresenter extends BasePresenter<ReaderActivity> {
  24. @Inject PreferencesHelper prefs;
  25. @Inject DatabaseHelper db;
  26. @Inject DownloadManager downloadManager;
  27. private Source source;
  28. private Manga manga;
  29. private Chapter chapter;
  30. private Chapter nextChapter;
  31. private Chapter previousChapter;
  32. private List<Page> pageList;
  33. private boolean isDownloaded;
  34. @State int currentPage;
  35. private Subscription nextChapterSubscription;
  36. private Subscription previousChapterSubscription;
  37. private static final int GET_PAGE_LIST = 1;
  38. private static final int GET_PAGE_IMAGES = 2;
  39. @Override
  40. protected void onCreate(Bundle savedState) {
  41. super.onCreate(savedState);
  42. restartableLatestCache(GET_PAGE_LIST,
  43. () -> getPageListObservable()
  44. .doOnNext(pages -> pageList = pages)
  45. .doOnCompleted(this::getAdjacentChapters)
  46. .doOnCompleted(() -> start(GET_PAGE_IMAGES)),
  47. (view, pages) -> {
  48. view.onPageListReady(pages);
  49. if (currentPage != 0)
  50. view.setSelectedPage(currentPage);
  51. },
  52. (view, error) -> Timber.e("An error occurred while downloading page list"));
  53. restartableReplay(GET_PAGE_IMAGES,
  54. this::getPageImagesObservable,
  55. (view, page) -> {},
  56. (view, error) -> Timber.e("An error occurred while downloading an image"));
  57. }
  58. @Override
  59. protected void onTakeView(ReaderActivity view) {
  60. super.onTakeView(view);
  61. registerForStickyEvents();
  62. }
  63. @Override
  64. protected void onDropView() {
  65. unregisterForEvents();
  66. super.onDropView();
  67. }
  68. @Override
  69. protected void onDestroy() {
  70. onChapterChange();
  71. super.onDestroy();
  72. }
  73. @EventBusHook
  74. public void onEventMainThread(SourceMangaChapterEvent event) {
  75. EventBus.getDefault().removeStickyEvent(event);
  76. source = event.getSource();
  77. manga = event.getManga();
  78. loadChapter(event.getChapter());
  79. }
  80. private void loadChapter(Chapter chapter) {
  81. this.chapter = chapter;
  82. isDownloaded = isChapterDownloaded(chapter);
  83. if (chapter.last_page_read != 0 && !chapter.read)
  84. currentPage = chapter.last_page_read;
  85. else
  86. currentPage = 0;
  87. // Reset next and previous chapter. They have to be fetched again
  88. nextChapter = null;
  89. previousChapter = null;
  90. start(GET_PAGE_LIST);
  91. }
  92. private void onChapterChange() {
  93. if (!isDownloaded)
  94. source.savePageList(chapter.url, pageList);
  95. saveChapterProgress();
  96. }
  97. private Observable<List<Page>> getPageListObservable() {
  98. if (!isDownloaded)
  99. return source.getCachedPageListOrPullFromNetwork(chapter.url)
  100. .subscribeOn(Schedulers.io())
  101. .observeOn(AndroidSchedulers.mainThread());
  102. else
  103. return Observable.just(downloadManager.getSavedPageList(source, manga, chapter));
  104. }
  105. private Observable<Page> getPageImagesObservable() {
  106. Observable<Page> pages;
  107. if (!isDownloaded) {
  108. pages = Observable
  109. .merge(Observable.from(pageList).filter(page -> page.getImageUrl() != null),
  110. source.getRemainingImageUrlsFromPageList(pageList))
  111. .flatMap(source::getCachedImage);
  112. } else {
  113. File chapterDir = downloadManager.getAbsoluteChapterDirectory(source, manga, chapter);
  114. pages = Observable.from(pageList)
  115. .flatMap(page -> downloadManager.getDownloadedImage(page, source, chapterDir));
  116. }
  117. return pages
  118. .subscribeOn(Schedulers.io())
  119. .observeOn(AndroidSchedulers.mainThread());
  120. }
  121. public void retryPage(Page page) {
  122. }
  123. public void setCurrentPage(int currentPage) {
  124. this.currentPage = currentPage;
  125. }
  126. private void saveChapterProgress() {
  127. chapter.last_page_read = currentPage;
  128. if (currentPage == pageList.size() - 1) {
  129. chapter.read = true;
  130. }
  131. db.insertChapter(chapter).executeAsBlocking();
  132. }
  133. private void getAdjacentChapters() {
  134. if (nextChapterSubscription != null)
  135. remove(nextChapterSubscription);
  136. add(nextChapterSubscription = db.getNextChapter(chapter).createObservable()
  137. .flatMap(Observable::from)
  138. .subscribeOn(Schedulers.io())
  139. .subscribe(result -> nextChapter = result));
  140. if (previousChapterSubscription != null)
  141. remove(previousChapterSubscription);
  142. add(previousChapterSubscription = db.getPreviousChapter(chapter).createObservable()
  143. .flatMap(Observable::from)
  144. .subscribeOn(Schedulers.io())
  145. .subscribe(result -> previousChapter = result));
  146. }
  147. public boolean isChapterDownloaded(Chapter chapter) {
  148. File dir = downloadManager.getAbsoluteChapterDirectory(source, manga, chapter);
  149. List<Page> pageList = downloadManager.getSavedPageList(source, manga, chapter);
  150. return pageList != null && pageList.size() + 1 == dir.listFiles().length;
  151. }
  152. public void loadNextChapter() {
  153. if (nextChapter != null) {
  154. onChapterChange();
  155. loadChapter(nextChapter);
  156. }
  157. }
  158. public void loadPreviousChapter() {
  159. if (previousChapter != null) {
  160. onChapterChange();
  161. loadChapter(previousChapter);
  162. }
  163. }
  164. }