Add ability to open FAQ and Guide, and Changelog in extension repository (#6469)
This commit is contained in:
parent
eb06667455
commit
66a180bc36
6 changed files with 70 additions and 9 deletions
|
@ -81,6 +81,8 @@ internal class ExtensionGithubApi {
|
||||||
versionCode = it.code,
|
versionCode = it.code,
|
||||||
lang = it.lang,
|
lang = it.lang,
|
||||||
isNsfw = it.nsfw == 1,
|
isNsfw = it.nsfw == 1,
|
||||||
|
hasReadme = it.hasReadme == 1,
|
||||||
|
hasChangelog = it.hasChangelog == 1,
|
||||||
sources = it.sources?.toExtensionSources() ?: emptyList(),
|
sources = it.sources?.toExtensionSources() ?: emptyList(),
|
||||||
apkName = it.apk,
|
apkName = it.apk,
|
||||||
iconUrl = "${REPO_URL_PREFIX}icon/${it.apk.replace(".apk", ".png")}"
|
iconUrl = "${REPO_URL_PREFIX}icon/${it.apk.replace(".apk", ".png")}"
|
||||||
|
@ -114,6 +116,8 @@ private data class ExtensionJsonObject(
|
||||||
val code: Long,
|
val code: Long,
|
||||||
val version: String,
|
val version: String,
|
||||||
val nsfw: Int,
|
val nsfw: Int,
|
||||||
|
val hasReadme: Int = 0,
|
||||||
|
val hasChangelog: Int = 0,
|
||||||
val sources: List<ExtensionSourceJsonObject>?,
|
val sources: List<ExtensionSourceJsonObject>?,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,8 @@ sealed class Extension {
|
||||||
abstract val versionCode: Long
|
abstract val versionCode: Long
|
||||||
abstract val lang: String?
|
abstract val lang: String?
|
||||||
abstract val isNsfw: Boolean
|
abstract val isNsfw: Boolean
|
||||||
|
abstract val hasReadme: Boolean
|
||||||
|
abstract val hasChangelog: Boolean
|
||||||
|
|
||||||
data class Installed(
|
data class Installed(
|
||||||
override val name: String,
|
override val name: String,
|
||||||
|
@ -19,6 +21,8 @@ sealed class Extension {
|
||||||
override val versionCode: Long,
|
override val versionCode: Long,
|
||||||
override val lang: String,
|
override val lang: String,
|
||||||
override val isNsfw: Boolean,
|
override val isNsfw: Boolean,
|
||||||
|
override val hasReadme: Boolean,
|
||||||
|
override val hasChangelog: Boolean,
|
||||||
val pkgFactory: String?,
|
val pkgFactory: String?,
|
||||||
val sources: List<Source>,
|
val sources: List<Source>,
|
||||||
val icon: Drawable?,
|
val icon: Drawable?,
|
||||||
|
@ -34,6 +38,8 @@ sealed class Extension {
|
||||||
override val versionCode: Long,
|
override val versionCode: Long,
|
||||||
override val lang: String,
|
override val lang: String,
|
||||||
override val isNsfw: Boolean,
|
override val isNsfw: Boolean,
|
||||||
|
override val hasReadme: Boolean,
|
||||||
|
override val hasChangelog: Boolean,
|
||||||
val sources: List<AvailableExtensionSources>,
|
val sources: List<AvailableExtensionSources>,
|
||||||
val apkName: String,
|
val apkName: String,
|
||||||
val iconUrl: String
|
val iconUrl: String
|
||||||
|
@ -46,7 +52,9 @@ sealed class Extension {
|
||||||
override val versionCode: Long,
|
override val versionCode: Long,
|
||||||
val signatureHash: String,
|
val signatureHash: String,
|
||||||
override val lang: String? = null,
|
override val lang: String? = null,
|
||||||
override val isNsfw: Boolean = false
|
override val isNsfw: Boolean = false,
|
||||||
|
override val hasReadme: Boolean = false,
|
||||||
|
override val hasChangelog: Boolean = false,
|
||||||
) : Extension()
|
) : Extension()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,8 @@ internal object ExtensionLoader {
|
||||||
private const val METADATA_SOURCE_CLASS = "tachiyomi.extension.class"
|
private const val METADATA_SOURCE_CLASS = "tachiyomi.extension.class"
|
||||||
private const val METADATA_SOURCE_FACTORY = "tachiyomi.extension.factory"
|
private const val METADATA_SOURCE_FACTORY = "tachiyomi.extension.factory"
|
||||||
private const val METADATA_NSFW = "tachiyomi.extension.nsfw"
|
private const val METADATA_NSFW = "tachiyomi.extension.nsfw"
|
||||||
|
private const val METADATA_HAS_README = "tachiyomi.extension.hasReadme"
|
||||||
|
private const val METADATA_HAS_CHANGELOG = "tachiyomi.extension.hasChangelog"
|
||||||
const val LIB_VERSION_MIN = 1.2
|
const val LIB_VERSION_MIN = 1.2
|
||||||
const val LIB_VERSION_MAX = 1.3
|
const val LIB_VERSION_MAX = 1.3
|
||||||
|
|
||||||
|
@ -139,6 +141,9 @@ internal object ExtensionLoader {
|
||||||
return LoadResult.Error("NSFW extension $pkgName not allowed")
|
return LoadResult.Error("NSFW extension $pkgName not allowed")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val hasReadme = appInfo.metaData.getInt(METADATA_HAS_README, 0) == 1
|
||||||
|
val hasChangelog = appInfo.metaData.getInt(METADATA_HAS_CHANGELOG, 0) == 1
|
||||||
|
|
||||||
val classLoader = PathClassLoader(appInfo.sourceDir, null, context.classLoader)
|
val classLoader = PathClassLoader(appInfo.sourceDir, null, context.classLoader)
|
||||||
|
|
||||||
val sources = appInfo.metaData.getString(METADATA_SOURCE_CLASS)!!
|
val sources = appInfo.metaData.getString(METADATA_SOURCE_CLASS)!!
|
||||||
|
@ -180,6 +185,8 @@ internal object ExtensionLoader {
|
||||||
versionCode,
|
versionCode,
|
||||||
lang,
|
lang,
|
||||||
isNsfw,
|
isNsfw,
|
||||||
|
hasReadme,
|
||||||
|
hasChangelog,
|
||||||
sources = sources,
|
sources = sources,
|
||||||
pkgFactory = appInfo.metaData.getString(METADATA_SOURCE_FACTORY),
|
pkgFactory = appInfo.metaData.getString(METADATA_SOURCE_FACTORY),
|
||||||
isUnofficial = signatureHash != officialSignature,
|
isUnofficial = signatureHash != officialSignature,
|
||||||
|
|
|
@ -183,12 +183,16 @@ class ExtensionDetailsController(bundle: Bundle? = null) :
|
||||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||||
inflater.inflate(R.menu.extension_details, menu)
|
inflater.inflate(R.menu.extension_details, menu)
|
||||||
|
|
||||||
menu.findItem(R.id.action_history).isVisible = presenter.extension?.isUnofficial == false
|
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 {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
R.id.action_history -> openCommitHistory()
|
R.id.action_history -> openChangelog()
|
||||||
|
R.id.action_faq_and_guides -> openReadme()
|
||||||
R.id.action_enable_all -> toggleAllSources(true)
|
R.id.action_enable_all -> toggleAllSources(true)
|
||||||
R.id.action_disable_all -> toggleAllSources(false)
|
R.id.action_disable_all -> toggleAllSources(false)
|
||||||
R.id.action_clear_cookies -> clearCookies()
|
R.id.action_clear_cookies -> clearCookies()
|
||||||
|
@ -212,16 +216,43 @@ class ExtensionDetailsController(bundle: Bundle? = null) :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun openCommitHistory() {
|
private fun openChangelog() {
|
||||||
val pkgName = presenter.extension!!.pkgName.substringAfter("eu.kanade.tachiyomi.extension.")
|
val extension = presenter.extension!!
|
||||||
val pkgFactory = presenter.extension!!.pkgFactory
|
val pkgName = extension.pkgName.substringAfter("eu.kanade.tachiyomi.extension.")
|
||||||
val url = when {
|
val pkgFactory = extension.pkgFactory
|
||||||
!pkgFactory.isNullOrEmpty() -> "$URL_EXTENSION_COMMITS/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/$pkgFactory"
|
if (extension.hasChangelog) {
|
||||||
else -> "$URL_EXTENSION_COMMITS/src/${pkgName.replace(".", "/")}"
|
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)
|
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 when {
|
||||||
|
!pkgFactory.isNullOrEmpty() -> "$url/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/$pkgFactory$path"
|
||||||
|
else -> "$url/src/${pkgName.replace(".", "/")}$path"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun clearCookies() {
|
private fun clearCookies() {
|
||||||
val urls = presenter.extension?.sources
|
val urls = presenter.extension?.sources
|
||||||
?.filterIsInstance<HttpSource>()
|
?.filterIsInstance<HttpSource>()
|
||||||
|
@ -248,3 +279,4 @@ class ExtensionDetailsController(bundle: Bundle? = null) :
|
||||||
|
|
||||||
private const val PKGNAME_KEY = "pkg_name"
|
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_COMMITS = "https://github.com/tachiyomiorg/tachiyomi-extensions/commits/master"
|
||||||
|
private const val URL_EXTENSION_BLOB = "https://github.com/tachiyomiorg/tachiyomi-extensions/blob/master"
|
||||||
|
|
|
@ -5,6 +5,15 @@
|
||||||
android:id="@+id/action_history"
|
android:id="@+id/action_history"
|
||||||
android:icon="@drawable/ic_history_24dp"
|
android:icon="@drawable/ic_history_24dp"
|
||||||
android:title="@string/whats_new"
|
android:title="@string/whats_new"
|
||||||
|
android:visible="false"
|
||||||
|
app:iconTint="?attr/colorOnSurface"
|
||||||
|
app:showAsAction="ifRoom" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_faq_and_guides"
|
||||||
|
android:icon="@drawable/ic_help_24dp"
|
||||||
|
android:title="@string/action_faq_and_guides"
|
||||||
|
android:visible="false"
|
||||||
app:iconTint="?attr/colorOnSurface"
|
app:iconTint="?attr/colorOnSurface"
|
||||||
app:showAsAction="ifRoom" />
|
app:showAsAction="ifRoom" />
|
||||||
|
|
||||||
|
|
|
@ -125,6 +125,7 @@
|
||||||
<string name="action_webview_forward">Forward</string>
|
<string name="action_webview_forward">Forward</string>
|
||||||
<string name="action_webview_refresh">Refresh</string>
|
<string name="action_webview_refresh">Refresh</string>
|
||||||
<string name="action_start_downloading_now">Start downloading now</string>
|
<string name="action_start_downloading_now">Start downloading now</string>
|
||||||
|
<string name="action_faq_and_guides">FAQ and Guides</string>
|
||||||
|
|
||||||
<!-- Operations -->
|
<!-- Operations -->
|
||||||
<string name="loading">Loading…</string>
|
<string name="loading">Loading…</string>
|
||||||
|
|
Reference in a new issue