Home Hero Scans: Add support for deeplinking + fix bug where webview wouldn't launch (#7003)
This commit is contained in:
parent
56d9d913f3
commit
3a90e498b1
|
@ -1,2 +1,32 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="eu.kanade.tachiyomi.extension" />
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="eu.kanade.tachiyomi.extension">
|
||||
|
||||
<application>
|
||||
<activity
|
||||
android:name=".en.homeheroscans.HomeHeroScansUrlActivity"
|
||||
android:excludeFromRecents="true"
|
||||
android:theme="@android:style/Theme.NoDisplay">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data
|
||||
android:host="hhs.vercel.app"
|
||||
android:pathPattern="/chapter"
|
||||
android:scheme="https" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data
|
||||
android:host="hhs.vercel.app"
|
||||
android:pathPattern="/series"
|
||||
android:scheme="https" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
||||
|
|
|
@ -5,7 +5,7 @@ ext {
|
|||
extName = 'Home Hero Scans'
|
||||
pkgNameSuffix = "en.homeheroscans"
|
||||
extClass = '.HomeHeroScans'
|
||||
extVersionCode = 1
|
||||
extVersionCode = 2
|
||||
libVersion = '1.2'
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package eu.kanade.tachiyomi.extension.en.homeheroscans
|
||||
|
||||
import android.util.Log
|
||||
import com.github.salomonbrys.kotson.forEach
|
||||
import com.google.gson.JsonParser
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
|
@ -28,6 +27,23 @@ open class HomeHeroScans : HttpSource() {
|
|||
// { seriesId |---> chapter |---> numPages }
|
||||
private val chapterNumberCache: MutableMap<String, MutableMap<String, Int>> = mutableMapOf()
|
||||
|
||||
/**
|
||||
* Given function f which returns an observable, returns a memoized version of f which'll
|
||||
* cache values emitted by the observable. Future calls will return an observable that
|
||||
* emits the cached values
|
||||
*/
|
||||
private fun <P, R> memoizeObservable(f: (arg: P) -> Observable<R>): (P) -> Observable<R> {
|
||||
val cache = mutableMapOf<P, MutableList<R>>()
|
||||
fun decorated(arg: P) = cache[arg]?.let { Observable.from(it) } ?: f(arg).map {
|
||||
cache.getOrPut(arg, ::mutableListOf).add(it)
|
||||
it
|
||||
}
|
||||
return ::decorated
|
||||
}
|
||||
|
||||
val memoizedFetchPopularManga = memoizeObservable { page: Int -> super.fetchPopularManga(page) }
|
||||
// reduce number of times we call their api, user can force a call to api by relaunching the app
|
||||
override fun fetchPopularManga(page: Int) = memoizedFetchPopularManga(page)
|
||||
override fun popularMangaRequest(page: Int) = GET("$baseUrl/series.json", headers)
|
||||
override fun popularMangaParse(response: Response): MangasPage {
|
||||
val res = JsonParser.parseString(response.body?.string()).asJsonObject
|
||||
|
@ -56,13 +72,35 @@ open class HomeHeroScans : HttpSource() {
|
|||
override fun latestUpdatesRequest(page: Int) = throw UnsupportedOperationException("Not used")
|
||||
override fun latestUpdatesParse(response: Response) = throw UnsupportedOperationException("Not used")
|
||||
|
||||
// search - site doesn't have a search, so just return the popular page
|
||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList) = popularMangaRequest(page)
|
||||
override fun searchMangaParse(response: Response) = popularMangaParse(response)
|
||||
// search
|
||||
|
||||
private fun getMangaId(s: String): String? {
|
||||
return s.toHttpUrlOrNull()?.let { url ->
|
||||
// allow for trailing slash
|
||||
if (url.pathSegments.size == 1 && url.pathSegments.last().isNotEmpty() || url.pathSegments.size == 2 && url.pathSegments.last().isEmpty())
|
||||
return url.queryParameter("series")
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
private fun fetchBySeriesId(id: String): Observable<List<SManga>> = fetchPopularManga(1).map { mp ->
|
||||
mp.mangas.filter { "$baseUrl${it.url}".toHttpUrlOrNull()?.queryParameter("series") == id }
|
||||
}
|
||||
|
||||
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
|
||||
if (!query.startsWith(URL_SEARCH_PREFIX))
|
||||
// site doesn't have a search, so just return the popular page
|
||||
return fetchPopularManga(page)
|
||||
return getMangaId(query.substringAfter(URL_SEARCH_PREFIX))?.let { id ->
|
||||
fetchBySeriesId(id).map { MangasPage(it, false) }
|
||||
} ?: Observable.just(MangasPage(emptyList(), false))
|
||||
}
|
||||
|
||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList) = throw UnsupportedOperationException("Not used")
|
||||
override fun searchMangaParse(response: Response) = throw UnsupportedOperationException("Not used")
|
||||
|
||||
// chapter list (is paginated),
|
||||
override fun chapterListParse(response: Response): List<SChapter> {
|
||||
Log.e("Genkan", "hello")
|
||||
return JsonParser.parseString(response.body?.string()!!).asJsonObject["data"].asJsonArray.map {
|
||||
val chapterData = it.asJsonObject["data"].asJsonObject
|
||||
fun get(k: String) = chapterData[k].asString
|
||||
|
@ -87,9 +125,18 @@ open class HomeHeroScans : HttpSource() {
|
|||
"$baseUrl/api/chapters", headers, """{"series":"$series"}""".toRequestBody("text/plain;charset=utf-8".toMediaTypeOrNull())
|
||||
)
|
||||
}
|
||||
override fun fetchMangaDetails(manga: SManga): Observable<SManga> = Observable.just(manga.apply { initialized = true }) // details already filled out by whatever originally fetched manga
|
||||
|
||||
override fun fetchMangaDetails(manga: SManga): Observable<SManga> =
|
||||
"$baseUrl${manga.url}".toHttpUrlOrNull()?.queryParameter("series")?.let { id ->
|
||||
fetchBySeriesId(id).map {
|
||||
(it.getOrNull(0) ?: manga).apply { initialized = true }
|
||||
}
|
||||
} ?: Observable.just(manga)
|
||||
|
||||
override fun mangaDetailsParse(response: Response) = throw UnsupportedOperationException("Not used")
|
||||
override fun mangaDetailsRequest(manga: SManga) = throw UnsupportedOperationException("Not used")
|
||||
// default implementation of mangaDetailsRequest has to exist for webview to work
|
||||
// override fun mangaDetailsRequest(manga: SManga) = throw UnsupportedOperationException("Not used")
|
||||
|
||||
// Pages
|
||||
override fun fetchPageList(chapter: SChapter): Observable<List<Page>> {
|
||||
val url = "$baseUrl${chapter.url}".toHttpUrlOrNull()!!
|
||||
|
@ -116,4 +163,8 @@ open class HomeHeroScans : HttpSource() {
|
|||
override fun pageListParse(response: Response) = throw UnsupportedOperationException("Not used")
|
||||
override fun pageListRequest(chapter: SChapter) = throw UnsupportedOperationException("Not Used")
|
||||
override fun imageUrlParse(response: Response): String = throw UnsupportedOperationException("Not used")
|
||||
|
||||
companion object {
|
||||
const val URL_SEARCH_PREFIX = "url:"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
package eu.kanade.tachiyomi.extension.en.homeheroscans
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
class HomeHeroScansUrlActivity : Activity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
val pathSegments = intent?.data?.pathSegments
|
||||
|
||||
if (pathSegments?.size == 1) {
|
||||
val mainIntent = Intent().apply {
|
||||
action = "eu.kanade.tachiyomi.SEARCH"
|
||||
putExtra("query", "${HomeHeroScans.URL_SEARCH_PREFIX}${intent?.data?.toString()}")
|
||||
putExtra("filter", packageName)
|
||||
}
|
||||
try {
|
||||
startActivity(mainIntent)
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
Log.e("HomeHeroScansUrl", e.toString())
|
||||
}
|
||||
} else {
|
||||
Log.e("HomeHeroScansUrl", "could not parse uri from intent $intent")
|
||||
}
|
||||
finish()
|
||||
exitProcess(0)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue