Convert extension details to full Compose
This commit is contained in:
+6
-106
@@ -2,135 +2,35 @@ package eu.kanade.tachiyomi.ui.browse.extension.details
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.Bundle
|
||||
import android.view.Menu
|
||||
import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
|
||||
import androidx.core.os.bundleOf
|
||||
import eu.kanade.presentation.browse.ExtensionDetailsScreen
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||
import eu.kanade.tachiyomi.ui.base.controller.ComposeController
|
||||
import eu.kanade.tachiyomi.ui.base.controller.openInBrowser
|
||||
import eu.kanade.tachiyomi.ui.base.controller.FullComposeController
|
||||
import eu.kanade.tachiyomi.ui.base.controller.pushController
|
||||
import eu.kanade.tachiyomi.util.system.logcat
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
|
||||
@SuppressLint("RestrictedApi")
|
||||
class ExtensionDetailsController(bundle: Bundle? = null) :
|
||||
ComposeController<ExtensionDetailsPresenter>(bundle) {
|
||||
|
||||
private val network: NetworkHelper by injectLazy()
|
||||
class ExtensionDetailsController(
|
||||
bundle: Bundle? = null,
|
||||
) : FullComposeController<ExtensionDetailsPresenter>(bundle) {
|
||||
|
||||
constructor(pkgName: String) : this(
|
||||
bundleOf(PKGNAME_KEY to pkgName),
|
||||
)
|
||||
|
||||
init {
|
||||
setHasOptionsMenu(true)
|
||||
}
|
||||
|
||||
override fun getTitle() = resources?.getString(R.string.label_extension_info)
|
||||
|
||||
override fun createPresenter() = ExtensionDetailsPresenter(args.getString(PKGNAME_KEY)!!)
|
||||
|
||||
@Composable
|
||||
override fun ComposeContent(nestedScrollInterop: NestedScrollConnection) {
|
||||
override fun ComposeContent() {
|
||||
ExtensionDetailsScreen(
|
||||
nestedScrollInterop = nestedScrollInterop,
|
||||
navigateUp = router::popCurrentController,
|
||||
presenter = presenter,
|
||||
onClickUninstall = { presenter.uninstallExtension() },
|
||||
onClickSourcePreferences = { router.pushController(SourcePreferencesController(it)) },
|
||||
onClickSource = { presenter.toggleSource(it) },
|
||||
)
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||
inflater.inflate(R.menu.extension_details, menu)
|
||||
|
||||
presenter.extension?.let { extension ->
|
||||
menu.findItem(R.id.action_history).isVisible = !extension.isUnofficial
|
||||
menu.findItem(R.id.action_faq_and_guides).isVisible = !extension.isUnofficial
|
||||
}
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
R.id.action_history -> openChangelog()
|
||||
R.id.action_faq_and_guides -> openReadme()
|
||||
R.id.action_enable_all -> toggleAllSources(true)
|
||||
R.id.action_disable_all -> toggleAllSources(false)
|
||||
R.id.action_clear_cookies -> clearCookies()
|
||||
}
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
fun onExtensionUninstalled() {
|
||||
router.popCurrentController()
|
||||
}
|
||||
|
||||
private fun toggleAllSources(enable: Boolean) {
|
||||
presenter.toggleSources(enable)
|
||||
}
|
||||
|
||||
private fun openChangelog() {
|
||||
val extension = presenter.extension!!
|
||||
val pkgName = extension.pkgName.substringAfter("eu.kanade.tachiyomi.extension.")
|
||||
val pkgFactory = extension.pkgFactory
|
||||
if (extension.hasChangelog) {
|
||||
val url = createUrl(URL_EXTENSION_BLOB, pkgName, pkgFactory, "/CHANGELOG.md")
|
||||
openInBrowser(url)
|
||||
return
|
||||
}
|
||||
|
||||
// Falling back on GitHub commit history because there is no explicit changelog in extension
|
||||
val url = createUrl(URL_EXTENSION_COMMITS, pkgName, pkgFactory)
|
||||
openInBrowser(url)
|
||||
}
|
||||
|
||||
private fun openReadme() {
|
||||
val extension = presenter.extension!!
|
||||
|
||||
if (!extension.hasReadme) {
|
||||
openInBrowser("https://tachiyomi.org/help/faq/#extensions")
|
||||
return
|
||||
}
|
||||
|
||||
val pkgName = extension.pkgName.substringAfter("eu.kanade.tachiyomi.extension.")
|
||||
val pkgFactory = extension.pkgFactory
|
||||
val url = createUrl(URL_EXTENSION_BLOB, pkgName, pkgFactory, "/README.md")
|
||||
openInBrowser(url)
|
||||
return
|
||||
}
|
||||
|
||||
private fun createUrl(url: String, pkgName: String, pkgFactory: String?, path: String = ""): String {
|
||||
return if (!pkgFactory.isNullOrEmpty()) {
|
||||
when (path.isEmpty()) {
|
||||
true -> "$url/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/$pkgFactory"
|
||||
else -> "$url/multisrc/overrides/$pkgFactory/" + (pkgName.split(".").lastOrNull() ?: "") + path
|
||||
}
|
||||
} else {
|
||||
url + "/src/" + pkgName.replace(".", "/") + path
|
||||
}
|
||||
}
|
||||
|
||||
private fun clearCookies() {
|
||||
val urls = presenter.extension?.sources
|
||||
?.filterIsInstance<HttpSource>()
|
||||
?.map { it.baseUrl }
|
||||
?.distinct() ?: emptyList()
|
||||
|
||||
val cleared = urls.sumOf {
|
||||
network.cookieManager.remove(it.toHttpUrl())
|
||||
}
|
||||
|
||||
logcat { "Cleared $cleared cookies for: ${urls.joinToString()}" }
|
||||
}
|
||||
}
|
||||
|
||||
private const val PKGNAME_KEY = "pkg_name"
|
||||
private const val URL_EXTENSION_COMMITS = "https://github.com/tachiyomiorg/tachiyomi-extensions/commits/master"
|
||||
private const val URL_EXTENSION_BLOB = "https://github.com/tachiyomiorg/tachiyomi-extensions/blob/master"
|
||||
|
||||
+58
-1
@@ -7,14 +7,18 @@ import eu.kanade.domain.source.interactor.ToggleSource
|
||||
import eu.kanade.presentation.browse.ExtensionDetailsState
|
||||
import eu.kanade.presentation.browse.ExtensionDetailsStateImpl
|
||||
import eu.kanade.tachiyomi.extension.ExtensionManager
|
||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||
import eu.kanade.tachiyomi.source.Source
|
||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
||||
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||
import eu.kanade.tachiyomi.util.lang.withUIContext
|
||||
import eu.kanade.tachiyomi.util.system.LocaleHelper
|
||||
import eu.kanade.tachiyomi.util.system.logcat
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.map
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
@@ -24,6 +28,7 @@ class ExtensionDetailsPresenter(
|
||||
private val context: Application = Injekt.get(),
|
||||
private val getExtensionSources: GetExtensionSources = Injekt.get(),
|
||||
private val toggleSource: ToggleSource = Injekt.get(),
|
||||
private val network: NetworkHelper = Injekt.get(),
|
||||
private val extensionManager: ExtensionManager = Injekt.get(),
|
||||
) : BasePresenter<ExtensionDetailsController>(), ExtensionDetailsState by state {
|
||||
|
||||
@@ -32,7 +37,7 @@ class ExtensionDetailsPresenter(
|
||||
|
||||
presenterScope.launchIO {
|
||||
extensionManager.getInstalledExtensionsFlow()
|
||||
.map { it.firstOrNull { it.pkgName == pkgName } }
|
||||
.map { it.firstOrNull { pkg-> pkg.pkgName == pkgName } }
|
||||
.collectLatest { extension ->
|
||||
// If extension is null it's most likely uninstalled
|
||||
if (extension == null) {
|
||||
@@ -65,6 +70,44 @@ class ExtensionDetailsPresenter(
|
||||
}
|
||||
}
|
||||
|
||||
fun getChangelogUrl(): String {
|
||||
extension ?: return ""
|
||||
|
||||
val pkgName = extension.pkgName.substringAfter("eu.kanade.tachiyomi.extension.")
|
||||
val pkgFactory = extension.pkgFactory
|
||||
if (extension.hasChangelog) {
|
||||
return createUrl(URL_EXTENSION_BLOB, pkgName, pkgFactory, "/CHANGELOG.md")
|
||||
}
|
||||
|
||||
// Falling back on GitHub commit history because there is no explicit changelog in extension
|
||||
return createUrl(URL_EXTENSION_COMMITS, pkgName, pkgFactory)
|
||||
}
|
||||
|
||||
fun getReadmeUrl(): String {
|
||||
extension ?: return ""
|
||||
|
||||
if (!extension.hasReadme) {
|
||||
return "https://tachiyomi.org/help/faq/#extensions"
|
||||
}
|
||||
|
||||
val pkgName = extension.pkgName.substringAfter("eu.kanade.tachiyomi.extension.")
|
||||
val pkgFactory = extension.pkgFactory
|
||||
return createUrl(URL_EXTENSION_BLOB, pkgName, pkgFactory, "/README.md")
|
||||
}
|
||||
|
||||
fun clearCookies() {
|
||||
val urls = extension?.sources
|
||||
?.filterIsInstance<HttpSource>()
|
||||
?.map { it.baseUrl }
|
||||
?.distinct() ?: emptyList()
|
||||
|
||||
val cleared = urls.sumOf {
|
||||
network.cookieManager.remove(it.toHttpUrl())
|
||||
}
|
||||
|
||||
logcat { "Cleared $cleared cookies for: ${urls.joinToString()}" }
|
||||
}
|
||||
|
||||
fun uninstallExtension() {
|
||||
val extension = extension ?: return
|
||||
extensionManager.uninstallExtension(extension.pkgName)
|
||||
@@ -77,6 +120,17 @@ class ExtensionDetailsPresenter(
|
||||
fun toggleSources(enable: Boolean) {
|
||||
extension?.sources?.forEach { toggleSource.await(it.id, enable) }
|
||||
}
|
||||
|
||||
private fun createUrl(url: String, pkgName: String, pkgFactory: String?, path: String = ""): String {
|
||||
return if (!pkgFactory.isNullOrEmpty()) {
|
||||
when (path.isEmpty()) {
|
||||
true -> "$url/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/$pkgFactory"
|
||||
else -> "$url/multisrc/overrides/$pkgFactory/" + (pkgName.split(".").lastOrNull() ?: "") + path
|
||||
}
|
||||
} else {
|
||||
url + "/src/" + pkgName.replace(".", "/") + path
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class ExtensionSourceItem(
|
||||
@@ -84,3 +138,6 @@ data class ExtensionSourceItem(
|
||||
val enabled: Boolean,
|
||||
val labelAsName: Boolean,
|
||||
)
|
||||
|
||||
private const val URL_EXTENSION_COMMITS = "https://github.com/tachiyomiorg/tachiyomi-extensions/commits/master"
|
||||
private const val URL_EXTENSION_BLOB = "https://github.com/tachiyomiorg/tachiyomi-extensions/blob/master"
|
||||
|
||||
Reference in New Issue
Block a user