Get rid of getView() calls in Chapters presenter. Minor changes in download manager

This commit is contained in:
inorichi 2015-12-02 09:50:01 +01:00
parent 771f49fa3b
commit b9da3cb914
9 changed files with 108 additions and 90 deletions

View file

@ -36,11 +36,7 @@ public class Chapter {
@StorIOSQLiteColumn(name = ChapterTable.COLUMN_CHAPTER_NUMBER) @StorIOSQLiteColumn(name = ChapterTable.COLUMN_CHAPTER_NUMBER)
public float chapter_number; public float chapter_number;
public int downloaded; public int status;
public static final int UNKNOWN = 0;
public static final int NOT_DOWNLOADED = 1;
public static final int DOWNLOADED = 2;
public Chapter() {} public Chapter() {}

View file

@ -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.database.models.Manga;
import eu.kanade.mangafeed.data.download.model.Download; import eu.kanade.mangafeed.data.download.model.Download;
import eu.kanade.mangafeed.data.download.model.DownloadQueue; 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.preference.PreferencesHelper;
import eu.kanade.mangafeed.data.source.SourceManager; 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.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.DiskUtils;
import eu.kanade.mangafeed.util.DynamicConcurrentMergeOperator; import eu.kanade.mangafeed.util.DynamicConcurrentMergeOperator;
import rx.Observable; import rx.Observable;
@ -112,15 +112,25 @@ public class DownloadManager {
for (Chapter chapter : event.getChapters()) { for (Chapter chapter : event.getChapters()) {
Download download = new Download(source, manga, chapter); Download download = new Download(source, manga, chapter);
if (!isChapterDownloaded(download)) { if (!prepareDownload(download)) {
queue.add(download); queue.add(download);
if (isRunning) downloadsQueueSubject.onNext(download); if (isRunning) downloadsQueueSubject.onNext(download);
} }
} }
} }
// Check if a chapter is already downloaded // Public method to checks if a chapter is downloaded
private boolean isChapterDownloaded(Download download) { public boolean isChapterDownloaded(Source source, Manga manga, Chapter chapter) {
File directory = getAbsoluteChapterDirectory(source, manga, chapter);
if (!directory.exists())
return false;
List<Page> 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 // If the chapter is already queued, don't add it again
for (Download queuedDownload : queue.get()) { for (Download queuedDownload : queue.get()) {
if (download.chapter.id.equals(queuedDownload.chapter.id)) if (download.chapter.id.equals(queuedDownload.chapter.id))
@ -135,8 +145,7 @@ public class DownloadManager {
return false; return false;
} }
// If the page list doesn't exist, the chapter isn't download (or maybe it's, // If the page list doesn't exist, the chapter isn't downloaded
// but we consider it's not)
List<Page> savedPages = getSavedPageList(download); List<Page> savedPages = getSavedPageList(download);
if (savedPages == null) if (savedPages == null)
return false; return false;
@ -146,7 +155,12 @@ public class DownloadManager {
// If the number of files matches the number of pages, the chapter is downloaded. // 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 // 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<Page> pages) {
return pages != null && pages.size() + 1 == directory.listFiles().length;
} }
// Download the entire chapter // Download the entire chapter

View file

@ -22,16 +22,18 @@ public class Download {
private transient PublishSubject<Download> statusSubject; private transient PublishSubject<Download> statusSubject;
public static final int QUEUE = 0; public static final int NOT_DOWNLOADED = 0;
public static final int DOWNLOADING = 1; public static final int QUEUE = 1;
public static final int DOWNLOADED = 2; public static final int DOWNLOADING = 2;
public static final int ERROR = 3; public static final int DOWNLOADED = 3;
public static final int ERROR = 4;
public Download(Source source, Manga manga, Chapter chapter) { public Download(Source source, Manga manga, Chapter chapter) {
this.source = source; this.source = source;
this.manga = manga; this.manga = manga;
this.chapter = chapter; this.chapter = chapter;
this.status = QUEUE;
} }
public int getStatus() { public int getStatus() {

View file

@ -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.database.models.Manga;
import eu.kanade.mangafeed.data.source.base.Source; import eu.kanade.mangafeed.data.source.base.Source;
public class SourceMangaChapterEvent { public class ReaderEvent {
private Source source; private Source source;
private Manga manga; private Manga manga;
private Chapter chapter; private Chapter chapter;
public SourceMangaChapterEvent(Source source, Manga manga, Chapter chapter) { public ReaderEvent(Source source, Manga manga, Chapter chapter) {
this.source = source; this.source = source;
this.manga = manga; this.manga = manga;
this.chapter = chapter; this.chapter = chapter;

View file

@ -92,7 +92,7 @@ public class MangaActivity extends BaseRxActivity<MangaPresenter> {
setToolbarTitle(manga.title); setToolbarTitle(manga.title);
} }
public boolean isOnlineManga() { public boolean isCatalogueManga() {
return is_online; return is_online;
} }

View file

@ -16,7 +16,6 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.CheckBox; import android.widget.CheckBox;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.Toast;
import java.util.List; 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.decoration.DividerItemDecoration;
import eu.kanade.mangafeed.ui.manga.MangaActivity; import eu.kanade.mangafeed.ui.manga.MangaActivity;
import eu.kanade.mangafeed.ui.reader.ReaderActivity; import eu.kanade.mangafeed.ui.reader.ReaderActivity;
import eu.kanade.mangafeed.util.ToastUtil;
import nucleus.factory.RequiresPresenter; import nucleus.factory.RequiresPresenter;
import rx.Observable; import rx.Observable;
@ -58,6 +58,7 @@ public class ChaptersFragment extends BaseRxFragment<ChaptersPresenter> implemen
public void onCreate(Bundle savedState) { public void onCreate(Bundle savedState) {
super.onCreate(savedState); super.onCreate(savedState);
setHasOptionsMenu(true); setHasOptionsMenu(true);
getPresenter().setIsCatalogueManga(isCatalogueManga());
} }
@Override @Override
@ -67,21 +68,29 @@ public class ChaptersFragment extends BaseRxFragment<ChaptersPresenter> implemen
View view = inflater.inflate(R.layout.fragment_manga_chapters, container, false); View view = inflater.inflate(R.layout.fragment_manga_chapters, container, false);
ButterKnife.bind(this, view); ButterKnife.bind(this, view);
// Init RecyclerView and adapter
chapters.setLayoutManager(new LinearLayoutManager(getActivity())); chapters.setLayoutManager(new LinearLayoutManager(getActivity()));
chapters.addItemDecoration(new DividerItemDecoration(ContextCompat.getDrawable(this.getContext(), R.drawable.line_divider))); chapters.addItemDecoration(new DividerItemDecoration(ContextCompat.getDrawable(this.getContext(), R.drawable.line_divider)));
createAdapter(); adapter = new ChaptersAdapter(this);
setSwipeRefreshListener(); 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()); sortBtn.setOnClickListener(v -> getPresenter().revertSortOrder());
nextUnreadBtn.setOnClickListener(v -> { nextUnreadBtn.setOnClickListener(v -> {
Chapter chapter = getPresenter().getNextUnreadChapter(); Chapter chapter = getPresenter().getNextUnreadChapter();
if (chapter != null) { if (chapter != null) {
openChapter(chapter); openChapter(chapter);
} else { } else {
Toast.makeText(getContext(), R.string.no_next_chapter, Toast.LENGTH_SHORT).show(); ToastUtil.showShort(getContext(), R.string.no_next_chapter);
} }
}); });
return view; return view;
} }
@ -89,49 +98,38 @@ public class ChaptersFragment extends BaseRxFragment<ChaptersPresenter> implemen
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.chapters, menu); inflater.inflate(R.menu.chapters, menu);
super.onCreateOptionsMenu(menu, inflater); super.onCreateOptionsMenu(menu, inflater);
getPresenter().initSortIcon();
getPresenter().initReadCb();
} }
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) { switch (item.getItemId()) {
case R.id.action_refresh: case R.id.action_refresh:
getPresenter().refreshChapters(); onFetchChapters();
break; break;
} }
return super.onOptionsItemSelected(item); 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<Chapter> chapters) { public void onNextChapters(List<Chapter> chapters) {
adapter.setItems(chapters);
closeActionMode(); closeActionMode();
adapter.setItems(chapters);
} }
public void onNextOnlineChapters() { public void onFetchChapters() {
swipeRefresh.setRefreshing(true);
getPresenter().fetchChapters();
}
public void onFetchChaptersFinish() {
swipeRefresh.setRefreshing(false); swipeRefresh.setRefreshing(false);
} }
public void setSwipeRefreshing() { public boolean isCatalogueManga() {
swipeRefresh.setRefreshing(true); return ((MangaActivity) getActivity()).isCatalogueManga();
}
public boolean isOnlineManga() {
return ((MangaActivity) getActivity()).isOnlineManga();
} }
protected void openChapter(Chapter chapter) { protected void openChapter(Chapter chapter) {
getPresenter().onChapterClicked(chapter); getPresenter().onOpenChapter(chapter);
Intent intent = ReaderActivity.newIntent(getActivity()); Intent intent = ReaderActivity.newIntent(getActivity());
startActivity(intent); startActivity(intent);
} }

