From 04a61edb38870722610d789e1180dba0c47835a8 Mon Sep 17 00:00:00 2001 From: inorichi Date: Tue, 1 Dec 2015 14:20:14 +0100 Subject: [PATCH 1/2] Changes: - Add a new cache to store library covers without relying on Glide's cache, making sure they are always available. - Use Observable's defer instead of create in NetworkHelper. - Fix Kissmanga showing only one genre. --- .../mangafeed/data/cache/CoverCache.java | 129 ++++++++++++++++++ .../mangafeed/data/network/NetworkHelper.java | 90 ++++++------ .../data/source/online/english/Kissmanga.java | 2 +- .../injection/module/DataModule.java | 7 + .../ui/catalogue/CatalogueAdapter.java | 2 +- .../ui/catalogue/CatalogueFragment.java | 2 + .../mangafeed/ui/library/LibraryHolder.java | 22 +-- .../ui/manga/info/MangaInfoFragment.java | 11 +- .../ui/manga/info/MangaInfoPresenter.java | 16 +++ 9 files changed, 205 insertions(+), 76 deletions(-) create mode 100644 app/src/main/java/eu/kanade/mangafeed/data/cache/CoverCache.java diff --git a/app/src/main/java/eu/kanade/mangafeed/data/cache/CoverCache.java b/app/src/main/java/eu/kanade/mangafeed/data/cache/CoverCache.java new file mode 100644 index 000000000..424820445 --- /dev/null +++ b/app/src/main/java/eu/kanade/mangafeed/data/cache/CoverCache.java @@ -0,0 +1,129 @@ +package eu.kanade.mangafeed.data.cache; + +import android.content.Context; +import android.widget.ImageView; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.load.engine.DiskCacheStrategy; +import com.bumptech.glide.load.model.GlideUrl; +import com.bumptech.glide.load.model.LazyHeaders; +import com.bumptech.glide.request.animation.GlideAnimation; +import com.bumptech.glide.request.target.SimpleTarget; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import eu.kanade.mangafeed.util.DiskUtils; + +public class CoverCache { + + private static final String PARAMETER_CACHE_DIRECTORY = "cover_disk_cache"; + + private Context context; + private File cacheDir; + + public CoverCache(Context context) { + this.context = context; + cacheDir = new File(context.getCacheDir(), PARAMETER_CACHE_DIRECTORY); + createCacheDir(); + } + + private boolean createCacheDir() { + return !cacheDir.exists() && cacheDir.mkdirs(); + } + + // Download the cover with Glide (it can avoid repeating requests) and save the file on this cache + public void save(String cover, LazyHeaders headers) { + GlideUrl url = new GlideUrl(cover, headers); + Glide.with(context) + .load(url) + .downloadOnly(new SimpleTarget() { + @Override + public void onResourceReady(File resource, GlideAnimation anim) { + try { + add(cover, resource); + } catch (IOException e) { + e.printStackTrace(); + } + } + }); + } + + // Copy the cover from Glide's cache to this cache + public void add(String key, File source) throws IOException { + File dest = new File(cacheDir, DiskUtils.hashKeyForDisk(key)); + if (dest.exists()) + dest.delete(); + + InputStream in = new FileInputStream(source); + try { + OutputStream out = new FileOutputStream(dest); + try { + // Transfer bytes from in to out + byte[] buf = new byte[1024]; + int len; + while ((len = in.read(buf)) > 0) { + out.write(buf, 0, len); + } + } finally { + out.close(); + } + } finally { + in.close(); + } + } + + // Get the cover from cache + public File get(String key) { + return new File(cacheDir, DiskUtils.hashKeyForDisk(key)); + } + + // Delete the cover from cache + public boolean delete(String key) { + File file = new File(cacheDir, DiskUtils.hashKeyForDisk(key)); + return file.exists() && file.delete(); + } + + // Load the cover from cache or network if it doesn't exist + public void loadOrFetchInto(ImageView imageView, String cover, LazyHeaders headers) { + File localCover = get(cover); + if (localCover.exists()) { + loadLocalInto(context, imageView, localCover); + } else { + loadRemoteInto(context, imageView, cover, headers); + } + } + + // Load the cover from cache + public static void loadLocalInto(Context context, ImageView imageView, String cover) { + File cacheDir = new File(context.getCacheDir(), PARAMETER_CACHE_DIRECTORY); + File localCover = new File(cacheDir, DiskUtils.hashKeyForDisk(cover)); + if (localCover.exists()) { + loadLocalInto(context, imageView, localCover); + } + } + + // Load the cover from the cache directory into the specified image view + private static void loadLocalInto(Context context, ImageView imageView, File file) { + Glide.with(context) + .load(file) + .diskCacheStrategy(DiskCacheStrategy.NONE) + .centerCrop() + .into(imageView); + } + + // Load the cover from network into the specified image view. It does NOT save the image in cache + private static void loadRemoteInto(Context context, ImageView imageView, String cover, LazyHeaders headers) { + GlideUrl url = new GlideUrl(cover, headers); + Glide.with(context) + .load(url) + .diskCacheStrategy(DiskCacheStrategy.SOURCE) + .centerCrop() + .into(imageView); + } + +} diff --git a/app/src/main/java/eu/kanade/mangafeed/data/network/NetworkHelper.java b/app/src/main/java/eu/kanade/mangafeed/data/network/NetworkHelper.java index e5ae5bb5a..2f05e3850 100644 --- a/app/src/main/java/eu/kanade/mangafeed/data/network/NetworkHelper.java +++ b/app/src/main/java/eu/kanade/mangafeed/data/network/NetworkHelper.java @@ -16,95 +16,85 @@ import rx.Observable; public final class NetworkHelper { - private OkHttpClient mClient; + private OkHttpClient client; private CookieManager cookieManager; public final CacheControl NULL_CACHE_CONTROL = new CacheControl.Builder().noCache().build(); public final Headers NULL_HEADERS = new Headers.Builder().build(); public NetworkHelper() { - mClient = new OkHttpClient(); + client = new OkHttpClient(); cookieManager = new CookieManager(); cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL); - mClient.setCookieHandler(cookieManager); + client.setCookieHandler(cookieManager); } public Observable getResponse(final String url, final Headers headers, final CacheControl cacheControl) { - return Observable.create(subscriber -> { + return Observable.defer(() -> { try { - if (!subscriber.isUnsubscribed()) { - Request request = new Request.Builder() - .url(url) - .cacheControl(cacheControl != null ? cacheControl : NULL_CACHE_CONTROL) - .headers(headers != null ? headers : NULL_HEADERS) - .build(); - subscriber.onNext(mClient.newCall(request).execute()); - } - subscriber.onCompleted(); + Request request = new Request.Builder() + .url(url) + .cacheControl(cacheControl != null ? cacheControl : NULL_CACHE_CONTROL) + .headers(headers != null ? headers : NULL_HEADERS) + .build(); + + return Observable.just(client.newCall(request).execute()); } catch (Throwable e) { - subscriber.onError(e); + return Observable.error(e); } }).retry(3); } public Observable mapResponseToString(final Response response) { - return Observable.create(subscriber -> { + return Observable.defer(() -> { try { - subscriber.onNext(response.body().string()); - subscriber.onCompleted(); + return Observable.just(response.body().string()); } catch (Throwable e) { - subscriber.onError(e); + return Observable.error(e); } }); } public Observable getStringResponse(final String url, final Headers headers, final CacheControl cacheControl) { - return getResponse(url, headers, cacheControl) .flatMap(this::mapResponseToString); } public Observable postData(final String url, final RequestBody formBody, final Headers headers) { - return Observable.create(subscriber -> { + return Observable.defer(() -> { try { - if (!subscriber.isUnsubscribed()) { - Request request = new Request.Builder() - .url(url) - .post(formBody) - .headers(headers != null ? headers : NULL_HEADERS) - .build(); - subscriber.onNext(mClient.newCall(request).execute()); - } - subscriber.onCompleted(); + Request request = new Request.Builder() + .url(url) + .post(formBody) + .headers(headers != null ? headers : NULL_HEADERS) + .build(); + return Observable.just(client.newCall(request).execute()); } catch (Throwable e) { - subscriber.onError(e); + return Observable.error(e); } - }); + }).retry(3); } public Observable getProgressResponse(final String url, final Headers headers, final ProgressListener listener) { - return Observable.create(subscriber -> { + return Observable.defer(() -> { try { - if (!subscriber.isUnsubscribed()) { - Request request = new Request.Builder() - .url(url) - .cacheControl(NULL_CACHE_CONTROL) - .headers(headers != null ? headers : NULL_HEADERS) + Request request = new Request.Builder() + .url(url) + .cacheControl(NULL_CACHE_CONTROL) + .headers(headers != null ? headers : NULL_HEADERS) + .build(); + + OkHttpClient progressClient = client.clone(); + + progressClient.networkInterceptors().add(chain -> { + Response originalResponse = chain.proceed(chain.request()); + return originalResponse.newBuilder() + .body(new ProgressResponseBody(originalResponse.body(), listener)) .build(); - - OkHttpClient progressClient = mClient.clone(); - - progressClient.networkInterceptors().add(chain -> { - Response originalResponse = chain.proceed(chain.request()); - return originalResponse.newBuilder() - .body(new ProgressResponseBody(originalResponse.body(), listener)) - .build(); - }); - subscriber.onNext(progressClient.newCall(request).execute()); - } - subscriber.onCompleted(); + }); + return Observable.just(progressClient.newCall(request).execute()); } catch (Throwable e) { - subscriber.onError(e); + return Observable.error(e); } }).retry(3); } diff --git a/app/src/main/java/eu/kanade/mangafeed/data/source/online/english/Kissmanga.java b/app/src/main/java/eu/kanade/mangafeed/data/source/online/english/Kissmanga.java index 6ddd43b8c..a18ce7790 100644 --- a/app/src/main/java/eu/kanade/mangafeed/data/source/online/english/Kissmanga.java +++ b/app/src/main/java/eu/kanade/mangafeed/data/source/online/english/Kissmanga.java @@ -151,7 +151,7 @@ public class Kissmanga extends Source { Element infoElement = parsedDocument.select("div.barContent").first(); Element titleElement = infoElement.select("a.bigChar").first(); Element authorElement = infoElement.select("p:has(span:contains(Author:)) > a").first(); - Element genreElement = infoElement.select("p:has(span:contains(Genres:)) > *:gt(0)").first(); + Elements genreElement = infoElement.select("p:has(span:contains(Genres:)) > *:gt(0)"); Elements descriptionElement = infoElement.select("p:has(span:contains(Summary:)) ~ p"); Element thumbnailUrlElement = parsedDocument.select(".rightBox:eq(0) img").first(); diff --git a/app/src/main/java/eu/kanade/mangafeed/injection/module/DataModule.java b/app/src/main/java/eu/kanade/mangafeed/injection/module/DataModule.java index a373c0870..d7fab6df7 100644 --- a/app/src/main/java/eu/kanade/mangafeed/injection/module/DataModule.java +++ b/app/src/main/java/eu/kanade/mangafeed/injection/module/DataModule.java @@ -7,6 +7,7 @@ import javax.inject.Singleton; import dagger.Module; import dagger.Provides; import eu.kanade.mangafeed.data.cache.CacheManager; +import eu.kanade.mangafeed.data.cache.CoverCache; import eu.kanade.mangafeed.data.chaptersync.ChapterSyncManager; import eu.kanade.mangafeed.data.database.DatabaseHelper; import eu.kanade.mangafeed.data.download.DownloadManager; @@ -38,6 +39,12 @@ public class DataModule { return new CacheManager(app); } + @Provides + @Singleton + CoverCache provideCoverCache(Application app) { + return new CoverCache(app); + } + @Provides @Singleton NetworkHelper provideNetworkHelper() { diff --git a/app/src/main/java/eu/kanade/mangafeed/ui/catalogue/CatalogueAdapter.java b/app/src/main/java/eu/kanade/mangafeed/ui/catalogue/CatalogueAdapter.java index d8380ce2b..784d3fba0 100644 --- a/app/src/main/java/eu/kanade/mangafeed/ui/catalogue/CatalogueAdapter.java +++ b/app/src/main/java/eu/kanade/mangafeed/ui/catalogue/CatalogueAdapter.java @@ -67,7 +67,7 @@ public class CatalogueAdapter extends ArrayAdapter { Glide.with(fragment) .load(url) - .diskCacheStrategy(DiskCacheStrategy.RESULT) + .diskCacheStrategy(DiskCacheStrategy.SOURCE) .centerCrop() .into(thumbnail); } else { diff --git a/app/src/main/java/eu/kanade/mangafeed/ui/catalogue/CatalogueFragment.java b/app/src/main/java/eu/kanade/mangafeed/ui/catalogue/CatalogueFragment.java index 89bbd8163..5c6950288 100644 --- a/app/src/main/java/eu/kanade/mangafeed/ui/catalogue/CatalogueFragment.java +++ b/app/src/main/java/eu/kanade/mangafeed/ui/catalogue/CatalogueFragment.java @@ -14,6 +14,7 @@ import android.widget.ImageView; import android.widget.ProgressBar; import com.bumptech.glide.Glide; +import com.bumptech.glide.load.engine.DiskCacheStrategy; import com.bumptech.glide.load.model.GlideUrl; import java.util.List; @@ -182,6 +183,7 @@ public class CatalogueFragment extends BaseRxFragment { Glide.with(this) .load(url) + .diskCacheStrategy(DiskCacheStrategy.SOURCE) .centerCrop() .into(imageView); } diff --git a/app/src/main/java/eu/kanade/mangafeed/ui/library/LibraryHolder.java b/app/src/main/java/eu/kanade/mangafeed/ui/library/LibraryHolder.java index bc7eab9c8..ec81c0f5a 100644 --- a/app/src/main/java/eu/kanade/mangafeed/ui/library/LibraryHolder.java +++ b/app/src/main/java/eu/kanade/mangafeed/ui/library/LibraryHolder.java @@ -4,12 +4,8 @@ import android.view.View; import android.widget.ImageView; import android.widget.TextView; -import com.bumptech.glide.Glide; -import com.bumptech.glide.load.engine.DiskCacheStrategy; - -import java.util.Objects; - import eu.kanade.mangafeed.R; +import eu.kanade.mangafeed.data.cache.CoverCache; import eu.kanade.mangafeed.data.database.models.Manga; import uk.co.ribot.easyadapter.ItemViewHolder; import uk.co.ribot.easyadapter.PositionInfo; @@ -43,17 +39,11 @@ public class LibraryHolder extends ItemViewHolder { unreadText.setVisibility(View.GONE); } - String thumbnail; - if (manga.thumbnail_url != null) - thumbnail = manga.thumbnail_url; - else - thumbnail = "http://img1.wikia.nocookie.net/__cb20090524204255/starwars/images/thumb/1/1a/R2d2.jpg/400px-R2d2.jpg"; - - Glide.with(getContext()) - .load(thumbnail) - .diskCacheStrategy(DiskCacheStrategy.RESULT) - .centerCrop() - .into(this.thumbnail); + if (manga.thumbnail_url != null) { + CoverCache.loadLocalInto(getContext(), thumbnail, manga.thumbnail_url); + } else { + thumbnail.setImageResource(android.R.color.transparent); + } } } diff --git a/app/src/main/java/eu/kanade/mangafeed/ui/manga/info/MangaInfoFragment.java b/app/src/main/java/eu/kanade/mangafeed/ui/manga/info/MangaInfoFragment.java index ffcd818af..746a9c899 100644 --- a/app/src/main/java/eu/kanade/mangafeed/ui/manga/info/MangaInfoFragment.java +++ b/app/src/main/java/eu/kanade/mangafeed/ui/manga/info/MangaInfoFragment.java @@ -8,9 +8,6 @@ import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; -import com.bumptech.glide.Glide; -import com.bumptech.glide.load.engine.DiskCacheStrategy; - import butterknife.Bind; import butterknife.ButterKnife; import eu.kanade.mangafeed.R; @@ -65,11 +62,9 @@ public class MangaInfoFragment extends BaseRxFragment { setFavoriteText(manga.favorite); - Glide.with(getActivity()) - .load(manga.thumbnail_url) - .diskCacheStrategy(DiskCacheStrategy.RESULT) - .centerCrop() - .into(mCover); + getPresenter().coverCache.loadOrFetchInto(mCover, + manga.thumbnail_url, getPresenter().source.getGlideHeaders()); + } public void setChapterCount(int count) { diff --git a/app/src/main/java/eu/kanade/mangafeed/ui/manga/info/MangaInfoPresenter.java b/app/src/main/java/eu/kanade/mangafeed/ui/manga/info/MangaInfoPresenter.java index 7503bcdc5..d128e99c6 100644 --- a/app/src/main/java/eu/kanade/mangafeed/ui/manga/info/MangaInfoPresenter.java +++ b/app/src/main/java/eu/kanade/mangafeed/ui/manga/info/MangaInfoPresenter.java @@ -4,8 +4,11 @@ import android.os.Bundle; import javax.inject.Inject; +import eu.kanade.mangafeed.data.cache.CoverCache; import eu.kanade.mangafeed.data.database.DatabaseHelper; import eu.kanade.mangafeed.data.database.models.Manga; +import eu.kanade.mangafeed.data.source.SourceManager; +import eu.kanade.mangafeed.data.source.base.Source; import eu.kanade.mangafeed.event.ChapterCountEvent; import eu.kanade.mangafeed.ui.base.presenter.BasePresenter; import eu.kanade.mangafeed.util.EventBusHook; @@ -14,8 +17,11 @@ import rx.Observable; public class MangaInfoPresenter extends BasePresenter { @Inject DatabaseHelper db; + @Inject SourceManager sourceManager; + @Inject CoverCache coverCache; private Manga manga; + protected Source source; private int count = -1; private static final int GET_MANGA = 1; @@ -49,6 +55,7 @@ public class MangaInfoPresenter extends BasePresenter { @EventBusHook public void onEventMainThread(Manga manga) { this.manga = manga; + source = sourceManager.get(manga.source); start(GET_MANGA); } @@ -67,7 +74,16 @@ public class MangaInfoPresenter extends BasePresenter { public void toggleFavorite() { manga.favorite = !manga.favorite; + onMangaFavoriteChange(manga.favorite); db.insertManga(manga).executeAsBlocking(); } + private void onMangaFavoriteChange(boolean isFavorite) { + if (isFavorite) { + coverCache.save(manga.thumbnail_url, source.getGlideHeaders()); + } else { + coverCache.delete(manga.thumbnail_url); + } + } + } From 0f5cf6a748a6a38e8e5844a6c6d5b4ef8ec637c1 Mon Sep 17 00:00:00 2001 From: inorichi Date: Tue, 1 Dec 2015 15:47:34 +0100 Subject: [PATCH 2/2] Simplify chapter's popup logic --- .../ui/manga/chapter/ChaptersAdapter.java | 2 +- .../ui/manga/chapter/ChaptersFragment.java | 53 +++++++++++++------ .../ui/manga/chapter/ChaptersHolder.java | 26 ++++----- 3 files changed, 48 insertions(+), 33 deletions(-) diff --git a/app/src/main/java/eu/kanade/mangafeed/ui/manga/chapter/ChaptersAdapter.java b/app/src/main/java/eu/kanade/mangafeed/ui/manga/chapter/ChaptersAdapter.java index a08cabaaa..50fc4f9e7 100644 --- a/app/src/main/java/eu/kanade/mangafeed/ui/manga/chapter/ChaptersAdapter.java +++ b/app/src/main/java/eu/kanade/mangafeed/ui/manga/chapter/ChaptersAdapter.java @@ -48,7 +48,7 @@ public class ChaptersAdapter extends FlexibleAdapter { void onListItemLongClick(int position); } - public ChaptersFragment getMangaChaptersFragment() { + public ChaptersFragment getChaptersFragment() { return (ChaptersFragment) fragment; } } 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 e3b79920e..1563d86d7 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 @@ -6,7 +6,6 @@ import android.support.v4.content.ContextCompat; import android.support.v4.widget.SwipeRefreshLayout; import android.support.v7.view.ActionMode; import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.PopupMenu; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; import android.view.LayoutInflater; @@ -24,11 +23,11 @@ import butterknife.ButterKnife; import eu.kanade.mangafeed.R; import eu.kanade.mangafeed.data.database.models.Chapter; import eu.kanade.mangafeed.data.download.DownloadService; +import eu.kanade.mangafeed.ui.base.activity.BaseActivity; +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.ui.base.activity.BaseActivity; -import eu.kanade.mangafeed.ui.base.fragment.BaseRxFragment; import nucleus.factory.RequiresPresenter; import rx.Observable; @@ -149,23 +148,15 @@ public class ChaptersFragment extends BaseRxFragment implemen public boolean onActionItemClicked(ActionMode mode, MenuItem item) { switch (item.getItemId()) { case R.id.action_select_all: - adapter.selectAll(); - return true; + return onSelectAll(); case R.id.action_mark_as_read: - getPresenter().markChaptersRead(getSelectedChapters(), true); - return true; + return onMarkAsRead(getSelectedChapters()); case R.id.action_mark_as_unread: - getPresenter().markChaptersRead(getSelectedChapters(), false); - return true; + return onMarkAsUnread(getSelectedChapters()); case R.id.action_download: - DownloadService.start(getActivity()); - getPresenter().downloadChapters(getSelectedChapters()); - closeActionMode(); - return true; + return onDownload(getSelectedChapters()); case R.id.action_delete: - getPresenter().deleteChapters(getSelectedChapters()); - closeActionMode(); - return true; + return onDelete(getSelectedChapters()); } return false; } @@ -187,6 +178,36 @@ public class ChaptersFragment extends BaseRxFragment implemen actionMode.finish(); } + protected boolean onSelectAll() { + adapter.selectAll(); + setContextTitle(adapter.getSelectedItemCount()); + actionMode.invalidate(); + return true; + } + + protected boolean onMarkAsRead(Observable chapters) { + getPresenter().markChaptersRead(chapters, true); + return true; + } + + protected boolean onMarkAsUnread(Observable chapters) { + getPresenter().markChaptersRead(chapters, false); + return true; + } + + protected boolean onDownload(Observable chapters) { + DownloadService.start(getActivity()); + getPresenter().downloadChapters(chapters); + closeActionMode(); + return true; + } + + protected boolean onDelete(Observable chapters) { + getPresenter().deleteChapters(chapters); + closeActionMode(); + return true; + } + @Override public boolean onListItemClick(int position) { if (actionMode != null && adapter.getMode() == ChaptersAdapter.MODE_MULTI) { 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 1e5a983de..3b2e1b7ff 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 @@ -2,11 +2,9 @@ package eu.kanade.mangafeed.ui.manga.chapter; import android.content.Context; import android.support.v4.content.ContextCompat; -import android.support.v7.widget.PopupMenu; import android.support.v7.widget.RecyclerView; -import android.view.MenuItem; import android.view.View; -import android.widget.ImageView; +import android.widget.PopupMenu; import android.widget.RelativeLayout; import android.widget.TextView; @@ -17,7 +15,6 @@ 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.DownloadService; import rx.Observable; public class ChaptersHolder extends RecyclerView.ViewHolder implements @@ -58,14 +55,14 @@ public class ChaptersHolder extends RecyclerView.ViewHolder implements title.setTextColor(ContextCompat.getColor(context, R.color.primary_text)); } - if (chapter.last_page_read > 0 && !chapter.read) { + if (!chapter.read && chapter.last_page_read > 0) { pages.setText(context.getString(R.string.chapter_progress, chapter.last_page_read + 1)); } else { pages.setText(""); } if (chapter.downloaded == Chapter.UNKNOWN) { - adapter.getMangaChaptersFragment().getPresenter().checkIsChapterDownloaded(chapter); + adapter.getChaptersFragment().getPresenter().checkIsChapterDownloaded(chapter); } if (chapter.downloaded == Chapter.DOWNLOADED) { downloadText.setVisibility(View.VISIBLE); @@ -97,27 +94,24 @@ public class ChaptersHolder extends RecyclerView.ViewHolder implements private void showPopupMenu(View view) { // Create a PopupMenu, giving it the clicked view for an anchor - PopupMenu popup = new PopupMenu(adapter.getMangaChaptersFragment().getActivity(), view); + PopupMenu popup = new PopupMenu(adapter.getChaptersFragment().getActivity(), view); // Inflate our menu resource into the PopupMenu's Menu popup.getMenuInflater().inflate(R.menu.chapter_single, popup.getMenu()); // Set a listener so we are notified if a menu item is clicked popup.setOnMenuItemClickListener(menuItem -> { + Observable chapter = Observable.just(item); + switch (menuItem.getItemId()) { case R.id.action_mark_as_read: - adapter.getMangaChaptersFragment().getPresenter().markChaptersRead(Observable.just(item), true); - return true; + return adapter.getChaptersFragment().onMarkAsRead(chapter); case R.id.action_mark_as_unread: - adapter.getMangaChaptersFragment().getPresenter().markChaptersRead(Observable.just(item), false); - return true; + return adapter.getChaptersFragment().onMarkAsUnread(chapter); case R.id.action_download: - DownloadService.start(adapter.getMangaChaptersFragment().getActivity()); - adapter.getMangaChaptersFragment().getPresenter().downloadChapters(Observable.just(item)); - return true; + return adapter.getChaptersFragment().onDownload(chapter); case R.id.action_delete: - adapter.getMangaChaptersFragment().getPresenter().deleteChapters(Observable.just(item)); - return true; + return adapter.getChaptersFragment().onDelete(chapter); } return false; });