瀏覽代碼

Allow reading downloaded chapters

inorichi 9 年之前
父節點
當前提交
11638ae917
共有 20 個文件被更改,包括 93 次插入19 次删除
  1. 8 4
      app/src/main/java/eu/kanade/mangafeed/data/helpers/DownloadManager.java
  2. 6 0
      app/src/main/java/eu/kanade/mangafeed/data/models/Chapter.java
  3. 9 2
      app/src/main/java/eu/kanade/mangafeed/events/SourceMangaChapterEvent.java
  4. 17 2
      app/src/main/java/eu/kanade/mangafeed/presenter/MangaChaptersPresenter.java
  5. 33 5
      app/src/main/java/eu/kanade/mangafeed/presenter/ReaderPresenter.java
  6. 9 5
      app/src/main/java/eu/kanade/mangafeed/ui/adapter/ChaptersAdapter.java
  7. 2 0
      app/src/main/java/eu/kanade/mangafeed/ui/holder/CatalogueHolder.java
  8. 9 1
      app/src/main/java/eu/kanade/mangafeed/ui/holder/ChaptersHolder.java
  9. 二進制
      app/src/main/res/drawable-hdpi/ic_action_delete_36dp.png
  10. 二進制
      app/src/main/res/drawable-hdpi/ic_file_download_black_36dp.png
  11. 二進制
      app/src/main/res/drawable-ldpi/ic_action_delete_36dp.png
  12. 二進制
      app/src/main/res/drawable-ldpi/ic_file_download_black_36dp.png
  13. 二進制
      app/src/main/res/drawable-mdpi/ic_action_delete_36dp.png
  14. 二進制
      app/src/main/res/drawable-mdpi/ic_file_download_black_36dp.png
  15. 二進制
      app/src/main/res/drawable-xhdpi/ic_action_delete_36dp.png
  16. 二進制
      app/src/main/res/drawable-xhdpi/ic_file_download_black_36dp.png
  17. 二進制
      app/src/main/res/drawable-xxhdpi/ic_action_delete_36dp.png
  18. 二進制
      app/src/main/res/drawable-xxhdpi/ic_file_download_black_36dp.png
  19. 二進制
      app/src/main/res/drawable-xxxhdpi/ic_action_delete_36dp.png
  20. 二進制
      app/src/main/res/drawable-xxxhdpi/ic_file_download_black_36dp.png

+ 8 - 4
app/src/main/java/eu/kanade/mangafeed/data/helpers/DownloadManager.java

@@ -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.-]", "_") +

+ 6 - 0
app/src/main/java/eu/kanade/mangafeed/data/models/Chapter.java

@@ -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() {}
 

+ 9 - 2
app/src/main/java/eu/kanade/mangafeed/events/SourceChapterEvent.java → app/src/main/java/eu/kanade/mangafeed/events/SourceMangaChapterEvent.java

@@ -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;
     }

+ 17 - 2
app/src/main/java/eu/kanade/mangafeed/presenter/MangaChaptersPresenter.java

@@ -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;
+        }
+    }
 }

+ 33 - 5
app/src/main/java/eu/kanade/mangafeed/presenter/ReaderPresenter.java

@@ -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) {

+ 9 - 5
app/src/main/java/eu/kanade/mangafeed/ui/adapter/ChaptersAdapter.java

@@ -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;
+    }
 }

+ 2 - 0
app/src/main/java/eu/kanade/mangafeed/ui/holder/CatalogueHolder.java

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

+ 9 - 1
app/src/main/java/eu/kanade/mangafeed/ui/holder/ChaptersHolder.java

@@ -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();
     }
 

二進制
app/src/main/res/drawable-hdpi/ic_action_delete_36dp.png


二進制
app/src/main/res/drawable-hdpi/ic_file_download_black_36dp.png


二進制
app/src/main/res/drawable-ldpi/ic_action_delete_36dp.png


二進制
app/src/main/res/drawable-ldpi/ic_file_download_black_36dp.png


二進制
app/src/main/res/drawable-mdpi/ic_action_delete_36dp.png


二進制
app/src/main/res/drawable-mdpi/ic_file_download_black_36dp.png


二進制
app/src/main/res/drawable-xhdpi/ic_action_delete_36dp.png


二進制
app/src/main/res/drawable-xhdpi/ic_file_download_black_36dp.png


二進制
app/src/main/res/drawable-xxhdpi/ic_action_delete_36dp.png


二進制
app/src/main/res/drawable-xxhdpi/ic_file_download_black_36dp.png


二進制
app/src/main/res/drawable-xxxhdpi/ic_action_delete_36dp.png


二進制
app/src/main/res/drawable-xxxhdpi/ic_file_download_black_36dp.png