Allow to share images when reading online. Move chapter cache to external cache dir. Dependency updates.

This commit is contained in:
len 2016-11-29 21:37:35 +01:00
parent 86b8712dd1
commit d30c019b89
12 changed files with 51 additions and 71 deletions

View File

@ -38,7 +38,7 @@ android {
minSdkVersion 16 minSdkVersion 16
targetSdkVersion 25 targetSdkVersion 25
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
versionCode 14 versionCode 15
versionName "0.3.2" versionName "0.3.2"
buildConfigField "String", "COMMIT_COUNT", "\"${getCommitCount()}\"" buildConfigField "String", "COMMIT_COUNT", "\"${getCommitCount()}\""
@ -112,12 +112,6 @@ dependencies {
compile 'com.android.support:multidex:1.0.1' 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 // ReactiveX
compile 'io.reactivex:rxandroid:1.2.1' compile 'io.reactivex:rxandroid:1.2.1'
compile 'io.reactivex:rxjava:1.2.3' compile 'io.reactivex:rxjava:1.2.3'
@ -145,12 +139,17 @@ dependencies {
// JavaScript engine // JavaScript engine
compile 'com.squareup.duktape:duktape-android:1.1.0' compile 'com.squareup.duktape:duktape-android:1.1.0'
// Disk cache // Disk
compile 'com.jakewharton:disklrucache:2.0.2' compile 'com.jakewharton:disklrucache:2.0.2'
compile 'com.github.seven332:unifile:1.0.0'
// HTML parser // HTML parser
compile 'org.jsoup:jsoup:1.10.1' 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 // Changelog
compile 'com.github.gabrielemariotti.changeloglib:changelog:2.1.0' compile 'com.github.gabrielemariotti.changeloglib:changelog:2.1.0'

View File

@ -2,8 +2,8 @@ package eu.kanade.tachiyomi.data.cache
import android.content.Context import android.content.Context
import android.text.format.Formatter import android.text.format.Formatter
import com.github.salomonbrys.kotson.fromJson
import com.google.gson.Gson import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.jakewharton.disklrucache.DiskLruCache import com.jakewharton.disklrucache.DiskLruCache
import eu.kanade.tachiyomi.data.source.model.Page import eu.kanade.tachiyomi.data.source.model.Page
import eu.kanade.tachiyomi.util.DiskUtil import eu.kanade.tachiyomi.util.DiskUtil
@ -11,9 +11,9 @@ import eu.kanade.tachiyomi.util.saveTo
import okhttp3.Response import okhttp3.Response
import okio.Okio import okio.Okio
import rx.Observable import rx.Observable
import uy.kohesive.injekt.injectLazy
import java.io.File import java.io.File
import java.io.IOException import java.io.IOException
import java.lang.reflect.Type
/** /**
* Class used to create chapter cache * Class used to create chapter cache
@ -26,15 +26,6 @@ import java.lang.reflect.Type
*/ */
class ChapterCache(private val context: Context) { 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<List<Page>>() {}.type
companion object { companion object {
/** Name of cache directory. */ /** Name of cache directory. */
const val PARAMETER_CACHE_DIRECTORY = "chapter_disk_cache" 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 const val PARAMETER_CACHE_SIZE = 75L * 1024 * 1024
} }
init { /** Google Json class used for parsing JSON files. */
// Open cache in default cache directory. private val gson: Gson by injectLazy()
diskCache = DiskLruCache.open(
File(context.cacheDir, PARAMETER_CACHE_DIRECTORY), /** Cache class used for cache management. */
PARAMETER_APP_VERSION, private val diskCache = DiskLruCache.open(
PARAMETER_VALUE_COUNT, File(context.externalCacheDir, PARAMETER_CACHE_DIRECTORY),
PARAMETER_CACHE_SIZE) PARAMETER_APP_VERSION,
} PARAMETER_VALUE_COUNT,
PARAMETER_CACHE_SIZE)
/** /**
* Returns directory of cache. * Returns directory of cache.
* @return directory of cache.
*/ */
val cacheDir: File val cacheDir: File
get() = diskCache.directory get() = diskCache.directory
/** /**
* Returns real size of directory. * Returns real size of directory.
* @return real size of directory.
*/ */
private val realSize: Long private val realSize: Long
get() = DiskUtil.getDirectorySize(cacheDir) get() = DiskUtil.getDirectorySize(cacheDir)
/** /**
* Returns real size of directory in human readable format. * Returns real size of directory in human readable format.
* @return real size of directory.
*/ */
val readableSize: String val readableSize: String
get() = Formatter.formatFileSize(context, realSize) get() = Formatter.formatFileSize(context, realSize)
/** /**
* Remove file from cache. * Remove file from cache.
*
* @param file name of file "md5.0". * @param file name of file "md5.0".
* @return status of deletion for the file. * @return status of deletion for the file.
*/ */
@ -101,6 +91,7 @@ class ChapterCache(private val context: Context) {
/** /**
* Get page list from cache. * Get page list from cache.
*
* @param chapterUrl the url of the chapter. * @param chapterUrl the url of the chapter.
* @return an observable of the list of pages. * @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 // Convert JSON string to list of objects. Throws an exception if snapshot is null
diskCache.get(key).use { diskCache.get(key).use {
gson.fromJson(it.getString(0), pageListCollection) gson.fromJson<List<Page>>(it.getString(0))
} }
} }
} }
/** /**
* Add page list to disk cache. * Add page list to disk cache.
*
* @param chapterUrl the url of the chapter. * @param chapterUrl the url of the chapter.
* @param pages list of pages. * @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. * @param imageUrl url of image.
* @return true if in cache otherwise false. * @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. * @param imageUrl url of image.
* @return path of image. * @return path of image.
*/ */
fun getImagePath(imageUrl: String): File? { fun getImageFile(imageUrl: String): File {
try { // Get file from md5 key.
// Get file from md5 key. val imageName = DiskUtil.hashKeyForDisk(imageUrl) + ".0"
val imageName = DiskUtil.hashKeyForDisk(imageUrl) + ".0" return File(diskCache.directory, imageName)
return File(diskCache.directory, imageName)
} catch (e: IOException) {
return null
}
} }
/** /**
* Add image to cache. * Add image to cache.
*
* @param imageUrl url of image. * @param imageUrl url of image.
* @param response http response from page. * @param response http response from page.
* @throws IOException image error. * @throws IOException image error.

View File

@ -41,8 +41,8 @@ class DownloadProvider(private val context: Context) {
*/ */
internal fun getMangaDir(source: Source, manga: Manga): UniFile { internal fun getMangaDir(source: Source, manga: Manga): UniFile {
return downloadsDir return downloadsDir
.subFile(getSourceDirName(source))!! .createDirectory(getSourceDirName(source))
.subFile(getMangaDirName(manga))!! .createDirectory(getMangaDirName(manga))
} }
/** /**

View File

@ -247,7 +247,7 @@ class Downloader(private val context: Context, private val provider: DownloadPro
private fun downloadChapter(download: Download): Observable<Download> { private fun downloadChapter(download: Download): Observable<Download> {
val chapterDirname = provider.getChapterDirName(download.chapter) val chapterDirname = provider.getChapterDirName(download.chapter)
val mangaDir = provider.getMangaDir(download.source, download.manga) 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) { val pageListObservable = if (download.pages == null) {
// Pull page list from network and add them to download object // 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 return pageListObservable
.doOnNext { pages -> .doOnNext { pages ->
tmpDir.ensureDir()
// Delete all temporary (unfinished) files // Delete all temporary (unfinished) files
tmpDir.listFiles() tmpDir.listFiles()
?.filter { it.name!!.endsWith(".tmp") } ?.filter { it.name!!.endsWith(".tmp") }

View File

@ -417,7 +417,7 @@ abstract class OnlineSource() : Source {
} }
} }
.doOnNext { .doOnNext {
page.uri = Uri.fromFile(chapterCache.getImagePath(imageUrl)) page.uri = Uri.fromFile(chapterCache.getImageFile(imageUrl))
page.status = Page.READY page.status = Page.READY
} }
.doOnError { page.status = Page.ERROR } .doOnError { page.status = Page.ERROR }

View File

@ -14,23 +14,29 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.data.updater.UpdateCheckerJob import eu.kanade.tachiyomi.data.updater.UpdateCheckerJob
import it.gmariotti.changelibs.library.view.ChangeLogRecyclerView import it.gmariotti.changelibs.library.view.ChangeLogRecyclerView
import java.io.File
class ChangelogDialogFragment : DialogFragment() { class ChangelogDialogFragment : DialogFragment() {
companion object { companion object {
fun show(preferences: PreferencesHelper, fragmentManager: FragmentManager) { fun show(context: Context, preferences: PreferencesHelper, fm: FragmentManager) {
val oldVersion = preferences.lastVersionCode().getOrDefault() val oldVersion = preferences.lastVersionCode().getOrDefault()
if (oldVersion < BuildConfig.VERSION_CODE) { if (oldVersion < BuildConfig.VERSION_CODE) {
preferences.lastVersionCode().set(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) { if (oldVersion < 14) {
// Restore jobs after upgrading to evernote's job scheduler.
if (BuildConfig.INCLUDE_UPDATER && preferences.automaticUpdates()) { if (BuildConfig.INCLUDE_UPDATER && preferences.automaticUpdates()) {
UpdateCheckerJob.setupTask() UpdateCheckerJob.setupTask()
} }
LibraryUpdateJob.setupTask() LibraryUpdateJob.setupTask()
} }
if (oldVersion < 15) {
// Delete internal chapter cache dir.
File(context.cacheDir, "chapter_disk_cache").deleteRecursively()
}
} }
} }
} }

View File

@ -11,8 +11,8 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.ui.backup.BackupFragment import eu.kanade.tachiyomi.ui.backup.BackupFragment
import eu.kanade.tachiyomi.ui.base.activity.BaseActivity import eu.kanade.tachiyomi.ui.base.activity.BaseActivity
import eu.kanade.tachiyomi.ui.catalogue.CatalogueFragment 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.download.DownloadFragment
import eu.kanade.tachiyomi.ui.latest_updates.LatestUpdatesFragment
import eu.kanade.tachiyomi.ui.library.LibraryFragment import eu.kanade.tachiyomi.ui.library.LibraryFragment
import eu.kanade.tachiyomi.ui.recent_updates.RecentChaptersFragment import eu.kanade.tachiyomi.ui.recent_updates.RecentChaptersFragment
import eu.kanade.tachiyomi.ui.recently_read.RecentlyReadFragment import eu.kanade.tachiyomi.ui.recently_read.RecentlyReadFragment
@ -79,7 +79,7 @@ class MainActivity : BaseActivity() {
setSelectedDrawerItem(startScreenId) setSelectedDrawerItem(startScreenId)
// Show changelog if needed // Show changelog if needed
ChangelogDialogFragment.show(preferences, supportFragmentManager) ChangelogDialogFragment.show(this, preferences, supportFragmentManager)
} }
} }

View File

@ -480,7 +480,7 @@ class ReaderActivity : BaseRxActivity<ReaderPresenter>() {
val intent = Intent(Intent.ACTION_SEND).apply { val intent = Intent(Intent.ACTION_SEND).apply {
putExtra(Intent.EXTRA_STREAM, page.uri) 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/*" type = "image/*"
} }
startActivity(Intent.createChooser(intent, getString(R.string.action_share))) startActivity(Intent.createChooser(intent, getString(R.string.action_share)))

View File

@ -2,7 +2,6 @@ package eu.kanade.tachiyomi.ui.reader.viewer.pager
import android.content.Context import android.content.Context
import android.graphics.PointF import android.graphics.PointF
import android.os.Build
import android.util.AttributeSet import android.util.AttributeSet
import android.view.MotionEvent import android.view.MotionEvent
import android.view.View import android.view.View
@ -24,7 +23,6 @@ import rx.Subscription
import rx.android.schedulers.AndroidSchedulers import rx.android.schedulers.AndroidSchedulers
import rx.subjects.PublishSubject import rx.subjects.PublishSubject
import rx.subjects.SerializedSubject import rx.subjects.SerializedSubject
import java.io.File
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
class PageView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) class PageView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null)
@ -216,12 +214,7 @@ class PageView @JvmOverloads constructor(context: Context, attrs: AttributeSet?
return return
} }
val file = if (Build.VERSION.SDK_INT < 21 || UniFile.isFileUri(uri)) { val file = UniFile.fromUri(context, uri)
UniFile.fromFile(File(uri.path))
} else {
// Tree uri returns the root folder
UniFile.fromSingleUri(context, uri)
}!!
if (!file.exists()) { if (!file.exists()) {
page.status = Page.ERROR page.status = Page.ERROR
return return

View File

@ -1,6 +1,5 @@
package eu.kanade.tachiyomi.ui.reader.viewer.webtoon package eu.kanade.tachiyomi.ui.reader.viewer.webtoon
import android.os.Build
import android.support.v7.widget.RecyclerView import android.support.v7.widget.RecyclerView
import android.view.MotionEvent import android.view.MotionEvent
import android.view.View import android.view.View
@ -20,7 +19,6 @@ import rx.Subscription
import rx.android.schedulers.AndroidSchedulers import rx.android.schedulers.AndroidSchedulers
import rx.subjects.PublishSubject import rx.subjects.PublishSubject
import rx.subjects.SerializedSubject import rx.subjects.SerializedSubject
import java.io.File
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
/** /**
@ -250,12 +248,7 @@ class WebtoonHolder(private val view: View, private val adapter: WebtoonAdapter)
return return
} }
val file = if (Build.VERSION.SDK_INT < 21 || UniFile.isFileUri(uri)) { val file = UniFile.fromUri(context, uri)
UniFile.fromFile(File(uri.path))
} else {
// Tree uri returns the root folder
UniFile.fromSingleUri(context, uri)
}!!
if (!file.exists()) { if (!file.exists()) {
page?.status = Page.ERROR page?.status = Page.ERROR
return return

View File

@ -116,7 +116,7 @@ class SettingsDownloadsFragment : SettingsFragment() {
@Suppress("NewApi") @Suppress("NewApi")
context.contentResolver.takePersistableUriPermission(uri, flags) context.contentResolver.takePersistableUriPermission(uri, flags)
val file = UniFile.fromTreeUri(context, uri) val file = UniFile.fromUri(context, uri)
preferences.downloadsDirectory().set(file.uri.toString()) preferences.downloadsDirectory().set(file.uri.toString())
} }
} }

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<paths> <paths>
<external-path name="pictures" path="Pictures" /> <external-path name="ext_files" path="." />
</paths> </paths>