View file

@ -15,6 +15,7 @@ import butterknife.Bind;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import eu.kanade.mangafeed.R; import eu.kanade.mangafeed.R;
import eu.kanade.mangafeed.data.database.models.Chapter; import eu.kanade.mangafeed.data.database.models.Chapter;
import eu.kanade.mangafeed.data.download.model.Download;
import rx.Observable; import rx.Observable;
public class ChaptersHolder extends RecyclerView.ViewHolder implements public class ChaptersHolder extends RecyclerView.ViewHolder implements
@ -61,12 +62,9 @@ public class ChaptersHolder extends RecyclerView.ViewHolder implements
pages.setText(""); pages.setText("");
} }
if (chapter.downloaded == Chapter.UNKNOWN) { if (chapter.status == Download.DOWNLOADED) {
adapter.getChaptersFragment().getPresenter().checkIsChapterDownloaded(chapter);
}
if (chapter.downloaded == Chapter.DOWNLOADED) {
downloadText.setVisibility(View.VISIBLE); downloadText.setVisibility(View.VISIBLE);
} else if (chapter.downloaded == Chapter.NOT_DOWNLOADED) { } else if (chapter.status == Download.NOT_DOWNLOADED) {
downloadText.setVisibility(View.INVISIBLE); downloadText.setVisibility(View.INVISIBLE);
} }

