From d30c019b89d91a80dfb05a59a6680eea8c8a976f Mon Sep 17 00:00:00 2001 From: len Date: Tue, 29 Nov 2016 21:37:35 +0100 Subject: [PATCH] Allow to share images when reading online. Move chapter cache to external cache dir. Dependency updates. --- app/build.gradle | 15 +++-- .../tachiyomi/data/cache/ChapterCache.kt | 57 ++++++++----------- .../data/download/DownloadProvider.kt | 4 +- .../tachiyomi/data/download/Downloader.kt | 4 +- .../data/source/online/OnlineSource.kt | 2 +- .../ui/main/ChangelogDialogFragment.kt | 12 +++- .../kanade/tachiyomi/ui/main/MainActivity.kt | 4 +- .../tachiyomi/ui/reader/ReaderActivity.kt | 2 +- .../ui/reader/viewer/pager/PageView.kt | 9 +-- .../ui/reader/viewer/webtoon/WebtoonHolder.kt | 9 +-- .../ui/setting/SettingsDownloadsFragment.kt | 2 +- app/src/main/res/xml/provider_paths.xml | 2 +- 12 files changed, 51 insertions(+), 71 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 708148ded7..b796613550 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -38,7 +38,7 @@ android { minSdkVersion 16 targetSdkVersion 25 testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" - versionCode 14 + versionCode 15 versionName "0.3.2" buildConfigField "String", "COMMIT_COUNT", "\"${getCommitCount()}\"" @@ -112,12 +112,6 @@ dependencies { compile 'com.android.support:multidex:1.0.1' - // Job scheduling - compile 'com.evernote:android-job:1.1.3' - compile 'com.google.android.gms:play-services-gcm:9.8.0' - - compile 'com.github.seven332:unifile:0.2.0' - // ReactiveX compile 'io.reactivex:rxandroid:1.2.1' compile 'io.reactivex:rxjava:1.2.3' @@ -145,12 +139,17 @@ dependencies { // JavaScript engine compile 'com.squareup.duktape:duktape-android:1.1.0' - // Disk cache + // Disk compile 'com.jakewharton:disklrucache:2.0.2' + compile 'com.github.seven332:unifile:1.0.0' // HTML parser compile 'org.jsoup:jsoup:1.10.1' + // Job scheduling + compile 'com.evernote:android-job:1.1.3' + compile 'com.google.android.gms:play-services-gcm:10.0.0' + // Changelog compile 'com.github.gabrielemariotti.changeloglib:changelog:2.1.0' diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/cache/ChapterCache.kt b/app/src/main/java/eu/kanade/tachiyomi/data/cache/ChapterCache.kt index 8609097eb4..7314ed10c1 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/cache/ChapterCache.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/cache/ChapterCache.kt @@ -2,8 +2,8 @@ package eu.kanade.tachiyomi.data.cache import android.content.Context import android.text.format.Formatter +import com.github.salomonbrys.kotson.fromJson import com.google.gson.Gson -import com.google.gson.reflect.TypeToken import com.jakewharton.disklrucache.DiskLruCache import eu.kanade.tachiyomi.data.source.model.Page import eu.kanade.tachiyomi.util.DiskUtil @@ -11,9 +11,9 @@ import eu.kanade.tachiyomi.util.saveTo import okhttp3.Response import okio.Okio import rx.Observable +import uy.kohesive.injekt.injectLazy import java.io.File import java.io.IOException -import java.lang.reflect.Type /** * Class used to create chapter cache @@ -26,15 +26,6 @@ import java.lang.reflect.Type */ class ChapterCache(private val context: Context) { - /** Google Json class used for parsing JSON files. */ - private val gson: Gson = Gson() - - /** Cache class used for cache management. */ - private val diskCache: DiskLruCache - - /** Page list collection used for deserializing from JSON. */ - private val pageListCollection: Type = object : TypeToken>() {}.type - companion object { /** Name of cache directory. */ const val PARAMETER_CACHE_DIRECTORY = "chapter_disk_cache" @@ -49,38 +40,37 @@ class ChapterCache(private val context: Context) { const val PARAMETER_CACHE_SIZE = 75L * 1024 * 1024 } - init { - // Open cache in default cache directory. - diskCache = DiskLruCache.open( - File(context.cacheDir, PARAMETER_CACHE_DIRECTORY), - PARAMETER_APP_VERSION, - PARAMETER_VALUE_COUNT, - PARAMETER_CACHE_SIZE) - } + /** Google Json class used for parsing JSON files. */ + private val gson: Gson by injectLazy() + + /** Cache class used for cache management. */ + private val diskCache = DiskLruCache.open( + File(context.externalCacheDir, PARAMETER_CACHE_DIRECTORY), + PARAMETER_APP_VERSION, + PARAMETER_VALUE_COUNT, + PARAMETER_CACHE_SIZE) /** * Returns directory of cache. - * @return directory of cache. */ val cacheDir: File get() = diskCache.directory /** * Returns real size of directory. - * @return real size of directory. */ private val realSize: Long get() = DiskUtil.getDirectorySize(cacheDir) /** * Returns real size of directory in human readable format. - * @return real size of directory. */ val readableSize: String get() = Formatter.formatFileSize(context, realSize) /** * Remove file from cache. + * * @param file name of file "md5.0". * @return status of deletion for the file. */ @@ -101,6 +91,7 @@ class ChapterCache(private val context: Context) { /** * Get page list from cache. + * * @param chapterUrl the url of the chapter. * @return an observable of the list of pages. */ @@ -111,13 +102,14 @@ class ChapterCache(private val context: Context) { // Convert JSON string to list of objects. Throws an exception if snapshot is null diskCache.get(key).use { - gson.fromJson(it.getString(0), pageListCollection) + gson.fromJson>(it.getString(0)) } } } /** * Add page list to disk cache. + * * @param chapterUrl the url of the chapter. * @param pages list of pages. */ @@ -151,7 +143,8 @@ class ChapterCache(private val context: Context) { } /** - * Check if image is in cache. + * Returns true if image is in cache. + * * @param imageUrl url of image. * @return true if in cache otherwise false. */ @@ -164,22 +157,20 @@ class ChapterCache(private val context: Context) { } /** - * Get image path from url. + * Get image file from url. + * * @param imageUrl url of image. * @return path of image. */ - fun getImagePath(imageUrl: String): File? { - try { - // Get file from md5 key. - val imageName = DiskUtil.hashKeyForDisk(imageUrl) + ".0" - return File(diskCache.directory, imageName) - } catch (e: IOException) { - return null - } + fun getImageFile(imageUrl: String): File { + // Get file from md5 key. + val imageName = DiskUtil.hashKeyForDisk(imageUrl) + ".0" + return File(diskCache.directory, imageName) } /** * Add image to cache. + * * @param imageUrl url of image. * @param response http response from page. * @throws IOException image error. diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadProvider.kt b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadProvider.kt index 77c2de04d1..8b7b1f0701 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadProvider.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadProvider.kt @@ -41,8 +41,8 @@ class DownloadProvider(private val context: Context) { */ internal fun getMangaDir(source: Source, manga: Manga): UniFile { return downloadsDir - .subFile(getSourceDirName(source))!! - .subFile(getMangaDirName(manga))!! + .createDirectory(getSourceDirName(source)) + .createDirectory(getMangaDirName(manga)) } /** diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/Downloader.kt b/app/src/main/java/eu/kanade/tachiyomi/data/download/Downloader.kt index eef46535da..d2928eb3da 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/Downloader.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/Downloader.kt @@ -247,7 +247,7 @@ class Downloader(private val context: Context, private val provider: DownloadPro private fun downloadChapter(download: Download): Observable { val chapterDirname = provider.getChapterDirName(download.chapter) val mangaDir = provider.getMangaDir(download.source, download.manga) - val tmpDir = mangaDir.subFile("${chapterDirname}_tmp")!! + val tmpDir = mangaDir.createDirectory("${chapterDirname}_tmp") val pageListObservable = if (download.pages == null) { // Pull page list from network and add them to download object @@ -262,8 +262,6 @@ class Downloader(private val context: Context, private val provider: DownloadPro return pageListObservable .doOnNext { pages -> - tmpDir.ensureDir() - // Delete all temporary (unfinished) files tmpDir.listFiles() ?.filter { it.name!!.endsWith(".tmp") } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/source/online/OnlineSource.kt b/app/src/main/java/eu/kanade/tachiyomi/data/source/online/OnlineSource.kt index 189efba344..71152a0486 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/source/online/OnlineSource.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/source/online/OnlineSource.kt @@ -417,7 +417,7 @@ abstract class OnlineSource() : Source { } } .doOnNext { - page.uri = Uri.fromFile(chapterCache.getImagePath(imageUrl)) + page.uri = Uri.fromFile(chapterCache.getImageFile(imageUrl)) page.status = Page.READY } .doOnError { page.status = Page.ERROR } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/main/ChangelogDialogFragment.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/main/ChangelogDialogFragment.kt index bed71e7e6f..0eeb10bc22 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/main/ChangelogDialogFragment.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/main/ChangelogDialogFragment.kt @@ -14,23 +14,29 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.data.updater.UpdateCheckerJob import it.gmariotti.changelibs.library.view.ChangeLogRecyclerView +import java.io.File class ChangelogDialogFragment : DialogFragment() { companion object { - fun show(preferences: PreferencesHelper, fragmentManager: FragmentManager) { + fun show(context: Context, preferences: PreferencesHelper, fm: FragmentManager) { val oldVersion = preferences.lastVersionCode().getOrDefault() if (oldVersion < BuildConfig.VERSION_CODE) { preferences.lastVersionCode().set(BuildConfig.VERSION_CODE) - ChangelogDialogFragment().show(fragmentManager, "changelog") + ChangelogDialogFragment().show(fm, "changelog") - // FIXME Ugly check to restore jobs. Remove me in a few months :D + // TODO better upgrades management if (oldVersion < 14) { + // Restore jobs after upgrading to evernote's job scheduler. if (BuildConfig.INCLUDE_UPDATER && preferences.automaticUpdates()) { UpdateCheckerJob.setupTask() } LibraryUpdateJob.setupTask() } + if (oldVersion < 15) { + // Delete internal chapter cache dir. + File(context.cacheDir, "chapter_disk_cache").deleteRecursively() + } } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt index 868d7a0ab9..ff269b63b7 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt @@ -11,8 +11,8 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.ui.backup.BackupFragment import eu.kanade.tachiyomi.ui.base.activity.BaseActivity import eu.kanade.tachiyomi.ui.catalogue.CatalogueFragment -import eu.kanade.tachiyomi.ui.latest_updates.LatestUpdatesFragment import eu.kanade.tachiyomi.ui.download.DownloadFragment +import eu.kanade.tachiyomi.ui.latest_updates.LatestUpdatesFragment import eu.kanade.tachiyomi.ui.library.LibraryFragment import eu.kanade.tachiyomi.ui.recent_updates.RecentChaptersFragment import eu.kanade.tachiyomi.ui.recently_read.RecentlyReadFragment @@ -79,7 +79,7 @@ class MainActivity : BaseActivity() { setSelectedDrawerItem(startScreenId) // Show changelog if needed - ChangelogDialogFragment.show(preferences, supportFragmentManager) + ChangelogDialogFragment.show(this, preferences, supportFragmentManager) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt index 46a73383fd..a2980ac4e6 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt @@ -480,7 +480,7 @@ class ReaderActivity : BaseRxActivity() { val intent = Intent(Intent.ACTION_SEND).apply { putExtra(Intent.EXTRA_STREAM, page.uri) - flags = Intent.FLAG_ACTIVITY_NEW_TASK + flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_GRANT_READ_URI_PERMISSION type = "image/*" } startActivity(Intent.createChooser(intent, getString(R.string.action_share))) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PageView.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PageView.kt index 28ce3ac75a..1ffb7f3097 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PageView.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PageView.kt @@ -2,7 +2,6 @@ package eu.kanade.tachiyomi.ui.reader.viewer.pager import android.content.Context import android.graphics.PointF -import android.os.Build import android.util.AttributeSet import android.view.MotionEvent import android.view.View @@ -24,7 +23,6 @@ import rx.Subscription import rx.android.schedulers.AndroidSchedulers import rx.subjects.PublishSubject import rx.subjects.SerializedSubject -import java.io.File import java.util.concurrent.TimeUnit class PageView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) @@ -216,12 +214,7 @@ class PageView @JvmOverloads constructor(context: Context, attrs: AttributeSet? return } - val file = if (Build.VERSION.SDK_INT < 21 || UniFile.isFileUri(uri)) { - UniFile.fromFile(File(uri.path)) - } else { - // Tree uri returns the root folder - UniFile.fromSingleUri(context, uri) - }!! + val file = UniFile.fromUri(context, uri) if (!file.exists()) { page.status = Page.ERROR return diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonHolder.kt index 6a18a6ca98..c06d9d4404 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonHolder.kt @@ -1,6 +1,5 @@ package eu.kanade.tachiyomi.ui.reader.viewer.webtoon -import android.os.Build import android.support.v7.widget.RecyclerView import android.view.MotionEvent import android.view.View @@ -20,7 +19,6 @@ import rx.Subscription import rx.android.schedulers.AndroidSchedulers import rx.subjects.PublishSubject import rx.subjects.SerializedSubject -import java.io.File import java.util.concurrent.TimeUnit /** @@ -250,12 +248,7 @@ class WebtoonHolder(private val view: View, private val adapter: WebtoonAdapter) return } - val file = if (Build.VERSION.SDK_INT < 21 || UniFile.isFileUri(uri)) { - UniFile.fromFile(File(uri.path)) - } else { - // Tree uri returns the root folder - UniFile.fromSingleUri(context, uri) - }!! + val file = UniFile.fromUri(context, uri) if (!file.exists()) { page?.status = Page.ERROR return diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsDownloadsFragment.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsDownloadsFragment.kt index 327478b49a..d3d5b06928 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsDownloadsFragment.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsDownloadsFragment.kt @@ -116,7 +116,7 @@ class SettingsDownloadsFragment : SettingsFragment() { @Suppress("NewApi") context.contentResolver.takePersistableUriPermission(uri, flags) - val file = UniFile.fromTreeUri(context, uri) + val file = UniFile.fromUri(context, uri) preferences.downloadsDirectory().set(file.uri.toString()) } } diff --git a/app/src/main/res/xml/provider_paths.xml b/app/src/main/res/xml/provider_paths.xml index 5817df3bcb..a75a3d1c3a 100644 --- a/app/src/main/res/xml/provider_paths.xml +++ b/app/src/main/res/xml/provider_paths.xml @@ -1,4 +1,4 @@ - + \ No newline at end of file