Minor changes

This commit is contained in:
len 2016-04-20 19:47:29 +02:00
parent a30705f197
commit bd8b9febd2
10 changed files with 112 additions and 128 deletions

View File

@ -7,6 +7,7 @@ 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.DiskUtils import eu.kanade.tachiyomi.util.DiskUtils
import eu.kanade.tachiyomi.util.saveTo
import okhttp3.Response import okhttp3.Response
import okio.Okio import okio.Okio
import rx.Observable import rx.Observable
@ -194,10 +195,7 @@ class ChapterCache(private val context: Context) {
editor = diskCache.edit(key) ?: throw IOException("Unable to edit key") editor = diskCache.edit(key) ?: throw IOException("Unable to edit key")
// Get OutputStream and write image with Okio. // Get OutputStream and write image with Okio.
Okio.buffer(Okio.sink(editor.newOutputStream(0))).use { response.body().source().saveTo(editor.newOutputStream(0))
it.writeAll(response.body().source())
it.flush()
}
diskCache.flush() diskCache.flush()
editor.commit() editor.commit()

View File

@ -33,7 +33,7 @@ class CoverCache(private val context: Context) {
* @param headers headers included in Glide request. * @param headers headers included in Glide request.
* @param onReady function to call when the image is ready * @param onReady function to call when the image is ready
*/ */
fun save(thumbnailUrl: String?, headers: LazyHeaders, onReady: ((File) -> Unit)? = null) { fun save(thumbnailUrl: String?, headers: LazyHeaders?, onReady: ((File) -> Unit)? = null) {
// Check if url is empty. // Check if url is empty.
if (thumbnailUrl.isNullOrEmpty()) if (thumbnailUrl.isNullOrEmpty())
return return
@ -62,7 +62,7 @@ class CoverCache(private val context: Context) {
* @param headers headers included in Glide request. * @param headers headers included in Glide request.
* @param onReady function to call when the image is ready * @param onReady function to call when the image is ready
*/ */
fun saveOrLoadFromCache(thumbnailUrl: String?, headers: LazyHeaders, onReady: ((File) -> Unit)?) { fun saveOrLoadFromCache(thumbnailUrl: String?, headers: LazyHeaders?, onReady: ((File) -> Unit)?) {
// Check if url is empty. // Check if url is empty.
if (thumbnailUrl.isNullOrEmpty()) if (thumbnailUrl.isNullOrEmpty())
return return

View File

@ -95,6 +95,13 @@ public class Manga implements Serializable {
return m; return m;
} }
public static Manga create(String pathUrl, int source) {
Manga m = new Manga();
m.url = pathUrl;
m.source = source;
return m;
}
public void setUrl(String url) { public void setUrl(String url) {
this.url = UrlUtil.getPath(url); this.url = UrlUtil.getPath(url);
} }

View File

@ -15,10 +15,7 @@ import eu.kanade.tachiyomi.data.source.SourceManager
import eu.kanade.tachiyomi.data.source.base.Source import eu.kanade.tachiyomi.data.source.base.Source
import eu.kanade.tachiyomi.data.source.model.Page import eu.kanade.tachiyomi.data.source.model.Page
import eu.kanade.tachiyomi.event.DownloadChaptersEvent import eu.kanade.tachiyomi.event.DownloadChaptersEvent
import eu.kanade.tachiyomi.util.DiskUtils import eu.kanade.tachiyomi.util.*
import eu.kanade.tachiyomi.util.DynamicConcurrentMergeOperator
import eu.kanade.tachiyomi.util.UrlUtil
import eu.kanade.tachiyomi.util.toast
import rx.Observable import rx.Observable
import rx.Subscription import rx.Subscription
import rx.android.schedulers.AndroidSchedulers import rx.android.schedulers.AndroidSchedulers
@ -27,9 +24,7 @@ import rx.subjects.BehaviorSubject
import rx.subjects.PublishSubject import rx.subjects.PublishSubject
import timber.log.Timber import timber.log.Timber
import java.io.File import java.io.File
import java.io.FileOutputStream
import java.io.FileReader import java.io.FileReader
import java.io.IOException
import java.util.* import java.util.*
class DownloadManager(private val context: Context, private val sourceManager: SourceManager, private val preferences: PreferencesHelper) { class DownloadManager(private val context: Context, private val sourceManager: SourceManager, private val preferences: PreferencesHelper) {
@ -176,7 +171,7 @@ class DownloadManager(private val context: Context, private val sourceManager: S
// Or if the page list already exists, start from the file // Or if the page list already exists, start from the file
Observable.just(download.pages) Observable.just(download.pages)
return Observable.defer<Download> { pageListObservable return Observable.defer { pageListObservable
.doOnNext { pages -> .doOnNext { pages ->
download.downloadedImages = 0 download.downloadedImages = 0
download.status = Download.DOWNLOADING download.status = Download.DOWNLOADING
@ -232,14 +227,11 @@ class DownloadManager(private val context: Context, private val sourceManager: S
private fun downloadImage(page: Page, source: Source, directory: File, filename: String): Observable<Page> { private fun downloadImage(page: Page, source: Source, directory: File, filename: String): Observable<Page> {
page.status = Page.DOWNLOAD_IMAGE page.status = Page.DOWNLOAD_IMAGE
return source.getImageProgressResponse(page) return source.getImageProgressResponse(page)
.flatMap({ resp -> .flatMap {
try { it.body().source().saveTo(File(directory, filename))
DiskUtils.saveBufferedSourceToDirectory(resp.body().source(), directory, filename)
} finally {
resp.body().close()
}
Observable.just(page) Observable.just(page)
}).retry(2) }
.retry(2)
} }
// Public method to get the image from the filesystem. It does NOT provide any way to download the image // Public method to get the image from the filesystem. It does NOT provide any way to download the image
@ -311,26 +303,14 @@ class DownloadManager(private val context: Context, private val sourceManager: S
val chapterDir = getAbsoluteChapterDirectory(source, manga, chapter) val chapterDir = getAbsoluteChapterDirectory(source, manga, chapter)
val pagesFile = File(chapterDir, PAGE_LIST_FILE) val pagesFile = File(chapterDir, PAGE_LIST_FILE)
var reader: JsonReader? = null return try {
try { JsonReader(FileReader(pagesFile)).use {
if (pagesFile.exists()) { val collectionType = object : TypeToken<List<Page>>() {}.type
reader = JsonReader(FileReader(pagesFile.absolutePath)) gson.fromJson(it, collectionType)
val collectionType = object : TypeToken<List<Page>>() {
}.type
return gson.fromJson<List<Page>>(reader, collectionType)
} }
} catch (e: Exception) { } catch (e: Exception) {
Timber.e(e.cause, e.message) null
} finally {
if (reader != null) try {
reader.close()
} catch (e: IOException) {
/* Do nothing */
}
} }
return null
} }
// Shortcut for the method above // Shortcut for the method above
@ -343,20 +323,13 @@ class DownloadManager(private val context: Context, private val sourceManager: S
val chapterDir = getAbsoluteChapterDirectory(source, manga, chapter) val chapterDir = getAbsoluteChapterDirectory(source, manga, chapter)
val pagesFile = File(chapterDir, PAGE_LIST_FILE) val pagesFile = File(chapterDir, PAGE_LIST_FILE)
var out: FileOutputStream? = null pagesFile.outputStream().use {
try { try {
out = FileOutputStream(pagesFile) it.write(gson.toJson(pages).toByteArray())
out.write(gson.toJson(pages).toByteArray()) it.flush()
out.flush() } catch (e: Exception) {
} catch (e: IOException) { Timber.e(e, e.message)
Timber.e(e.cause, e.message)
} finally {
if (out != null) try {
out.close()
} catch (e: IOException) {
/* Do nothing */
} }
} }
} }

View File

@ -10,10 +10,13 @@ import java.net.CookieStore
class NetworkHelper(context: Context) { class NetworkHelper(context: Context) {
private val client: OkHttpClient private val cacheDir = File(context.cacheDir, "network_cache")
private val forceCacheClient: OkHttpClient
private val cookieManager: CookieManager private val cacheSize = 5L * 1024 * 1024 // 5 MiB
private val cookieManager = CookieManager().apply {
setCookiePolicy(CookiePolicy.ACCEPT_ALL)
}
private val forceCacheInterceptor = { chain: Interceptor.Chain -> private val forceCacheInterceptor = { chain: Interceptor.Chain ->
val originalResponse = chain.proceed(chain.request()) val originalResponse = chain.proceed(chain.request())
@ -23,24 +26,17 @@ class NetworkHelper(context: Context) {
.build() .build()
} }
private val cacheSize = 5L * 1024 * 1024 // 5 MiB private val client = OkHttpClient.Builder()
private val cacheDir = "network_cache" .cookieJar(JavaNetCookieJar(cookieManager))
.cache(Cache(cacheDir, cacheSize))
.build()
init { private val forceCacheClient = client.newBuilder()
val cacheDir = File(context.cacheDir, cacheDir) .addNetworkInterceptor(forceCacheInterceptor)
.build()
cookieManager = CookieManager() val cookies: CookieStore
cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL) get() = cookieManager.cookieStore
client = OkHttpClient.Builder()
.cookieJar(JavaNetCookieJar(cookieManager))
.cache(Cache(cacheDir, cacheSize))
.build()
forceCacheClient = client.newBuilder()
.addNetworkInterceptor(forceCacheInterceptor)
.build()
}
@JvmOverloads @JvmOverloads
fun request(request: Request, forceCache: Boolean = false): Observable<Response> { fun request(request: Request, forceCache: Boolean = false): Observable<Response> {
@ -59,22 +55,22 @@ class NetworkHelper(context: Context) {
} }
fun requestBodyProgress(request: Request, listener: ProgressListener): Observable<Response> { fun requestBodyProgress(request: Request, listener: ProgressListener): Observable<Response> {
return Observable.fromCallable { return Observable.fromCallable { requestBodyProgressBlocking(request, listener) }
val progressClient = client.newBuilder() }
.cache(null)
.addNetworkInterceptor { chain -> fun requestBodyProgressBlocking(request: Request, listener: ProgressListener): Response {
val originalResponse = chain.proceed(chain.request()) val progressClient = client.newBuilder()
originalResponse.newBuilder() .cache(null)
.body(ProgressResponseBody(originalResponse.body(), listener)) .addNetworkInterceptor { chain ->
.build() val originalResponse = chain.proceed(chain.request())
} originalResponse.newBuilder()
.build() .body(ProgressResponseBody(originalResponse.body(), listener))
.build()
progressClient.newCall(request).execute() }
} .build()
return progressClient.newCall(request).execute()
} }
val cookies: CookieStore
get() = cookieManager.cookieStore
} }

View File

@ -1,8 +1,8 @@
package eu.kanade.tachiyomi.data.source package eu.kanade.tachiyomi.data.source
class Language(val lang: String, val code: String) class Language(val code: String, val lang: String)
val EN = Language("English", "EN") val EN = Language("EN", "English")
val RU = Language("Russian", "RU") val RU = Language("RU", "Russian")
fun getLanguages(): List<Language> = listOf(EN, RU) fun getLanguages() = listOf(EN, RU)

View File

@ -1,6 +1,5 @@
package eu.kanade.tachiyomi.data.source.model; package eu.kanade.tachiyomi.data.source.model;
import java.io.Serializable;
import java.util.List; import java.util.List;
import eu.kanade.tachiyomi.data.database.models.Chapter; import eu.kanade.tachiyomi.data.database.models.Chapter;
@ -25,6 +24,14 @@ public class Page implements ProgressListener {
public static final int READY = 3; public static final int READY = 3;
public static final int ERROR = 4; public static final int ERROR = 4;
public Page(int pageNumber, String url) {
this(pageNumber, url, null, null);
}
public Page(int pageNumber, String url, String imageUrl) {
this(pageNumber, url, imageUrl, null);
}
public Page(int pageNumber, String url, String imageUrl, String imagePath) { public Page(int pageNumber, String url, String imageUrl, String imagePath) {
this.pageNumber = pageNumber; this.pageNumber = pageNumber;
this.url = url; this.url = url;
@ -32,10 +39,6 @@ public class Page implements ProgressListener {
this.imagePath = imagePath; this.imagePath = imagePath;
} }
public Page(int pageNumber, String url) {
this(pageNumber, url, null, null);
}
public int getPageNumber() { public int getPageNumber() {
return pageNumber; return pageNumber;
} }

View File

@ -5,11 +5,6 @@ import java.io.IOException;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import okhttp3.internal.Util;
import okio.BufferedSink;
import okio.BufferedSource;
import okio.Okio;
public final class DiskUtils { public final class DiskUtils {
private DiskUtils() { private DiskUtils() {
@ -40,33 +35,6 @@ public final class DiskUtils {
return sb.toString(); return sb.toString();
} }
public static File saveBufferedSourceToDirectory(BufferedSource bufferedSource, File directory, String name) throws IOException {
createDirectory(directory);
File writeFile = new File(directory, name);
if (writeFile.exists()) {
if (writeFile.delete()) {
writeFile = new File(directory, name);
} else {
throw new IOException("Failed Deleting Existing File for Overwrite");
}
}
BufferedSink bufferedSink = null;
try {
bufferedSink = Okio.buffer(Okio.sink(writeFile));
bufferedSink.writeAll(bufferedSource);
Util.closeQuietly(bufferedSink);
} catch (Exception e) {
Util.closeQuietly(bufferedSink);
//noinspection ResultOfMethodCallIgnored
writeFile.delete();
throw new IOException("Unable to save image");
}
return writeFile;
}
public static void deleteFiles(File inputFile) { public static void deleteFiles(File inputFile) {
if (inputFile.isDirectory()) { if (inputFile.isDirectory()) {
for (File childFile : inputFile.listFiles()) { for (File childFile : inputFile.listFiles()) {

View File

@ -0,0 +1,39 @@
package eu.kanade.tachiyomi.util
import okio.BufferedSource
import okio.Okio
import java.io.File
import java.io.OutputStream
/**
* Saves the given source to a file and closes it. Directories will be created if needed.
*
* @param file the file where the source is copied.
*/
fun BufferedSource.saveTo(file: File) {
try {
// Create parent dirs if needed
file.parentFile.mkdirs()
// Copy to destination
saveTo(file.outputStream())
} catch (e: Exception) {
close()
file.delete()
throw e
}
}
/**
* Saves the given source to an output stream and closes both resources.
*
* @param stream the stream where the source is copied.
*/
fun BufferedSource.saveTo(stream: OutputStream) {
use { input ->
Okio.buffer(Okio.sink(stream)).use {
it.writeAll(input)
it.flush()
}
}
}

View File

@ -11,8 +11,8 @@ import com.afollestad.materialdialogs.MaterialDialog
import com.dd.processbutton.iml.ActionProcessButton import com.dd.processbutton.iml.ActionProcessButton
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.ui.setting.SettingsActivity
import eu.kanade.tachiyomi.ui.base.listener.SimpleTextWatcher import eu.kanade.tachiyomi.ui.base.listener.SimpleTextWatcher
import eu.kanade.tachiyomi.ui.setting.SettingsActivity
import kotlinx.android.synthetic.main.pref_account_login.view.* import kotlinx.android.synthetic.main.pref_account_login.view.*
import rx.Subscription import rx.Subscription
@ -30,7 +30,7 @@ abstract class LoginDialogPreference : DialogFragment() {
val dialog = MaterialDialog.Builder(activity) val dialog = MaterialDialog.Builder(activity)
.customView(R.layout.pref_account_login, false) .customView(R.layout.pref_account_login, false)
.negativeText(android.R.string.cancel) .negativeText(android.R.string.cancel)
.build(); .build()
onViewCreated(dialog.view, savedState) onViewCreated(dialog.view, savedState)