View file

@ -2,7 +2,6 @@ package eu.kanade.mangafeed.ui.manga.chapter;
import android.os.Bundle; import android.os.Bundle;
import java.io.File;
import java.util.List; import java.util.List;
import javax.inject.Inject; 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.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.download.DownloadManager;
import eu.kanade.mangafeed.data.download.model.Download;
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.source.base.Source; 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.ChapterCountEvent;
import eu.kanade.mangafeed.event.DownloadChaptersEvent; 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.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;
@ -36,11 +35,12 @@ public class ChaptersPresenter extends BasePresenter<ChaptersFragment> {
private Manga manga; private Manga manga;
private Source source; private Source source;
private boolean isCatalogueManga;
private boolean sortOrderAToZ = true; private boolean sortOrderAToZ = true;
private boolean onlyUnread = true; private boolean onlyUnread = true;
private static final int DB_CHAPTERS = 1; 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 markReadSubscription;
private Subscription downloadSubscription; private Subscription downloadSubscription;
@ -58,9 +58,9 @@ public class ChaptersPresenter extends BasePresenter<ChaptersFragment> {
} }
); );
restartableLatestCache(ONLINE_CHAPTERS, restartableLatestCache(FETCH_CHAPTERS,
this::getOnlineChaptersObs, this::getOnlineChaptersObs,
(view, result) -> view.onNextOnlineChapters() (view, result) -> view.onFetchChaptersFinish()
); );
} }
@ -90,21 +90,19 @@ public class ChaptersPresenter extends BasePresenter<ChaptersFragment> {
start(DB_CHAPTERS); start(DB_CHAPTERS);
// Get chapters if it's an online source // Get chapters if it's an online source
if (getView() != null && getView().isOnlineManga()) { if (isCatalogueManga) {
refreshChapters(); fetchChapters();
} }
} }
} }
public void refreshChapters() { public void fetchChapters() {
if (getView() != null) start(FETCH_CHAPTERS);
getView().setSwipeRefreshing();
start(ONLINE_CHAPTERS);
} }
private Observable<List<Chapter>> getDbChaptersObs() { private Observable<List<Chapter>> getDbChaptersObs() {
return db.getChapters(manga.id, sortOrderAToZ, onlyUnread).createObservable() return db.getChapters(manga.id, sortOrderAToZ, onlyUnread).createObservable()
.doOnNext(this::checkChaptersStatus)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()); .observeOn(AndroidSchedulers.mainThread());
} }
@ -117,13 +115,13 @@ public class ChaptersPresenter extends BasePresenter<ChaptersFragment> {
.observeOn(AndroidSchedulers.mainThread()); .observeOn(AndroidSchedulers.mainThread());
} }
public void onChapterClicked(Chapter chapter) { public void onOpenChapter(Chapter chapter) {
EventBus.getDefault().postSticky(new SourceMangaChapterEvent(source, manga, chapter)); EventBus.getDefault().postSticky(new ReaderEvent(source, manga, chapter));
} }
public Chapter getNextUnreadChapter() { public Chapter getNextUnreadChapter() {
List<Chapter> chapters = db.getNextUnreadChapter(manga).executeAsBlocking(); List<Chapter> chapters = db.getNextUnreadChapter(manga).executeAsBlocking();
if(chapters.size() < 1){ if (chapters.isEmpty()) {
return null; return null;
} }
return chapters.get(0); return chapters.get(0);
@ -159,42 +157,54 @@ public class ChaptersPresenter extends BasePresenter<ChaptersFragment> {
.doOnCompleted(() -> remove(deleteSubscription)) .doOnCompleted(() -> remove(deleteSubscription))
.subscribe(chapter -> { .subscribe(chapter -> {
downloadManager.deleteChapter(source, manga, chapter); downloadManager.deleteChapter(source, manga, chapter);
chapter.downloaded = Chapter.NOT_DOWNLOADED; chapter.status = Download.NOT_DOWNLOADED;
}); });
} }
private void checkChaptersStatus(List<Chapter> chapters) {
for (Chapter chapter : chapters) {
checkIsChapterDownloaded(chapter);
}
}
public void checkIsChapterDownloaded(Chapter chapter) { public void checkIsChapterDownloaded(Chapter chapter) {
File dir = downloadManager.getAbsoluteChapterDirectory(source, manga, chapter); for (Download download : downloadManager.getQueue().get()) {
List<Page> pageList = downloadManager.getSavedPageList(source, manga, chapter); if (chapter.id.equals(download.chapter.id)) {
chapter.status = download.getStatus();
return;
}
}
if (pageList != null && pageList.size() + 1 == dir.listFiles().length) { if (downloadManager.isChapterDownloaded(source, manga, chapter)) {
chapter.downloaded = Chapter.DOWNLOADED; chapter.status = Download.DOWNLOADED;
} else { } else {
chapter.downloaded = Chapter.NOT_DOWNLOADED; chapter.status = Download.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?
} }
} }
public void revertSortOrder() { public void revertSortOrder() {
//TODO manga.chapter_order
sortOrderAToZ = !sortOrderAToZ; sortOrderAToZ = !sortOrderAToZ;
initSortIcon();
start(DB_CHAPTERS); start(DB_CHAPTERS);
} }
public void setReadFilter(boolean onlyUnread) { public void setReadFilter(boolean onlyUnread) {
//TODO do we need save filter for manga?
this.onlyUnread = onlyUnread; this.onlyUnread = onlyUnread;
initReadCb();
start(DB_CHAPTERS); start(DB_CHAPTERS);
} }
public void setIsCatalogueManga(boolean value) {
isCatalogueManga = value;
}
public boolean getSortOrder() {
return sortOrderAToZ;
}
public boolean getReadFilter() {
return onlyUnread;
}
} }

View file

@ -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.base.Source;
import eu.kanade.mangafeed.data.source.model.Page; import eu.kanade.mangafeed.data.source.model.Page;
import eu.kanade.mangafeed.event.RetryPageEvent; 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.event.UpdateChapterSyncEvent;
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;
@ -118,7 +118,7 @@ public class ReaderPresenter extends BasePresenter<ReaderActivity> {
} }
@EventBusHook @EventBusHook
public void onEventMainThread(SourceMangaChapterEvent event) { public void onEventMainThread(ReaderEvent event) {
EventBus.getDefault().removeStickyEvent(event); EventBus.getDefault().removeStickyEvent(event);
source = event.getSource(); source = event.getSource();
manga = event.getManga(); manga = event.getManga();