Fix cbz cover fetcher closing, update Kotlin and other small fixes
This commit is contained in:
@@ -101,7 +101,7 @@ dependencies {
|
|||||||
implementation 'io.insert-koin:koin-android:3.1.2'
|
implementation 'io.insert-koin:koin-android:3.1.2'
|
||||||
implementation 'io.coil-kt:coil-base:1.3.2'
|
implementation 'io.coil-kt:coil-base:1.3.2'
|
||||||
implementation 'com.davemorrissey.labs:subsampling-scale-image-view-androidx:3.10.0'
|
implementation 'com.davemorrissey.labs:subsampling-scale-image-view-androidx:3.10.0'
|
||||||
implementation 'com.github.solkin:disk-lru-cache:1.2'
|
implementation 'com.github.solkin:disk-lru-cache:1.3'
|
||||||
|
|
||||||
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.7'
|
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.7'
|
||||||
|
|
||||||
|
|||||||
@@ -6,17 +6,36 @@ import android.util.AttributeSet
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.appcompat.widget.Toolbar
|
import androidx.appcompat.widget.Toolbar
|
||||||
import androidx.core.view.isGone
|
import androidx.core.view.isGone
|
||||||
|
import com.google.android.material.R
|
||||||
import com.google.android.material.appbar.MaterialToolbar
|
import com.google.android.material.appbar.MaterialToolbar
|
||||||
|
import java.lang.reflect.Field
|
||||||
|
|
||||||
class AnimatedToolbar(context: Context, attrs: AttributeSet?) : MaterialToolbar(context, attrs) {
|
class AnimatedToolbar @JvmOverloads constructor(
|
||||||
companion object {
|
context: Context,
|
||||||
private val navButtonViewField = Toolbar::class.java.getDeclaredField("mNavButtonView")
|
attrs: AttributeSet? = null,
|
||||||
.also { it.isAccessible = true }
|
defStyleAttr: Int = R.attr.toolbarStyle,
|
||||||
}
|
) : MaterialToolbar(context, attrs, defStyleAttr) {
|
||||||
|
|
||||||
|
private var navButtonView: View? = null
|
||||||
|
get() {
|
||||||
|
if (field == null) {
|
||||||
|
runCatching {
|
||||||
|
field = navButtonViewField?.get(this) as? View
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return field
|
||||||
|
}
|
||||||
|
|
||||||
override fun setNavigationIcon(icon: Drawable?) {
|
override fun setNavigationIcon(icon: Drawable?) {
|
||||||
super.setNavigationIcon(icon)
|
super.setNavigationIcon(icon)
|
||||||
|
navButtonView?.isGone = (icon == null)
|
||||||
|
}
|
||||||
|
|
||||||
(navButtonViewField.get(this) as? View)?.isGone = (icon == null)
|
private companion object {
|
||||||
|
|
||||||
|
val navButtonViewField: Field? = runCatching {
|
||||||
|
Toolbar::class.java.getDeclaredField("mNavButtonView")
|
||||||
|
.also { it.isAccessible = true }
|
||||||
|
}.getOrNull()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8,7 +8,7 @@ import org.koitharu.kotatsu.utils.ext.parseHtml
|
|||||||
|
|
||||||
class HenChanRepository(loaderContext: MangaLoaderContext) : ChanRepository(loaderContext) {
|
class HenChanRepository(loaderContext: MangaLoaderContext) : ChanRepository(loaderContext) {
|
||||||
|
|
||||||
override val defaultDomain = "hentaichan.pro"
|
override val defaultDomain = "hentaichan.live"
|
||||||
override val source = MangaSource.HENCHAN
|
override val source = MangaSource.HENCHAN
|
||||||
|
|
||||||
override suspend fun getList(
|
override suspend fun getList(
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import coil.ImageLoader
|
|||||||
import coil.request.ImageRequest
|
import coil.request.ImageRequest
|
||||||
import coil.size.Scale
|
import coil.size.Scale
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
import kotlinx.coroutines.flow.catch
|
import kotlinx.coroutines.flow.catch
|
||||||
import kotlinx.coroutines.flow.flow
|
import kotlinx.coroutines.flow.flow
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
@@ -48,7 +47,7 @@ class DownloadManager(
|
|||||||
androidx.core.R.dimen.compat_notification_large_icon_max_height
|
androidx.core.R.dimen.compat_notification_large_icon_max_height
|
||||||
)
|
)
|
||||||
|
|
||||||
fun downloadManga(manga: Manga, chaptersIds: Set<Long>?, startId: Int): Flow<State> = flow {
|
fun downloadManga(manga: Manga, chaptersIds: Set<Long>?, startId: Int) = flow<State> {
|
||||||
emit(State.Preparing(startId, manga, null))
|
emit(State.Preparing(startId, manga, null))
|
||||||
var cover: Drawable? = null
|
var cover: Drawable? = null
|
||||||
val destination = settings.getStorageDir(context)
|
val destination = settings.getStorageDir(context)
|
||||||
|
|||||||
@@ -20,19 +20,22 @@ class CbzFetcher : Fetcher<Uri> {
|
|||||||
pool: BitmapPool,
|
pool: BitmapPool,
|
||||||
data: Uri,
|
data: Uri,
|
||||||
size: Size,
|
size: Size,
|
||||||
options: Options
|
options: Options,
|
||||||
): FetchResult {
|
): FetchResult {
|
||||||
val zip = ZipFile(data.schemeSpecificPart)
|
val zip = ZipFile(data.schemeSpecificPart)
|
||||||
val entry = zip.getEntry(data.fragment)
|
val entry = zip.getEntry(data.fragment)
|
||||||
val ext = MimeTypeMap.getFileExtensionFromUrl(entry.name)
|
val ext = MimeTypeMap.getFileExtensionFromUrl(entry.name)
|
||||||
return SourceResult(
|
return SourceResult(
|
||||||
source = zip.getInputStream(entry).source().buffer(),
|
source = ExtraCloseableBufferedSource(
|
||||||
|
zip.getInputStream(entry).source().buffer(),
|
||||||
|
zip,
|
||||||
|
),
|
||||||
mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(ext),
|
mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(ext),
|
||||||
dataSource = DataSource.DISK
|
dataSource = DataSource.DISK
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun key(data: Uri): String? = data.toString()
|
override fun key(data: Uri) = data.toString()
|
||||||
|
|
||||||
override fun handles(data: Uri) = data.scheme == "cbz"
|
override fun handles(data: Uri) = data.scheme == "cbz"
|
||||||
}
|
}
|
||||||
@@ -7,7 +7,7 @@ import java.util.*
|
|||||||
class CbzFilter : FilenameFilter {
|
class CbzFilter : FilenameFilter {
|
||||||
|
|
||||||
override fun accept(dir: File, name: String): Boolean {
|
override fun accept(dir: File, name: String): Boolean {
|
||||||
val ext = name.substringAfterLast('.', "").toLowerCase(Locale.ROOT)
|
val ext = name.substringAfterLast('.', "").lowercase(Locale.ROOT)
|
||||||
return ext == "cbz" || ext == "zip"
|
return ext == "cbz" || ext == "zip"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package org.koitharu.kotatsu.local.data
|
||||||
|
|
||||||
|
import okhttp3.internal.closeQuietly
|
||||||
|
import okio.BufferedSource
|
||||||
|
import okio.Closeable
|
||||||
|
|
||||||
|
class ExtraCloseableBufferedSource(
|
||||||
|
private val delegate: BufferedSource,
|
||||||
|
vararg closeable: Closeable,
|
||||||
|
) : BufferedSource by delegate {
|
||||||
|
|
||||||
|
private val extraCloseable = closeable
|
||||||
|
|
||||||
|
override fun close() {
|
||||||
|
delegate.close()
|
||||||
|
extraCloseable.forEach { x -> x.closeQuietly() }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,10 +15,7 @@ import org.koitharu.kotatsu.local.data.CbzFilter
|
|||||||
import org.koitharu.kotatsu.local.data.MangaIndex
|
import org.koitharu.kotatsu.local.data.MangaIndex
|
||||||
import org.koitharu.kotatsu.local.data.MangaZip
|
import org.koitharu.kotatsu.local.data.MangaZip
|
||||||
import org.koitharu.kotatsu.utils.AlphanumComparator
|
import org.koitharu.kotatsu.utils.AlphanumComparator
|
||||||
import org.koitharu.kotatsu.utils.ext.longHashCode
|
import org.koitharu.kotatsu.utils.ext.*
|
||||||
import org.koitharu.kotatsu.utils.ext.readText
|
|
||||||
import org.koitharu.kotatsu.utils.ext.sub
|
|
||||||
import org.koitharu.kotatsu.utils.ext.toCamelCase
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.zip.ZipEntry
|
import java.util.zip.ZipEntry
|
||||||
@@ -78,9 +75,9 @@ class LocalMangaRepository(private val context: Context) : MangaRepository {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun delete(manga: Manga): Boolean {
|
suspend fun delete(manga: Manga): Boolean {
|
||||||
val file = Uri.parse(manga.url).toFile()
|
val file = Uri.parse(manga.url).toFile()
|
||||||
return file.delete()
|
return file.deleteAwait()
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("DefaultLocale")
|
@SuppressLint("DefaultLocale")
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ buildscript {
|
|||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:4.2.2'
|
classpath 'com.android.tools.build:gradle:4.2.2'
|
||||||
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.21'
|
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.30'
|
||||||
|
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
// in the individual module build.gradle files
|
// in the individual module build.gradle files
|
||||||
|
|||||||
Reference in New Issue
Block a user