From ded46048bd176874ec3e0c75cf578cb2b28a0920 Mon Sep 17 00:00:00 2001 From: NoodleMage Date: Tue, 26 Jan 2016 13:26:41 +0100 Subject: [PATCH 01/12] Code optimization. Added javadoc. Removed setSize for it is not used --- .../tachiyomi/data/cache/ChapterCache.java | 113 ++++++++++++++++-- 1 file changed, 101 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/cache/ChapterCache.java b/app/src/main/java/eu/kanade/tachiyomi/data/cache/ChapterCache.java index 9571c6020c..2f1c825b17 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/cache/ChapterCache.java +++ b/app/src/main/java/eu/kanade/tachiyomi/data/cache/ChapterCache.java @@ -23,20 +23,39 @@ import rx.Observable; public class ChapterCache { + /** Name of cache directory. */ private static final String PARAMETER_CACHE_DIRECTORY = "chapter_disk_cache"; + + /** Application version. */ private static final int PARAMETER_APP_VERSION = 1; + + /** The number of values per cache entry. Must be positive. */ private static final int PARAMETER_VALUE_COUNT = 1; + + /** The maximum number of bytes this cache should use to store. */ private static final int PARAMETER_CACHE_SIZE = 75 * 1024 * 1024; - private Context context; - private Gson gson; + /** Interface to global information about an application environment. */ + private final Context context; + /** Google Json class used for parsing json files. */ + private final Gson gson; + + /** Cache class used for cache management. */ private DiskLruCache diskCache; + /** + * Constructor of ChapterCache. + * @param context application environment interface. + */ public ChapterCache(Context context) { + // Set context. this.context = context; + + // Initialize Json handler. gson = new Gson(); + // Try to open cache in default cache directory. try { diskCache = DiskLruCache.open( new File(context.getCacheDir(), PARAMETER_CACHE_DIRECTORY), @@ -45,15 +64,22 @@ public class ChapterCache { PARAMETER_CACHE_SIZE ); } catch (IOException e) { - // Do Nothing. + // Do Nothing. TODO error handling? } } + /** + * Remove Chapter from cache. + * @param file name of chapter file. + * @return false if file is journal or error else returns true. + */ public boolean remove(String file) { + // Make sure we don't delete the journal file (keeps track of cache). if (file.equals("journal") || file.startsWith("journal.")) return false; try { + // Take dot(.) substring to avoid conflicts. String key = file.substring(0, file.lastIndexOf(".")); return diskCache.remove(key); } catch (IOException e) { @@ -61,27 +87,43 @@ public class ChapterCache { } } + /** + * Returns directory of cache. + * @return directory of cache. + */ public File getCacheDir() { return diskCache.getDirectory(); } - public long getRealSize() { + /** + * Returns real size of directory. + * @return real size of directory. + */ + private long getRealSize() { return DiskUtils.getDirectorySize(getCacheDir()); } + /** + * Returns real size of directory in human readable format. + * @return real size of directory. + */ public String getReadableSize() { return Formatter.formatFileSize(context, getRealSize()); } - public void setSize(int value) { - diskCache.setMaxSize(value * 1024 * 1024); - } - + /** + * Get page urls from cache. + * @param chapterUrl the url of the chapter. + * @return list of chapter pages. + */ public Observable> getPageUrlsFromDiskCache(final String chapterUrl) { return Observable.create(subscriber -> { try { + // Get list of pages from chapterUrl. List pages = getPageUrlsFromDiskCacheImpl(chapterUrl); + // Provides the Observer with a new item to observe. subscriber.onNext(pages); + // Notify the Observer that finished sending push-based notifications. subscriber.onCompleted(); } catch (Throwable e) { subscriber.onError(e); @@ -89,18 +131,31 @@ public class ChapterCache { }); } - private List getPageUrlsFromDiskCacheImpl(String chapterUrl) throws IOException { + /** + * Implementation of the getPageUrlsFromDiskCache() function + * @param chapterUrl the url of the chapter + * @return returns list of chapter pages + * @throws IOException does nothing atm + */ + private List getPageUrlsFromDiskCacheImpl(String chapterUrl) throws IOException /*TODO IOException never thrown*/ { + // Initialize snapshot (a snapshot of the values for an entry). DiskLruCache.Snapshot snapshot = null; + + // Initialize list of pages. List pages = null; try { + // Create md5 key and retrieve snapshot. String key = DiskUtils.hashKeyForDisk(chapterUrl); snapshot = diskCache.get(key); + + // Convert JSON string to list of objects. Type collectionType = new TypeToken>() {}.getType(); pages = gson.fromJson(snapshot.getString(0), collectionType); + } catch (IOException e) { - // Do Nothing. + // Do Nothing. //TODO error handling? } finally { if (snapshot != null) { snapshot.close(); @@ -109,18 +164,30 @@ public class ChapterCache { return pages; } + /** + * Add page urls to disk cache. + * @param chapterUrl the url of the chapter. + * @param pages list of chapter pages. + */ public void putPageUrlsToDiskCache(final String chapterUrl, final List pages) { + // Convert list of pages to json string. String cachedValue = gson.toJson(pages); + // Initialize the editor (edits the values for an entry). DiskLruCache.Editor editor = null; + + // Initialize OutputStream. OutputStream outputStream = null; + try { + // Get editor from md5 key. String key = DiskUtils.hashKeyForDisk(chapterUrl); editor = diskCache.edit(key); if (editor == null) { return; } + // Write chapter urls to cache. outputStream = new BufferedOutputStream(editor.newOutputStream(0)); outputStream.write(cachedValue.getBytes()); outputStream.flush(); @@ -128,7 +195,7 @@ public class ChapterCache { diskCache.flush(); editor.commit(); } catch (Exception e) { - // Do Nothing. + // Do Nothing. TODO error handling? } finally { if (editor != null) { editor.abortUnlessCommitted(); @@ -137,12 +204,17 @@ public class ChapterCache { try { outputStream.close(); } catch (IOException ignore) { - // Do Nothing. + // Do Nothing. TODO error handling? } } } } + /** + * Check if image is in cache. + * @param imageUrl url of image. + * @return true if in cache otherwise false. + */ public boolean isImageInCache(final String imageUrl) { try { return diskCache.get(DiskUtils.hashKeyForDisk(imageUrl)) != null; @@ -152,8 +224,14 @@ public class ChapterCache { return false; } + /** + * Get image path from url. + * @param imageUrl url of image. + * @return path of image. + */ public String getImagePath(final String imageUrl) { try { + // Get file from md5 key. String imageName = DiskUtils.hashKeyForDisk(imageUrl) + ".0"; File file = new File(diskCache.getDirectory(), imageName); return file.getCanonicalPath(); @@ -163,17 +241,28 @@ public class ChapterCache { return null; } + /** + * Add image to cache + * @param imageUrl url of image. + * @param response http response from page. + * @throws IOException image error. + */ public void putImageToDiskCache(final String imageUrl, final Response response) throws IOException { + // Initialize editor (edits the values for an entry). DiskLruCache.Editor editor = null; + + // Initialize BufferedSink (used for small writes). BufferedSink sink = null; try { + // Get editor from md5 key. String key = DiskUtils.hashKeyForDisk(imageUrl); editor = diskCache.edit(key); if (editor == null) { throw new IOException("Unable to edit key"); } + // Initialize OutputStream and write image. OutputStream outputStream = new BufferedOutputStream(editor.newOutputStream(0)); sink = Okio.buffer(Okio.sink(outputStream)); sink.writeAll(response.body().source()); From 2014b228e8fae546660a801722d124f38e952101 Mon Sep 17 00:00:00 2001 From: NoodleMage Date: Tue, 26 Jan 2016 13:54:43 +0100 Subject: [PATCH 02/12] Fixed some mistakes. --- .../tachiyomi/data/cache/ChapterCache.java | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/cache/ChapterCache.java b/app/src/main/java/eu/kanade/tachiyomi/data/cache/ChapterCache.java index 2f1c825b17..278b2f18a2 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/cache/ChapterCache.java +++ b/app/src/main/java/eu/kanade/tachiyomi/data/cache/ChapterCache.java @@ -21,6 +21,12 @@ import okio.BufferedSink; import okio.Okio; import rx.Observable; +/** + * Class used to create chapter cache + * For each image in a chapter a file is created + * For each chapter a Json list is created and converted to a file. + * The files are in format *md5key*.0 + */ public class ChapterCache { /** Name of cache directory. */ @@ -69,18 +75,19 @@ public class ChapterCache { } /** - * Remove Chapter from cache. - * @param file name of chapter file. - * @return false if file is journal or error else returns true. + * Remove file from cache. + * @param file name of chapter file md5.o. + * @return false if file is journal or error else returns status of deletion. */ - public boolean remove(String file) { + public boolean removeFileFromCache(String file) { // Make sure we don't delete the journal file (keeps track of cache). if (file.equals("journal") || file.startsWith("journal.")) return false; try { - // Take dot(.) substring to avoid conflicts. + // Take dot(.) substring to get filename without the .0 at the end. String key = file.substring(0, file.lastIndexOf(".")); + // Remove file from cache. return diskCache.remove(key); } catch (IOException e) { return false; @@ -112,7 +119,7 @@ public class ChapterCache { } /** - * Get page urls from cache. + * Get page objects from cache. * @param chapterUrl the url of the chapter. * @return list of chapter pages. */ From 11b68f914f2780068cd36d4b51248ba37a8a8e56 Mon Sep 17 00:00:00 2001 From: NoodleMage Date: Tue, 26 Jan 2016 15:02:16 +0100 Subject: [PATCH 03/12] Code optimization. Added comments. Few comment mistake fixes --- .../tachiyomi/data/cache/ChapterCache.java | 3 +- .../tachiyomi/data/cache/CoverCache.java | 122 +++++++++++++++--- 2 files changed, 105 insertions(+), 20 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/cache/ChapterCache.java b/app/src/main/java/eu/kanade/tachiyomi/data/cache/ChapterCache.java index 278b2f18a2..cece9a47d9 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/cache/ChapterCache.java +++ b/app/src/main/java/eu/kanade/tachiyomi/data/cache/ChapterCache.java @@ -32,7 +32,7 @@ public class ChapterCache { /** Name of cache directory. */ private static final String PARAMETER_CACHE_DIRECTORY = "chapter_disk_cache"; - /** Application version. */ + /** Application cache version. */ private static final int PARAMETER_APP_VERSION = 1; /** The number of values per cache entry. Must be positive. */ @@ -55,7 +55,6 @@ public class ChapterCache { * @param context application environment interface. */ public ChapterCache(Context context) { - // Set context. this.context = context; // Initialize Json handler. diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/cache/CoverCache.java b/app/src/main/java/eu/kanade/tachiyomi/data/cache/CoverCache.java index 7f2697a37f..8c3a14f946 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/cache/CoverCache.java +++ b/app/src/main/java/eu/kanade/tachiyomi/data/cache/CoverCache.java @@ -20,33 +20,70 @@ import java.io.OutputStream; import eu.kanade.tachiyomi.util.DiskUtils; +/** + * Class used to create cover cache + * Makes us of Glide which can avoid repeating requests and save the file. + * It is not necessary to load the images to the cache. + * Names of files are created with the md5 of the thumbnailURL + */ public class CoverCache { + /** Name of cache directory. */ private static final String PARAMETER_CACHE_DIRECTORY = "cover_disk_cache"; - private Context context; - private File cacheDir; + /** Interface to global information about an application environment. */ + private final Context context; + /** Cache class used for cache management. */ + private final File cacheDir; + + /** + * Constructor of CoverCache. + * @param context application environment interface. + */ public CoverCache(Context context) { this.context = context; + + // Get cache directory from parameter. cacheDir = new File(context.getCacheDir(), PARAMETER_CACHE_DIRECTORY); + + // Create cache directory. createCacheDir(); } + /** + * Check if cache dir exist if not create directory. + * @return true if cache dir exist or is created. + */ private boolean createCacheDir() { + // TODO return value never used. return !cacheDir.exists() && cacheDir.mkdirs(); } + /** + * Download the cover with Glide (it can avoid repeating requests) and save the file. + * TODO maybe remove? + * @param thumbnailUrl url of thumbnail. + * @param headers headers included in Glide request. + */ public void save(String thumbnailUrl, LazyHeaders headers) { save(thumbnailUrl, headers, null); } - // Download the cover with Glide (it can avoid repeating requests) and save the file on this cache - // Optionally, load the image in the given image view when the resource is ready, if not null - public void save(String thumbnailUrl, LazyHeaders headers, ImageView imageView) { + /** + * Download the cover with Glide (it can avoid repeating requests) and save the file. + * @param thumbnailUrl url of thumbnail. + * @param headers headers included in Glide request. + * @param imageView imageView where picture should be displayed. + */ + private void save(String thumbnailUrl, LazyHeaders headers, ImageView imageView) { + + // Check if url is empty. if (TextUtils.isEmpty(thumbnailUrl)) + // Do not try and create the string. Instead... only try to realize the truth. There is no string. return; + // Download the cover with Glide and save the file. GlideUrl url = new GlideUrl(thumbnailUrl, headers); Glide.with(context) .load(url) @@ -54,7 +91,10 @@ public class CoverCache { @Override public void onResourceReady(File resource, GlideAnimation anim) { try { + // Copy the cover from Glide's cache to local cache. add(thumbnailUrl, resource); + + // Check if imageView isn't null and show picture in imageView. if (imageView != null) { loadFromCache(imageView, resource); } @@ -65,18 +105,31 @@ public class CoverCache { }); } - // Copy the cover from Glide's cache to this cache - public void add(String thumbnailUrl, File source) throws IOException { + + /** + * Copy the cover from Glide's cache to local cache. + * //TODO rename add => copyToLocalCache? + * @param thumbnailUrl url of thumbnail. + * @param source the cover image. + * @throws IOException TODO not returned atm? + */ + private void add(String thumbnailUrl, File source) throws IOException { + // Create cache directory. TODO is this needed. Already called in constructor. createCacheDir(); + + // Create destination file. File dest = new File(cacheDir, DiskUtils.hashKeyForDisk(thumbnailUrl)); + + // Check if file already exists, if true delete it. if (dest.exists()) dest.delete(); + // Write thumbnail image to file. InputStream in = new FileInputStream(source); try { OutputStream out = new FileOutputStream(dest); try { - // Transfer bytes from in to out + // Transfer bytes from in to out. byte[] buf = new byte[1024]; int len; while ((len = in.read(buf)) > 0) { @@ -90,22 +143,40 @@ public class CoverCache { } } - // Get the cover from cache - public File get(String thumbnailUrl) { + /** + * Returns the cover from cache. + * TODO rename get => getCoverFromCache + * @param thumbnailUrl the thumbnail url. + * @return cover image. + */ + private File get(String thumbnailUrl) { return new File(cacheDir, DiskUtils.hashKeyForDisk(thumbnailUrl)); } - // Delete the cover from cache + /** + * Delete the cover file from the cache. + * TODO rename delete => deleteCoverFromCache. + * @param thumbnailUrl the thumbnail url. + * @return status of deletion. + */ public boolean delete(String thumbnailUrl) { + // Check if url is empty. if (TextUtils.isEmpty(thumbnailUrl)) return false; + // Remove file. File file = new File(cacheDir, DiskUtils.hashKeyForDisk(thumbnailUrl)); return file.exists() && file.delete(); } - // Save and load the image from cache - public void saveAndLoadFromCache(ImageView imageView, String thumbnailUrl, LazyHeaders headers) { + /** + * Save or load the image from cache + * @param imageView imageView where picture should be displayed. + * @param thumbnailUrl the thumbnail url. + * @param headers headers included in Glide request. + */ + public void saveOrLoadFromCache(ImageView imageView, String thumbnailUrl, LazyHeaders headers) { + // If file exist load it otherwise save it. File localCover = get(thumbnailUrl); if (localCover.exists()) { loadFromCache(imageView, localCover); @@ -114,8 +185,15 @@ public class CoverCache { } } - // If the image is already in our cache, use it. If not, load it with glide + /** + * If the image is already in our cache, use it. If not, load it with glide. + * TODO not used atm. + * @param imageView imageView where picture should be displayed. + * @param thumbnailUrl url of thumbnail. + * @param headers headers included in Glide request. + */ public void loadFromCacheOrNetwork(ImageView imageView, String thumbnailUrl, LazyHeaders headers) { + // If localCover exist load it from cache otherwise load it from network. File localCover = get(thumbnailUrl); if (localCover.exists()) { loadFromCache(imageView, localCover); @@ -124,8 +202,11 @@ public class CoverCache { } } - // Helper method to load the cover from the cache directory into the specified image view - // The file must exist + /** + * Helper method to load the cover from the cache directory into the specified image view. + * @param imageView imageView where picture should be displayed. + * @param file file to load. Must exist!. + */ private void loadFromCache(ImageView imageView, File file) { Glide.with(context) .load(file) @@ -134,8 +215,13 @@ public class CoverCache { .into(imageView); } - // Helper method to load the cover from network into the specified image view. - // It does NOT save the image in cache + /** + * Helper method to load the cover from network into the specified image view. + * It does NOT save the image in cache! + * @param imageView imageView where picture should be displayed. + * @param thumbnailUrl url of thumbnail. + * @param headers headers included in Glide request. + */ public void loadFromNetwork(ImageView imageView, String thumbnailUrl, LazyHeaders headers) { GlideUrl url = new GlideUrl(thumbnailUrl, headers); Glide.with(context) From 5c59e553523b927938e921ef4b7826875b20cf84 Mon Sep 17 00:00:00 2001 From: NoodleMage Date: Tue, 26 Jan 2016 15:04:38 +0100 Subject: [PATCH 04/12] Few comments --- .../kanade/tachiyomi/data/cache/CoverGlideModule.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/cache/CoverGlideModule.java b/app/src/main/java/eu/kanade/tachiyomi/data/cache/CoverGlideModule.java index c94397bcd9..1a890daa1b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/cache/CoverGlideModule.java +++ b/app/src/main/java/eu/kanade/tachiyomi/data/cache/CoverGlideModule.java @@ -7,8 +7,16 @@ import com.bumptech.glide.GlideBuilder; import com.bumptech.glide.load.DecodeFormat; import com.bumptech.glide.module.GlideModule; +/** + * Class used to update Glide module settings + */ public class CoverGlideModule implements GlideModule { + + /** + * Bitmaps decoded from most image formats (other than GIFs with hidden configs), will be decoded with the + * ARGB_8888 config. + */ @Override public void applyOptions(Context context, GlideBuilder builder) { builder.setDecodeFormat(DecodeFormat.PREFER_ARGB_8888); @@ -16,6 +24,6 @@ public class CoverGlideModule implements GlideModule { @Override public void registerComponents(Context context, Glide glide) { - + //TODO empty class? } } From 00e1dc8fca68e8afc2852a59dfa0f11e51ca76d6 Mon Sep 17 00:00:00 2001 From: NoodleMage Date: Tue, 26 Jan 2016 15:10:30 +0100 Subject: [PATCH 05/12] Added classes because of renaming --- .../java/eu/kanade/tachiyomi/data/cache/CoverCache.java | 4 ++-- .../eu/kanade/tachiyomi/ui/base/presenter/RxPresenter.java | 2 +- .../java/eu/kanade/tachiyomi/ui/library/LibraryHolder.java | 2 +- .../kanade/tachiyomi/ui/manga/info/MangaInfoFragment.java | 2 +- .../reader/viewer/pager/vertical/VerticalViewPagerImpl.java | 6 +++--- .../tachiyomi/ui/setting/SettingsAdvancedFragment.java | 2 +- .../java/eu/kanade/tachiyomi/util/ChapterRecognition.java | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/cache/CoverCache.java b/app/src/main/java/eu/kanade/tachiyomi/data/cache/CoverCache.java index 8c3a14f946..47ee660dc4 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/cache/CoverCache.java +++ b/app/src/main/java/eu/kanade/tachiyomi/data/cache/CoverCache.java @@ -22,7 +22,7 @@ import eu.kanade.tachiyomi.util.DiskUtils; /** * Class used to create cover cache - * Makes us of Glide which can avoid repeating requests and save the file. + * Makes us of Glide(which can avoid repeating requests) for saving the file. * It is not necessary to load the images to the cache. * Names of files are created with the md5 of the thumbnailURL */ @@ -62,7 +62,7 @@ public class CoverCache { /** * Download the cover with Glide (it can avoid repeating requests) and save the file. - * TODO maybe remove? + * TODO maybe remove and update the call made to this method with ,null? * @param thumbnailUrl url of thumbnail. * @param headers headers included in Glide request. */ diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/presenter/RxPresenter.java b/app/src/main/java/eu/kanade/tachiyomi/ui/base/presenter/RxPresenter.java index 914750a198..0dd11f26c5 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/base/presenter/RxPresenter.java +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/base/presenter/RxPresenter.java @@ -61,7 +61,7 @@ public class RxPresenter extends Presenter { * Removes and unsubscribes a subscription that has been registered with {@link #add} previously. * See {@link SubscriptionList#remove(Subscription)} for details. * - * @param subscription a subscription to remove. + * @param subscription a subscription to removeFileFromCache. */ public void remove(Subscription subscription) { subscriptions.remove(subscription); diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryHolder.java b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryHolder.java index 525c176a36..d115758ee4 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryHolder.java +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryHolder.java @@ -44,7 +44,7 @@ public class LibraryHolder extends FlexibleViewHolder { private void loadCover(Manga manga, Source source, CoverCache coverCache) { if (manga.thumbnail_url != null) { - coverCache.saveAndLoadFromCache(thumbnail, manga.thumbnail_url, source.getGlideHeaders()); + coverCache.saveOrLoadFromCache(thumbnail, manga.thumbnail_url, source.getGlideHeaders()); } else { thumbnail.setImageResource(android.R.color.transparent); } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoFragment.java b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoFragment.java index bee8651f45..033e8e7ce8 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoFragment.java +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoFragment.java @@ -88,7 +88,7 @@ public class MangaInfoFragment extends BaseRxFragment { LazyHeaders headers = getPresenter().source.getGlideHeaders(); if (manga.thumbnail_url != null && cover.getDrawable() == null) { if (manga.favorite) { - coverCache.saveAndLoadFromCache(cover, manga.thumbnail_url, headers); + coverCache.saveOrLoadFromCache(cover, manga.thumbnail_url, headers); } else { coverCache.loadFromNetwork(cover, manga.thumbnail_url, headers); } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/vertical/VerticalViewPagerImpl.java b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/vertical/VerticalViewPagerImpl.java index baded3360e..864c031356 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/vertical/VerticalViewPagerImpl.java +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/vertical/VerticalViewPagerImpl.java @@ -607,9 +607,9 @@ public class VerticalViewPagerImpl extends ViewGroup { * Add a listener that will be invoked whenever the page changes or is incrementally * scrolled. See {@link OnPageChangeListener}. * - *

Components that add a listener should take care to remove it when finished. + *

Components that add a listener should take care to removeFileFromCache it when finished. * Other components that take ownership of a view may call {@link #clearOnPageChangeListeners()} - * to remove all attached listeners.

+ * to removeFileFromCache all attached listeners.

* * @param listener listener to add */ @@ -624,7 +624,7 @@ public class VerticalViewPagerImpl extends ViewGroup { * Remove a listener that was previously added via * {@link #addOnPageChangeListener(OnPageChangeListener)}. * - * @param listener listener to remove + * @param listener listener to removeFileFromCache */ public void removeOnPageChangeListener(OnPageChangeListener listener) { if (mOnPageChangeListeners != null) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAdvancedFragment.java b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAdvancedFragment.java index eb9318820a..6feccd55bb 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAdvancedFragment.java +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAdvancedFragment.java @@ -71,7 +71,7 @@ public class SettingsAdvancedFragment extends SettingsNestedFragment { subscriptions.add(Observable.defer(() -> Observable.from(files)) .concatMap(file -> { - if (chapterCache.remove(file.getName())) { + if (chapterCache.removeFileFromCache(file.getName())) { deletedFiles.incrementAndGet(); } return Observable.just(file); diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/ChapterRecognition.java b/app/src/main/java/eu/kanade/tachiyomi/util/ChapterRecognition.java index 287c288edc..b3fb0052f6 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/ChapterRecognition.java +++ b/app/src/main/java/eu/kanade/tachiyomi/util/ChapterRecognition.java @@ -55,7 +55,7 @@ public class ChapterRecognition { // This can lead to issues if two numbers are separated by an space name = name.replaceAll("\\s+", ""); - // Try to remove the manga name from the chapter, and try again + // Try to removeFileFromCache the manga name from the chapter, and try again String mangaName = replaceIrrelevantCharacters(manga.title); String nameWithoutManga = difference(mangaName, name); if (!nameWithoutManga.isEmpty()) { From ea2e8bfb6fceed130a295ab81580b98278d12bf9 Mon Sep 17 00:00:00 2001 From: NoodleMage Date: Tue, 26 Jan 2016 15:18:22 +0100 Subject: [PATCH 06/12] Fixed refactor mistakes :(. --- .../eu/kanade/tachiyomi/ui/base/presenter/RxPresenter.java | 2 +- .../reader/viewer/pager/vertical/VerticalViewPagerImpl.java | 6 +++--- .../java/eu/kanade/tachiyomi/util/ChapterRecognition.java | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/presenter/RxPresenter.java b/app/src/main/java/eu/kanade/tachiyomi/ui/base/presenter/RxPresenter.java index 0dd11f26c5..914750a198 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/base/presenter/RxPresenter.java +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/base/presenter/RxPresenter.java @@ -61,7 +61,7 @@ public class RxPresenter extends Presenter { * Removes and unsubscribes a subscription that has been registered with {@link #add} previously. * See {@link SubscriptionList#remove(Subscription)} for details. * - * @param subscription a subscription to removeFileFromCache. + * @param subscription a subscription to remove. */ public void remove(Subscription subscription) { subscriptions.remove(subscription); diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/vertical/VerticalViewPagerImpl.java b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/vertical/VerticalViewPagerImpl.java index 864c031356..baded3360e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/vertical/VerticalViewPagerImpl.java +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/vertical/VerticalViewPagerImpl.java @@ -607,9 +607,9 @@ public class VerticalViewPagerImpl extends ViewGroup { * Add a listener that will be invoked whenever the page changes or is incrementally * scrolled. See {@link OnPageChangeListener}. * - *

Components that add a listener should take care to removeFileFromCache it when finished. + *

Components that add a listener should take care to remove it when finished. * Other components that take ownership of a view may call {@link #clearOnPageChangeListeners()} - * to removeFileFromCache all attached listeners.

+ * to remove all attached listeners.

* * @param listener listener to add */ @@ -624,7 +624,7 @@ public class VerticalViewPagerImpl extends ViewGroup { * Remove a listener that was previously added via * {@link #addOnPageChangeListener(OnPageChangeListener)}. * - * @param listener listener to removeFileFromCache + * @param listener listener to remove */ public void removeOnPageChangeListener(OnPageChangeListener listener) { if (mOnPageChangeListeners != null) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/ChapterRecognition.java b/app/src/main/java/eu/kanade/tachiyomi/util/ChapterRecognition.java index b3fb0052f6..287c288edc 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/ChapterRecognition.java +++ b/app/src/main/java/eu/kanade/tachiyomi/util/ChapterRecognition.java @@ -55,7 +55,7 @@ public class ChapterRecognition { // This can lead to issues if two numbers are separated by an space name = name.replaceAll("\\s+", ""); - // Try to removeFileFromCache the manga name from the chapter, and try again + // Try to remove the manga name from the chapter, and try again String mangaName = replaceIrrelevantCharacters(manga.title); String nameWithoutManga = difference(mangaName, name); if (!nameWithoutManga.isEmpty()) { From df3dde422b2d275097c7b1bca04ea2f91ffdd519 Mon Sep 17 00:00:00 2001 From: NoodleMage Date: Tue, 26 Jan 2016 15:54:27 +0100 Subject: [PATCH 07/12] typo + removed todo empty class --- .../main/java/eu/kanade/tachiyomi/data/cache/CoverCache.java | 2 +- .../java/eu/kanade/tachiyomi/data/cache/CoverGlideModule.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/cache/CoverCache.java b/app/src/main/java/eu/kanade/tachiyomi/data/cache/CoverCache.java index 47ee660dc4..3425511f7c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/cache/CoverCache.java +++ b/app/src/main/java/eu/kanade/tachiyomi/data/cache/CoverCache.java @@ -22,7 +22,7 @@ import eu.kanade.tachiyomi.util.DiskUtils; /** * Class used to create cover cache - * Makes us of Glide(which can avoid repeating requests) for saving the file. + * Makes use of Glide(which can avoid repeating requests) for saving the file. * It is not necessary to load the images to the cache. * Names of files are created with the md5 of the thumbnailURL */ diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/cache/CoverGlideModule.java b/app/src/main/java/eu/kanade/tachiyomi/data/cache/CoverGlideModule.java index 1a890daa1b..e3613ed560 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/cache/CoverGlideModule.java +++ b/app/src/main/java/eu/kanade/tachiyomi/data/cache/CoverGlideModule.java @@ -24,6 +24,6 @@ public class CoverGlideModule implements GlideModule { @Override public void registerComponents(Context context, Glide glide) { - //TODO empty class? + // Nothing to see here! } } From 2c293734f49721cdaa9b75e336c27d1db88d785a Mon Sep 17 00:00:00 2001 From: NoodleMage Date: Wed, 27 Jan 2016 11:39:03 +0100 Subject: [PATCH 08/12] Changed o to 0. Some renaming. Checked for nullability on string.isEmpty() function to prevent crashes --- .../tachiyomi/data/cache/ChapterCache.java | 2 +- .../tachiyomi/data/cache/CoverCache.java | 78 ++++++++++++------- .../ui/manga/info/MangaInfoPresenter.java | 19 ++--- 3 files changed, 59 insertions(+), 40 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/cache/ChapterCache.java b/app/src/main/java/eu/kanade/tachiyomi/data/cache/ChapterCache.java index cece9a47d9..ba995c23a4 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/cache/ChapterCache.java +++ b/app/src/main/java/eu/kanade/tachiyomi/data/cache/ChapterCache.java @@ -69,7 +69,7 @@ public class ChapterCache { PARAMETER_CACHE_SIZE ); } catch (IOException e) { - // Do Nothing. TODO error handling? + // Do Nothing. TODO error handling. } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/cache/CoverCache.java b/app/src/main/java/eu/kanade/tachiyomi/data/cache/CoverCache.java index 3425511f7c..f4f7b51e1c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/cache/CoverCache.java +++ b/app/src/main/java/eu/kanade/tachiyomi/data/cache/CoverCache.java @@ -28,17 +28,24 @@ import eu.kanade.tachiyomi.util.DiskUtils; */ public class CoverCache { - /** Name of cache directory. */ + /** + * Name of cache directory. + */ private static final String PARAMETER_CACHE_DIRECTORY = "cover_disk_cache"; - /** Interface to global information about an application environment. */ + /** + * Interface to global information about an application environment. + */ private final Context context; - /** Cache class used for cache management. */ + /** + * Cache class used for cache management. + */ private final File cacheDir; /** * Constructor of CoverCache. + * * @param context application environment interface. */ public CoverCache(Context context) { @@ -53,18 +60,18 @@ public class CoverCache { /** * Check if cache dir exist if not create directory. - * @return true if cache dir exist or is created. + * + * @return true if cache dir does exist and is created. */ private boolean createCacheDir() { - // TODO return value never used. return !cacheDir.exists() && cacheDir.mkdirs(); } /** * Download the cover with Glide (it can avoid repeating requests) and save the file. - * TODO maybe remove and update the call made to this method with ,null? + * * @param thumbnailUrl url of thumbnail. - * @param headers headers included in Glide request. + * @param headers headers included in Glide request. */ public void save(String thumbnailUrl, LazyHeaders headers) { save(thumbnailUrl, headers, null); @@ -72,14 +79,15 @@ public class CoverCache { /** * Download the cover with Glide (it can avoid repeating requests) and save the file. + * * @param thumbnailUrl url of thumbnail. - * @param headers headers included in Glide request. - * @param imageView imageView where picture should be displayed. + * @param headers headers included in Glide request. + * @param imageView imageView where picture should be displayed. */ private void save(String thumbnailUrl, LazyHeaders headers, ImageView imageView) { // Check if url is empty. - if (TextUtils.isEmpty(thumbnailUrl)) + if (thumbnailUrl == null || TextUtils.isEmpty(thumbnailUrl)) // Do not try and create the string. Instead... only try to realize the truth. There is no string. return; @@ -92,7 +100,7 @@ public class CoverCache { public void onResourceReady(File resource, GlideAnimation anim) { try { // Copy the cover from Glide's cache to local cache. - add(thumbnailUrl, resource); + copyToLocalCache(thumbnailUrl, resource); // Check if imageView isn't null and show picture in imageView. if (imageView != null) { @@ -108,18 +116,19 @@ public class CoverCache { /** * Copy the cover from Glide's cache to local cache. - * //TODO rename add => copyToLocalCache? + * * @param thumbnailUrl url of thumbnail. - * @param source the cover image. + * @param source the cover image. * @throws IOException TODO not returned atm? */ - private void add(String thumbnailUrl, File source) throws IOException { - // Create cache directory. TODO is this needed. Already called in constructor. + private void copyToLocalCache(String thumbnailUrl, File source) throws IOException { + // Create cache directory and check if directory exist createCacheDir(); // Create destination file. File dest = new File(cacheDir, DiskUtils.hashKeyForDisk(thumbnailUrl)); + // Check if file already exists, if true delete it. if (dest.exists()) dest.delete(); @@ -143,25 +152,26 @@ public class CoverCache { } } + /** * Returns the cover from cache. - * TODO rename get => getCoverFromCache + * * @param thumbnailUrl the thumbnail url. * @return cover image. */ - private File get(String thumbnailUrl) { + private File getCoverFromCache(String thumbnailUrl) { return new File(cacheDir, DiskUtils.hashKeyForDisk(thumbnailUrl)); } /** * Delete the cover file from the cache. - * TODO rename delete => deleteCoverFromCache. + * * @param thumbnailUrl the thumbnail url. * @return status of deletion. */ - public boolean delete(String thumbnailUrl) { + public boolean deleteCoverFromCache(String thumbnailUrl) { // Check if url is empty. - if (TextUtils.isEmpty(thumbnailUrl)) + if (thumbnailUrl == null || TextUtils.isEmpty(thumbnailUrl)) return false; // Remove file. @@ -171,13 +181,14 @@ public class CoverCache { /** * Save or load the image from cache - * @param imageView imageView where picture should be displayed. + * + * @param imageView imageView where picture should be displayed. * @param thumbnailUrl the thumbnail url. - * @param headers headers included in Glide request. + * @param headers headers included in Glide request. */ public void saveOrLoadFromCache(ImageView imageView, String thumbnailUrl, LazyHeaders headers) { // If file exist load it otherwise save it. - File localCover = get(thumbnailUrl); + File localCover = getCoverFromCache(thumbnailUrl); if (localCover.exists()) { loadFromCache(imageView, localCover); } else { @@ -188,13 +199,14 @@ public class CoverCache { /** * If the image is already in our cache, use it. If not, load it with glide. * TODO not used atm. - * @param imageView imageView where picture should be displayed. + * + * @param imageView imageView where picture should be displayed. * @param thumbnailUrl url of thumbnail. - * @param headers headers included in Glide request. + * @param headers headers included in Glide request. */ public void loadFromCacheOrNetwork(ImageView imageView, String thumbnailUrl, LazyHeaders headers) { // If localCover exist load it from cache otherwise load it from network. - File localCover = get(thumbnailUrl); + File localCover = getCoverFromCache(thumbnailUrl); if (localCover.exists()) { loadFromCache(imageView, localCover); } else { @@ -203,9 +215,10 @@ public class CoverCache { } /** - * Helper method to load the cover from the cache directory into the specified image view. + * Helper method to load the cover from the cache directory into the specified image view. + * * @param imageView imageView where picture should be displayed. - * @param file file to load. Must exist!. + * @param file file to load. Must exist!. */ private void loadFromCache(ImageView imageView, File file) { Glide.with(context) @@ -218,11 +231,16 @@ public class CoverCache { /** * Helper method to load the cover from network into the specified image view. * It does NOT save the image in cache! - * @param imageView imageView where picture should be displayed. + * + * @param imageView imageView where picture should be displayed. * @param thumbnailUrl url of thumbnail. - * @param headers headers included in Glide request. + * @param headers headers included in Glide request. */ public void loadFromNetwork(ImageView imageView, String thumbnailUrl, LazyHeaders headers) { + // Check if url is empty. + if (thumbnailUrl == null || TextUtils.isEmpty(thumbnailUrl)) + return; + GlideUrl url = new GlideUrl(thumbnailUrl, headers); Glide.with(context) .load(url) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoPresenter.java b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoPresenter.java index ea69a76fcd..bfeb251be1 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoPresenter.java +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoPresenter.java @@ -19,17 +19,18 @@ import rx.schedulers.Schedulers; 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; private static final int GET_CHAPTER_COUNT = 2; private static final int FETCH_MANGA_INFO = 3; + protected Source source; + @Inject + DatabaseHelper db; + @Inject + SourceManager sourceManager; + @Inject + CoverCache coverCache; + private Manga manga; + private int count = -1; @Override protected void onCreate(Bundle savedState) { @@ -111,7 +112,7 @@ public class MangaInfoPresenter extends BasePresenter { if (isFavorite) { coverCache.save(manga.thumbnail_url, source.getGlideHeaders()); } else { - coverCache.delete(manga.thumbnail_url); + coverCache.deleteCoverFromCache(manga.thumbnail_url); } } From 6ba371500437c57c9e105d9f73bbf06ddab944a1 Mon Sep 17 00:00:00 2001 From: NoodleMage Date: Wed, 27 Jan 2016 12:54:40 +0100 Subject: [PATCH 09/12] Update ChapterCache.java Another o to 0 change. Damn this .o! :) --- .../main/java/eu/kanade/tachiyomi/data/cache/ChapterCache.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/cache/ChapterCache.java b/app/src/main/java/eu/kanade/tachiyomi/data/cache/ChapterCache.java index ba995c23a4..3a4e8c1503 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/cache/ChapterCache.java +++ b/app/src/main/java/eu/kanade/tachiyomi/data/cache/ChapterCache.java @@ -75,7 +75,7 @@ public class ChapterCache { /** * Remove file from cache. - * @param file name of chapter file md5.o. + * @param file name of chapter file md5.0. * @return false if file is journal or error else returns status of deletion. */ public boolean removeFileFromCache(String file) { From 424b64550eb132349f17a9ded0fb9c8228c30580 Mon Sep 17 00:00:00 2001 From: NoodleMage Date: Wed, 27 Jan 2016 15:19:50 +0100 Subject: [PATCH 10/12] Removed redundant null check --- .../java/eu/kanade/tachiyomi/data/cache/CoverCache.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/cache/CoverCache.java b/app/src/main/java/eu/kanade/tachiyomi/data/cache/CoverCache.java index f4f7b51e1c..e76bcf34d3 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/cache/CoverCache.java +++ b/app/src/main/java/eu/kanade/tachiyomi/data/cache/CoverCache.java @@ -87,7 +87,7 @@ public class CoverCache { private void save(String thumbnailUrl, LazyHeaders headers, ImageView imageView) { // Check if url is empty. - if (thumbnailUrl == null || TextUtils.isEmpty(thumbnailUrl)) + if (TextUtils.isEmpty(thumbnailUrl)) // Do not try and create the string. Instead... only try to realize the truth. There is no string. return; @@ -171,7 +171,7 @@ public class CoverCache { */ public boolean deleteCoverFromCache(String thumbnailUrl) { // Check if url is empty. - if (thumbnailUrl == null || TextUtils.isEmpty(thumbnailUrl)) + if (TextUtils.isEmpty(thumbnailUrl)) return false; // Remove file. @@ -238,7 +238,7 @@ public class CoverCache { */ public void loadFromNetwork(ImageView imageView, String thumbnailUrl, LazyHeaders headers) { // Check if url is empty. - if (thumbnailUrl == null || TextUtils.isEmpty(thumbnailUrl)) + if (TextUtils.isEmpty(thumbnailUrl)) return; GlideUrl url = new GlideUrl(thumbnailUrl, headers); From 9c331e3f9c5b3e182c4cbf3591028550d2e07c6f Mon Sep 17 00:00:00 2001 From: NoodleMage Date: Wed, 27 Jan 2016 15:30:26 +0100 Subject: [PATCH 11/12] Added comments --- README.md | 2 +- app/build.gradle | 8 +- .../tachiyomi/data/cache/ChapterCache.java | 121 ++------------ .../tachiyomi/data/cache/CoverCache.java | 148 +++--------------- .../data/cache/CoverGlideModule.java | 10 +- .../tachiyomi/data/database/models/Manga.java | 29 ---- .../resolvers/MangaChapterGetResolver.java | 1 - .../data/download/DownloadManager.java | 33 ++-- .../data/preference/PreferencesHelper.java | 8 +- .../eu/kanade/tachiyomi/event/MangaEvent.java | 12 -- .../ui/base/presenter/RxPresenter.java | 12 +- .../ui/catalogue/CatalogueAdapter.java | 13 +- .../ui/catalogue/CatalogueFragment.java | 107 +++---------- .../ui/catalogue/CatalogueGridHolder.java | 38 ----- .../ui/catalogue/CatalogueHolder.java | 29 +++- .../ui/catalogue/CatalogueListHolder.java | 32 ---- .../ui/catalogue/CataloguePresenter.java | 44 ++---- .../ui/download/DownloadPresenter.java | 1 - .../ui/library/LibraryCategoryAdapter.java | 4 +- .../tachiyomi/ui/library/LibraryHolder.java | 6 +- .../ui/library/LibraryPresenter.java | 2 +- .../tachiyomi/ui/manga/MangaActivity.java | 29 ++-- .../tachiyomi/ui/manga/MangaPresenter.java | 32 ++-- .../ui/manga/chapter/ChaptersAdapter.java | 4 +- .../ui/manga/chapter/ChaptersFragment.java | 92 +++-------- .../ui/manga/chapter/ChaptersHolder.java | 45 ++---- .../ui/manga/chapter/ChaptersPresenter.java | 36 ++--- .../ui/manga/info/MangaInfoFragment.java | 14 +- .../ui/manga/info/MangaInfoPresenter.java | 43 +++-- .../myanimelist/MyAnimeListPresenter.java | 5 +- .../tachiyomi/ui/reader/ReaderActivity.java | 4 - .../tachiyomi/ui/reader/ReaderMenu.java | 2 +- .../tachiyomi/ui/reader/ReaderPresenter.java | 14 +- .../ui/setting/SettingsAdvancedFragment.java | 2 +- .../eu/kanade/tachiyomi/util/UrlUtil.java | 37 ----- .../widget/EndlessListScrollListener.java | 49 ------ ...ava => EndlessRecyclerScrollListener.java} | 4 +- .../drawable-hdpi/ic_view_list_white_24dp.png | Bin 125 -> 0 bytes .../ic_view_module_white_24dp.png | Bin 115 -> 0 bytes .../drawable-ldpi/ic_view_list_white_24dp.png | Bin 187 -> 0 bytes .../ic_view_module_white_24dp.png | Bin 278 -> 0 bytes .../drawable-mdpi/ic_view_list_white_24dp.png | Bin 89 -> 0 bytes .../ic_view_module_white_24dp.png | Bin 87 -> 0 bytes .../ic_view_list_white_24dp.png | Bin 117 -> 0 bytes .../ic_view_module_white_24dp.png | Bin 115 -> 0 bytes .../ic_view_list_white_24dp.png | Bin 144 -> 0 bytes .../ic_view_module_white_24dp.png | Bin 139 -> 0 bytes .../ic_view_list_white_24dp.png | Bin 176 -> 0 bytes .../ic_view_module_white_24dp.png | Bin 171 -> 0 bytes app/src/main/res/drawable/gradient_shape.xml | 12 -- .../res/layout/activity_edit_categories.xml | 1 - .../main/res/layout/fragment_catalogue.xml | 23 +-- .../res/layout/fragment_library_category.xml | 2 +- .../main/res/layout/fragment_manga_info.xml | 28 +--- ..._catalogue_grid.xml => item_catalogue.xml} | 71 ++++----- .../main/res/layout/item_catalogue_list.xml | 16 -- app/src/main/res/layout/item_chapter.xml | 2 +- app/src/main/res/layout/item_pager_reader.xml | 4 +- app/src/main/res/layout/toolbar.xml | 4 +- app/src/main/res/menu/catalogue_list.xml | 7 +- app/src/main/res/menu/chapters.xml | 9 -- app/src/main/res/values/keys.xml | 2 - app/src/main/res/values/strings.xml | 5 - build.gradle | 2 + libs/SubsamplingScaleImageView/build.gradle | 6 +- 65 files changed, 286 insertions(+), 980 deletions(-) delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/event/MangaEvent.java delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueGridHolder.java delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueListHolder.java delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/widget/EndlessListScrollListener.java rename app/src/main/java/eu/kanade/tachiyomi/widget/{EndlessGridScrollListener.java => EndlessRecyclerScrollListener.java} (89%) delete mode 100644 app/src/main/res/drawable-hdpi/ic_view_list_white_24dp.png delete mode 100644 app/src/main/res/drawable-hdpi/ic_view_module_white_24dp.png delete mode 100644 app/src/main/res/drawable-ldpi/ic_view_list_white_24dp.png delete mode 100644 app/src/main/res/drawable-ldpi/ic_view_module_white_24dp.png delete mode 100644 app/src/main/res/drawable-mdpi/ic_view_list_white_24dp.png delete mode 100644 app/src/main/res/drawable-mdpi/ic_view_module_white_24dp.png delete mode 100644 app/src/main/res/drawable-xhdpi/ic_view_list_white_24dp.png delete mode 100644 app/src/main/res/drawable-xhdpi/ic_view_module_white_24dp.png delete mode 100644 app/src/main/res/drawable-xxhdpi/ic_view_list_white_24dp.png delete mode 100644 app/src/main/res/drawable-xxhdpi/ic_view_module_white_24dp.png delete mode 100644 app/src/main/res/drawable-xxxhdpi/ic_view_list_white_24dp.png delete mode 100644 app/src/main/res/drawable-xxxhdpi/ic_view_module_white_24dp.png delete mode 100644 app/src/main/res/drawable/gradient_shape.xml rename app/src/main/res/layout/{item_catalogue_grid.xml => item_catalogue.xml} (52%) delete mode 100644 app/src/main/res/layout/item_catalogue_list.xml delete mode 100644 app/src/main/res/menu/chapters.xml diff --git a/README.md b/README.md index 4981b0b66c..f4781b7a4a 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Current features: ## Download -[![stable release](https://img.shields.io/badge/release-v0.1.2-blue.svg)](https://github.com/inorichi/tachiyomi/releases/download/v0.1.2/tachiyomi-v0.1.2.apk) +[![stable release](https://img.shields.io/badge/release-v0.1.1-blue.svg)](https://github.com/inorichi/tachiyomi/releases/download/v0.1.1/tachiyomi-v0.1.1.apk) [![latest debug build](https://img.shields.io/badge/debug-latest%20build-blue.svg)](http://tachiyomi.kanade.eu/latest/app-debug.apk) ## License diff --git a/app/build.gradle b/app/build.gradle index aeb407209b..f096687994 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -39,8 +39,8 @@ android { minSdkVersion 16 targetSdkVersion 23 testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" - versionCode 3 - versionName "0.1.2" + versionCode 2 + versionName "0.1.1" buildConfigField "String", "COMMIT_COUNT", "\"${getCommitCount()}\"" buildConfigField "String", "COMMIT_SHA", "\"${getGitSha()}\"" @@ -73,7 +73,6 @@ android { lintOptions { abortOnError false - checkReleaseBuilds false } } @@ -94,7 +93,6 @@ dependencies { compile "com.android.support:design:$SUPPORT_LIBRARY_VERSION" compile "com.android.support:recyclerview-v7:$SUPPORT_LIBRARY_VERSION" compile "com.android.support:support-annotations:$SUPPORT_LIBRARY_VERSION" - compile "com.android.support:percent:$SUPPORT_LIBRARY_VERSION" compile 'com.squareup.okhttp:okhttp-urlconnection:2.7.2' compile 'com.squareup.okhttp:okhttp:2.7.2' compile 'com.squareup.okio:okio:1.6.0' @@ -118,7 +116,7 @@ dependencies { compile 'com.github.dmytrodanylyk.android-process-button:library:1.0.4' compile 'eu.davidea:flexible-adapter:4.2.0' compile 'com.nononsenseapps:filepicker:2.5.1' - compile 'com.github.amulyakhare:TextDrawable:558677e' + compile 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1' compile 'com.github.pwittchen:reactivenetwork:0.1.5' compile "com.google.dagger:dagger:$DAGGER_VERSION" diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/cache/ChapterCache.java b/app/src/main/java/eu/kanade/tachiyomi/data/cache/ChapterCache.java index 3a4e8c1503..9571c6020c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/cache/ChapterCache.java +++ b/app/src/main/java/eu/kanade/tachiyomi/data/cache/ChapterCache.java @@ -21,46 +21,22 @@ import okio.BufferedSink; import okio.Okio; import rx.Observable; -/** - * Class used to create chapter cache - * For each image in a chapter a file is created - * For each chapter a Json list is created and converted to a file. - * The files are in format *md5key*.0 - */ public class ChapterCache { - /** Name of cache directory. */ private static final String PARAMETER_CACHE_DIRECTORY = "chapter_disk_cache"; - - /** Application cache version. */ private static final int PARAMETER_APP_VERSION = 1; - - /** The number of values per cache entry. Must be positive. */ private static final int PARAMETER_VALUE_COUNT = 1; - - /** The maximum number of bytes this cache should use to store. */ private static final int PARAMETER_CACHE_SIZE = 75 * 1024 * 1024; - /** Interface to global information about an application environment. */ - private final Context context; + private Context context; + private Gson gson; - /** Google Json class used for parsing json files. */ - private final Gson gson; - - /** Cache class used for cache management. */ private DiskLruCache diskCache; - /** - * Constructor of ChapterCache. - * @param context application environment interface. - */ public ChapterCache(Context context) { this.context = context; - - // Initialize Json handler. gson = new Gson(); - // Try to open cache in default cache directory. try { diskCache = DiskLruCache.open( new File(context.getCacheDir(), PARAMETER_CACHE_DIRECTORY), @@ -69,67 +45,43 @@ public class ChapterCache { PARAMETER_CACHE_SIZE ); } catch (IOException e) { - // Do Nothing. TODO error handling. + // Do Nothing. } } - /** - * Remove file from cache. - * @param file name of chapter file md5.0. - * @return false if file is journal or error else returns status of deletion. - */ - public boolean removeFileFromCache(String file) { - // Make sure we don't delete the journal file (keeps track of cache). + public boolean remove(String file) { if (file.equals("journal") || file.startsWith("journal.")) return false; try { - // Take dot(.) substring to get filename without the .0 at the end. String key = file.substring(0, file.lastIndexOf(".")); - // Remove file from cache. return diskCache.remove(key); } catch (IOException e) { return false; } } - /** - * Returns directory of cache. - * @return directory of cache. - */ public File getCacheDir() { return diskCache.getDirectory(); } - /** - * Returns real size of directory. - * @return real size of directory. - */ - private long getRealSize() { + public long getRealSize() { return DiskUtils.getDirectorySize(getCacheDir()); } - /** - * Returns real size of directory in human readable format. - * @return real size of directory. - */ public String getReadableSize() { return Formatter.formatFileSize(context, getRealSize()); } - /** - * Get page objects from cache. - * @param chapterUrl the url of the chapter. - * @return list of chapter pages. - */ + public void setSize(int value) { + diskCache.setMaxSize(value * 1024 * 1024); + } + public Observable> getPageUrlsFromDiskCache(final String chapterUrl) { return Observable.create(subscriber -> { try { - // Get list of pages from chapterUrl. List pages = getPageUrlsFromDiskCacheImpl(chapterUrl); - // Provides the Observer with a new item to observe. subscriber.onNext(pages); - // Notify the Observer that finished sending push-based notifications. subscriber.onCompleted(); } catch (Throwable e) { subscriber.onError(e); @@ -137,31 +89,18 @@ public class ChapterCache { }); } - /** - * Implementation of the getPageUrlsFromDiskCache() function - * @param chapterUrl the url of the chapter - * @return returns list of chapter pages - * @throws IOException does nothing atm - */ - private List getPageUrlsFromDiskCacheImpl(String chapterUrl) throws IOException /*TODO IOException never thrown*/ { - // Initialize snapshot (a snapshot of the values for an entry). + private List getPageUrlsFromDiskCacheImpl(String chapterUrl) throws IOException { DiskLruCache.Snapshot snapshot = null; - - // Initialize list of pages. List pages = null; try { - // Create md5 key and retrieve snapshot. String key = DiskUtils.hashKeyForDisk(chapterUrl); snapshot = diskCache.get(key); - - // Convert JSON string to list of objects. Type collectionType = new TypeToken>() {}.getType(); pages = gson.fromJson(snapshot.getString(0), collectionType); - } catch (IOException e) { - // Do Nothing. //TODO error handling? + // Do Nothing. } finally { if (snapshot != null) { snapshot.close(); @@ -170,30 +109,18 @@ public class ChapterCache { return pages; } - /** - * Add page urls to disk cache. - * @param chapterUrl the url of the chapter. - * @param pages list of chapter pages. - */ public void putPageUrlsToDiskCache(final String chapterUrl, final List pages) { - // Convert list of pages to json string. String cachedValue = gson.toJson(pages); - // Initialize the editor (edits the values for an entry). DiskLruCache.Editor editor = null; - - // Initialize OutputStream. OutputStream outputStream = null; - try { - // Get editor from md5 key. String key = DiskUtils.hashKeyForDisk(chapterUrl); editor = diskCache.edit(key); if (editor == null) { return; } - // Write chapter urls to cache. outputStream = new BufferedOutputStream(editor.newOutputStream(0)); outputStream.write(cachedValue.getBytes()); outputStream.flush(); @@ -201,7 +128,7 @@ public class ChapterCache { diskCache.flush(); editor.commit(); } catch (Exception e) { - // Do Nothing. TODO error handling? + // Do Nothing. } finally { if (editor != null) { editor.abortUnlessCommitted(); @@ -210,17 +137,12 @@ public class ChapterCache { try { outputStream.close(); } catch (IOException ignore) { - // Do Nothing. TODO error handling? + // Do Nothing. } } } } - /** - * Check if image is in cache. - * @param imageUrl url of image. - * @return true if in cache otherwise false. - */ public boolean isImageInCache(final String imageUrl) { try { return diskCache.get(DiskUtils.hashKeyForDisk(imageUrl)) != null; @@ -230,14 +152,8 @@ public class ChapterCache { return false; } - /** - * Get image path from url. - * @param imageUrl url of image. - * @return path of image. - */ public String getImagePath(final String imageUrl) { try { - // Get file from md5 key. String imageName = DiskUtils.hashKeyForDisk(imageUrl) + ".0"; File file = new File(diskCache.getDirectory(), imageName); return file.getCanonicalPath(); @@ -247,28 +163,17 @@ public class ChapterCache { return null; } - /** - * Add image to cache - * @param imageUrl url of image. - * @param response http response from page. - * @throws IOException image error. - */ public void putImageToDiskCache(final String imageUrl, final Response response) throws IOException { - // Initialize editor (edits the values for an entry). DiskLruCache.Editor editor = null; - - // Initialize BufferedSink (used for small writes). BufferedSink sink = null; try { - // Get editor from md5 key. String key = DiskUtils.hashKeyForDisk(imageUrl); editor = diskCache.edit(key); if (editor == null) { throw new IOException("Unable to edit key"); } - // Initialize OutputStream and write image. OutputStream outputStream = new BufferedOutputStream(editor.newOutputStream(0)); sink = Okio.buffer(Okio.sink(outputStream)); sink.writeAll(response.body().source()); diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/cache/CoverCache.java b/app/src/main/java/eu/kanade/tachiyomi/data/cache/CoverCache.java index e76bcf34d3..7f2697a37f 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/cache/CoverCache.java +++ b/app/src/main/java/eu/kanade/tachiyomi/data/cache/CoverCache.java @@ -20,78 +20,33 @@ import java.io.OutputStream; import eu.kanade.tachiyomi.util.DiskUtils; -/** - * Class used to create cover cache - * Makes use of Glide(which can avoid repeating requests) for saving the file. - * It is not necessary to load the images to the cache. - * Names of files are created with the md5 of the thumbnailURL - */ public class CoverCache { - /** - * Name of cache directory. - */ private static final String PARAMETER_CACHE_DIRECTORY = "cover_disk_cache"; - /** - * Interface to global information about an application environment. - */ - private final Context context; + private Context context; + private File cacheDir; - /** - * Cache class used for cache management. - */ - private final File cacheDir; - - /** - * Constructor of CoverCache. - * - * @param context application environment interface. - */ public CoverCache(Context context) { this.context = context; - - // Get cache directory from parameter. cacheDir = new File(context.getCacheDir(), PARAMETER_CACHE_DIRECTORY); - - // Create cache directory. createCacheDir(); } - /** - * Check if cache dir exist if not create directory. - * - * @return true if cache dir does exist and is created. - */ private boolean createCacheDir() { return !cacheDir.exists() && cacheDir.mkdirs(); } - /** - * Download the cover with Glide (it can avoid repeating requests) and save the file. - * - * @param thumbnailUrl url of thumbnail. - * @param headers headers included in Glide request. - */ public void save(String thumbnailUrl, LazyHeaders headers) { save(thumbnailUrl, headers, null); } - /** - * Download the cover with Glide (it can avoid repeating requests) and save the file. - * - * @param thumbnailUrl url of thumbnail. - * @param headers headers included in Glide request. - * @param imageView imageView where picture should be displayed. - */ - private void save(String thumbnailUrl, LazyHeaders headers, ImageView imageView) { - - // Check if url is empty. + // Download the cover with Glide (it can avoid repeating requests) and save the file on this cache + // Optionally, load the image in the given image view when the resource is ready, if not null + public void save(String thumbnailUrl, LazyHeaders headers, ImageView imageView) { if (TextUtils.isEmpty(thumbnailUrl)) - // Do not try and create the string. Instead... only try to realize the truth. There is no string. return; - // Download the cover with Glide and save the file. GlideUrl url = new GlideUrl(thumbnailUrl, headers); Glide.with(context) .load(url) @@ -99,10 +54,7 @@ public class CoverCache { @Override public void onResourceReady(File resource, GlideAnimation anim) { try { - // Copy the cover from Glide's cache to local cache. - copyToLocalCache(thumbnailUrl, resource); - - // Check if imageView isn't null and show picture in imageView. + add(thumbnailUrl, resource); if (imageView != null) { loadFromCache(imageView, resource); } @@ -113,32 +65,18 @@ public class CoverCache { }); } - - /** - * Copy the cover from Glide's cache to local cache. - * - * @param thumbnailUrl url of thumbnail. - * @param source the cover image. - * @throws IOException TODO not returned atm? - */ - private void copyToLocalCache(String thumbnailUrl, File source) throws IOException { - // Create cache directory and check if directory exist + // Copy the cover from Glide's cache to this cache + public void add(String thumbnailUrl, File source) throws IOException { createCacheDir(); - - // Create destination file. File dest = new File(cacheDir, DiskUtils.hashKeyForDisk(thumbnailUrl)); - - - // Check if file already exists, if true delete it. if (dest.exists()) dest.delete(); - // Write thumbnail image to file. InputStream in = new FileInputStream(source); try { OutputStream out = new FileOutputStream(dest); try { - // Transfer bytes from in to out. + // Transfer bytes from in to out byte[] buf = new byte[1024]; int len; while ((len = in.read(buf)) > 0) { @@ -152,43 +90,23 @@ public class CoverCache { } } - - /** - * Returns the cover from cache. - * - * @param thumbnailUrl the thumbnail url. - * @return cover image. - */ - private File getCoverFromCache(String thumbnailUrl) { + // Get the cover from cache + public File get(String thumbnailUrl) { return new File(cacheDir, DiskUtils.hashKeyForDisk(thumbnailUrl)); } - /** - * Delete the cover file from the cache. - * - * @param thumbnailUrl the thumbnail url. - * @return status of deletion. - */ - public boolean deleteCoverFromCache(String thumbnailUrl) { - // Check if url is empty. + // Delete the cover from cache + public boolean delete(String thumbnailUrl) { if (TextUtils.isEmpty(thumbnailUrl)) return false; - // Remove file. File file = new File(cacheDir, DiskUtils.hashKeyForDisk(thumbnailUrl)); return file.exists() && file.delete(); } - /** - * Save or load the image from cache - * - * @param imageView imageView where picture should be displayed. - * @param thumbnailUrl the thumbnail url. - * @param headers headers included in Glide request. - */ - public void saveOrLoadFromCache(ImageView imageView, String thumbnailUrl, LazyHeaders headers) { - // If file exist load it otherwise save it. - File localCover = getCoverFromCache(thumbnailUrl); + // Save and load the image from cache + public void saveAndLoadFromCache(ImageView imageView, String thumbnailUrl, LazyHeaders headers) { + File localCover = get(thumbnailUrl); if (localCover.exists()) { loadFromCache(imageView, localCover); } else { @@ -196,17 +114,9 @@ public class CoverCache { } } - /** - * If the image is already in our cache, use it. If not, load it with glide. - * TODO not used atm. - * - * @param imageView imageView where picture should be displayed. - * @param thumbnailUrl url of thumbnail. - * @param headers headers included in Glide request. - */ + // If the image is already in our cache, use it. If not, load it with glide public void loadFromCacheOrNetwork(ImageView imageView, String thumbnailUrl, LazyHeaders headers) { - // If localCover exist load it from cache otherwise load it from network. - File localCover = getCoverFromCache(thumbnailUrl); + File localCover = get(thumbnailUrl); if (localCover.exists()) { loadFromCache(imageView, localCover); } else { @@ -214,12 +124,8 @@ public class CoverCache { } } - /** - * Helper method to load the cover from the cache directory into the specified image view. - * - * @param imageView imageView where picture should be displayed. - * @param file file to load. Must exist!. - */ + // Helper method to load the cover from the cache directory into the specified image view + // The file must exist private void loadFromCache(ImageView imageView, File file) { Glide.with(context) .load(file) @@ -228,19 +134,9 @@ public class CoverCache { .into(imageView); } - /** - * Helper method to load the cover from network into the specified image view. - * It does NOT save the image in cache! - * - * @param imageView imageView where picture should be displayed. - * @param thumbnailUrl url of thumbnail. - * @param headers headers included in Glide request. - */ + // Helper method to load the cover from network into the specified image view. + // It does NOT save the image in cache public void loadFromNetwork(ImageView imageView, String thumbnailUrl, LazyHeaders headers) { - // Check if url is empty. - if (TextUtils.isEmpty(thumbnailUrl)) - return; - GlideUrl url = new GlideUrl(thumbnailUrl, headers); Glide.with(context) .load(url) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/cache/CoverGlideModule.java b/app/src/main/java/eu/kanade/tachiyomi/data/cache/CoverGlideModule.java index e3613ed560..c94397bcd9 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/cache/CoverGlideModule.java +++ b/app/src/main/java/eu/kanade/tachiyomi/data/cache/CoverGlideModule.java @@ -7,16 +7,8 @@ import com.bumptech.glide.GlideBuilder; import com.bumptech.glide.load.DecodeFormat; import com.bumptech.glide.module.GlideModule; -/** - * Class used to update Glide module settings - */ public class CoverGlideModule implements GlideModule { - - /** - * Bitmaps decoded from most image formats (other than GIFs with hidden configs), will be decoded with the - * ARGB_8888 config. - */ @Override public void applyOptions(Context context, GlideBuilder builder) { builder.setDecodeFormat(DecodeFormat.PREFER_ARGB_8888); @@ -24,6 +16,6 @@ public class CoverGlideModule implements GlideModule { @Override public void registerComponents(Context context, Glide glide) { - // Nothing to see here! + } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/models/Manga.java b/app/src/main/java/eu/kanade/tachiyomi/data/database/models/Manga.java index a8acba4994..5548f69ff8 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/models/Manga.java +++ b/app/src/main/java/eu/kanade/tachiyomi/data/database/models/Manga.java @@ -68,14 +68,6 @@ public class Manga implements Serializable { public static final int COMPLETED = 2; public static final int LICENSED = 3; - public static final int SORT_AZ = 0x00000000; - public static final int SORT_ZA = 0x00000001; - public static final int SORT_MASK = 0x00000001; - - public static final int DISPLAY_NAME = 0x00000000; - public static final int DISPLAY_NUMBER = 0x00100000; - public static final int DISPLAY_MASK = 0x00100000; - public Manga() {} public static Manga create(String pathUrl) { @@ -128,27 +120,6 @@ public class Manga implements Serializable { } } - public void setChapterOrder(int order) { - setFlags(order, SORT_MASK); - } - - public void setDisplayMode(int mode) { - setFlags(mode, DISPLAY_MASK); - } - - private void setFlags(int flag, int mask) { - chapter_flags = (chapter_flags & ~mask) | (flag & mask); - } - - public boolean sortChaptersAZ() { - return (chapter_flags & SORT_MASK) == SORT_AZ; - } - - // Used to display the chapter's title one way or another - public int getDisplayMode() { - return chapter_flags & DISPLAY_MASK; - } - @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaChapterGetResolver.java b/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaChapterGetResolver.java index 2313f6bd38..67eb65e83f 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaChapterGetResolver.java +++ b/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaChapterGetResolver.java @@ -49,7 +49,6 @@ public class MangaChapterGetResolver extends DefaultGetResolver { public MangaChapter mapFromCursor(@NonNull Cursor cursor) { final Manga manga = mangaGetResolver.mapFromCursor(cursor); final Chapter chapter = chapterGetResolver.mapFromCursor(cursor); - manga.id = chapter.manga_id; return new MangaChapter(manga, chapter); } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.java b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.java index da828f33ec..e4f71632bf 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.java +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.java @@ -15,6 +15,8 @@ import java.io.IOException; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import eu.kanade.tachiyomi.data.database.models.Chapter; import eu.kanade.tachiyomi.data.database.models.Manga; @@ -26,8 +28,6 @@ import eu.kanade.tachiyomi.data.source.base.Source; import eu.kanade.tachiyomi.data.source.model.Page; import eu.kanade.tachiyomi.event.DownloadChaptersEvent; import eu.kanade.tachiyomi.util.DiskUtils; -import eu.kanade.tachiyomi.util.DynamicConcurrentMergeOperator; -import eu.kanade.tachiyomi.util.UrlUtil; import rx.Observable; import rx.Subscription; import rx.android.schedulers.AndroidSchedulers; @@ -47,12 +47,11 @@ public class DownloadManager { private BehaviorSubject runningSubject; private Subscription downloadsSubscription; - private BehaviorSubject threadsSubject; - private Subscription threadsSubscription; - private DownloadQueue queue; private volatile boolean isRunning; + private ExecutorService threadPool; + public static final String PAGE_LIST_FILE = "index.json"; public DownloadManager(Context context, SourceManager sourceManager, PreferencesHelper preferences) { @@ -65,20 +64,17 @@ public class DownloadManager { downloadsQueueSubject = PublishSubject.create(); runningSubject = BehaviorSubject.create(); - threadsSubject = BehaviorSubject.create(); } private void initializeSubscriptions() { if (downloadsSubscription != null && !downloadsSubscription.isUnsubscribed()) downloadsSubscription.unsubscribe(); - threadsSubscription = preferences.downloadThreads().asObservable() - .subscribe(threadsSubject::onNext); + threadPool = Executors.newFixedThreadPool(preferences.downloadThreads()); downloadsSubscription = downloadsQueueSubject .flatMap(Observable::from) - .lift(new DynamicConcurrentMergeOperator<>(this::downloadChapter, threadsSubject)) - .onBackpressureBuffer() + .flatMap(c -> downloadChapter(c).subscribeOn(Schedulers.from(threadPool))) .observeOn(AndroidSchedulers.mainThread()) .map(download -> areAllDownloadsFinished()) .subscribe(finished -> { @@ -104,10 +100,9 @@ public class DownloadManager { downloadsSubscription = null; } - if (threadsSubscription != null && !threadsSubscription.isUnsubscribed()) { - threadsSubscription.unsubscribe(); + if (threadPool != null && !threadPool.isShutdown()) { + threadPool.shutdown(); } - } // Create a download object for every chapter in the event and add them to the downloads queue @@ -212,8 +207,7 @@ public class DownloadManager { .onErrorResumeNext(error -> { download.setStatus(Download.ERROR); return Observable.just(download); - })) - .subscribeOn(Schedulers.io()); + })); } // Get the image from the filesystem if it exists or download from network @@ -285,15 +279,6 @@ public class DownloadManager { // Get the filename for an image given the page private String getImageFilename(Page page) { String url = page.getImageUrl(); - int number = page.getPageNumber() + 1; - // Try to preserve file extension - if (UrlUtil.isJpg(url)) { - return number + ".jpg"; - } else if (UrlUtil.isPng(url)) { - return number + ".png"; - } else if (UrlUtil.isGif(url)) { - return number + ".gif"; - } return Uri.parse(url).getLastPathSegment().replaceAll("[^\\sa-zA-Z0-9.-]", "_"); } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.java b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.java index af8001c573..896883c4dd 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.java +++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.java @@ -116,10 +116,6 @@ public class PreferencesHelper { return rxPrefs.getInteger(getKey(R.string.pref_reader_theme_key), 0); } - public Preference catalogueAsList() { - return rxPrefs.getBoolean(getKey(R.string.pref_display_catalogue_as_list), false); - } - public String getSourceUsername(Source source) { return prefs.getString(SOURCE_ACCOUNT_USERNAME + source.getId(), ""); } @@ -159,8 +155,8 @@ public class PreferencesHelper { prefs.edit().putString(getKey(R.string.pref_download_directory_key), path).apply(); } - public Preference downloadThreads() { - return rxPrefs.getInteger(getKey(R.string.pref_download_slots_key), 1); + public int downloadThreads() { + return prefs.getInt(getKey(R.string.pref_download_slots_key), 1); } public boolean downloadOnlyOverWifi() { diff --git a/app/src/main/java/eu/kanade/tachiyomi/event/MangaEvent.java b/app/src/main/java/eu/kanade/tachiyomi/event/MangaEvent.java deleted file mode 100644 index 9cfa8d1734..0000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/event/MangaEvent.java +++ /dev/null @@ -1,12 +0,0 @@ -package eu.kanade.tachiyomi.event; - -import eu.kanade.tachiyomi.data.database.models.Manga; - -public class MangaEvent { - - public final Manga manga; - - public MangaEvent(Manga manga) { - this.manga = manga; - } -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/presenter/RxPresenter.java b/app/src/main/java/eu/kanade/tachiyomi/ui/base/presenter/RxPresenter.java index 914750a198..57ba302deb 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/base/presenter/RxPresenter.java +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/base/presenter/RxPresenter.java @@ -107,14 +107,14 @@ public class RxPresenter extends Presenter { } /** - * Checks if a restartable is unsubscribed. + * Checks if a restartable is subscribed. * - * @param restartableId id of the restartable. - * @return true if the subscription is null or unsubscribed, false otherwise. + * @param restartableId id of a restartable. + * @return True if the restartable is subscribed, false otherwise. */ - public boolean isUnsubscribed(int restartableId) { - Subscription subscription = restartableSubscriptions.get(restartableId); - return subscription == null || subscription.isUnsubscribed(); + public boolean isSubscribed(int restartableId) { + Subscription s = restartableSubscriptions.get(restartableId); + return s != null && !s.isUnsubscribed(); } /** diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueAdapter.java b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueAdapter.java index 9d7cd6f704..69871e28fa 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueAdapter.java +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueAdapter.java @@ -31,10 +31,6 @@ public class CatalogueAdapter extends FlexibleAdapter { notifyDataSetChanged(); } - public List getItems() { - return mItems; - } - @Override public long getItemId(int position) { return mItems.get(position).id; @@ -48,13 +44,8 @@ public class CatalogueAdapter extends FlexibleAdapter { @Override public CatalogueHolder onCreateViewHolder(ViewGroup parent, int viewType) { LayoutInflater inflater = fragment.getActivity().getLayoutInflater(); - if (parent.getId() == R.id.catalogue_grid) { - View v = inflater.inflate(R.layout.item_catalogue_grid, parent, false); - return new CatalogueGridHolder(v, this, fragment); - } else { - View v = inflater.inflate(R.layout.item_catalogue_list, parent, false); - return new CatalogueListHolder(v, this, fragment); - } + View v = inflater.inflate(R.layout.item_catalogue, parent, false); + return new CatalogueHolder(v, this, fragment); } @Override diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueFragment.java b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueFragment.java index fff75b078c..8b2460023f 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueFragment.java +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueFragment.java @@ -4,10 +4,7 @@ import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.support.annotation.Nullable; -import android.support.v4.content.ContextCompat; import android.support.v7.widget.GridLayoutManager; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; import android.support.v7.widget.SearchView; import android.support.v7.widget.Toolbar; import android.text.TextUtils; @@ -17,12 +14,9 @@ import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; -import android.view.animation.Animation; -import android.view.animation.AnimationUtils; import android.widget.AdapterView; import android.widget.ProgressBar; import android.widget.Spinner; -import android.widget.ViewSwitcher; import com.afollestad.materialdialogs.MaterialDialog; @@ -36,13 +30,11 @@ import eu.kanade.tachiyomi.data.database.models.Manga; import eu.kanade.tachiyomi.data.source.base.Source; import eu.kanade.tachiyomi.ui.base.adapter.FlexibleViewHolder; import eu.kanade.tachiyomi.ui.base.fragment.BaseRxFragment; -import eu.kanade.tachiyomi.ui.decoration.DividerItemDecoration; import eu.kanade.tachiyomi.ui.main.MainActivity; import eu.kanade.tachiyomi.ui.manga.MangaActivity; import eu.kanade.tachiyomi.util.ToastUtil; import eu.kanade.tachiyomi.widget.AutofitRecyclerView; -import eu.kanade.tachiyomi.widget.EndlessGridScrollListener; -import eu.kanade.tachiyomi.widget.EndlessListScrollListener; +import eu.kanade.tachiyomi.widget.EndlessRecyclerScrollListener; import icepick.State; import nucleus.factory.RequiresPresenter; import rx.Subscription; @@ -53,17 +45,14 @@ import rx.subjects.PublishSubject; public class CatalogueFragment extends BaseRxFragment implements FlexibleViewHolder.OnListItemClickListener { - @Bind(R.id.switcher) ViewSwitcher switcher; - @Bind(R.id.catalogue_grid) AutofitRecyclerView catalogueGrid; - @Bind(R.id.catalogue_list) RecyclerView catalogueList; + @Bind(R.id.recycler) AutofitRecyclerView recycler; @Bind(R.id.progress) ProgressBar progress; @Bind(R.id.progress_grid) ProgressBar progressGrid; private Toolbar toolbar; private Spinner spinner; private CatalogueAdapter adapter; - private EndlessGridScrollListener gridScrollListener; - private EndlessListScrollListener listScrollListener; + private EndlessRecyclerScrollListener scrollListener; @State String query = ""; @State int selectedIndex = -1; @@ -72,9 +61,6 @@ public class CatalogueFragment extends BaseRxFragment private PublishSubject queryDebouncerSubject; private Subscription queryDebouncerSubscription; - private MenuItem displayMode; - private MenuItem searchItem; - public static CatalogueFragment newInstance() { return new CatalogueFragment(); } @@ -91,32 +77,13 @@ public class CatalogueFragment extends BaseRxFragment View view = inflater.inflate(R.layout.fragment_catalogue, container, false); ButterKnife.bind(this, view); - // Initialize adapter, scroll listener and recycler views + // Initialize adapter and scroll listener + GridLayoutManager layoutManager = (GridLayoutManager) recycler.getLayoutManager(); adapter = new CatalogueAdapter(this); - - GridLayoutManager glm = (GridLayoutManager) catalogueGrid.getLayoutManager(); - gridScrollListener = new EndlessGridScrollListener(glm, this::requestNextPage); - catalogueGrid.setHasFixedSize(true); - catalogueGrid.setAdapter(adapter); - catalogueGrid.addOnScrollListener(gridScrollListener); - - LinearLayoutManager llm = new LinearLayoutManager(getActivity()); - listScrollListener = new EndlessListScrollListener(llm, this::requestNextPage); - catalogueList.setHasFixedSize(true); - catalogueList.setAdapter(adapter); - catalogueList.setLayoutManager(llm); - catalogueList.addOnScrollListener(listScrollListener); - catalogueList.addItemDecoration(new DividerItemDecoration( - ContextCompat.getDrawable(getContext(), R.drawable.line_divider))); - - if (getPresenter().isListMode()) { - switcher.showNext(); - } - - Animation inAnim = AnimationUtils.loadAnimation(getActivity(), android.R.anim.fade_in); - Animation outAnim = AnimationUtils.loadAnimation(getActivity(), android.R.anim.fade_out); - switcher.setInAnimation(inAnim); - switcher.setOutAnimation(outAnim); + scrollListener = new EndlessRecyclerScrollListener(layoutManager, this::requestNextPage); + recycler.setHasFixedSize(true); + recycler.setAdapter(adapter); + recycler.addOnScrollListener(scrollListener); // Create toolbar spinner Context themedContext = getBaseActivity().getSupportActionBar() != null ? @@ -142,8 +109,7 @@ public class CatalogueFragment extends BaseRxFragment } else { selectedIndex = position; showProgressBar(); - glm.scrollToPositionWithOffset(0, 0); - llm.scrollToPositionWithOffset(0, 0); + recycler.setAdapter(adapter); getPresenter().startRequesting(source); } } @@ -165,7 +131,7 @@ public class CatalogueFragment extends BaseRxFragment inflater.inflate(R.menu.catalogue_list, menu); // Initialize search menu - searchItem = menu.findItem(R.id.action_search); + MenuItem searchItem = menu.findItem(R.id.action_search); final SearchView searchView = (SearchView) searchItem.getActionView(); if (!TextUtils.isEmpty(query)) { @@ -186,22 +152,6 @@ public class CatalogueFragment extends BaseRxFragment return true; } }); - - // Show next display mode - displayMode = menu.findItem(R.id.action_display_mode); - int icon = getPresenter().isListMode() ? - R.drawable.ic_view_module_white_24dp : R.drawable.ic_view_list_white_24dp; - displayMode.setIcon(icon); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case R.id.action_display_mode: - swapDisplayMode(); - break; - } - return super.onOptionsItemSelected(item); } @Override @@ -218,9 +168,6 @@ public class CatalogueFragment extends BaseRxFragment @Override public void onDestroyView() { - if (searchItem != null && searchItem.isActionViewExpanded()) { - searchItem.collapseActionView(); - } toolbar.removeView(spinner); super.onDestroyView(); } @@ -247,13 +194,11 @@ public class CatalogueFragment extends BaseRxFragment private void restartRequest(String newQuery) { // If text didn't change, do nothing - if (query.equals(newQuery) || getPresenter().getSource() == null) - return; + if (query.equals(newQuery)) return; query = newQuery; showProgressBar(); - catalogueGrid.getLayoutManager().scrollToPosition(0); - catalogueList.getLayoutManager().scrollToPosition(0); + recycler.getLayoutManager().scrollToPosition(0); getPresenter().restartRequest(query); } @@ -269,8 +214,7 @@ public class CatalogueFragment extends BaseRxFragment hideProgressBar(); if (page == 0) { adapter.clear(); - gridScrollListener.resetScroll(); - listScrollListener.resetScroll(); + scrollListener.resetScroll(); } adapter.addItems(mangas); } @@ -280,28 +224,15 @@ public class CatalogueFragment extends BaseRxFragment } public void updateImage(Manga manga) { - CatalogueGridHolder holder = getHolder(manga); + CatalogueHolder holder = getHolder(manga); if (holder != null) { holder.setImage(manga, getPresenter()); } } - public void swapDisplayMode() { - getPresenter().swapDisplayMode(); - boolean isListMode = getPresenter().isListMode(); - int icon = isListMode ? - R.drawable.ic_view_module_white_24dp : R.drawable.ic_view_list_white_24dp; - displayMode.setIcon(icon); - switcher.showNext(); - if (!isListMode) { - // Initialize mangas if going to grid view - getPresenter().initializeMangas(adapter.getItems()); - } - } - @Nullable - private CatalogueGridHolder getHolder(Manga manga) { - return (CatalogueGridHolder) catalogueGrid.findViewHolderForItemId(manga.id); + private CatalogueHolder getHolder(Manga manga) { + return (CatalogueHolder) recycler.findViewHolderForItemId(manga.id); } private void showProgressBar() { @@ -330,8 +261,9 @@ public class CatalogueFragment extends BaseRxFragment @Override public void onListItemLongClick(int position) { final Manga selectedManga = adapter.getItem(position); + final Manga dbManga = getPresenter().getDbManga(selectedManga.id); - int textRes = selectedManga.favorite ? R.string.remove_from_library : R.string.add_to_library; + int textRes = dbManga.favorite ? R.string.remove_from_library : R.string.add_to_library; new MaterialDialog.Builder(getActivity()) .items(getString(textRes)) @@ -339,7 +271,6 @@ public class CatalogueFragment extends BaseRxFragment switch (which) { case 0: getPresenter().changeMangaFavorite(selectedManga); - adapter.notifyItemChanged(position); break; } }) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueGridHolder.java b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueGridHolder.java deleted file mode 100644 index b45fe51e6d..0000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueGridHolder.java +++ /dev/null @@ -1,38 +0,0 @@ -package eu.kanade.tachiyomi.ui.catalogue; - -import android.view.View; -import android.widget.ImageView; -import android.widget.TextView; - -import butterknife.Bind; -import butterknife.ButterKnife; -import eu.kanade.tachiyomi.R; -import eu.kanade.tachiyomi.data.database.models.Manga; - -public class CatalogueGridHolder extends CatalogueHolder { - - @Bind(R.id.title) TextView title; - @Bind(R.id.thumbnail) ImageView thumbnail; - @Bind(R.id.favorite_sticker) ImageView favoriteSticker; - - public CatalogueGridHolder(View view, CatalogueAdapter adapter, OnListItemClickListener listener) { - super(view, adapter, listener); - ButterKnife.bind(this, view); - } - - @Override - public void onSetValues(Manga manga, CataloguePresenter presenter) { - title.setText(manga.title); - favoriteSticker.setVisibility(manga.favorite ? View.VISIBLE : View.GONE); - setImage(manga, presenter); - } - - public void setImage(Manga manga, CataloguePresenter presenter) { - if (manga.thumbnail_url != null) { - presenter.coverCache.loadFromNetwork(thumbnail, manga.thumbnail_url, - presenter.getSource().getGlideHeaders()); - } else { - thumbnail.setImageResource(android.R.color.transparent); - } - } -} \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueHolder.java b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueHolder.java index 8de83acee1..243b6d8041 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueHolder.java +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueHolder.java @@ -1,15 +1,38 @@ package eu.kanade.tachiyomi.ui.catalogue; import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; +import butterknife.Bind; +import butterknife.ButterKnife; +import eu.kanade.tachiyomi.R; import eu.kanade.tachiyomi.data.database.models.Manga; import eu.kanade.tachiyomi.ui.base.adapter.FlexibleViewHolder; -public abstract class CatalogueHolder extends FlexibleViewHolder { +public class CatalogueHolder extends FlexibleViewHolder { + + @Bind(R.id.title) TextView title; + @Bind(R.id.thumbnail) ImageView thumbnail; + @Bind(R.id.favorite_sticker) ImageView favoriteSticker; public CatalogueHolder(View view, CatalogueAdapter adapter, OnListItemClickListener listener) { super(view, adapter, listener); + ButterKnife.bind(this, view); } - abstract void onSetValues(Manga manga, CataloguePresenter presenter); -} + public void onSetValues(Manga manga, CataloguePresenter presenter) { + title.setText(manga.title); + favoriteSticker.setVisibility(manga.favorite ? View.VISIBLE : View.GONE); + setImage(manga, presenter); + } + + public void setImage(Manga manga, CataloguePresenter presenter) { + if (manga.thumbnail_url != null) { + presenter.coverCache.loadFromNetwork(thumbnail, manga.thumbnail_url, + presenter.getSource().getGlideHeaders()); + } else { + thumbnail.setImageResource(android.R.color.transparent); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueListHolder.java b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueListHolder.java deleted file mode 100644 index 94042c4494..0000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueListHolder.java +++ /dev/null @@ -1,32 +0,0 @@ -package eu.kanade.tachiyomi.ui.catalogue; - -import android.support.v4.content.ContextCompat; -import android.view.View; -import android.widget.TextView; - -import butterknife.Bind; -import butterknife.ButterKnife; -import eu.kanade.tachiyomi.R; -import eu.kanade.tachiyomi.data.database.models.Manga; - -public class CatalogueListHolder extends CatalogueHolder { - - @Bind(R.id.title) TextView title; - - private final int favoriteColor; - private final int unfavoriteColor; - - public CatalogueListHolder(View view, CatalogueAdapter adapter, OnListItemClickListener listener) { - super(view, adapter, listener); - ButterKnife.bind(this, view); - - favoriteColor = ContextCompat.getColor(view.getContext(), R.color.hint_text); - unfavoriteColor = ContextCompat.getColor(view.getContext(), R.color.primary_text); - } - - @Override - public void onSetValues(Manga manga, CataloguePresenter presenter) { - title.setText(manga.title); - title.setTextColor(manga.favorite ? favoriteColor : unfavoriteColor); - } -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CataloguePresenter.java b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CataloguePresenter.java index 97e835c204..bc30ba7602 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CataloguePresenter.java +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CataloguePresenter.java @@ -42,8 +42,6 @@ public class CataloguePresenter extends BasePresenter { private PublishSubject> mangaDetailSubject; - private boolean isListMode; - private static final int GET_MANGA_LIST = 1; private static final int GET_MANGA_DETAIL = 2; private static final int GET_MANGA_PAGE = 3; @@ -74,14 +72,12 @@ public class CataloguePresenter extends BasePresenter { .observeOn(Schedulers.io()) .flatMap(Observable::from) .filter(manga -> !manga.initialized) - .concatMap(this::getMangaDetails) + .window(3) + .concatMap(pack -> pack.concatMap(this::getMangaDetails)) .onBackpressureBuffer() .observeOn(AndroidSchedulers.mainThread()), CatalogueFragment::updateImage, (view, error) -> Timber.e(error.getMessage())); - - add(prefs.catalogueAsList().asObservable() - .subscribe(this::setDisplayMode)); } private void onProcessRestart() { @@ -91,15 +87,6 @@ public class CataloguePresenter extends BasePresenter { stop(GET_MANGA_PAGE); } - private void setDisplayMode(boolean asList) { - this.isListMode = asList; - if (asList) { - stop(GET_MANGA_DETAIL); - } else { - start(GET_MANGA_DETAIL); - } - } - public void startRequesting(Source source) { this.source = source; sourceId = source.getId(); @@ -111,9 +98,7 @@ public class CataloguePresenter extends BasePresenter { stop(GET_MANGA_PAGE); lastMangasPage = null; - if (!isListMode) { - start(GET_MANGA_DETAIL); - } + start(GET_MANGA_DETAIL); start(GET_MANGA_LIST); start(GET_MANGA_PAGE); } @@ -139,7 +124,10 @@ public class CataloguePresenter extends BasePresenter { .flatMap(mangasPage -> Observable.from(mangasPage.mangas)) .map(this::networkToLocalManga) .toList() - .doOnNext(this::initializeMangas) + .doOnNext(mangas -> { + if (mangaDetailSubject != null) + mangaDetailSubject.onNext(mangas); + }) .observeOn(AndroidSchedulers.mainThread()); } @@ -153,12 +141,9 @@ public class CataloguePresenter extends BasePresenter { return localManga; } - public void initializeMangas(List mangas) { - mangaDetailSubject.onNext(mangas); - } - private Observable getMangaDetails(final Manga manga) { return source.pullMangaFromNetwork(manga.url) + .subscribeOn(Schedulers.io()) .flatMap(networkManga -> { manga.copyFrom(networkManga); db.insertManga(manga).executeAsBlocking(); @@ -167,6 +152,10 @@ public class CataloguePresenter extends BasePresenter { .onErrorResumeNext(error -> Observable.just(manga)); } + public Manga getDbManga(long id) { + return db.getManga(id).executeAsBlocking(); + } + public Source getSource() { return source; } @@ -192,13 +181,4 @@ public class CataloguePresenter extends BasePresenter { manga.favorite = !manga.favorite; db.insertManga(manga).executeAsBlocking(); } - - public boolean isListMode() { - return isListMode; - } - - public void swapDisplayMode() { - prefs.catalogueAsList().set(!isListMode); - } - } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/download/DownloadPresenter.java b/app/src/main/java/eu/kanade/tachiyomi/ui/download/DownloadPresenter.java index fe69bc884d..429180f758 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/download/DownloadPresenter.java +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/download/DownloadPresenter.java @@ -90,7 +90,6 @@ public class DownloadPresenter extends BasePresenter { .flatMap(tick -> Observable.from(download.pages) .map(Page::getProgress) .reduce((x, y) -> x + y)) - .onBackpressureLatest() .observeOn(AndroidSchedulers.mainThread()) .subscribe(progress -> { if (download.totalProgress != progress) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryAdapter.java b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryAdapter.java index d4cbfd4eee..9319e9db93 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryAdapter.java +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryAdapter.java @@ -52,7 +52,7 @@ public class LibraryCategoryAdapter extends FlexibleAdapter { @Override protected void onTakeView(LibraryFragment libraryFragment) { super.onTakeView(libraryFragment); - if (isUnsubscribed(GET_LIBRARY)) { + if (!isSubscribed(GET_LIBRARY)) { start(GET_LIBRARY); } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaActivity.java b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaActivity.java index 7a550b536d..8899cf04f6 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaActivity.java +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaActivity.java @@ -14,7 +14,6 @@ import javax.inject.Inject; import butterknife.Bind; import butterknife.ButterKnife; -import de.greenrobot.event.EventBus; import eu.kanade.tachiyomi.App; import eu.kanade.tachiyomi.R; import eu.kanade.tachiyomi.data.database.models.Manga; @@ -31,21 +30,21 @@ public class MangaActivity extends BaseRxActivity { @Bind(R.id.toolbar) Toolbar toolbar; @Bind(R.id.tabs) TabLayout tabs; - @Bind(R.id.view_pager) ViewPager viewPager; + @Bind(R.id.view_pager) ViewPager view_pager; @Inject PreferencesHelper preferences; @Inject MangaSyncManager mangaSyncManager; private MangaDetailAdapter adapter; - private boolean isOnline; + private long manga_id; + private boolean is_online; + public final static String MANGA_ID = "manga_id"; public final static String MANGA_ONLINE = "manga_online"; public static Intent newIntent(Context context, Manga manga) { Intent intent = new Intent(context, MangaActivity.class); - if (manga != null) { - EventBus.getDefault().postSticky(manga); - } + intent.putExtra(MANGA_ID, manga.id); return intent; } @@ -60,19 +59,23 @@ public class MangaActivity extends BaseRxActivity { Intent intent = getIntent(); - isOnline = intent.getBooleanExtra(MANGA_ONLINE, false); + manga_id = intent.getLongExtra(MANGA_ID, -1); + is_online = intent.getBooleanExtra(MANGA_ONLINE, false); setupViewPager(); + + if (savedState == null) + getPresenter().queryManga(manga_id); } private void setupViewPager() { adapter = new MangaDetailAdapter(getSupportFragmentManager(), this); - viewPager.setAdapter(adapter); - tabs.setupWithViewPager(viewPager); + view_pager.setAdapter(adapter); + tabs.setupWithViewPager(view_pager); - if (!isOnline) - viewPager.setCurrentItem(MangaDetailAdapter.CHAPTERS_FRAGMENT); + if (!is_online) + view_pager.setCurrentItem(MangaDetailAdapter.CHAPTERS_FRAGMENT); } public void setManga(Manga manga) { @@ -80,7 +83,7 @@ public class MangaActivity extends BaseRxActivity { } public boolean isCatalogueManga() { - return isOnline; + return is_online; } class MangaDetailAdapter extends FragmentPagerAdapter { @@ -101,7 +104,7 @@ public class MangaActivity extends BaseRxActivity { }; pageCount = 2; - if (!isOnline && mangaSyncManager.getMyAnimeList().isLogged()) + if (!is_online && mangaSyncManager.getMyAnimeList().isLogged()) pageCount++; } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.java b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.java index a24f093e71..15faffb3ea 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.java +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.java @@ -7,48 +7,44 @@ import javax.inject.Inject; import de.greenrobot.event.EventBus; import eu.kanade.tachiyomi.data.database.DatabaseHelper; import eu.kanade.tachiyomi.data.database.models.Manga; -import eu.kanade.tachiyomi.event.MangaEvent; import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter; -import eu.kanade.tachiyomi.util.EventBusHook; import icepick.State; import rx.Observable; +import rx.android.schedulers.AndroidSchedulers; +import rx.schedulers.Schedulers; public class MangaPresenter extends BasePresenter { @Inject DatabaseHelper db; - @State Manga manga; + @State long mangaId; - private static final int GET_MANGA = 1; + private static final int DB_MANGA = 1; @Override protected void onCreate(Bundle savedState) { super.onCreate(savedState); - restartableLatestCache(GET_MANGA, this::getMangaObservable, MangaActivity::setManga); - - if (savedState == null) - registerForStickyEvents(); + restartableLatestCache(DB_MANGA, this::getDbMangaObservable, MangaActivity::setManga); } @Override protected void onDestroy() { super.onDestroy(); // Avoid new instances receiving wrong manga - EventBus.getDefault().removeStickyEvent(MangaEvent.class); + EventBus.getDefault().removeStickyEvent(Manga.class); } - private Observable getMangaObservable() { - return Observable.just(manga) - .doOnNext(manga -> EventBus.getDefault().postSticky(new MangaEvent(manga))); + private Observable getDbMangaObservable() { + return db.getManga(mangaId).asRxObservable() + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .doOnNext(manga -> EventBus.getDefault().postSticky(manga)); } - @EventBusHook - public void onEventMainThread(Manga manga) { - EventBus.getDefault().removeStickyEvent(manga); - unregisterForEvents(); - this.manga = manga; - start(GET_MANGA); + public void queryManga(long mangaId) { + this.mangaId = mangaId; + start(DB_MANGA); } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersAdapter.java b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersAdapter.java index ba7db26bcb..0e0e64392a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersAdapter.java +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersAdapter.java @@ -10,7 +10,6 @@ import java.util.List; import eu.davidea.flexibleadapter.FlexibleAdapter; import eu.kanade.tachiyomi.R; import eu.kanade.tachiyomi.data.database.models.Chapter; -import eu.kanade.tachiyomi.data.database.models.Manga; public class ChaptersAdapter extends FlexibleAdapter { @@ -34,8 +33,7 @@ public class ChaptersAdapter extends FlexibleAdapter { @Override public void onBindViewHolder(ChaptersHolder holder, int position) { final Chapter chapter = getItem(position); - final Manga manga = fragment.getPresenter().getManga(); - holder.onSetValues(chapter, manga); + holder.onSetValues(fragment.getActivity(), chapter); //When user scrolls this bind the correct selection status holder.itemView.setActivated(isSelected(position)); diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersFragment.java b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersFragment.java index 682aa34a50..0ecd4e9395 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersFragment.java +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersFragment.java @@ -10,7 +10,6 @@ import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.Menu; -import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; @@ -25,7 +24,6 @@ import butterknife.Bind; import butterknife.ButterKnife; import eu.kanade.tachiyomi.R; import eu.kanade.tachiyomi.data.database.models.Chapter; -import eu.kanade.tachiyomi.data.database.models.Manga; import eu.kanade.tachiyomi.data.download.DownloadService; import eu.kanade.tachiyomi.data.download.model.Download; import eu.kanade.tachiyomi.ui.base.adapter.FlexibleViewHolder; @@ -63,12 +61,6 @@ public class ChaptersFragment extends BaseRxFragment implemen return new ChaptersFragment(); } - @Override - public void onCreate(Bundle bundle) { - super.onCreate(bundle); - setHasOptionsMenu(true); - } - @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -79,14 +71,26 @@ public class ChaptersFragment extends BaseRxFragment implemen // Init RecyclerView and adapter linearLayout = new LinearLayoutManager(getActivity()); recyclerView.setLayoutManager(linearLayout); - recyclerView.addItemDecoration(new DividerItemDecoration( - ContextCompat.getDrawable(getContext(), R.drawable.line_divider))); + recyclerView.addItemDecoration(new DividerItemDecoration(ContextCompat.getDrawable(getContext(), R.drawable.line_divider))); recyclerView.setHasFixedSize(true); adapter = new ChaptersAdapter(this); recyclerView.setAdapter(adapter); - swipeRefresh.setOnRefreshListener(this::fetchChapters); + // Set initial values + setReadFilter(); + setDownloadedFilter(); + setSortIcon(); + // Init listeners + swipeRefresh.setOnRefreshListener(this::fetchChapters); + readCb.setOnCheckedChangeListener((arg, isChecked) -> + getPresenter().setReadFilter(isChecked)); + downloadedCb.setOnCheckedChangeListener((v, isChecked) -> + getPresenter().setDownloadedFilter(isChecked)); + sortBtn.setOnClickListener(v -> { + getPresenter().revertSortOrder(); + setSortIcon(); + }); nextUnreadBtn.setOnClickListener(v -> { Chapter chapter = getPresenter().getNextUnreadChapter(); if (chapter != null) { @@ -100,40 +104,15 @@ public class ChaptersFragment extends BaseRxFragment implemen } @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - inflater.inflate(R.menu.chapters, menu); + public void onResume() { + super.onResume(); + observeChapterDownloadProgress(); } @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case R.id.action_display_mode: - showDisplayModeDialog(); - return true; - } - return false; - } - - public void onNextManga(Manga manga) { - // Remove listeners before setting the values - readCb.setOnCheckedChangeListener(null); - downloadedCb.setOnCheckedChangeListener(null); - sortBtn.setOnClickListener(null); - - // Set initial values - setReadFilter(); - setDownloadedFilter(); - setSortIcon(); - - // Init listeners - readCb.setOnCheckedChangeListener((arg, isChecked) -> - getPresenter().setReadFilter(isChecked)); - downloadedCb.setOnCheckedChangeListener((v, isChecked) -> - getPresenter().setDownloadedFilter(isChecked)); - sortBtn.setOnClickListener(v -> { - getPresenter().revertSortOrder(); - setSortIcon(); - }); + public void onPause() { + unsubscribeChapterDownloadProgress(); + super.onPause(); } public void onNextChapters(List chapters) { @@ -179,29 +158,6 @@ public class ChaptersFragment extends BaseRxFragment implemen startActivity(intent); } - private void showDisplayModeDialog() { - final Manga manga = getPresenter().getManga(); - if (manga == null) - return; - - // Get available modes, ids and the selected mode - String[] modes = {getString(R.string.show_title), getString(R.string.show_chapter_number)}; - int[] ids = {Manga.DISPLAY_NAME, Manga.DISPLAY_NUMBER}; - int selectedIndex = manga.getDisplayMode() == Manga.DISPLAY_NAME ? 0 : 1; - - new MaterialDialog.Builder(getActivity()) - .items(modes) - .itemsIds(ids) - .itemsCallbackSingleChoice(selectedIndex, (dialog, itemView, which, text) -> { - // Save the new display mode - getPresenter().setDisplayMode(itemView.getId()); - // Refresh ui - adapter.notifyDataSetChanged(); - return true; - }) - .show(); - } - private void observeChapterDownloadProgress() { downloadProgressSubscription = getPresenter().getDownloadProgressObs() .subscribe(this::onDownloadProgressChange, @@ -219,10 +175,10 @@ public class ChaptersFragment extends BaseRxFragment implemen holder.onProgressChange(getContext(), download.downloadedImages, download.pages.size()); } - public void onChapterStatusChange(Download download) { - ChaptersHolder holder = getHolder(download.chapter); + public void onChapterStatusChange(Chapter chapter) { + ChaptersHolder holder = getHolder(chapter); if (holder != null) - holder.onStatusChange(download.getStatus()); + holder.onStatusChange(chapter.status); } @Nullable diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersHolder.java b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersHolder.java index a8c76fa82f..b57813e821 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersHolder.java +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersHolder.java @@ -7,8 +7,6 @@ import android.widget.PopupMenu; import android.widget.RelativeLayout; import android.widget.TextView; -import java.text.DecimalFormat; -import java.text.DecimalFormatSymbols; import java.text.SimpleDateFormat; import java.util.Date; @@ -16,61 +14,40 @@ import butterknife.Bind; import butterknife.ButterKnife; import eu.kanade.tachiyomi.R; import eu.kanade.tachiyomi.data.database.models.Chapter; -import eu.kanade.tachiyomi.data.database.models.Manga; import eu.kanade.tachiyomi.data.download.model.Download; import eu.kanade.tachiyomi.ui.base.adapter.FlexibleViewHolder; import rx.Observable; public class ChaptersHolder extends FlexibleViewHolder { + private final ChaptersAdapter adapter; + private Chapter item; + @Bind(R.id.chapter_title) TextView title; @Bind(R.id.download_text) TextView downloadText; @Bind(R.id.chapter_menu) RelativeLayout chapterMenu; @Bind(R.id.chapter_pages) TextView pages; @Bind(R.id.chapter_date) TextView date; - private Context context; - - private final ChaptersAdapter adapter; - private Chapter item; - - private final int readColor; - private final int unreadColor; - - private final DecimalFormat decimalFormat; - private SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy"); + SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy"); public ChaptersHolder(View view, ChaptersAdapter adapter, OnListItemClickListener listener) { super(view, adapter, listener); this.adapter = adapter; - context = view.getContext(); ButterKnife.bind(this, view); - readColor = ContextCompat.getColor(view.getContext(), R.color.hint_text); - unreadColor = ContextCompat.getColor(view.getContext(), R.color.primary_text); - - DecimalFormatSymbols symbols = new DecimalFormatSymbols(); - symbols.setDecimalSeparator('.'); - decimalFormat = new DecimalFormat("#.###", symbols); - chapterMenu.setOnClickListener(v -> v.post(() -> showPopupMenu(v))); } - public void onSetValues(Chapter chapter, Manga manga) { + public void onSetValues(Context context, Chapter chapter) { this.item = chapter; - String name; - switch (manga.getDisplayMode()) { - case Manga.DISPLAY_NAME: - default: - name = chapter.name; - break; - case Manga.DISPLAY_NUMBER: - String formattedNumber = decimalFormat.format(chapter.chapter_number); - name = context.getString(R.string.display_mode_chapter, formattedNumber); - break; + title.setText(chapter.name); + + if (chapter.read) { + title.setTextColor(ContextCompat.getColor(context, R.color.hint_text)); + } else { + title.setTextColor(ContextCompat.getColor(context, R.color.primary_text)); } - title.setText(name); - title.setTextColor(chapter.read ? readColor : unreadColor); if (!chapter.read && chapter.last_page_read > 0) { pages.setText(context.getString(R.string.chapter_progress, chapter.last_page_read + 1)); diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersPresenter.java b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersPresenter.java index e981ec0e7b..de89c1c796 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersPresenter.java +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersPresenter.java @@ -18,7 +18,6 @@ import eu.kanade.tachiyomi.data.source.SourceManager; import eu.kanade.tachiyomi.data.source.base.Source; import eu.kanade.tachiyomi.event.ChapterCountEvent; import eu.kanade.tachiyomi.event.DownloadChaptersEvent; -import eu.kanade.tachiyomi.event.MangaEvent; import eu.kanade.tachiyomi.event.ReaderEvent; import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter; import eu.kanade.tachiyomi.util.EventBusHook; @@ -39,16 +38,16 @@ public class ChaptersPresenter extends BasePresenter { private Manga manga; private Source source; private List chapters; + private boolean sortOrderAToZ = true; private boolean onlyUnread = true; private boolean onlyDownloaded; @State boolean hasRequested; private PublishSubject> chaptersSubject; - private static final int GET_MANGA = 1; - private static final int DB_CHAPTERS = 2; - private static final int FETCH_CHAPTERS = 3; - private static final int CHAPTER_STATUS_CHANGES = 4; + private static final int DB_CHAPTERS = 1; + private static final int FETCH_CHAPTERS = 2; + private static final int CHAPTER_STATUS_CHANGES = 3; @Override protected void onCreate(Bundle savedState) { @@ -60,10 +59,6 @@ public class ChaptersPresenter extends BasePresenter { chaptersSubject = PublishSubject.create(); - restartableLatestCache(GET_MANGA, - () -> Observable.just(manga), - ChaptersFragment::onNextManga); - restartableLatestCache(DB_CHAPTERS, this::getDbChaptersObs, ChaptersFragment::onNextChapters); @@ -75,14 +70,13 @@ public class ChaptersPresenter extends BasePresenter { restartableLatestCache(CHAPTER_STATUS_CHANGES, this::getChapterStatusObs, - (view, download) -> view.onChapterStatusChange(download), + (view, download) -> view.onChapterStatusChange(download.chapter), (view, error) -> Timber.e(error.getCause(), error.getMessage())); registerForStickyEvents(); } private void onProcessRestart() { - stop(GET_MANGA); stop(DB_CHAPTERS); stop(FETCH_CHAPTERS); stop(CHAPTER_STATUS_CHANGES); @@ -96,11 +90,10 @@ public class ChaptersPresenter extends BasePresenter { } @EventBusHook - public void onEventMainThread(MangaEvent event) { - this.manga = event.manga; - start(GET_MANGA); + public void onEventMainThread(Manga manga) { + this.manga = manga; - if (isUnsubscribed(DB_CHAPTERS)) { + if (!isSubscribed(DB_CHAPTERS)) { source = sourceManager.get(manga.source); start(DB_CHAPTERS); @@ -148,7 +141,7 @@ public class ChaptersPresenter extends BasePresenter { if (onlyDownloaded) { observable = observable.filter(chapter -> chapter.status == Download.DOWNLOADED); } - return observable.toSortedList((chapter, chapter2) -> getSortOrder() ? + return observable.toSortedList((chapter, chapter2) -> sortOrderAToZ ? Float.compare(chapter2.chapter_number, chapter.chapter_number) : Float.compare(chapter.chapter_number, chapter2.chapter_number)); } @@ -248,8 +241,8 @@ public class ChaptersPresenter extends BasePresenter { } public void revertSortOrder() { - manga.setChapterOrder(getSortOrder() ? Manga.SORT_ZA : Manga.SORT_AZ); - db.insertManga(manga).executeAsBlocking(); + //TODO manga.chapter_order + sortOrderAToZ = !sortOrderAToZ; refreshChapters(); } @@ -264,13 +257,8 @@ public class ChaptersPresenter extends BasePresenter { refreshChapters(); } - public void setDisplayMode(int mode) { - manga.setDisplayMode(mode); - db.insertManga(manga).executeAsBlocking(); - } - public boolean getSortOrder() { - return manga.sortChaptersAZ(); + return sortOrderAToZ; } public boolean getReadFilter() { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoFragment.java b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoFragment.java index 033e8e7ce8..16aaeee9e0 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoFragment.java +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoFragment.java @@ -16,7 +16,6 @@ import butterknife.ButterKnife; import eu.kanade.tachiyomi.R; import eu.kanade.tachiyomi.data.cache.CoverCache; import eu.kanade.tachiyomi.data.database.models.Manga; -import eu.kanade.tachiyomi.data.source.base.Source; import eu.kanade.tachiyomi.ui.base.fragment.BaseRxFragment; import nucleus.factory.RequiresPresenter; @@ -30,7 +29,6 @@ public class MangaInfoFragment extends BaseRxFragment { @Bind(R.id.manga_chapters) TextView chapterCount; @Bind(R.id.manga_genres) TextView genres; @Bind(R.id.manga_status) TextView status; - @Bind(R.id.manga_source) TextView source; @Bind(R.id.manga_summary) TextView description; @Bind(R.id.manga_cover) ImageView cover; @@ -62,22 +60,18 @@ public class MangaInfoFragment extends BaseRxFragment { return view; } - public void onNextManga(Manga manga, Source source) { + public void onNextManga(Manga manga) { if (manga.initialized) { - setMangaInfo(manga, source); + setMangaInfo(manga); } else { // Initialize manga fetchMangaFromSource(); } } - private void setMangaInfo(Manga manga, Source mangaSource) { + private void setMangaInfo(Manga manga) { artist.setText(manga.artist); author.setText(manga.author); - - if (mangaSource != null) { - source.setText(mangaSource.getName()); - } genres.setText(manga.genre); status.setText(manga.getStatus(getActivity())); description.setText(manga.description); @@ -88,7 +82,7 @@ public class MangaInfoFragment extends BaseRxFragment { LazyHeaders headers = getPresenter().source.getGlideHeaders(); if (manga.thumbnail_url != null && cover.getDrawable() == null) { if (manga.favorite) { - coverCache.saveOrLoadFromCache(cover, manga.thumbnail_url, headers); + coverCache.saveAndLoadFromCache(cover, manga.thumbnail_url, headers); } else { coverCache.loadFromNetwork(cover, manga.thumbnail_url, headers); } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoPresenter.java b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoPresenter.java index bfeb251be1..8965419059 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoPresenter.java +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoPresenter.java @@ -10,7 +10,6 @@ import eu.kanade.tachiyomi.data.database.models.Manga; import eu.kanade.tachiyomi.data.source.SourceManager; import eu.kanade.tachiyomi.data.source.base.Source; import eu.kanade.tachiyomi.event.ChapterCountEvent; -import eu.kanade.tachiyomi.event.MangaEvent; import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter; import eu.kanade.tachiyomi.util.EventBusHook; import rx.Observable; @@ -19,18 +18,19 @@ import rx.schedulers.Schedulers; 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 boolean isFetching; + private static final int GET_MANGA = 1; private static final int GET_CHAPTER_COUNT = 2; private static final int FETCH_MANGA_INFO = 3; - protected Source source; - @Inject - DatabaseHelper db; - @Inject - SourceManager sourceManager; - @Inject - CoverCache coverCache; - private Manga manga; - private int count = -1; @Override protected void onCreate(Bundle savedState) { @@ -42,7 +42,7 @@ public class MangaInfoPresenter extends BasePresenter { restartableLatestCache(GET_MANGA, () -> Observable.just(manga), - (view, manga) -> view.onNextManga(manga, source)); + MangaInfoFragment::onNextManga); restartableLatestCache(GET_CHAPTER_COUNT, () -> Observable.just(count), @@ -69,10 +69,10 @@ public class MangaInfoPresenter extends BasePresenter { } @EventBusHook - public void onEventMainThread(MangaEvent event) { - this.manga = event.manga; + public void onEventMainThread(Manga manga) { + this.manga = manga; source = sourceManager.get(manga.source); - refreshManga(); + start(GET_MANGA); } @EventBusHook @@ -84,7 +84,8 @@ public class MangaInfoPresenter extends BasePresenter { } public void fetchMangaFromSource() { - if (isUnsubscribed(FETCH_MANGA_INFO)) { + if (!isFetching) { + isFetching = true; start(FETCH_MANGA_INFO); } } @@ -96,29 +97,23 @@ public class MangaInfoPresenter extends BasePresenter { db.insertManga(manga).executeAsBlocking(); return Observable.just(manga); }) + .finallyDo(() -> isFetching = false) .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .doOnNext(manga -> refreshManga()); + .observeOn(AndroidSchedulers.mainThread()); } public void toggleFavorite() { manga.favorite = !manga.favorite; onMangaFavoriteChange(manga.favorite); db.insertManga(manga).executeAsBlocking(); - refreshManga(); } private void onMangaFavoriteChange(boolean isFavorite) { if (isFavorite) { coverCache.save(manga.thumbnail_url, source.getGlideHeaders()); } else { - coverCache.deleteCoverFromCache(manga.thumbnail_url); + coverCache.delete(manga.thumbnail_url); } } - // Used to refresh the view - private void refreshManga() { - start(GET_MANGA); - } - } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/myanimelist/MyAnimeListPresenter.java b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/myanimelist/MyAnimeListPresenter.java index db23a4e651..a49b169cde 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/myanimelist/MyAnimeListPresenter.java +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/myanimelist/MyAnimeListPresenter.java @@ -12,7 +12,6 @@ import eu.kanade.tachiyomi.data.database.models.Manga; import eu.kanade.tachiyomi.data.database.models.MangaSync; import eu.kanade.tachiyomi.data.mangasync.MangaSyncManager; import eu.kanade.tachiyomi.data.mangasync.services.MyAnimeList; -import eu.kanade.tachiyomi.event.MangaEvent; import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter; import eu.kanade.tachiyomi.util.EventBusHook; import eu.kanade.tachiyomi.util.ToastUtil; @@ -103,8 +102,8 @@ public class MyAnimeListPresenter extends BasePresenter { } @EventBusHook - public void onEventMainThread(MangaEvent event) { - this.manga = event.manga; + public void onEventMainThread(Manga manga) { + this.manga = manga; start(GET_MANGA_SYNC); } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.java b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.java index aa27e2e523..cbe7eabde5 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.java +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.java @@ -164,10 +164,6 @@ public class ReaderActivity extends BaseRxActivity { } public void onChapterReady(List pages, Manga manga, Chapter chapter, int currentPage) { - if (currentPage == -1) { - currentPage = pages.size() - 1; - } - if (viewer == null) { viewer = createViewer(manga); getSupportFragmentManager().beginTransaction().replace(R.id.reader, viewer).commit(); diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderMenu.java b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderMenu.java index 938cc2b9f8..8f8a840a0f 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderMenu.java +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderMenu.java @@ -70,7 +70,7 @@ public class ReaderMenu { bottomMenu.setOnTouchListener((v, event) -> true); seekBar.setOnSeekBarChangeListener(new PageSeekBarChangeListener()); - decimalFormat = new DecimalFormat("#.###"); + decimalFormat = new DecimalFormat("#.##"); inverted = false; initializeOptions(); diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.java b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.java index 4834a5fd27..7022d12918 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.java +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.java @@ -215,12 +215,8 @@ public class ReaderPresenter extends BasePresenter { .doOnNext(mangaSync -> this.mangaSyncList = mangaSync); } - private void loadChapter(Chapter chapter) { - loadChapter(chapter, 0); - } - // Loads the given chapter - private void loadChapter(Chapter chapter, int requestedPage) { + private void loadChapter(Chapter chapter) { // Before loading the chapter, stop preloading (if it's working) and save current progress stopPreloadingNextChapter(); @@ -231,7 +227,7 @@ public class ReaderPresenter extends BasePresenter { if (!chapter.read && chapter.last_page_read != 0) currentPage = chapter.last_page_read; else - currentPage = requestedPage; + currentPage = 0; // Reset next and previous chapter. They have to be fetched again nextChapter = null; @@ -316,7 +312,7 @@ public class ReaderPresenter extends BasePresenter { public boolean loadNextChapter() { if (hasNextChapter()) { onChapterLeft(); - loadChapter(nextChapter, 0); + loadChapter(nextChapter); return true; } return false; @@ -325,7 +321,7 @@ public class ReaderPresenter extends BasePresenter { public boolean loadPreviousChapter() { if (hasPreviousChapter()) { onChapterLeft(); - loadChapter(previousChapter, -1); + loadChapter(previousChapter); return true; } return false; @@ -346,7 +342,7 @@ public class ReaderPresenter extends BasePresenter { } private void stopPreloadingNextChapter() { - if (!isUnsubscribed(PRELOAD_NEXT_CHAPTER)) { + if (isSubscribed(PRELOAD_NEXT_CHAPTER)) { stop(PRELOAD_NEXT_CHAPTER); if (nextChapterPageList != null) source.savePageList(nextChapter.url, nextChapterPageList); diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAdvancedFragment.java b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAdvancedFragment.java index 6feccd55bb..eb9318820a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAdvancedFragment.java +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAdvancedFragment.java @@ -71,7 +71,7 @@ public class SettingsAdvancedFragment extends SettingsNestedFragment { subscriptions.add(Observable.defer(() -> Observable.from(files)) .concatMap(file -> { - if (chapterCache.removeFileFromCache(file.getName())) { + if (chapterCache.remove(file.getName())) { deletedFiles.incrementAndGet(); } return Observable.just(file); diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/UrlUtil.java b/app/src/main/java/eu/kanade/tachiyomi/util/UrlUtil.java index baf7ce9dce..65e0ea618d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/UrlUtil.java +++ b/app/src/main/java/eu/kanade/tachiyomi/util/UrlUtil.java @@ -5,10 +5,6 @@ import java.net.URISyntaxException; public class UrlUtil { - private static final String JPG = ".jpg"; - private static final String PNG = ".png"; - private static final String GIF = ".gif"; - public static String getPath(String s) { try { URI uri = new URI(s); @@ -22,37 +18,4 @@ public class UrlUtil { return s; } } - - public static boolean isJpg(String url) { - return containsIgnoreCase(url, JPG); - } - - public static boolean isPng(String url) { - return containsIgnoreCase(url, PNG); - } - - public static boolean isGif(String url) { - return containsIgnoreCase(url, GIF); - } - - public static boolean containsIgnoreCase(String src, String what) { - final int length = what.length(); - if (length == 0) - return true; // Empty string is contained - - final char firstLo = Character.toLowerCase(what.charAt(0)); - final char firstUp = Character.toUpperCase(what.charAt(0)); - - for (int i = src.length() - length; i >= 0; i--) { - // Quick check before calling the more expensive regionMatches() method: - final char ch = src.charAt(i); - if (ch != firstLo && ch != firstUp) - continue; - - if (src.regionMatches(true, i, what, 0, length)) - return true; - } - - return false; - } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/widget/EndlessListScrollListener.java b/app/src/main/java/eu/kanade/tachiyomi/widget/EndlessListScrollListener.java deleted file mode 100644 index b5fcfa9408..0000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/widget/EndlessListScrollListener.java +++ /dev/null @@ -1,49 +0,0 @@ -package eu.kanade.tachiyomi.widget; - -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; - -import rx.functions.Action0; - -public class EndlessListScrollListener extends RecyclerView.OnScrollListener { - - private int previousTotal = 0; // The total number of items in the dataset after the last load - private boolean loading = true; // True if we are still waiting for the last set of data to load. - private int visibleThreshold = 5; // The minimum amount of items to have below your current scroll position before loading more. - int firstVisibleItem, visibleItemCount, totalItemCount; - - private LinearLayoutManager layoutManager; - - private Action0 requestNext; - - public EndlessListScrollListener(LinearLayoutManager layoutManager, Action0 requestNext) { - this.layoutManager = layoutManager; - this.requestNext = requestNext; - } - - public void resetScroll() { - previousTotal = 0; - loading = true; - } - - @Override - public void onScrolled(RecyclerView recyclerView, int dx, int dy) { - super.onScrolled(recyclerView, dx, dy); - - visibleItemCount = recyclerView.getChildCount(); - totalItemCount = layoutManager.getItemCount(); - firstVisibleItem = layoutManager.findFirstVisibleItemPosition(); - - if (loading && (totalItemCount > previousTotal)) { - loading = false; - previousTotal = totalItemCount; - } - if (!loading && (totalItemCount - visibleItemCount) - <= (firstVisibleItem + visibleThreshold)) { - // End has been reached - requestNext.call(); - loading = true; - } - } - -} \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/widget/EndlessGridScrollListener.java b/app/src/main/java/eu/kanade/tachiyomi/widget/EndlessRecyclerScrollListener.java similarity index 89% rename from app/src/main/java/eu/kanade/tachiyomi/widget/EndlessGridScrollListener.java rename to app/src/main/java/eu/kanade/tachiyomi/widget/EndlessRecyclerScrollListener.java index a4d74d5502..d55b2a5834 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/widget/EndlessGridScrollListener.java +++ b/app/src/main/java/eu/kanade/tachiyomi/widget/EndlessRecyclerScrollListener.java @@ -5,7 +5,7 @@ import android.support.v7.widget.RecyclerView; import rx.functions.Action0; -public class EndlessGridScrollListener extends RecyclerView.OnScrollListener { +public class EndlessRecyclerScrollListener extends RecyclerView.OnScrollListener { private int previousTotal = 0; // The total number of items in the dataset after the last load private boolean loading = true; // True if we are still waiting for the last set of data to load. @@ -16,7 +16,7 @@ public class EndlessGridScrollListener extends RecyclerView.OnScrollListener { private Action0 requestNext; - public EndlessGridScrollListener(GridLayoutManager layoutManager, Action0 requestNext) { + public EndlessRecyclerScrollListener(GridLayoutManager layoutManager, Action0 requestNext) { this.layoutManager = layoutManager; this.requestNext = requestNext; } diff --git a/app/src/main/res/drawable-hdpi/ic_view_list_white_24dp.png b/app/src/main/res/drawable-hdpi/ic_view_list_white_24dp.png deleted file mode 100644 index 98c45924adc61322072a0058cb4911b6f69aa87f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 125 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k0wldT1B8K;i>HfYNX4z>ALkupPZ(rfm|(tw zk<;i;xx>TccD@_DPHYOvoXu^4%_mGdvNpPHEisYGcD}gaVp7T$3CWP7CssH*A68(H XVAy%vs;MpuXdZ*7tDnm{r-UW|K|k0wldT1B8K;m8XkiNX4z>ALkupPZ(rfm|(tw zk=05-v+1Zp$OVTbCssHvX1l227^K_XbL`d%$L3QDE>`7US-@z~-m}O2k5>Rq OVeoYIb6Mw<&;$VPJ0+I@ diff --git a/app/src/main/res/drawable-ldpi/ic_view_list_white_24dp.png b/app/src/main/res/drawable-ldpi/ic_view_list_white_24dp.png deleted file mode 100644 index 35df0ba80137b2af3a32cfa80269140acbbcf40a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 187 zcmeAS@N?(olHy`uVBq!ia0vp^JRr=$1|-8uW1a)4CQlc~kcwN$2@2vJ9UTP@hQd?Q z+z%<(ad$n+zP@hh{;IE9!X2g!7OWk{6AGjP?#V?qa|C?2w!i-WJLW2tDnm{r-UW|1BO7w diff --git a/app/src/main/res/drawable-ldpi/ic_view_module_white_24dp.png b/app/src/main/res/drawable-ldpi/ic_view_module_white_24dp.png deleted file mode 100644 index 7bf1e34eeed3c2e7158784eac74781a6684b9ca9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 278 zcmV+x0qOpUP)8xd@Ux8#UvtJgv4wyia}6@x(v6#A~CrLF<7_&n<#_$ih)*Q5?kYc8ogh$Wwo|t2g zD>}Hrr5^Oh>JOCeOzKnr=9ne^pz}J@`>nO$GYxz;z*{WhaP$h$>tDnm{r-UW|HCz?x diff --git a/app/src/main/res/drawable-xhdpi/ic_view_list_white_24dp.png b/app/src/main/res/drawable-xhdpi/ic_view_list_white_24dp.png deleted file mode 100644 index 8ce8a806c4f9c9bc791d7122365de2a6a37bbb0e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 117 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA0wn)(8}a}t8&4Op@B2u{L3FVdQ&MBb@09c476951J diff --git a/app/src/main/res/drawable-xhdpi/ic_view_module_white_24dp.png b/app/src/main/res/drawable-xhdpi/ic_view_module_white_24dp.png deleted file mode 100644 index 89980e2620249af35757014a33be50f23fe85882..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 115 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA0wn)(8}a}tD^C~4kcwMxuNZOxC72KV`G5Hv z^IR?0mhR|j(JCwd>}6nR;CwJ`x*SMtgXvdS28IK(m>3%79$?(sdgPjuh4O!(41=eu KpUXO@geCyl&?8|0 diff --git a/app/src/main/res/drawable-xxhdpi/ic_view_list_white_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_view_list_white_24dp.png deleted file mode 100644 index 6082dad61711ad208e576b363ddbf4f0b396caba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 144 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY0wn)GsXhaw!aZFaLn>~)y|$5)!GMG1!2SA6 zV@D=2#)FqHJ>xp+pBl!_0R|bmFT&nuZf^jCe~mTO9}iDu1c6R@hiOtEB_4kS>><(( aw`v*8Zar%^?y3P~)y|z%0!GMG1;QRfV zmmEV_8d~)y}pr?!GOc{;Qs%Y z(pp$lnhI{+ic#JZQkD-?g9Pdr^FCKymqmy)R5mCvUpTT)04~&^7M8*=>xMWJT;#%$ gE*>}s$Vjk%!0>|M(xD^XWz#_7p00i_>zopr0Mmym!vFvP diff --git a/app/src/main/res/drawable-xxxhdpi/ic_view_module_white_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_view_module_white_24dp.png deleted file mode 100644 index 02cd1b32145ee129e393340d21f1514af93b4ebe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 171 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD0wg^q?%xcgiacE$Ln>~)y|Iv&!GVM2;OqUF z84u4+c3{&<<4Fp>xt9^B1_6GsR?J;ljo?FA4U!E;> - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/activity_edit_categories.xml b/app/src/main/res/layout/activity_edit_categories.xml index c709d07735..564865341f 100644 --- a/app/src/main/res/layout/activity_edit_categories.xml +++ b/app/src/main/res/layout/activity_edit_categories.xml @@ -23,7 +23,6 @@ android:layout_gravity="bottom|right" android:layout_margin="@dimen/fab_margin" android:src="@drawable/ic_action_add_18dp" - app:backgroundTint="@color/colorPrimary" app:layout_anchor="@id/categories_list" app:layout_anchorGravity="bottom|right|end" app:layout_behavior="eu.kanade.tachiyomi.ui.base.fab.ScrollAwareFABBehavior"/> diff --git a/app/src/main/res/layout/fragment_catalogue.xml b/app/src/main/res/layout/fragment_catalogue.xml index 38956c3f0f..ad7b10cd24 100644 --- a/app/src/main/res/layout/fragment_catalogue.xml +++ b/app/src/main/res/layout/fragment_catalogue.xml @@ -11,28 +11,17 @@ android:id="@+id/progress" style="?android:attr/progressBarStyleLarge" android:layout_width="wrap_content" - android:layout_height="match_parent" + android:layout_height="fill_parent" android:layout_gravity="center_vertical|center_horizontal" android:visibility="gone"/> - - - - - - - + android:columnWidth="140dp" + tools:listitem="@layout/item_catalogue" /> + tools:listitem="@layout/item_catalogue" /> \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_manga_info.xml b/app/src/main/res/layout/fragment_manga_info.xml index f5eaeabf15..2631044ba0 100644 --- a/app/src/main/res/layout/fragment_manga_info.xml +++ b/app/src/main/res/layout/fragment_manga_info.xml @@ -154,31 +154,7 @@ android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignBaseline="@id/manga_status_label" - android:layout_toRightOf="@id/manga_status_label" - android:ellipsize="end" - android:focusable="false" - android:focusableInTouchMode="false" - android:maxLines="1" - android:singleLine="true" /> - - - - diff --git a/app/src/main/res/layout/item_catalogue_grid.xml b/app/src/main/res/layout/item_catalogue.xml similarity index 52% rename from app/src/main/res/layout/item_catalogue_grid.xml rename to app/src/main/res/layout/item_catalogue.xml index 9836b21f71..a4197e5aaa 100644 --- a/app/src/main/res/layout/item_catalogue_grid.xml +++ b/app/src/main/res/layout/item_catalogue.xml @@ -12,27 +12,13 @@ android:layout_height="wrap_content" android:background="@drawable/card_background"> - - - - - - - + android:background="@color/white" + tools:background="@color/md_red_100" + tools:src="@mipmap/ic_launcher"/> - + android:layout_alignBottom="@+id/thumbnail" + android:background="@color/manga_cover_title_background"> + + + + diff --git a/app/src/main/res/layout/item_catalogue_list.xml b/app/src/main/res/layout/item_catalogue_list.xml deleted file mode 100644 index 409714fe62..0000000000 --- a/app/src/main/res/layout/item_catalogue_list.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/item_chapter.xml b/app/src/main/res/layout/item_chapter.xml index 4ceac37b00..6c873cbbb4 100644 --- a/app/src/main/res/layout/item_chapter.xml +++ b/app/src/main/res/layout/item_chapter.xml @@ -66,7 +66,7 @@ android:layout_alignParentTop="true" android:layout_alignWithParentIfMissing="true" android:layout_marginRight="30dp" - android:ellipsize="middle" + android:ellipsize="end" android:gravity="center_vertical" android:maxLines="1" android:textSize="17sp" diff --git a/app/src/main/res/layout/item_pager_reader.xml b/app/src/main/res/layout/item_pager_reader.xml index 4fefdc9b19..6813bcb2de 100644 --- a/app/src/main/res/layout/item_pager_reader.xml +++ b/app/src/main/res/layout/item_pager_reader.xml @@ -30,8 +30,6 @@ - -