Allow reading downloaded chapters

This commit is contained in:
inorichi 2015-11-03 21:27:56 +01:00
parent 62ae572c72
commit 11638ae917
20 changed files with 93 additions and 19 deletions

View file

@ -48,10 +48,9 @@ public class DownloadManager {
.subscribe();
}
private Observable<Page> downloadChapter(Manga manga, Chapter chapter) {
public Observable<Page> downloadChapter(Manga manga, Chapter chapter) {
final Source source = sourceManager.get(manga.source);
final File chapterDirectory = new File(
preferences.getDownloadsDirectory(), getChapterDirectory(source, manga, chapter));
final File chapterDirectory = getAbsoluteChapterDirectory(source, manga, chapter);
return source
.pullPageListFromNetwork(chapter.url)
@ -64,8 +63,13 @@ public class DownloadManager {
// Start downloading images
.flatMap(page -> getDownloadedImage(page, source, chapterDirectory));
}
public File getAbsoluteChapterDirectory(Source source, Manga manga, Chapter chapter) {
return new File(preferences.getDownloadsDirectory(),
getChapterDirectory(source, manga, chapter));
}
private String getChapterDirectory(Source source, Manga manga, Chapter chapter) {
public String getChapterDirectory(Source source, Manga manga, Chapter chapter) {
return source.getName() +
File.separator +
manga.title.replaceAll("[^a-zA-Z0-9.-]", "_") +

View file

@ -32,6 +32,12 @@ public class Chapter {
@StorIOSQLiteColumn(name = ChaptersTable.COLUMN_DATE_UPLOAD)
public long date_upload;
public int downloaded;
public static final int UNKNOWN = 0;
public static final int NOT_DOWNLOADED = 1;
public static final int DOWNLOADED = 2;
public Chapter() {}

View file

@ -1,15 +1,18 @@
package eu.kanade.mangafeed.events;
import eu.kanade.mangafeed.data.models.Chapter;
import eu.kanade.mangafeed.data.models.Manga;
import eu.kanade.mangafeed.sources.base.Source;
public class SourceChapterEvent {
public class SourceMangaChapterEvent {
private Source source;
private Manga manga;
private Chapter chapter;
public SourceChapterEvent(Source source, Chapter chapter) {
public SourceMangaChapterEvent(Source source, Manga manga, Chapter chapter) {
this.source = source;
this.manga = manga;
this.chapter = chapter;
}
@ -17,6 +20,10 @@ public class SourceChapterEvent {
return source;
}
public Manga getManga() {
return manga;
}
public Chapter getChapter() {
return chapter;
}

View file

@ -2,17 +2,20 @@ package eu.kanade.mangafeed.presenter;
import android.os.Bundle;
import java.io.File;
import java.util.List;
import javax.inject.Inject;
import de.greenrobot.event.EventBus;
import eu.kanade.mangafeed.data.helpers.DatabaseHelper;
import eu.kanade.mangafeed.data.helpers.DownloadManager;
import eu.kanade.mangafeed.data.helpers.PreferencesHelper;
import eu.kanade.mangafeed.data.helpers.SourceManager;
import eu.kanade.mangafeed.data.models.Chapter;
import eu.kanade.mangafeed.data.models.Manga;
import eu.kanade.mangafeed.events.ChapterCountEvent;
import eu.kanade.mangafeed.events.SourceChapterEvent;
import eu.kanade.mangafeed.events.SourceMangaChapterEvent;
import eu.kanade.mangafeed.sources.base.Source;
import eu.kanade.mangafeed.ui.fragment.MangaChaptersFragment;
import eu.kanade.mangafeed.util.EventBusHook;
@ -26,6 +29,8 @@ public class MangaChaptersPresenter extends BasePresenter<MangaChaptersFragment>
@Inject DatabaseHelper db;
@Inject SourceManager sourceManager;
@Inject PreferencesHelper preferences;
@Inject DownloadManager downloadManager;
private Manga manga;
private Source source;
@ -111,7 +116,7 @@ public class MangaChaptersPresenter extends BasePresenter<MangaChaptersFragment>
}
public void onChapterClicked(Chapter chapter) {
EventBus.getDefault().postSticky(new SourceChapterEvent(source, chapter));
EventBus.getDefault().postSticky(new SourceMangaChapterEvent(source, manga, chapter));
}
public void markChaptersRead(Observable<Chapter> selectedChapters, boolean read) {
@ -131,4 +136,14 @@ public class MangaChaptersPresenter extends BasePresenter<MangaChaptersFragment>
}));
}
public void checkIsChapterDownloaded(Chapter chapter) {
File dir = downloadManager.getAbsoluteChapterDirectory(source, manga, chapter);
if (dir.exists() && dir.listFiles().length > 0) {
chapter.downloaded = Chapter.DOWNLOADED;
} else {
chapter.downloaded = Chapter.NOT_DOWNLOADED;
}
}
}

View file

@ -2,16 +2,19 @@ package eu.kanade.mangafeed.presenter;
import android.os.Bundle;
import java.io.File;
import java.util.List;
import javax.inject.Inject;
import de.greenrobot.event.EventBus;
import eu.kanade.mangafeed.data.helpers.DatabaseHelper;
import eu.kanade.mangafeed.data.helpers.DownloadManager;
import eu.kanade.mangafeed.data.helpers.PreferencesHelper;
import eu.kanade.mangafeed.data.models.Chapter;
import eu.kanade.mangafeed.data.models.Manga;
import eu.kanade.mangafeed.data.models.Page;
import eu.kanade.mangafeed.events.SourceChapterEvent;
import eu.kanade.mangafeed.events.SourceMangaChapterEvent;
import eu.kanade.mangafeed.sources.base.Source;
import eu.kanade.mangafeed.ui.activity.ReaderActivity;
import eu.kanade.mangafeed.util.EventBusHook;
@ -25,14 +28,17 @@ public class ReaderPresenter extends BasePresenter<ReaderActivity> {
@Inject PreferencesHelper prefs;
@Inject DatabaseHelper db;
@Inject DownloadManager downloadManager;
private Source source;
private Manga manga;
private Chapter chapter;
private List<Page> pageList;
@State int currentPage;
private static final int GET_PAGE_LIST = 1;
private static final int GET_PAGE_IMAGES = 2;
private static final int GET_LOCAL_IMAGES = 3;
@Override
protected void onCreate(Bundle savedState) {
@ -41,7 +47,7 @@ public class ReaderPresenter extends BasePresenter<ReaderActivity> {
restartableLatestCache(GET_PAGE_LIST,
() -> getPageListObservable()
.doOnNext(pages -> pageList = pages)
.doOnCompleted(() -> start(GET_PAGE_IMAGES)),
.doOnCompleted(this::prepareChapter),
(view, pages) -> {
view.onPageListReady(pages);
if (currentPage != 0)
@ -55,6 +61,10 @@ public class ReaderPresenter extends BasePresenter<ReaderActivity> {
(view, page) -> {
},
(view, error) -> Timber.e("An error occurred while downloading an image"));
restartableReplay(GET_LOCAL_IMAGES,
this::getLocalImagesObservable,
(view, page) -> {});
}
@Override
@ -77,14 +87,16 @@ public class ReaderPresenter extends BasePresenter<ReaderActivity> {
}
@EventBusHook
public void onEventMainThread(SourceChapterEvent event) {
public void onEventMainThread(SourceMangaChapterEvent event) {
source = event.getSource();
manga = event.getManga();
chapter = event.getChapter();
if (chapter.last_page_read != 0 && !chapter.read)
currentPage = chapter.last_page_read;
start(1);
EventBus.getDefault().removeStickyEvent(SourceChapterEvent.class);
start(GET_PAGE_LIST);
EventBus.getDefault().removeStickyEvent(SourceMangaChapterEvent.class);
}
private Observable<List<Page>> getPageListObservable() {
@ -103,10 +115,26 @@ public class ReaderPresenter extends BasePresenter<ReaderActivity> {
.observeOn(AndroidSchedulers.mainThread());
}
private Observable<Page> getLocalImagesObservable() {
File chapterDir = downloadManager.getAbsoluteChapterDirectory(source, manga, chapter);
return Observable.from(pageList)
.flatMap(page -> downloadManager.getDownloadedImage(page, source, chapterDir))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
}
public void setCurrentPage(int currentPage) {
this.currentPage = currentPage;
}
private void prepareChapter() {
if (chapter.downloaded != Chapter.DOWNLOADED)
start(GET_PAGE_IMAGES);
else
start(GET_LOCAL_IMAGES);
}
private void saveChapter() {
chapter.last_page_read = currentPage;
if (currentPage == pageList.size() - 1) {

View file

@ -1,6 +1,5 @@
package eu.kanade.mangafeed.ui.adapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -11,16 +10,17 @@ import java.util.List;
import eu.davidea.flexibleadapter.FlexibleAdapter;
import eu.kanade.mangafeed.R;
import eu.kanade.mangafeed.data.models.Chapter;
import eu.kanade.mangafeed.ui.fragment.MangaChaptersFragment;
import eu.kanade.mangafeed.ui.fragment.base.BaseFragment;
import eu.kanade.mangafeed.ui.holder.ChaptersHolder;
public class ChaptersAdapter extends FlexibleAdapter<ChaptersHolder, Chapter> {
private Context context;
private BaseFragment fragment;
public OnItemClickListener clickListener;
public ChaptersAdapter(BaseFragment fragment) {
this.context = fragment.getActivity();
this.fragment = fragment;
mItems = new ArrayList<>();
clickListener = (OnItemClickListener) fragment;
}
@ -30,14 +30,14 @@ public class ChaptersAdapter extends FlexibleAdapter<ChaptersHolder, Chapter> {
@Override
public ChaptersHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(context).inflate(R.layout.item_chapter, parent, false);
View v = LayoutInflater.from(fragment.getActivity()).inflate(R.layout.item_chapter, parent, false);
return new ChaptersHolder(v, this);
}
@Override
public void onBindViewHolder(ChaptersHolder holder, int position) {
final Chapter chapter = getItem(position);
holder.onSetValues(context, chapter);
holder.onSetValues(fragment.getActivity(), chapter);
}
public void setItems(List<Chapter> chapters) {
@ -49,4 +49,8 @@ public class ChaptersAdapter extends FlexibleAdapter<ChaptersHolder, Chapter> {
boolean onListItemClick(int position);
void onListItemLongClick(int position);
}
public MangaChaptersFragment getMangaChaptersFragment() {
return (MangaChaptersFragment) fragment;
}
}

View file

@ -37,6 +37,8 @@ public class CatalogueHolder extends ItemViewHolder<Manga> {
.diskCacheStrategy(DiskCacheStrategy.RESULT)
.centerCrop()
.into(image);
} else {
image.setImageResource(android.R.color.transparent);
}
}
}

View file

@ -38,7 +38,7 @@ public class ChaptersHolder extends RecyclerView.ViewHolder implements
public void onSetValues(Context context, Chapter chapter) {
title.setText(chapter.name);
download_icon.setImageResource(R.drawable.ic_file_download_black_48dp);
if (chapter.read) {
title.setTextColor(ContextCompat.getColor(context, R.color.chapter_read_text));
@ -52,6 +52,14 @@ public class ChaptersHolder extends RecyclerView.ViewHolder implements
pages.setText("");
}
if (chapter.downloaded == Chapter.UNKNOWN) {
adapter.getMangaChaptersFragment().getPresenter().checkIsChapterDownloaded(chapter);
}
if (chapter.downloaded == Chapter.DOWNLOADED)
download_icon.setImageResource(R.drawable.ic_action_delete_36dp);
else if (chapter.downloaded == Chapter.NOT_DOWNLOADED)
download_icon.setImageResource(R.drawable.ic_file_download_black_36dp);
toggleActivation();
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 213 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 265 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 200 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 298 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 365 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 348 B