Dependency update / Dropped features that supports <Android 21 / Dropped support for hiyobi.me
This commit is contained in:
2
.idea/compiler.xml
generated
2
.idea/compiler.xml
generated
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<bytecodeTargetLevel target="1.8" />
|
||||
<bytecodeTargetLevel target="11" />
|
||||
</component>
|
||||
</project>
|
||||
1
.idea/gradle.xml
generated
1
.idea/gradle.xml
generated
@@ -14,7 +14,6 @@
|
||||
</set>
|
||||
</option>
|
||||
<option name="resolveModulePerSourceSet" value="false" />
|
||||
<option name="useQualifiedModuleNames" value="true" />
|
||||
</GradleProjectSettings>
|
||||
</option>
|
||||
</component>
|
||||
|
||||
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
|
||||
1
.idea/runConfigurations.xml
generated
1
.idea/runConfigurations.xml
generated
@@ -3,6 +3,7 @@
|
||||
<component name="RunConfigurationProducerService">
|
||||
<option name="ignoredProducers">
|
||||
<set>
|
||||
<option value="com.android.tools.idea.compose.preview.runconfiguration.ComposePreviewRunConfigurationProducer" />
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
|
||||
|
||||
@@ -14,23 +14,6 @@ if (file("google-services.json").exists()) {
|
||||
logger.lifecycle("Firebase Disabled")
|
||||
}
|
||||
|
||||
ext {
|
||||
okhttp_version = "3.12.12"
|
||||
}
|
||||
|
||||
configurations {
|
||||
all {
|
||||
resolutionStrategy {
|
||||
eachDependency { DependencyResolveDetails details ->
|
||||
if (details.requested.group == "com.squareup.okhttp3" && details.requested.name == "okhttp") {
|
||||
// OkHttp drops support before 5.0 since 3.13.0
|
||||
details.useVersion okhttp_version
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 30
|
||||
defaultConfig {
|
||||
@@ -75,7 +58,6 @@ android {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
buildToolsVersion = "29.0.3"
|
||||
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
@@ -84,27 +66,27 @@ android {
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: "libs", include: ["*.jar", "*.aar"])
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.0.1"
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.5.0"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.0-RC"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.2.0"
|
||||
|
||||
implementation "androidx.appcompat:appcompat:1.2.0"
|
||||
implementation "androidx.activity:activity-ktx:1.3.0-alpha05"
|
||||
implementation "androidx.fragment:fragment-ktx:1.3.2"
|
||||
implementation "androidx.activity:activity-ktx:1.3.0-alpha07"
|
||||
implementation "androidx.fragment:fragment-ktx:1.3.3"
|
||||
implementation "androidx.preference:preference-ktx:1.1.1"
|
||||
implementation "androidx.recyclerview:recyclerview:1.1.0"
|
||||
implementation "androidx.recyclerview:recyclerview:1.2.0"
|
||||
implementation "androidx.constraintlayout:constraintlayout:2.0.4"
|
||||
implementation "androidx.gridlayout:gridlayout:1.0.0"
|
||||
implementation "androidx.biometric:biometric:1.1.0"
|
||||
implementation "androidx.work:work-runtime-ktx:2.5.0"
|
||||
implementation "androidx.work:work-runtime-ktx:2.6.0-alpha02"
|
||||
|
||||
implementation 'org.kodein.di:kodein-di-framework-android-x:7.4.0'
|
||||
implementation 'org.kodein.di:kodein-di-framework-android-x:7.5.0'
|
||||
|
||||
implementation "com.daimajia.swipelayout:library:1.2.0@aar"
|
||||
|
||||
implementation "com.google.android.material:material:1.3.0"
|
||||
|
||||
implementation platform("com.google.firebase:firebase-bom:26.1.0")
|
||||
implementation platform("com.google.firebase:firebase-bom:28.0.0")
|
||||
implementation "com.google.firebase:firebase-analytics-ktx"
|
||||
implementation "com.google.firebase:firebase-crashlytics"
|
||||
implementation "com.google.firebase:firebase-perf"
|
||||
@@ -115,26 +97,23 @@ dependencies {
|
||||
|
||||
//implementation "com.quiph.ui:recyclerviewfastscroller:0.2.1"
|
||||
|
||||
implementation 'com.github.piasy:BigImageViewer:1.7.0'
|
||||
implementation 'com.github.piasy:FrescoImageLoader:1.7.0'
|
||||
implementation 'com.github.piasy:FrescoImageViewFactory:1.7.0'
|
||||
implementation 'com.github.piasy:BigImageViewer:1.8.0'
|
||||
implementation 'com.github.piasy:FrescoImageLoader:1.8.0'
|
||||
implementation 'com.github.piasy:FrescoImageViewFactory:1.8.0'
|
||||
|
||||
//noinspection GradleDependency
|
||||
implementation "com.squareup.okhttp3:okhttp:$okhttp_version"
|
||||
implementation "com.squareup.okhttp3:okhttp:4.9.0"
|
||||
|
||||
implementation "com.tbuonomo.andrui:viewpagerdotsindicator:4.1.2"
|
||||
implementation "com.tbuonomo:dotsindicator:4.2"
|
||||
|
||||
implementation "net.rdrei.android.dirchooser:library:3.2@aar"
|
||||
implementation "com.gu:option:1.3"
|
||||
|
||||
implementation "com.andrognito.patternlockview:patternlockview:1.0.0"
|
||||
//implementation "com.andrognito.patternlockview:patternlockview:1.0.0"
|
||||
//implementation "com.andrognito.pinlockview:pinlockview:2.1.0"
|
||||
|
||||
implementation "ru.noties.markwon:core:3.1.0"
|
||||
|
||||
implementation "xyz.quaver:libpupil:1.9.7"
|
||||
implementation "xyz.quaver:documentfilex:0.5-SNAPSHOT"
|
||||
implementation "xyz.quaver:floatingsearchview:1.1.3-SNAPSHOT"
|
||||
implementation "xyz.quaver:libpupil:2.0.0"
|
||||
implementation "xyz.quaver:documentfilex:0.6.1"
|
||||
implementation "xyz.quaver:floatingsearchview:1.1.7"
|
||||
|
||||
implementation "com.orhanobut:logger:2.2.0"
|
||||
|
||||
|
||||
BIN
app/libs/patternlockview-release.aar
Normal file
BIN
app/libs/patternlockview-release.aar
Normal file
Binary file not shown.
@@ -143,8 +143,7 @@ val sourceModule = DI.Module(name = "source") {
|
||||
bind() from setBinding<SourceEntry>()
|
||||
|
||||
listOf(
|
||||
Hitomi(),
|
||||
Hiyobi()
|
||||
Hitomi()
|
||||
).forEach { source ->
|
||||
bind<SourceEntry>().inSet() with multiton { _: Unit -> source.name to (source as AnySource) }
|
||||
}
|
||||
|
||||
@@ -227,7 +227,7 @@ class Hitomi : Source<Hitomi.SortMode, Hitomi.TagSuggestion>() {
|
||||
}.getOrDefault("") },
|
||||
ExtraType.SERIES to CoroutineScope(Dispatchers.Unconfined).async { galleryBlock.series.joinToString { it.wordCapitalize() } },
|
||||
ExtraType.TYPE to CoroutineScope(Dispatchers.Unconfined).async { galleryBlock.type.wordCapitalize() },
|
||||
ExtraType.LANGUAGE to CoroutineScope(Dispatchers.Unconfined).async { galleryBlock.language },
|
||||
ExtraType.LANGUAGE to CoroutineScope(Dispatchers.Unconfined).async { languageMap[galleryBlock.language] },
|
||||
ExtraType.PAGECOUNT to CoroutineScope(Dispatchers.IO).async { kotlin.runCatching {
|
||||
getGalleryInfo(galleryBlock.id).files.size.toString()
|
||||
}.getOrNull() },
|
||||
|
||||
@@ -1,140 +0,0 @@
|
||||
/*
|
||||
* Pupil, Hitomi.la viewer for Android
|
||||
* Copyright (C) 2020 tom5079
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package xyz.quaver.pupil.sources
|
||||
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import okhttp3.Request
|
||||
import xyz.quaver.floatingsearchview.databinding.SearchSuggestionItemBinding
|
||||
import xyz.quaver.hiyobi.*
|
||||
import xyz.quaver.pupil.R
|
||||
import xyz.quaver.pupil.client
|
||||
import xyz.quaver.pupil.util.wordCapitalize
|
||||
import java.io.IOException
|
||||
import java.util.*
|
||||
|
||||
class Hiyobi : Source<DefaultSortMode, DefaultSearchSuggestion>() {
|
||||
|
||||
override val name: String = "hiyobi.me"
|
||||
override val iconResID: Int = R.drawable.ic_hiyobi
|
||||
override val availableSortMode: Array<DefaultSortMode> = DefaultSortMode.values()
|
||||
|
||||
override suspend fun search(query: String, range: IntRange, sortMode: Enum<*>): Pair<Channel<ItemInfo>, Int> {
|
||||
val channel = Channel<ItemInfo>()
|
||||
|
||||
val (results, total) = if (query.isEmpty())
|
||||
list(range)
|
||||
else
|
||||
search(query.trim(), range)
|
||||
|
||||
CoroutineScope(Dispatchers.Unconfined).launch {
|
||||
results.forEach {
|
||||
channel.send(transform(name, it))
|
||||
}
|
||||
|
||||
channel.close()
|
||||
}
|
||||
|
||||
return Pair(channel, total)
|
||||
}
|
||||
|
||||
override suspend fun suggestion(query: String): List<DefaultSearchSuggestion> {
|
||||
val result = mutableSetOf<String>()
|
||||
|
||||
for (tag in allTags.await()) {
|
||||
if (result.size >= 10)
|
||||
break
|
||||
|
||||
val lowQuery = query.toLowerCase(Locale.ROOT)
|
||||
|
||||
if (tag.contains(lowQuery, true))
|
||||
result.add(tag)
|
||||
}
|
||||
|
||||
return result.map { DefaultSearchSuggestion(it) }
|
||||
}
|
||||
|
||||
override suspend fun images(itemID: String): List<String> {
|
||||
return createImgList(itemID, getGalleryInfo(itemID), true).map {
|
||||
it.path
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun info(itemID: String): ItemInfo {
|
||||
return transform(name, getGalleryBlock(itemID))
|
||||
}
|
||||
|
||||
override fun onSuggestionBind(binding: SearchSuggestionItemBinding, item: DefaultSearchSuggestion) {
|
||||
val split = item.body.split(':', limit = 2)
|
||||
|
||||
if (split.size != 2)
|
||||
return
|
||||
|
||||
binding.leftIcon.setImageResource(
|
||||
when(split.first()) {
|
||||
"female" -> R.drawable.gender_female
|
||||
"male" -> R.drawable.gender_male
|
||||
"language" -> R.drawable.translate
|
||||
"group" -> R.drawable.account_group
|
||||
"character" -> R.drawable.account_star
|
||||
"series" -> R.drawable.book_open
|
||||
"artist" -> R.drawable.brush
|
||||
else -> R.drawable.tag
|
||||
}
|
||||
)
|
||||
|
||||
binding.body.text = split.last()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private fun downloadAllTagsAsync(): Deferred<List<String>> = CoroutineScope(Dispatchers.IO).async {
|
||||
Json.decodeFromString(kotlin.runCatching {
|
||||
client.newCall(Request.Builder().url("https://api.hiyobi.me/auto.json").build()).execute().also { if (it.code() != 200) throw IOException() }.body()?.use { it.string() }
|
||||
}.getOrNull() ?: "[]")
|
||||
}
|
||||
|
||||
private var _allTags: Deferred<List<String>>? = null
|
||||
|
||||
val allTags: Deferred<List<String>>
|
||||
get() = if (_allTags == null || (_allTags!!.isCompleted && runBlocking { _allTags!!.await() }.isEmpty())) downloadAllTagsAsync().also {
|
||||
_allTags = it
|
||||
} else _allTags!!
|
||||
|
||||
suspend fun transform(name: String, galleryBlock: GalleryBlock): ItemInfo = withContext(Dispatchers.IO) {
|
||||
ItemInfo(
|
||||
name,
|
||||
galleryBlock.id,
|
||||
galleryBlock.title,
|
||||
"https://cdn.$hiyobi/tn/${galleryBlock.id}.jpg",
|
||||
galleryBlock.artists.joinToString { it.value.wordCapitalize() },
|
||||
mapOf(
|
||||
ItemInfo.ExtraType.CHARACTER to async { galleryBlock.characters.joinToString { it.value.wordCapitalize() } },
|
||||
ItemInfo.ExtraType.SERIES to async { galleryBlock.parodys.joinToString { it.value.wordCapitalize() } },
|
||||
ItemInfo.ExtraType.TYPE to async { galleryBlock.type.name.replace('_', ' ').wordCapitalize() },
|
||||
ItemInfo.ExtraType.PAGECOUNT to async { getGalleryInfo(galleryBlock.id).files.size.toString() },
|
||||
ItemInfo.ExtraType.GROUP to async { galleryBlock.groups.joinToString { it.value.wordCapitalize() } },
|
||||
ItemInfo.ExtraType.TAGS to async { galleryBlock.tags.joinToString() { it.value } }
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -29,8 +29,6 @@ import androidx.core.content.ContextCompat
|
||||
import androidx.core.net.toUri
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import net.rdrei.android.dirchooser.DirectoryChooserActivity
|
||||
import net.rdrei.android.dirchooser.DirectoryChooserConfig
|
||||
import org.kodein.di.DIAware
|
||||
import org.kodein.di.android.x.di
|
||||
import org.kodein.di.instance
|
||||
@@ -63,8 +61,7 @@ class DownloadLocationDialogFragment : DialogFragment(), DIAware {
|
||||
it.data?.data?.let { uri ->
|
||||
val takeFlags: Int = Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
|
||||
context.contentResolver.takePersistableUriPermission(uri, takeFlags)
|
||||
context.contentResolver.takePersistableUriPermission(uri, takeFlags)
|
||||
|
||||
if (kotlin.runCatching { FileX(context, uri).canWrite() }.getOrDefault(false)) {
|
||||
entries[null]?.locationAvailable?.text = uri.toFile(context)?.canonicalPath
|
||||
@@ -85,32 +82,6 @@ class DownloadLocationDialogFragment : DialogFragment(), DIAware {
|
||||
}
|
||||
}
|
||||
|
||||
private val requestDownloadFolderOldLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||
val context = context ?: return@registerForActivityResult
|
||||
val dialog = dialog ?: return@registerForActivityResult
|
||||
|
||||
if (it.resultCode == DirectoryChooserActivity.RESULT_CODE_DIR_SELECTED) {
|
||||
val directory = it.data?.getStringExtra(DirectoryChooserActivity.RESULT_SELECTED_DIR)!!
|
||||
|
||||
if (!File(directory).canWrite()) {
|
||||
Snackbar.make(
|
||||
dialog.window!!.decorView.rootView,
|
||||
R.string.settings_download_folder_not_writable,
|
||||
Snackbar.LENGTH_LONG
|
||||
).show()
|
||||
|
||||
val downloadFolder = downloadManager.downloadFolder.canonicalPath
|
||||
val key = entries.keys.firstOrNull { it?.canonicalPath == downloadFolder }
|
||||
entries[key]!!.button.isChecked = true
|
||||
if (key == null) entries[key]!!.locationAvailable.text = downloadFolder
|
||||
}
|
||||
else {
|
||||
entries[null]?.locationAvailable?.text = directory
|
||||
Preferences["download_folder"] = File(directory).toURI().toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun initView() {
|
||||
val externalFilesDirs = ContextCompat.getExternalFilesDirs(requireContext(), null)
|
||||
|
||||
@@ -145,29 +116,16 @@ class DownloadLocationDialogFragment : DialogFragment(), DIAware {
|
||||
}
|
||||
button.performClick()
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).apply {
|
||||
addFlags(
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||
or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||
or Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
|
||||
)
|
||||
putExtra("android.content.extra.SHOW_ADVANCED", true)
|
||||
}
|
||||
|
||||
requestDownloadFolderLauncher.launch(intent)
|
||||
} else { // Can't use SAF on old Androids!
|
||||
val config = DirectoryChooserConfig.builder()
|
||||
.newDirectoryName("Pupil")
|
||||
.allowNewDirectoryNameModification(true)
|
||||
.build()
|
||||
|
||||
val intent = Intent(context, DirectoryChooserActivity::class.java).apply {
|
||||
putExtra(DirectoryChooserActivity.EXTRA_CONFIG, config)
|
||||
}
|
||||
|
||||
requestDownloadFolderOldLauncher.launch(intent)
|
||||
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).apply {
|
||||
addFlags(
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||
or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||
or Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
|
||||
)
|
||||
putExtra("android.content.extra.SHOW_ADVANCED", true)
|
||||
}
|
||||
|
||||
requestDownloadFolderLauncher.launch(intent)
|
||||
}
|
||||
entries[null] = this
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import androidx.fragment.app.DialogFragment
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.kodein.di.*
|
||||
import org.kodein.di.android.x.closestDI
|
||||
import org.kodein.di.android.x.di
|
||||
import org.kodein.type.jvmType
|
||||
import xyz.quaver.floatingsearchview.suggestions.model.SearchSuggestion
|
||||
@@ -36,7 +37,7 @@ import xyz.quaver.pupil.sources.SourceEntries
|
||||
|
||||
class SourceSelectDialog : DialogFragment(), DIAware {
|
||||
|
||||
override val di by di()
|
||||
override val di by closestDI()
|
||||
|
||||
var onSourceSelectedListener: ((String) -> Unit)? = null
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ import androidx.preference.PreferenceFragmentCompat
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import okhttp3.*
|
||||
import org.kodein.di.DIAware
|
||||
import org.kodein.di.android.x.closestDI
|
||||
import org.kodein.di.android.x.di
|
||||
import xyz.quaver.pupil.R
|
||||
import xyz.quaver.pupil.client
|
||||
@@ -38,7 +39,7 @@ import java.io.IOException
|
||||
|
||||
class ManageFavoritesFragment : PreferenceFragmentCompat(), DIAware {
|
||||
|
||||
override val di by di()
|
||||
override val di by closestDI()
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
setPreferencesFromResource(R.xml.manage_favorites_preferences, rootKey)
|
||||
@@ -65,14 +66,14 @@ class ManageFavoritesFragment : PreferenceFragmentCompat(), DIAware {
|
||||
}
|
||||
|
||||
override fun onResponse(call: Call, response: Response) {
|
||||
if (response.code() != 200) {
|
||||
if (response.code != 200) {
|
||||
response.close()
|
||||
return
|
||||
}
|
||||
|
||||
Intent(Intent.ACTION_SEND).apply {
|
||||
type = "text/plain"
|
||||
putExtra(Intent.EXTRA_TEXT, response.body()?.use { it.string() }?.replace("\n", ""))
|
||||
putExtra(Intent.EXTRA_TEXT, response.body?.use { it.string() }?.replace("\n", ""))
|
||||
}.let {
|
||||
getContext()?.startActivity(Intent.createChooser(it, getString(R.string.settings_backup_share)))
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ import xyz.quaver.pupil.types.NoResultSuggestion
|
||||
import java.util.*
|
||||
|
||||
class FloatingSearchView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
|
||||
FloatingSearchView(context, attrs),
|
||||
xyz.quaver.floatingsearchview.FloatingSearchView(context, attrs),
|
||||
FloatingSearchView.OnSearchListener,
|
||||
TextWatcher
|
||||
{
|
||||
|
||||
@@ -26,6 +26,7 @@ import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import kotlinx.coroutines.*
|
||||
import okhttp3.Headers
|
||||
import okhttp3.Headers.Companion.toHeaders
|
||||
import okhttp3.Request
|
||||
import org.kodein.di.DIAware
|
||||
import org.kodein.di.android.x.di
|
||||
@@ -73,7 +74,7 @@ class ReaderViewModel(app: Application) : AndroidViewModel(app), DIAware {
|
||||
val file = cache.load(
|
||||
Request.Builder()
|
||||
.url(image)
|
||||
.headers(Headers.of(source.getHeadersForImage(itemID, image)))
|
||||
.headers(source.getHeadersForImage(itemID, image).toHeaders())
|
||||
.build()
|
||||
)
|
||||
|
||||
|
||||
@@ -62,8 +62,8 @@ class ImageCache(context: Context) : DIAware {
|
||||
}
|
||||
|
||||
fun free(images: List<String>) {
|
||||
client.dispatcher().let { it.queuedCalls() + it.runningCalls() }
|
||||
.filter { it.request().url().toString() in images }
|
||||
client.dispatcher.let { it.queuedCalls() + it.runningCalls() }
|
||||
.filter { it.request().url.toString() in images }
|
||||
.forEach { it.cancel() }
|
||||
|
||||
images.forEach { _channels.remove(it) }
|
||||
@@ -71,7 +71,7 @@ class ImageCache(context: Context) : DIAware {
|
||||
|
||||
@Synchronized
|
||||
suspend fun clear() = coroutineScope {
|
||||
client.dispatcher().queuedCalls().forEach { it.cancel() }
|
||||
client.dispatcher.queuedCalls().forEach { it.cancel() }
|
||||
|
||||
cacheFolder.listFiles()?.forEach { it.delete() }
|
||||
cache.clear()
|
||||
@@ -79,7 +79,7 @@ class ImageCache(context: Context) : DIAware {
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
fun load(request: Request): File {
|
||||
val key = request.url().toString()
|
||||
val key = request.url.toString()
|
||||
|
||||
val channel = if (_channels[key]?.isClosedForSend == false)
|
||||
_channels[key]!!
|
||||
@@ -93,16 +93,16 @@ class ImageCache(context: Context) : DIAware {
|
||||
client.newCall(request).enqueue(object: Callback {
|
||||
override fun onFailure(call: Call, e: IOException) {
|
||||
file.delete()
|
||||
cache.remove(call.request().url().toString())
|
||||
cache.remove(call.request().url.toString())
|
||||
|
||||
FirebaseCrashlytics.getInstance().recordException(e)
|
||||
channel.close(e)
|
||||
}
|
||||
|
||||
override fun onResponse(call: Call, response: Response) {
|
||||
if (response.code() != 200) {
|
||||
if (response.code != 200) {
|
||||
file.delete()
|
||||
cache.remove(call.request().url().toString())
|
||||
cache.remove(call.request().url.toString())
|
||||
|
||||
channel.close(IOException("HTTP Response code is not 200"))
|
||||
|
||||
@@ -110,7 +110,7 @@ class ImageCache(context: Context) : DIAware {
|
||||
return
|
||||
}
|
||||
|
||||
response.body()?.use { body ->
|
||||
response.body?.use { body ->
|
||||
if (!file.exists())
|
||||
file.createNewFile()
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ data class ProxyInfo(
|
||||
Authenticator { _, response ->
|
||||
val credential = Credentials.basic(username, password)
|
||||
|
||||
response.request().newBuilder()
|
||||
response.request.newBuilder()
|
||||
.header("Proxy-Authorization", credential)
|
||||
.build()
|
||||
}
|
||||
|
||||
@@ -44,10 +44,10 @@ fun updateTranslations() = CoroutineScope(Dispatchers.IO).launch {
|
||||
translations = emptyMap()
|
||||
kotlin.runCatching {
|
||||
translations = Json.decodeFromString<Map<String, String>>(client.newCall(
|
||||
Request.Builder()
|
||||
.url(contentURL + "${Preferences["tag_translation", ""].let { if (it.isEmpty()) Locale.getDefault().language else it }}.json")
|
||||
.build()
|
||||
).execute().also { if (it.code() != 200) return@launch }.body()?.use { it.string() } ?: return@launch).filterValues { it.isNotEmpty() }
|
||||
Request.Builder()
|
||||
.url(contentURL + "${Preferences["tag_translation", ""].let { if (it.isEmpty()) Locale.getDefault().language else it }}.json")
|
||||
.build()
|
||||
).execute().also { if (it.code != 200) return@launch }.body?.use { it.string() } ?: return@launch).filterValues { it.isNotEmpty() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ fun getAvailableLanguages(): List<String> {
|
||||
Request.Builder()
|
||||
.url(filesURL)
|
||||
.build()
|
||||
).execute().also { if (it.code() != 200) throw IOException() }.body()?.use { it.string() } ?: return emptyList())
|
||||
).execute().also { if (it.code != 200) throw IOException() }.body?.use { it.string() } ?: return emptyList())
|
||||
|
||||
return listOf("en") + (json["tree"]?.jsonArray?.mapNotNull {
|
||||
val name = it["path"]?.jsonPrimitive?.content?.takeWhile { c -> c != '.' }
|
||||
|
||||
@@ -199,7 +199,7 @@ fun restore(context: Context, url: String, onFailure: ((Throwable) -> Unit)? = n
|
||||
override fun onResponse(call: Call, response: Response) {
|
||||
val favorites = object: DIAware { override val di by di(context); val favorites: SavedSourceSet by instance(tag = "favorites") }
|
||||
kotlin.runCatching {
|
||||
Json.decodeFromString<Set<String>>(response.also { if (it.code() != 200) throw IOException() }.body().use { it?.string() } ?: "[]").let {
|
||||
Json.decodeFromString<Set<String>>(response.also { if (it.code != 200) throw IOException() }.body.use { it?.string() } ?: "[]").let {
|
||||
favorites.favorites.addAll(mapOf("hitomi.la" to it))
|
||||
onSuccess?.invoke(it)
|
||||
}
|
||||
|
||||
13
build.gradle
13
build.gradle
@@ -3,32 +3,29 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:4.1.3'
|
||||
classpath 'com.android.tools.build:gradle:4.2.1'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version"
|
||||
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
|
||||
classpath "com.google.gms:google-services:4.3.5"
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
classpath "com.google.firebase:firebase-crashlytics-gradle:2.5.2"
|
||||
classpath "com.google.firebase:perf-plugin:1.3.5"
|
||||
classpath "com.google.android.gms:oss-licenses-plugin:0.10.2"
|
||||
classpath "com.google.firebase:firebase-crashlytics-gradle:2.6.0"
|
||||
classpath "com.google.firebase:perf-plugin:1.4.0"
|
||||
classpath "com.google.android.gms:oss-licenses-plugin:0.10.4"
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
maven { url "https://dl.bintray.com/piasy/maven" }
|
||||
google()
|
||||
mavenCentral()
|
||||
jcenter()
|
||||
mavenLocal()
|
||||
maven { url "https://oss.sonatype.org/content/repositories/snapshots" }
|
||||
maven { url "https://jitpack.io" }
|
||||
maven { url "https://guardian.github.com/maven/repo-releases" }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,4 +21,4 @@ android.enableJetifier=true
|
||||
android.useAndroidX=true
|
||||
android.enableBuildCache=true
|
||||
|
||||
kotlin_version=1.4.32
|
||||
kotlin_version=1.5.0
|
||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip
|
||||
|
||||
Reference in New Issue
Block a user