diff --git a/app/src/main/java/eu/kanade/mangafeed/data/database/models/Chapter.java b/app/src/main/java/eu/kanade/mangafeed/data/database/models/Chapter.java index b8fdacaa98..146e918709 100644 --- a/app/src/main/java/eu/kanade/mangafeed/data/database/models/Chapter.java +++ b/app/src/main/java/eu/kanade/mangafeed/data/database/models/Chapter.java @@ -36,11 +36,7 @@ public class Chapter { @StorIOSQLiteColumn(name = ChapterTable.COLUMN_CHAPTER_NUMBER) public float chapter_number; - public int downloaded; - - public static final int UNKNOWN = 0; - public static final int NOT_DOWNLOADED = 1; - public static final int DOWNLOADED = 2; + public int status; public Chapter() {} diff --git a/app/src/main/java/eu/kanade/mangafeed/data/download/DownloadManager.java b/app/src/main/java/eu/kanade/mangafeed/data/download/DownloadManager.java index 343da2c3b2..5c06bbba13 100644 --- a/app/src/main/java/eu/kanade/mangafeed/data/download/DownloadManager.java +++ b/app/src/main/java/eu/kanade/mangafeed/data/download/DownloadManager.java @@ -20,11 +20,11 @@ import eu.kanade.mangafeed.data.database.models.Chapter; import eu.kanade.mangafeed.data.database.models.Manga; import eu.kanade.mangafeed.data.download.model.Download; import eu.kanade.mangafeed.data.download.model.DownloadQueue; -import eu.kanade.mangafeed.data.source.model.Page; import eu.kanade.mangafeed.data.preference.PreferencesHelper; import eu.kanade.mangafeed.data.source.SourceManager; -import eu.kanade.mangafeed.event.DownloadChaptersEvent; import eu.kanade.mangafeed.data.source.base.Source; +import eu.kanade.mangafeed.data.source.model.Page; +import eu.kanade.mangafeed.event.DownloadChaptersEvent; import eu.kanade.mangafeed.util.DiskUtils; import eu.kanade.mangafeed.util.DynamicConcurrentMergeOperator; import rx.Observable; @@ -112,15 +112,25 @@ public class DownloadManager { for (Chapter chapter : event.getChapters()) { Download download = new Download(source, manga, chapter); - if (!isChapterDownloaded(download)) { + if (!prepareDownload(download)) { queue.add(download); if (isRunning) downloadsQueueSubject.onNext(download); } } } - // Check if a chapter is already downloaded - private boolean isChapterDownloaded(Download download) { + // Public method to checks if a chapter is downloaded + public boolean isChapterDownloaded(Source source, Manga manga, Chapter chapter) { + File directory = getAbsoluteChapterDirectory(source, manga, chapter); + if (!directory.exists()) + return false; + + List pages = getSavedPageList(source, manga, chapter); + return isChapterDownloaded(directory, pages); + } + + // Prepare the download. Returns true if the chapter is already downloaded + private boolean prepareDownload(Download download) { // If the chapter is already queued, don't add it again for (Download queuedDownload : queue.get()) { if (download.chapter.id.equals(queuedDownload.chapter.id)) @@ -135,8 +145,7 @@ public class DownloadManager { return false; } - // If the page list doesn't exist, the chapter isn't download (or maybe it's, - // but we consider it's not) + // If the page list doesn't exist, the chapter isn't downloaded List savedPages = getSavedPageList(download); if (savedPages == null) return false; @@ -146,7 +155,12 @@ public class DownloadManager { // If the number of files matches the number of pages, the chapter is downloaded. // We have the index file, so we check one file more - return savedPages.size() + 1 == download.directory.listFiles().length; + return isChapterDownloaded(download.directory, download.pages); + } + + // Check that all the images are downloaded + private boolean isChapterDownloaded(File directory, List pages) { + return pages != null && pages.size() + 1 == directory.listFiles().length; } // Download the entire chapter diff --git a/app/src/main/java/eu/kanade/mangafeed/data/download/model/Download.java b/app/src/main/java/eu/kanade/mangafeed/data/download/model/Download.java index 07b39908e2..1ebf9bdb3a 100644 --- a/app/src/main/java/eu/kanade/mangafeed/data/download/model/Download.java +++ b/app/src/main/java/eu/kanade/mangafeed/data/download/model/Download.java @@ -22,16 +22,18 @@ public class Download { private transient PublishSubject statusSubject; - public static final int QUEUE = 0; - public static final int DOWNLOADING = 1; - public static final int DOWNLOADED = 2; - public static final int ERROR = 3; + public static final int NOT_DOWNLOADED = 0; + public static final int QUEUE = 1; + public static final int DOWNLOADING = 2; + public static final int DOWNLOADED = 3; + public static final int ERROR = 4; public Download(Source source, Manga manga, Chapter chapter) { this.source = source; this.manga = manga; this.chapter = chapter; + this.status = QUEUE; } public int getStatus() { diff --git a/app/src/main/java/eu/kanade/mangafeed/event/SourceMangaChapterEvent.java b/app/src/main/java/eu/kanade/mangafeed/event/ReaderEvent.java similarity index 82% rename from app/src/main/java/eu/kanade/mangafeed/event/SourceMangaChapterEvent.java rename to app/src/main/java/eu/kanade/mangafeed/event/ReaderEvent.java index b08eb6fbfd..66553e5def 100644 --- a/app/src/main/java/eu/kanade/mangafeed/event/SourceMangaChapterEvent.java +++ b/app/src/main/java/eu/kanade/mangafeed/event/ReaderEvent.java @@ -4,13 +4,13 @@ import eu.kanade.mangafeed.data.database.models.Chapter; import eu.kanade.mangafeed.data.database.models.Manga; import eu.kanade.mangafeed.data.source.base.Source; -public class SourceMangaChapterEvent { +public class ReaderEvent { private Source source; private Manga manga; private Chapter chapter; - public SourceMangaChapterEvent(Source source, Manga manga, Chapter chapter) { + public ReaderEvent(Source source, Manga manga, Chapter chapter) { this.source = source; this.manga = manga; this.chapter = chapter; diff --git a/app/src/main/java/eu/kanade/mangafeed/ui/manga/MangaActivity.java b/app/src/main/java/eu/kanade/mangafeed/ui/manga/MangaActivity.java index 3036134e83..a0a2f751cc 100644 --- a/app/src/main/java/eu/kanade/mangafeed/ui/manga/MangaActivity.java +++ b/app/src/main/java/eu/kanade/mangafeed/ui/manga/MangaActivity.java @@ -92,7 +92,7 @@ public class MangaActivity extends BaseRxActivity { setToolbarTitle(manga.title); } - public boolean isOnlineManga() { + public boolean isCatalogueManga() { return is_online; } diff --git a/app/src/main/java/eu/kanade/mangafeed/ui/manga/chapter/ChaptersFragment.java b/app/src/main/java/eu/kanade/mangafeed/ui/manga/chapter/ChaptersFragment.java index 95757542f7..4bed992d14 100644 --- a/app/src/main/java/eu/kanade/mangafeed/ui/manga/chapter/ChaptersFragment.java +++ b/app/src/main/java/eu/kanade/mangafeed/ui/manga/chapter/ChaptersFragment.java @@ -16,7 +16,6 @@ import android.view.View; import android.view.ViewGroup; import android.widget.CheckBox; import android.widget.ImageView; -import android.widget.Toast; import java.util.List; @@ -30,6 +29,7 @@ import eu.kanade.mangafeed.ui.base.fragment.BaseRxFragment; import eu.kanade.mangafeed.ui.decoration.DividerItemDecoration; import eu.kanade.mangafeed.ui.manga.MangaActivity; import eu.kanade.mangafeed.ui.reader.ReaderActivity; +import eu.kanade.mangafeed.util.ToastUtil; import nucleus.factory.RequiresPresenter; import rx.Observable; @@ -58,6 +58,7 @@ public class ChaptersFragment extends BaseRxFragment implemen public void onCreate(Bundle savedState) { super.onCreate(savedState); setHasOptionsMenu(true); + getPresenter().setIsCatalogueManga(isCatalogueManga()); } @Override @@ -67,21 +68,29 @@ public class ChaptersFragment extends BaseRxFragment implemen View view = inflater.inflate(R.layout.fragment_manga_chapters, container, false); ButterKnife.bind(this, view); + // Init RecyclerView and adapter chapters.setLayoutManager(new LinearLayoutManager(getActivity())); chapters.addItemDecoration(new DividerItemDecoration(ContextCompat.getDrawable(this.getContext(), R.drawable.line_divider))); - createAdapter(); - setSwipeRefreshListener(); + adapter = new ChaptersAdapter(this); + chapters.setAdapter(adapter); - readCb.setOnCheckedChangeListener((arg, isCheked) -> getPresenter().setReadFilter(isCheked)); + // Set initial values + setReadFilter(getPresenter().getReadFilter()); + setSortIcon(getPresenter().getSortOrder()); + + // Init listeners + swipeRefresh.setOnRefreshListener(this::onFetchChapters); + readCb.setOnCheckedChangeListener((arg, isChecked) -> getPresenter().setReadFilter(isChecked)); sortBtn.setOnClickListener(v -> getPresenter().revertSortOrder()); nextUnreadBtn.setOnClickListener(v -> { Chapter chapter = getPresenter().getNextUnreadChapter(); if (chapter != null) { openChapter(chapter); } else { - Toast.makeText(getContext(), R.string.no_next_chapter, Toast.LENGTH_SHORT).show(); + ToastUtil.showShort(getContext(), R.string.no_next_chapter); } }); + return view; } @@ -89,49 +98,38 @@ public class ChaptersFragment extends BaseRxFragment implemen public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { inflater.inflate(R.menu.chapters, menu); super.onCreateOptionsMenu(menu, inflater); - - getPresenter().initSortIcon(); - getPresenter().initReadCb(); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.action_refresh: - getPresenter().refreshChapters(); + onFetchChapters(); break; } return super.onOptionsItemSelected(item); } - private void createAdapter() { - adapter = new ChaptersAdapter(this); - chapters.setAdapter(adapter); - } - - private void setSwipeRefreshListener() { - swipeRefresh.setOnRefreshListener(() -> getPresenter().refreshChapters()); - } - public void onNextChapters(List chapters) { - adapter.setItems(chapters); closeActionMode(); + adapter.setItems(chapters); } - public void onNextOnlineChapters() { + public void onFetchChapters() { + swipeRefresh.setRefreshing(true); + getPresenter().fetchChapters(); + } + + public void onFetchChaptersFinish() { swipeRefresh.setRefreshing(false); } - public void setSwipeRefreshing() { - swipeRefresh.setRefreshing(true); - } - - public boolean isOnlineManga() { - return ((MangaActivity) getActivity()).isOnlineManga(); + public boolean isCatalogueManga() { + return ((MangaActivity) getActivity()).isCatalogueManga(); } protected void openChapter(Chapter chapter) { - getPresenter().onChapterClicked(chapter); + getPresenter().onOpenChapter(chapter); Intent intent = ReaderActivity.newIntent(getActivity()); startActivity(intent); } diff --git a/app/src/main/java/eu/kanade/mangafeed/ui/manga/chapter/ChaptersHolder.java b/app/src/main/java/eu/kanade/mangafeed/ui/manga/chapter/ChaptersHolder.java index 3b2e1b7ff6..6bd0938406 100644 --- a/app/src/main/java/eu/kanade/mangafeed/ui/manga/chapter/ChaptersHolder.java +++ b/app/src/main/java/eu/kanade/mangafeed/ui/manga/chapter/ChaptersHolder.java @@ -15,6 +15,7 @@ import butterknife.Bind; import butterknife.ButterKnife; import eu.kanade.mangafeed.R; import eu.kanade.mangafeed.data.database.models.Chapter; +import eu.kanade.mangafeed.data.download.model.Download; import rx.Observable; public class ChaptersHolder extends RecyclerView.ViewHolder implements @@ -61,12 +62,9 @@ public class ChaptersHolder extends RecyclerView.ViewHolder implements pages.setText(""); } - if (chapter.downloaded == Chapter.UNKNOWN) { - adapter.getChaptersFragment().getPresenter().checkIsChapterDownloaded(chapter); - } - if (chapter.downloaded == Chapter.DOWNLOADED) { + if (chapter.status == Download.DOWNLOADED) { downloadText.setVisibility(View.VISIBLE); - } else if (chapter.downloaded == Chapter.NOT_DOWNLOADED) { + } else if (chapter.status == Download.NOT_DOWNLOADED) { downloadText.setVisibility(View.INVISIBLE); } diff --git a/app/src/main/java/eu/kanade/mangafeed/ui/manga/chapter/ChaptersPresenter.java b/app/src/main/java/eu/kanade/mangafeed/ui/manga/chapter/ChaptersPresenter.java index 3358e7f230..0722d5ea03 100644 --- a/app/src/main/java/eu/kanade/mangafeed/ui/manga/chapter/ChaptersPresenter.java +++ b/app/src/main/java/eu/kanade/mangafeed/ui/manga/chapter/ChaptersPresenter.java @@ -2,7 +2,6 @@ package eu.kanade.mangafeed.ui.manga.chapter; import android.os.Bundle; -import java.io.File; import java.util.List; import javax.inject.Inject; @@ -12,13 +11,13 @@ 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.model.Download; import eu.kanade.mangafeed.data.preference.PreferencesHelper; import eu.kanade.mangafeed.data.source.SourceManager; import eu.kanade.mangafeed.data.source.base.Source; -import eu.kanade.mangafeed.data.source.model.Page; import eu.kanade.mangafeed.event.ChapterCountEvent; import eu.kanade.mangafeed.event.DownloadChaptersEvent; -import eu.kanade.mangafeed.event.SourceMangaChapterEvent; +import eu.kanade.mangafeed.event.ReaderEvent; import eu.kanade.mangafeed.ui.base.presenter.BasePresenter; import eu.kanade.mangafeed.util.EventBusHook; import eu.kanade.mangafeed.util.PostResult; @@ -36,11 +35,12 @@ public class ChaptersPresenter extends BasePresenter { private Manga manga; private Source source; + private boolean isCatalogueManga; private boolean sortOrderAToZ = true; private boolean onlyUnread = true; private static final int DB_CHAPTERS = 1; - private static final int ONLINE_CHAPTERS = 2; + private static final int FETCH_CHAPTERS = 2; private Subscription markReadSubscription; private Subscription downloadSubscription; @@ -58,9 +58,9 @@ public class ChaptersPresenter extends BasePresenter { } ); - restartableLatestCache(ONLINE_CHAPTERS, + restartableLatestCache(FETCH_CHAPTERS, this::getOnlineChaptersObs, - (view, result) -> view.onNextOnlineChapters() + (view, result) -> view.onFetchChaptersFinish() ); } @@ -90,21 +90,19 @@ public class ChaptersPresenter extends BasePresenter { start(DB_CHAPTERS); // Get chapters if it's an online source - if (getView() != null && getView().isOnlineManga()) { - refreshChapters(); + if (isCatalogueManga) { + fetchChapters(); } } } - public void refreshChapters() { - if (getView() != null) - getView().setSwipeRefreshing(); - - start(ONLINE_CHAPTERS); + public void fetchChapters() { + start(FETCH_CHAPTERS); } private Observable> getDbChaptersObs() { return db.getChapters(manga.id, sortOrderAToZ, onlyUnread).createObservable() + .doOnNext(this::checkChaptersStatus) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); } @@ -117,13 +115,13 @@ public class ChaptersPresenter extends BasePresenter { .observeOn(AndroidSchedulers.mainThread()); } - public void onChapterClicked(Chapter chapter) { - EventBus.getDefault().postSticky(new SourceMangaChapterEvent(source, manga, chapter)); + public void onOpenChapter(Chapter chapter) { + EventBus.getDefault().postSticky(new ReaderEvent(source, manga, chapter)); } public Chapter getNextUnreadChapter() { List chapters = db.getNextUnreadChapter(manga).executeAsBlocking(); - if(chapters.size() < 1){ + if (chapters.isEmpty()) { return null; } return chapters.get(0); @@ -159,42 +157,54 @@ public class ChaptersPresenter extends BasePresenter { .doOnCompleted(() -> remove(deleteSubscription)) .subscribe(chapter -> { downloadManager.deleteChapter(source, manga, chapter); - chapter.downloaded = Chapter.NOT_DOWNLOADED; + chapter.status = Download.NOT_DOWNLOADED; }); } + + private void checkChaptersStatus(List chapters) { + for (Chapter chapter : chapters) { + checkIsChapterDownloaded(chapter); + } + } + + public void checkIsChapterDownloaded(Chapter chapter) { - File dir = downloadManager.getAbsoluteChapterDirectory(source, manga, chapter); - List pageList = downloadManager.getSavedPageList(source, manga, chapter); + for (Download download : downloadManager.getQueue().get()) { + if (chapter.id.equals(download.chapter.id)) { + chapter.status = download.getStatus(); + return; + } + } - if (pageList != null && pageList.size() + 1 == dir.listFiles().length) { - chapter.downloaded = Chapter.DOWNLOADED; + if (downloadManager.isChapterDownloaded(source, manga, chapter)) { + chapter.status = Download.DOWNLOADED; } else { - chapter.downloaded = Chapter.NOT_DOWNLOADED; - } - } - - public void initSortIcon() { - if (getView() != null) { - getView().setSortIcon(sortOrderAToZ);//TODO manga.chapter_order - } - } - - public void initReadCb() { - if (getView() != null) { - getView().setReadFilter(onlyUnread);//TODO do we need save filter for manga? + chapter.status = Download.NOT_DOWNLOADED; } } public void revertSortOrder() { + //TODO manga.chapter_order sortOrderAToZ = !sortOrderAToZ; - initSortIcon(); start(DB_CHAPTERS); } public void setReadFilter(boolean onlyUnread) { + //TODO do we need save filter for manga? this.onlyUnread = onlyUnread; - initReadCb(); start(DB_CHAPTERS); } + + public void setIsCatalogueManga(boolean value) { + isCatalogueManga = value; + } + + public boolean getSortOrder() { + return sortOrderAToZ; + } + + public boolean getReadFilter() { + return onlyUnread; + } } diff --git a/app/src/main/java/eu/kanade/mangafeed/ui/reader/ReaderPresenter.java b/app/src/main/java/eu/kanade/mangafeed/ui/reader/ReaderPresenter.java index 78a2bd6847..e764bf9181 100644 --- a/app/src/main/java/eu/kanade/mangafeed/ui/reader/ReaderPresenter.java +++ b/app/src/main/java/eu/kanade/mangafeed/ui/reader/ReaderPresenter.java @@ -20,7 +20,7 @@ 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.event.RetryPageEvent; -import eu.kanade.mangafeed.event.SourceMangaChapterEvent; +import eu.kanade.mangafeed.event.ReaderEvent; import eu.kanade.mangafeed.event.UpdateChapterSyncEvent; import eu.kanade.mangafeed.ui.base.presenter.BasePresenter; import eu.kanade.mangafeed.util.EventBusHook; @@ -118,7 +118,7 @@ public class ReaderPresenter extends BasePresenter { } @EventBusHook - public void onEventMainThread(SourceMangaChapterEvent event) { + public void onEventMainThread(ReaderEvent event) { EventBus.getDefault().removeStickyEvent(event); source = event.getSource(); manga = event.getManga();