mirror of
https://github.com/null2264/yokai.git
synced 2025-06-21 10:44:42 +00:00
Use index.json from extensions repo to list sources instead of the id
Manga details shows the source name, just with (source not installed), backups show the actual source missing Also fixed the error for "Source not found" error in manga info
This commit is contained in:
parent
495d2316ed
commit
7a8de6c0e7
11 changed files with 89 additions and 25 deletions
|
@ -29,7 +29,7 @@ class FullBackupRestoreValidator : AbstractBackupRestoreValidator() {
|
|||
val sources = backup.backupSources.map { it.sourceId to it.name }.toMap()
|
||||
val missingSources = sources
|
||||
.filter { sourceManager.get(it.key) == null }
|
||||
.values
|
||||
.map { sourceManager.getOrStub(it.key).name }
|
||||
.sorted()
|
||||
|
||||
val trackers = backup.backupManga
|
||||
|
|
|
@ -34,7 +34,7 @@ class LegacyBackupRestoreValidator : AbstractBackupRestoreValidator() {
|
|||
val sources = getSourceMapping(json)
|
||||
val missingSources = sources
|
||||
.filter { sourceManager.get(it.key) == null }
|
||||
.values
|
||||
.map { sourceManager.getOrStub(it.key).name }
|
||||
.sorted()
|
||||
|
||||
val trackers = mangas
|
||||
|
|
|
@ -112,8 +112,11 @@ class ExtensionManager(
|
|||
availableExtensionsRelay.call(value)
|
||||
updatedInstalledExtensionsStatuses(value)
|
||||
listener?.extensionsUpdated()
|
||||
setupAvailableSourcesMap()
|
||||
}
|
||||
|
||||
private var availableSources = hashMapOf<String, Extension.AvailableSource>()
|
||||
|
||||
/**
|
||||
* Relay used to notify the untrusted extensions.
|
||||
*/
|
||||
|
@ -200,6 +203,15 @@ class ExtensionManager(
|
|||
}
|
||||
}
|
||||
|
||||
private fun setupAvailableSourcesMap() {
|
||||
availableSources = hashMapOf()
|
||||
availableExtensions.map { it.sources.orEmpty() }.flatten().forEach {
|
||||
availableSources[it.id] = it
|
||||
}
|
||||
}
|
||||
|
||||
fun getStubSource(id: Long) = availableSources[id.toString()]
|
||||
|
||||
/**
|
||||
* Finds the available extensions in the [api] and updates [availableExtensions].
|
||||
*/
|
||||
|
|
|
@ -12,6 +12,7 @@ import eu.kanade.tachiyomi.network.parseAs
|
|||
import eu.kanade.tachiyomi.util.system.withIOContext
|
||||
import kotlinx.serialization.json.JsonArray
|
||||
import kotlinx.serialization.json.int
|
||||
import kotlinx.serialization.json.jsonArray
|
||||
import kotlinx.serialization.json.jsonObject
|
||||
import kotlinx.serialization.json.jsonPrimitive
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
|
@ -30,9 +31,9 @@ internal class ExtensionGithubApi {
|
|||
}
|
||||
}
|
||||
|
||||
suspend fun checkForUpdates(context: Context): List<Extension.Available> {
|
||||
suspend fun checkForUpdates(context: Context, prefetchedExtensions: List<Extension.Available>? = null): List<Extension.Available> {
|
||||
return withIOContext {
|
||||
val extensions = findExtensions()
|
||||
val extensions = prefetchedExtensions ?: findExtensions()
|
||||
|
||||
val installedExtensions = ExtensionLoader.loadExtensions(context)
|
||||
.filterIsInstance<LoadResult.Success>()
|
||||
|
@ -68,9 +69,16 @@ internal class ExtensionGithubApi {
|
|||
val versionCode = element.jsonObject["code"]!!.jsonPrimitive.int
|
||||
val lang = element.jsonObject["lang"]!!.jsonPrimitive.content
|
||||
val nsfw = element.jsonObject["nsfw"]!!.jsonPrimitive.int == 1
|
||||
val sources = element.jsonObject["sources"]?.jsonArray?.map f@{
|
||||
val sName = it.jsonObject["name"]?.jsonPrimitive?.content ?: return@f null
|
||||
val sId = it.jsonObject["id"]?.jsonPrimitive?.content ?: return@f null
|
||||
val sLang = it.jsonObject["lang"]?.jsonPrimitive?.content ?: ""
|
||||
val sBaseUrl = it.jsonObject["baseUrl"]?.jsonPrimitive?.content ?: ""
|
||||
Extension.AvailableSource(sName, sId, sLang, sBaseUrl)
|
||||
}?.filterNotNull()
|
||||
val icon = "${REPO_URL_PREFIX}icon/${apkName.replace(".apk", ".png")}"
|
||||
|
||||
Extension.Available(name, pkgName, versionName, versionCode, lang, nsfw, apkName, icon)
|
||||
Extension.Available(name, pkgName, versionName, versionCode, lang, nsfw, apkName, icon, sources)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,9 +33,17 @@ sealed class Extension {
|
|||
override val lang: String,
|
||||
override val isNsfw: Boolean,
|
||||
val apkName: String,
|
||||
val iconUrl: String
|
||||
val iconUrl: String,
|
||||
val sources: List<AvailableSource>? = null
|
||||
) : Extension()
|
||||
|
||||
data class AvailableSource(
|
||||
val name: String,
|
||||
val id: String,
|
||||
val lang: String,
|
||||
val baseUrl: String
|
||||
)
|
||||
|
||||
data class Untrusted(
|
||||
override val name: String,
|
||||
override val pkgName: String,
|
||||
|
|
|
@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.source
|
|||
|
||||
import android.content.Context
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.extension.ExtensionManager
|
||||
import eu.kanade.tachiyomi.source.model.Page
|
||||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
|
@ -12,6 +13,7 @@ import eu.kanade.tachiyomi.source.online.all.MangaDex
|
|||
import eu.kanade.tachiyomi.source.online.english.KireiCake
|
||||
import eu.kanade.tachiyomi.source.online.english.MangaPlus
|
||||
import rx.Observable
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
|
||||
open class SourceManager(private val context: Context) {
|
||||
|
||||
|
@ -19,6 +21,8 @@ open class SourceManager(private val context: Context) {
|
|||
|
||||
private val stubSourcesMap = mutableMapOf<Long, StubSource>()
|
||||
|
||||
protected val extensionManager: ExtensionManager by injectLazy()
|
||||
|
||||
private val delegatedSources = listOf(
|
||||
DelegatedSource(
|
||||
"reader.kireicake.com",
|
||||
|
@ -83,10 +87,10 @@ open class SourceManager(private val context: Context) {
|
|||
LocalSource(context)
|
||||
)
|
||||
|
||||
private inner class StubSource(override val id: Long) : Source {
|
||||
inner class StubSource(override val id: Long) : Source {
|
||||
|
||||
override val name: String
|
||||
get() = id.toString()
|
||||
get() = extensionManager.getStubSource(id)?.name ?: id.toString()
|
||||
|
||||
override fun fetchMangaDetails(manga: SManga): Observable<SManga> {
|
||||
return Observable.error(getSourceNotInstalledException())
|
||||
|
@ -108,7 +112,7 @@ open class SourceManager(private val context: Context) {
|
|||
return SourceNotFoundException(
|
||||
context.getString(
|
||||
R.string.source_not_installed_,
|
||||
id.toString()
|
||||
extensionManager.getStubSource(id)?.name ?: id.toString()
|
||||
),
|
||||
id
|
||||
)
|
||||
|
@ -117,6 +121,13 @@ open class SourceManager(private val context: Context) {
|
|||
override fun hashCode(): Int {
|
||||
return id.hashCode()
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
other as StubSource
|
||||
return id == other.id
|
||||
}
|
||||
}
|
||||
|
||||
private data class DelegatedSource(
|
||||
|
|
|
@ -58,6 +58,7 @@ import eu.kanade.tachiyomi.data.updater.UpdateChecker
|
|||
import eu.kanade.tachiyomi.data.updater.UpdateResult
|
||||
import eu.kanade.tachiyomi.data.updater.UpdaterNotifier
|
||||
import eu.kanade.tachiyomi.databinding.MainActivityBinding
|
||||
import eu.kanade.tachiyomi.extension.ExtensionManager
|
||||
import eu.kanade.tachiyomi.extension.api.ExtensionGithubApi
|
||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||
import eu.kanade.tachiyomi.ui.base.MaterialMenuSheet
|
||||
|
@ -91,7 +92,6 @@ import eu.kanade.tachiyomi.util.view.updatePadding
|
|||
import eu.kanade.tachiyomi.util.view.withFadeTransaction
|
||||
import eu.kanade.tachiyomi.widget.EndAnimatorListener
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
@ -119,6 +119,7 @@ open class MainActivity : BaseActivity<MainActivityBinding>(), DownloadServiceLi
|
|||
private var animationSet: AnimatorSet? = null
|
||||
private val downloadManager: DownloadManager by injectLazy()
|
||||
private val mangaShortcutManager: MangaShortcutManager by injectLazy()
|
||||
private val extensionManager: ExtensionManager by injectLazy()
|
||||
private val hideBottomNav
|
||||
get() = router.backstackSize > 1 && router.backstack[1].controller !is DialogController
|
||||
|
||||
|
@ -384,6 +385,7 @@ open class MainActivity : BaseActivity<MainActivityBinding>(), DownloadServiceLi
|
|||
}
|
||||
}
|
||||
}
|
||||
getExtensionUpdates(true)
|
||||
|
||||
preferences.extensionUpdatesCount()
|
||||
.asImmediateFlowIn(lifecycleScope) {
|
||||
|
@ -402,7 +404,6 @@ open class MainActivity : BaseActivity<MainActivityBinding>(), DownloadServiceLi
|
|||
else -> Gravity.TOP
|
||||
}
|
||||
}
|
||||
setExtensionsBadge()
|
||||
setFloatingToolbar(canShowFloatingToolbar(router.backstack.lastOrNull()?.controller), changeBG = false)
|
||||
}
|
||||
|
||||
|
@ -509,7 +510,7 @@ open class MainActivity : BaseActivity<MainActivityBinding>(), DownloadServiceLi
|
|||
override fun onResume() {
|
||||
super.onResume()
|
||||
getAppUpdates()
|
||||
getExtensionUpdates()
|
||||
getExtensionUpdates(false)
|
||||
DownloadService.callListeners()
|
||||
showDLQueueTutorial()
|
||||
}
|
||||
|
@ -577,11 +578,17 @@ open class MainActivity : BaseActivity<MainActivityBinding>(), DownloadServiceLi
|
|||
}
|
||||
}
|
||||
|
||||
private fun getExtensionUpdates() {
|
||||
if (Date().time >= preferences.lastExtCheck().getOrDefault() + TimeUnit.HOURS.toMillis(6)) {
|
||||
GlobalScope.launch(Dispatchers.IO) {
|
||||
fun getExtensionUpdates(force: Boolean) {
|
||||
if ((force && extensionManager.availableExtensions.isEmpty()) ||
|
||||
Date().time >= preferences.lastExtCheck().getOrDefault() + TimeUnit.HOURS.toMillis(6)
|
||||
) {
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
try {
|
||||
val pendingUpdates = ExtensionGithubApi().checkForUpdates(this@MainActivity)
|
||||
extensionManager.findAvailableExtensionsAsync()
|
||||
val pendingUpdates = ExtensionGithubApi().checkForUpdates(
|
||||
this@MainActivity,
|
||||
extensionManager.availableExtensions.takeIf { it.isNotEmpty() }
|
||||
)
|
||||
preferences.extensionUpdatesCount().set(pendingUpdates.size)
|
||||
preferences.lastExtCheck().set(Date().time)
|
||||
} catch (e: java.lang.Exception) {
|
||||
|
|
|
@ -32,6 +32,7 @@ import eu.kanade.tachiyomi.data.track.TrackService
|
|||
import eu.kanade.tachiyomi.data.track.UnattendedTrackService
|
||||
import eu.kanade.tachiyomi.source.LocalSource
|
||||
import eu.kanade.tachiyomi.source.Source
|
||||
import eu.kanade.tachiyomi.source.SourceNotFoundException
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.model.toSChapter
|
||||
import eu.kanade.tachiyomi.source.model.toSManga
|
||||
|
@ -438,7 +439,9 @@ class MangaDetailsPresenter(
|
|||
|
||||
private fun trimException(e: java.lang.Exception): String {
|
||||
return (
|
||||
if (e.message?.contains(": ") == true) e.message?.split(": ")?.drop(1)
|
||||
if (e !is SourceNotFoundException &&
|
||||
e.message?.contains(": ") == true
|
||||
) e.message?.split(": ")?.drop(1)
|
||||
?.joinToString(": ")
|
||||
else e.message
|
||||
) ?: preferences.context.getString(R.string.unknown_error)
|
||||
|
|
|
@ -16,6 +16,8 @@ import androidx.constraintlayout.widget.ConstraintLayout
|
|||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.graphics.ColorUtils
|
||||
import androidx.core.graphics.drawable.toDrawable
|
||||
import androidx.core.text.buildSpannedString
|
||||
import androidx.core.text.scale
|
||||
import androidx.core.view.isInvisible
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.view.updateLayoutParams
|
||||
|
@ -30,6 +32,7 @@ import eu.kanade.tachiyomi.data.image.coil.loadManga
|
|||
import eu.kanade.tachiyomi.databinding.ChapterHeaderItemBinding
|
||||
import eu.kanade.tachiyomi.databinding.MangaHeaderItemBinding
|
||||
import eu.kanade.tachiyomi.source.LocalSource
|
||||
import eu.kanade.tachiyomi.source.SourceManager
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder
|
||||
import eu.kanade.tachiyomi.util.system.getResourceColor
|
||||
|
@ -361,15 +364,25 @@ class MangaHeaderHolder(
|
|||
}
|
||||
)
|
||||
)
|
||||
binding.mangaSource.text = run {
|
||||
val preferences = presenter.preferences
|
||||
val enabledLanguages = preferences.enabledLanguages().get()
|
||||
with(binding.mangaSource) {
|
||||
val enabledLanguages = presenter.preferences.enabledLanguages().get()
|
||||
.filterNot { it == "all" }
|
||||
|
||||
if (enabledLanguages.size > 1 && presenter.extension?.lang == "all") {
|
||||
presenter.source.toString()
|
||||
} else {
|
||||
return@run presenter.source.name
|
||||
text = buildSpannedString {
|
||||
append(
|
||||
if (enabledLanguages.size > 1 && presenter.extension?.lang == "all") {
|
||||
presenter.source.toString()
|
||||
} else {
|
||||
presenter.source.name
|
||||
}
|
||||
)
|
||||
if (presenter.source is SourceManager.StubSource &&
|
||||
presenter.source.name != presenter.source.id.toString()
|
||||
) {
|
||||
scale(0.9f) {
|
||||
append(" (${context.getString(R.string.source_not_installed)})")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ import eu.kanade.tachiyomi.data.backup.full.models.BackupFull
|
|||
import eu.kanade.tachiyomi.data.backup.legacy.LegacyBackupRestoreValidator
|
||||
import eu.kanade.tachiyomi.data.preference.asImmediateFlow
|
||||
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
||||
import eu.kanade.tachiyomi.ui.main.MainActivity
|
||||
import eu.kanade.tachiyomi.util.system.getFilePicker
|
||||
import eu.kanade.tachiyomi.util.system.MiuiUtil
|
||||
import eu.kanade.tachiyomi.util.system.toast
|
||||
|
@ -78,6 +79,7 @@ class SettingsBackupController : SettingsController() {
|
|||
}
|
||||
|
||||
if (!BackupRestoreService.isRunning(context)) {
|
||||
(activity as? MainActivity)?.getExtensionUpdates(true)
|
||||
val intent = Intent(Intent.ACTION_GET_CONTENT)
|
||||
intent.addCategory(Intent.CATEGORY_OPENABLE)
|
||||
intent.type = "application/*"
|
||||
|
|
|
@ -140,7 +140,7 @@
|
|||
app:layout_constrainedWidth="true"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:maxLines="2"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@id/title"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue