Browse Source

Add ability to open FAQ and Guide, and Changelog in extension repository (#6469)

Andreas 3 years ago
parent
commit
66a180bc36

+ 4 - 0
app/src/main/java/eu/kanade/tachiyomi/extension/api/ExtensionGithubApi.kt

@@ -81,6 +81,8 @@ internal class ExtensionGithubApi {
                     versionCode = it.code,
                     lang = it.lang,
                     isNsfw = it.nsfw == 1,
+                    hasReadme = it.hasReadme == 1,
+                    hasChangelog = it.hasChangelog == 1,
                     sources = it.sources?.toExtensionSources() ?: emptyList(),
                     apkName = it.apk,
                     iconUrl = "${REPO_URL_PREFIX}icon/${it.apk.replace(".apk", ".png")}"
@@ -114,6 +116,8 @@ private data class ExtensionJsonObject(
     val code: Long,
     val version: String,
     val nsfw: Int,
+    val hasReadme: Int = 0,
+    val hasChangelog: Int = 0,
     val sources: List<ExtensionSourceJsonObject>?,
 )
 

+ 9 - 1
app/src/main/java/eu/kanade/tachiyomi/extension/model/Extension.kt

@@ -11,6 +11,8 @@ sealed class Extension {
     abstract val versionCode: Long
     abstract val lang: String?
     abstract val isNsfw: Boolean
+    abstract val hasReadme: Boolean
+    abstract val hasChangelog: Boolean
 
     data class Installed(
         override val name: String,
@@ -19,6 +21,8 @@ sealed class Extension {
         override val versionCode: Long,
         override val lang: String,
         override val isNsfw: Boolean,
+        override val hasReadme: Boolean,
+        override val hasChangelog: Boolean,
         val pkgFactory: String?,
         val sources: List<Source>,
         val icon: Drawable?,
@@ -34,6 +38,8 @@ sealed class Extension {
         override val versionCode: Long,
         override val lang: String,
         override val isNsfw: Boolean,
+        override val hasReadme: Boolean,
+        override val hasChangelog: Boolean,
         val sources: List<AvailableExtensionSources>,
         val apkName: String,
         val iconUrl: String
@@ -46,7 +52,9 @@ sealed class Extension {
         override val versionCode: Long,
         val signatureHash: String,
         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()
 }
 

+ 7 - 0
app/src/main/java/eu/kanade/tachiyomi/extension/util/ExtensionLoader.kt

@@ -35,6 +35,8 @@ internal object ExtensionLoader {
     private const val METADATA_SOURCE_CLASS = "tachiyomi.extension.class"
     private const val METADATA_SOURCE_FACTORY = "tachiyomi.extension.factory"
     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_MAX = 1.3
 
@@ -139,6 +141,9 @@ internal object ExtensionLoader {
             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 sources = appInfo.metaData.getString(METADATA_SOURCE_CLASS)!!
@@ -180,6 +185,8 @@ internal object ExtensionLoader {
             versionCode,
             lang,
             isNsfw,
+            hasReadme,
+            hasChangelog,
             sources = sources,
             pkgFactory = appInfo.metaData.getString(METADATA_SOURCE_FACTORY),
             isUnofficial = signatureHash != officialSignature,

+ 40 - 8
app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/details/ExtensionDetailsController.kt

@@ -183,12 +183,16 @@ class ExtensionDetailsController(bundle: Bundle? = null) :
     override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
         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 {
         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_disable_all -> toggleAllSources(false)
             R.id.action_clear_cookies -> clearCookies()
@@ -212,16 +216,43 @@ class ExtensionDetailsController(bundle: Bundle? = null) :
         }
     }
 
-    private fun openCommitHistory() {
-        val pkgName = presenter.extension!!.pkgName.substringAfter("eu.kanade.tachiyomi.extension.")
-        val pkgFactory = presenter.extension!!.pkgFactory
-        val url = when {
-            !pkgFactory.isNullOrEmpty() -> "$URL_EXTENSION_COMMITS/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/$pkgFactory"
-            else -> "$URL_EXTENSION_COMMITS/src/${pkgName.replace(".", "/")}"
+    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 when {
+            !pkgFactory.isNullOrEmpty() -> "$url/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/$pkgFactory$path"
+            else -> "$url/src/${pkgName.replace(".", "/")}$path"
+        }
+    }
+
     private fun clearCookies() {
         val urls = presenter.extension?.sources
             ?.filterIsInstance<HttpSource>()
@@ -248,3 +279,4 @@ class ExtensionDetailsController(bundle: Bundle? = null) :
 
 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"

+ 9 - 0
app/src/main/res/menu/extension_details.xml

@@ -5,6 +5,15 @@
         android:id="@+id/action_history"
         android:icon="@drawable/ic_history_24dp"
         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:showAsAction="ifRoom" />
 

+ 1 - 0
app/src/main/res/values/strings.xml

@@ -125,6 +125,7 @@
     <string name="action_webview_forward">Forward</string>
     <string name="action_webview_refresh">Refresh</string>
     <string name="action_start_downloading_now">Start downloading now</string>
+    <string name="action_faq_and_guides">FAQ and Guides</string>
 
     <!-- Operations -->
     <string name="loading">Loading…</string>