Merge remote-tracking branch 'inorichi/master'
This commit is contained in:
commit
89683c24a8
12 changed files with 253 additions and 109 deletions
129
app/src/main/java/eu/kanade/mangafeed/data/cache/CoverCache.java
vendored
Normal file
129
app/src/main/java/eu/kanade/mangafeed/data/cache/CoverCache.java
vendored
Normal file
|
@ -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<File>() {
|
||||||
|
@Override
|
||||||
|
public void onResourceReady(File resource, GlideAnimation<? super File> 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -16,83 +16,75 @@ import rx.Observable;
|
||||||
|
|
||||||
public final class NetworkHelper {
|
public final class NetworkHelper {
|
||||||
|
|
||||||
private OkHttpClient mClient;
|
private OkHttpClient client;
|
||||||
private CookieManager cookieManager;
|
private CookieManager cookieManager;
|
||||||
|
|
||||||
public final CacheControl NULL_CACHE_CONTROL = new CacheControl.Builder().noCache().build();
|
public final CacheControl NULL_CACHE_CONTROL = new CacheControl.Builder().noCache().build();
|
||||||
public final Headers NULL_HEADERS = new Headers.Builder().build();
|
public final Headers NULL_HEADERS = new Headers.Builder().build();
|
||||||
|
|
||||||
public NetworkHelper() {
|
public NetworkHelper() {
|
||||||
mClient = new OkHttpClient();
|
client = new OkHttpClient();
|
||||||
cookieManager = new CookieManager();
|
cookieManager = new CookieManager();
|
||||||
cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
|
cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
|
||||||
mClient.setCookieHandler(cookieManager);
|
client.setCookieHandler(cookieManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Observable<Response> getResponse(final String url, final Headers headers, final CacheControl cacheControl) {
|
public Observable<Response> getResponse(final String url, final Headers headers, final CacheControl cacheControl) {
|
||||||
return Observable.<Response>create(subscriber -> {
|
return Observable.defer(() -> {
|
||||||
try {
|
try {
|
||||||
if (!subscriber.isUnsubscribed()) {
|
|
||||||
Request request = new Request.Builder()
|
Request request = new Request.Builder()
|
||||||
.url(url)
|
.url(url)
|
||||||
.cacheControl(cacheControl != null ? cacheControl : NULL_CACHE_CONTROL)
|
.cacheControl(cacheControl != null ? cacheControl : NULL_CACHE_CONTROL)
|
||||||
.headers(headers != null ? headers : NULL_HEADERS)
|
.headers(headers != null ? headers : NULL_HEADERS)
|
||||||
.build();
|
.build();
|
||||||
subscriber.onNext(mClient.newCall(request).execute());
|
|
||||||
}
|
return Observable.just(client.newCall(request).execute());
|
||||||
subscriber.onCompleted();
|
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
subscriber.onError(e);
|
return Observable.error(e);
|
||||||
}
|
}
|
||||||
}).retry(3);
|
}).retry(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Observable<String> mapResponseToString(final Response response) {
|
public Observable<String> mapResponseToString(final Response response) {
|
||||||
return Observable.create(subscriber -> {
|
return Observable.defer(() -> {
|
||||||
try {
|
try {
|
||||||
subscriber.onNext(response.body().string());
|
return Observable.just(response.body().string());
|
||||||
subscriber.onCompleted();
|
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
subscriber.onError(e);
|
return Observable.error(e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public Observable<String> getStringResponse(final String url, final Headers headers, final CacheControl cacheControl) {
|
public Observable<String> getStringResponse(final String url, final Headers headers, final CacheControl cacheControl) {
|
||||||
|
|
||||||
return getResponse(url, headers, cacheControl)
|
return getResponse(url, headers, cacheControl)
|
||||||
.flatMap(this::mapResponseToString);
|
.flatMap(this::mapResponseToString);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Observable<Response> postData(final String url, final RequestBody formBody, final Headers headers) {
|
public Observable<Response> postData(final String url, final RequestBody formBody, final Headers headers) {
|
||||||
return Observable.create(subscriber -> {
|
return Observable.defer(() -> {
|
||||||
try {
|
try {
|
||||||
if (!subscriber.isUnsubscribed()) {
|
|
||||||
Request request = new Request.Builder()
|
Request request = new Request.Builder()
|
||||||
.url(url)
|
.url(url)
|
||||||
.post(formBody)
|
.post(formBody)
|
||||||
.headers(headers != null ? headers : NULL_HEADERS)
|
.headers(headers != null ? headers : NULL_HEADERS)
|
||||||
.build();
|
.build();
|
||||||
subscriber.onNext(mClient.newCall(request).execute());
|
return Observable.just(client.newCall(request).execute());
|
||||||
}
|
|
||||||
subscriber.onCompleted();
|
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
subscriber.onError(e);
|
return Observable.error(e);
|
||||||
}
|
}
|
||||||
});
|
}).retry(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Observable<Response> getProgressResponse(final String url, final Headers headers, final ProgressListener listener) {
|
public Observable<Response> getProgressResponse(final String url, final Headers headers, final ProgressListener listener) {
|
||||||
return Observable.<Response>create(subscriber -> {
|
return Observable.defer(() -> {
|
||||||
try {
|
try {
|
||||||
if (!subscriber.isUnsubscribed()) {
|
|
||||||
Request request = new Request.Builder()
|
Request request = new Request.Builder()
|
||||||
.url(url)
|
.url(url)
|
||||||
.cacheControl(NULL_CACHE_CONTROL)
|
.cacheControl(NULL_CACHE_CONTROL)
|
||||||
.headers(headers != null ? headers : NULL_HEADERS)
|
.headers(headers != null ? headers : NULL_HEADERS)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
OkHttpClient progressClient = mClient.clone();
|
OkHttpClient progressClient = client.clone();
|
||||||
|
|
||||||
progressClient.networkInterceptors().add(chain -> {
|
progressClient.networkInterceptors().add(chain -> {
|
||||||
Response originalResponse = chain.proceed(chain.request());
|
Response originalResponse = chain.proceed(chain.request());
|
||||||
|
@ -100,11 +92,9 @@ public final class NetworkHelper {
|
||||||
.body(new ProgressResponseBody(originalResponse.body(), listener))
|
.body(new ProgressResponseBody(originalResponse.body(), listener))
|
||||||
.build();
|
.build();
|
||||||
});
|
});
|
||||||
subscriber.onNext(progressClient.newCall(request).execute());
|
return Observable.just(progressClient.newCall(request).execute());
|
||||||
}
|
|
||||||
subscriber.onCompleted();
|
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
subscriber.onError(e);
|
return Observable.error(e);
|
||||||
}
|
}
|
||||||
}).retry(3);
|
}).retry(3);
|
||||||
}
|
}
|
||||||
|
|
|
@ -151,7 +151,7 @@ public class Kissmanga extends Source {
|
||||||
Element infoElement = parsedDocument.select("div.barContent").first();
|
Element infoElement = parsedDocument.select("div.barContent").first();
|
||||||
Element titleElement = infoElement.select("a.bigChar").first();
|
Element titleElement = infoElement.select("a.bigChar").first();
|
||||||
Element authorElement = infoElement.select("p:has(span:contains(Author:)) > a").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");
|
Elements descriptionElement = infoElement.select("p:has(span:contains(Summary:)) ~ p");
|
||||||
Element thumbnailUrlElement = parsedDocument.select(".rightBox:eq(0) img").first();
|
Element thumbnailUrlElement = parsedDocument.select(".rightBox:eq(0) img").first();
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ import javax.inject.Singleton;
|
||||||
import dagger.Module;
|
import dagger.Module;
|
||||||
import dagger.Provides;
|
import dagger.Provides;
|
||||||
import eu.kanade.mangafeed.data.cache.CacheManager;
|
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.chaptersync.ChapterSyncManager;
|
||||||
import eu.kanade.mangafeed.data.database.DatabaseHelper;
|
import eu.kanade.mangafeed.data.database.DatabaseHelper;
|
||||||
import eu.kanade.mangafeed.data.download.DownloadManager;
|
import eu.kanade.mangafeed.data.download.DownloadManager;
|
||||||
|
@ -38,6 +39,12 @@ public class DataModule {
|
||||||
return new CacheManager(app);
|
return new CacheManager(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
CoverCache provideCoverCache(Application app) {
|
||||||
|
return new CoverCache(app);
|
||||||
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
NetworkHelper provideNetworkHelper() {
|
NetworkHelper provideNetworkHelper() {
|
||||||
|
|
|
@ -68,7 +68,7 @@ public class CatalogueAdapter extends ArrayAdapter<Manga> {
|
||||||
|
|
||||||
Glide.with(fragment)
|
Glide.with(fragment)
|
||||||
.load(url)
|
.load(url)
|
||||||
.diskCacheStrategy(DiskCacheStrategy.RESULT)
|
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
|
||||||
.centerCrop()
|
.centerCrop()
|
||||||
.into(thumbnail);
|
.into(thumbnail);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -14,6 +14,7 @@ import android.widget.ImageView;
|
||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
|
|
||||||
import com.bumptech.glide.Glide;
|
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.GlideUrl;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -182,6 +183,7 @@ public class CatalogueFragment extends BaseRxFragment<CataloguePresenter> {
|
||||||
|
|
||||||
Glide.with(this)
|
Glide.with(this)
|
||||||
.load(url)
|
.load(url)
|
||||||
|
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
|
||||||
.centerCrop()
|
.centerCrop()
|
||||||
.into(imageView);
|
.into(imageView);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,12 +4,8 @@ import android.view.View;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
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.R;
|
||||||
|
import eu.kanade.mangafeed.data.cache.CoverCache;
|
||||||
import eu.kanade.mangafeed.data.database.models.Manga;
|
import eu.kanade.mangafeed.data.database.models.Manga;
|
||||||
import uk.co.ribot.easyadapter.ItemViewHolder;
|
import uk.co.ribot.easyadapter.ItemViewHolder;
|
||||||
import uk.co.ribot.easyadapter.PositionInfo;
|
import uk.co.ribot.easyadapter.PositionInfo;
|
||||||
|
@ -43,17 +39,11 @@ public class LibraryHolder extends ItemViewHolder<Manga> {
|
||||||
unreadText.setVisibility(View.GONE);
|
unreadText.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
String thumbnail;
|
if (manga.thumbnail_url != null) {
|
||||||
if (manga.thumbnail_url != null)
|
CoverCache.loadLocalInto(getContext(), thumbnail, manga.thumbnail_url);
|
||||||
thumbnail = manga.thumbnail_url;
|
} else {
|
||||||
else
|
thumbnail.setImageResource(android.R.color.transparent);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ public class ChaptersAdapter extends FlexibleAdapter<ChaptersHolder, Chapter> {
|
||||||
void onListItemLongClick(int position);
|
void onListItemLongClick(int position);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChaptersFragment getMangaChaptersFragment() {
|
public ChaptersFragment getChaptersFragment() {
|
||||||
return (ChaptersFragment) fragment;
|
return (ChaptersFragment) fragment;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@ import android.support.v4.content.ContextCompat;
|
||||||
import android.support.v4.widget.SwipeRefreshLayout;
|
import android.support.v4.widget.SwipeRefreshLayout;
|
||||||
import android.support.v7.view.ActionMode;
|
import android.support.v7.view.ActionMode;
|
||||||
import android.support.v7.widget.LinearLayoutManager;
|
import android.support.v7.widget.LinearLayoutManager;
|
||||||
import android.support.v7.widget.PopupMenu;
|
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.support.v7.widget.Toolbar;
|
import android.support.v7.widget.Toolbar;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
@ -24,11 +23,11 @@ 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.DownloadService;
|
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.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.ui.base.activity.BaseActivity;
|
|
||||||
import eu.kanade.mangafeed.ui.base.fragment.BaseRxFragment;
|
|
||||||
import nucleus.factory.RequiresPresenter;
|
import nucleus.factory.RequiresPresenter;
|
||||||
import rx.Observable;
|
import rx.Observable;
|
||||||
|
|
||||||
|
@ -149,23 +148,15 @@ public class ChaptersFragment extends BaseRxFragment<ChaptersPresenter> implemen
|
||||||
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
|
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
case R.id.action_select_all:
|
case R.id.action_select_all:
|
||||||
adapter.selectAll();
|
return onSelectAll();
|
||||||
return true;
|
|
||||||
case R.id.action_mark_as_read:
|
case R.id.action_mark_as_read:
|
||||||
getPresenter().markChaptersRead(getSelectedChapters(), true);
|
return onMarkAsRead(getSelectedChapters());
|
||||||
return true;
|
|
||||||
case R.id.action_mark_as_unread:
|
case R.id.action_mark_as_unread:
|
||||||
getPresenter().markChaptersRead(getSelectedChapters(), false);
|
return onMarkAsUnread(getSelectedChapters());
|
||||||
return true;
|
|
||||||
case R.id.action_download:
|
case R.id.action_download:
|
||||||
DownloadService.start(getActivity());
|
return onDownload(getSelectedChapters());
|
||||||
getPresenter().downloadChapters(getSelectedChapters());
|
|
||||||
closeActionMode();
|
|
||||||
return true;
|
|
||||||
case R.id.action_delete:
|
case R.id.action_delete:
|
||||||
getPresenter().deleteChapters(getSelectedChapters());
|
return onDelete(getSelectedChapters());
|
||||||
closeActionMode();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -187,6 +178,36 @@ public class ChaptersFragment extends BaseRxFragment<ChaptersPresenter> implemen
|
||||||
actionMode.finish();
|
actionMode.finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected boolean onSelectAll() {
|
||||||
|
adapter.selectAll();
|
||||||
|
setContextTitle(adapter.getSelectedItemCount());
|
||||||
|
actionMode.invalidate();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean onMarkAsRead(Observable<Chapter> chapters) {
|
||||||
|
getPresenter().markChaptersRead(chapters, true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean onMarkAsUnread(Observable<Chapter> chapters) {
|
||||||
|
getPresenter().markChaptersRead(chapters, false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean onDownload(Observable<Chapter> chapters) {
|
||||||
|
DownloadService.start(getActivity());
|
||||||
|
getPresenter().downloadChapters(chapters);
|
||||||
|
closeActionMode();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean onDelete(Observable<Chapter> chapters) {
|
||||||
|
getPresenter().deleteChapters(chapters);
|
||||||
|
closeActionMode();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onListItemClick(int position) {
|
public boolean onListItemClick(int position) {
|
||||||
if (actionMode != null && adapter.getMode() == ChaptersAdapter.MODE_MULTI) {
|
if (actionMode != null && adapter.getMode() == ChaptersAdapter.MODE_MULTI) {
|
||||||
|
|
|
@ -2,11 +2,9 @@ package eu.kanade.mangafeed.ui.manga.chapter;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.support.v4.content.ContextCompat;
|
import android.support.v4.content.ContextCompat;
|
||||||
import android.support.v7.widget.PopupMenu;
|
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.view.MenuItem;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.ImageView;
|
import android.widget.PopupMenu;
|
||||||
import android.widget.RelativeLayout;
|
import android.widget.RelativeLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
@ -17,7 +15,6 @@ 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.DownloadService;
|
|
||||||
import rx.Observable;
|
import rx.Observable;
|
||||||
|
|
||||||
public class ChaptersHolder extends RecyclerView.ViewHolder implements
|
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));
|
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));
|
pages.setText(context.getString(R.string.chapter_progress, chapter.last_page_read + 1));
|
||||||
} else {
|
} else {
|
||||||
pages.setText("");
|
pages.setText("");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chapter.downloaded == Chapter.UNKNOWN) {
|
if (chapter.downloaded == Chapter.UNKNOWN) {
|
||||||
adapter.getMangaChaptersFragment().getPresenter().checkIsChapterDownloaded(chapter);
|
adapter.getChaptersFragment().getPresenter().checkIsChapterDownloaded(chapter);
|
||||||
}
|
}
|
||||||
if (chapter.downloaded == Chapter.DOWNLOADED) {
|
if (chapter.downloaded == Chapter.DOWNLOADED) {
|
||||||
downloadText.setVisibility(View.VISIBLE);
|
downloadText.setVisibility(View.VISIBLE);
|
||||||
|
@ -97,27 +94,24 @@ public class ChaptersHolder extends RecyclerView.ViewHolder implements
|
||||||
|
|
||||||
private void showPopupMenu(View view) {
|
private void showPopupMenu(View view) {
|
||||||
// Create a PopupMenu, giving it the clicked view for an anchor
|
// 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
|
// Inflate our menu resource into the PopupMenu's Menu
|
||||||
popup.getMenuInflater().inflate(R.menu.chapter_single, popup.getMenu());
|
popup.getMenuInflater().inflate(R.menu.chapter_single, popup.getMenu());
|
||||||
|
|
||||||
// Set a listener so we are notified if a menu item is clicked
|
// Set a listener so we are notified if a menu item is clicked
|
||||||
popup.setOnMenuItemClickListener(menuItem -> {
|
popup.setOnMenuItemClickListener(menuItem -> {
|
||||||
|
Observable<Chapter> chapter = Observable.just(item);
|
||||||
|
|
||||||
switch (menuItem.getItemId()) {
|
switch (menuItem.getItemId()) {
|
||||||
case R.id.action_mark_as_read:
|
case R.id.action_mark_as_read:
|
||||||
adapter.getMangaChaptersFragment().getPresenter().markChaptersRead(Observable.just(item), true);
|
return adapter.getChaptersFragment().onMarkAsRead(chapter);
|
||||||
return true;
|
|
||||||
case R.id.action_mark_as_unread:
|
case R.id.action_mark_as_unread:
|
||||||
adapter.getMangaChaptersFragment().getPresenter().markChaptersRead(Observable.just(item), false);
|
return adapter.getChaptersFragment().onMarkAsUnread(chapter);
|
||||||
return true;
|
|
||||||
case R.id.action_download:
|
case R.id.action_download:
|
||||||
DownloadService.start(adapter.getMangaChaptersFragment().getActivity());
|
return adapter.getChaptersFragment().onDownload(chapter);
|
||||||
adapter.getMangaChaptersFragment().getPresenter().downloadChapters(Observable.just(item));
|
|
||||||
return true;
|
|
||||||
case R.id.action_delete:
|
case R.id.action_delete:
|
||||||
adapter.getMangaChaptersFragment().getPresenter().deleteChapters(Observable.just(item));
|
return adapter.getChaptersFragment().onDelete(chapter);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
|
@ -8,9 +8,6 @@ import android.widget.Button;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.bumptech.glide.Glide;
|
|
||||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
|
||||||
|
|
||||||
import butterknife.Bind;
|
import butterknife.Bind;
|
||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
import eu.kanade.mangafeed.R;
|
import eu.kanade.mangafeed.R;
|
||||||
|
@ -65,11 +62,9 @@ public class MangaInfoFragment extends BaseRxFragment<MangaInfoPresenter> {
|
||||||
|
|
||||||
setFavoriteText(manga.favorite);
|
setFavoriteText(manga.favorite);
|
||||||
|
|
||||||
Glide.with(getActivity())
|
getPresenter().coverCache.loadOrFetchInto(mCover,
|
||||||
.load(manga.thumbnail_url)
|
manga.thumbnail_url, getPresenter().source.getGlideHeaders());
|
||||||
.diskCacheStrategy(DiskCacheStrategy.RESULT)
|
|
||||||
.centerCrop()
|
|
||||||
.into(mCover);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setChapterCount(int count) {
|
public void setChapterCount(int count) {
|
||||||
|
|
|
@ -4,8 +4,11 @@ import android.os.Bundle;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import eu.kanade.mangafeed.data.cache.CoverCache;
|
||||||
import eu.kanade.mangafeed.data.database.DatabaseHelper;
|
import eu.kanade.mangafeed.data.database.DatabaseHelper;
|
||||||
import eu.kanade.mangafeed.data.database.models.Manga;
|
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.event.ChapterCountEvent;
|
||||||
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;
|
||||||
|
@ -14,8 +17,11 @@ import rx.Observable;
|
||||||
public class MangaInfoPresenter extends BasePresenter<MangaInfoFragment> {
|
public class MangaInfoPresenter extends BasePresenter<MangaInfoFragment> {
|
||||||
|
|
||||||
@Inject DatabaseHelper db;
|
@Inject DatabaseHelper db;
|
||||||
|
@Inject SourceManager sourceManager;
|
||||||
|
@Inject CoverCache coverCache;
|
||||||
|
|
||||||
private Manga manga;
|
private Manga manga;
|
||||||
|
protected Source source;
|
||||||
private int count = -1;
|
private int count = -1;
|
||||||
|
|
||||||
private static final int GET_MANGA = 1;
|
private static final int GET_MANGA = 1;
|
||||||
|
@ -49,6 +55,7 @@ public class MangaInfoPresenter extends BasePresenter<MangaInfoFragment> {
|
||||||
@EventBusHook
|
@EventBusHook
|
||||||
public void onEventMainThread(Manga manga) {
|
public void onEventMainThread(Manga manga) {
|
||||||
this.manga = manga;
|
this.manga = manga;
|
||||||
|
source = sourceManager.get(manga.source);
|
||||||
start(GET_MANGA);
|
start(GET_MANGA);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,7 +74,16 @@ public class MangaInfoPresenter extends BasePresenter<MangaInfoFragment> {
|
||||||
|
|
||||||
public void toggleFavorite() {
|
public void toggleFavorite() {
|
||||||
manga.favorite = !manga.favorite;
|
manga.favorite = !manga.favorite;
|
||||||
|
onMangaFavoriteChange(manga.favorite);
|
||||||
db.insertManga(manga).executeAsBlocking();
|
db.insertManga(manga).executeAsBlocking();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void onMangaFavoriteChange(boolean isFavorite) {
|
||||||
|
if (isFavorite) {
|
||||||
|
coverCache.save(manga.thumbnail_url, source.getGlideHeaders());
|
||||||
|
} else {
|
||||||
|
coverCache.delete(manga.thumbnail_url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue