feat: extension testing
This commit is contained in:
parent
949bcc418a
commit
ab360b3a75
15 changed files with 1103 additions and 4 deletions
|
@ -200,6 +200,7 @@
|
||||||
android:parentActivityName=".MainActivity" />
|
android:parentActivityName=".MainActivity" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".util.MarkdownCreatorActivity"/>
|
android:name=".util.MarkdownCreatorActivity"/>
|
||||||
|
<activity android:name=".parsers.ParserTestActivity" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".media.ReviewActivity"
|
android:name=".media.ReviewActivity"
|
||||||
android:parentActivityName=".media.MediaDetailsActivity" />
|
android:parentActivityName=".media.MediaDetailsActivity" />
|
||||||
|
|
|
@ -53,8 +53,11 @@ class DynamicAnimeParser(extension: AnimeExtension.Installed) : AnimeParser() {
|
||||||
|
|
||||||
override val name = extension.name
|
override val name = extension.name
|
||||||
override val saveName = extension.name
|
override val saveName = extension.name
|
||||||
override val hostUrl = extension.sources.first().name
|
override val hostUrl =
|
||||||
|
(extension.sources.first() as? AnimeHttpSource)?.baseUrl ?: extension.sources.first().name
|
||||||
override val isNSFW = extension.isNsfw
|
override val isNSFW = extension.isNsfw
|
||||||
|
override val icon = extension.icon
|
||||||
|
|
||||||
override var selectDub: Boolean
|
override var selectDub: Boolean
|
||||||
get() = getDub()
|
get() = getDub()
|
||||||
set(value) {
|
set(value) {
|
||||||
|
@ -324,8 +327,10 @@ class DynamicMangaParser(extension: MangaExtension.Installed) : MangaParser() {
|
||||||
|
|
||||||
override val name = extension.name
|
override val name = extension.name
|
||||||
override val saveName = extension.name
|
override val saveName = extension.name
|
||||||
override val hostUrl = extension.sources.first().name
|
override val hostUrl =
|
||||||
|
(extension.sources.first() as? HttpSource)?.baseUrl ?: extension.sources.first().name
|
||||||
override val isNSFW = extension.isNsfw
|
override val isNSFW = extension.isNsfw
|
||||||
|
override val icon = extension.icon
|
||||||
|
|
||||||
override suspend fun loadChapters(
|
override suspend fun loadChapters(
|
||||||
mangaLink: String,
|
mangaLink: String,
|
||||||
|
|
|
@ -1,17 +1,21 @@
|
||||||
package ani.dantotsu.parsers
|
package ani.dantotsu.parsers
|
||||||
|
|
||||||
|
import android.graphics.drawable.Drawable
|
||||||
import ani.dantotsu.FileUrl
|
import ani.dantotsu.FileUrl
|
||||||
import ani.dantotsu.R
|
import ani.dantotsu.R
|
||||||
import ani.dantotsu.currContext
|
import ani.dantotsu.currContext
|
||||||
import ani.dantotsu.media.Media
|
import ani.dantotsu.media.Media
|
||||||
|
import ani.dantotsu.okHttpClient
|
||||||
import ani.dantotsu.settings.saving.PrefManager
|
import ani.dantotsu.settings.saving.PrefManager
|
||||||
import ani.dantotsu.util.Logger
|
import ani.dantotsu.util.Logger
|
||||||
import eu.kanade.tachiyomi.animesource.model.SAnime
|
import eu.kanade.tachiyomi.animesource.model.SAnime
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
import me.xdrop.fuzzywuzzy.FuzzySearch
|
import me.xdrop.fuzzywuzzy.FuzzySearch
|
||||||
|
import okhttp3.Request
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
import java.net.URLDecoder
|
import java.net.URLDecoder
|
||||||
import java.net.URLEncoder
|
import java.net.URLEncoder
|
||||||
|
import kotlin.system.measureTimeMillis
|
||||||
|
|
||||||
|
|
||||||
abstract class BaseParser {
|
abstract class BaseParser {
|
||||||
|
@ -41,6 +45,11 @@ abstract class BaseParser {
|
||||||
* **/
|
* **/
|
||||||
open val language = "English"
|
open val language = "English"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Icon of the site, can be null
|
||||||
|
*/
|
||||||
|
open val icon: Drawable? = null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search for Anime/Manga/Novel, returns a List of Responses
|
* Search for Anime/Manga/Novel, returns a List of Responses
|
||||||
*
|
*
|
||||||
|
@ -133,10 +142,39 @@ abstract class BaseParser {
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ping the site to check if it's working or not.
|
||||||
|
* @return Triple<Int, Int?, String> : First Int is the status code, Second Int is the response time in milliseconds, Third String is the response message.
|
||||||
|
*/
|
||||||
|
fun ping(): Triple<Int, Int?, String> {
|
||||||
|
val client = okHttpClient
|
||||||
|
var statusCode = 0
|
||||||
|
var responseTime: Int? = null
|
||||||
|
var responseMessage = ""
|
||||||
|
try {
|
||||||
|
val request = Request.Builder()
|
||||||
|
.url(hostUrl)
|
||||||
|
.build()
|
||||||
|
responseTime = measureTimeMillis {
|
||||||
|
client.newCall(request).execute().use { response ->
|
||||||
|
statusCode = response.code
|
||||||
|
responseMessage = response.message
|
||||||
|
}
|
||||||
|
}.toInt()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Logger.log("Failed to ping $name")
|
||||||
|
statusCode = -1
|
||||||
|
responseMessage = if (e.message.isNullOrEmpty()) "None" else e.message!!
|
||||||
|
Logger.log(e)
|
||||||
|
}
|
||||||
|
return Triple(statusCode, responseTime, responseMessage)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to get an existing Search Response which was selected by the user.
|
* Used to get an existing Search Response which was selected by the user.
|
||||||
* **/
|
* @param mediaId : The mediaId of the Media object.
|
||||||
|
* @return ShowResponse? : The ShowResponse object if found, else null.
|
||||||
|
*/
|
||||||
open suspend fun loadSavedShowResponse(mediaId: Int): ShowResponse? {
|
open suspend fun loadSavedShowResponse(mediaId: Int): ShowResponse? {
|
||||||
checkIfVariablesAreEmpty()
|
checkIfVariablesAreEmpty()
|
||||||
return PrefManager.getNullableCustomVal(
|
return PrefManager.getNullableCustomVal(
|
||||||
|
@ -148,7 +186,10 @@ abstract class BaseParser {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to save Shows Response using `saveName`.
|
* Used to save Shows Response using `saveName`.
|
||||||
* **/
|
* @param mediaId : The mediaId of the Media object.
|
||||||
|
* @param response : The ShowResponse object to save.
|
||||||
|
* @param selected : Boolean : If the ShowResponse was selected by the user or not.
|
||||||
|
*/
|
||||||
open fun saveShowResponse(mediaId: Int, response: ShowResponse?, selected: Boolean = false) {
|
open fun saveShowResponse(mediaId: Int, response: ShowResponse?, selected: Boolean = false) {
|
||||||
if (response != null) {
|
if (response != null) {
|
||||||
checkIfVariablesAreEmpty()
|
checkIfVariablesAreEmpty()
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
package ani.dantotsu.parsers
|
||||||
|
|
||||||
|
import android.graphics.drawable.Drawable
|
||||||
|
import android.view.View
|
||||||
|
import ani.dantotsu.R
|
||||||
|
import ani.dantotsu.databinding.ItemExtensionSelectBinding
|
||||||
|
import com.xwray.groupie.viewbinding.BindableItem
|
||||||
|
|
||||||
|
class ExtensionSelectItem(
|
||||||
|
private val name: String,
|
||||||
|
private val image: Drawable?,
|
||||||
|
private var isSelected: Boolean,
|
||||||
|
val selectCallback: (String, Boolean) -> Unit
|
||||||
|
) : BindableItem<ItemExtensionSelectBinding>() {
|
||||||
|
private lateinit var binding: ItemExtensionSelectBinding
|
||||||
|
|
||||||
|
override fun bind(viewBinding: ItemExtensionSelectBinding, position: Int) {
|
||||||
|
binding = viewBinding
|
||||||
|
binding.extensionNameTextView.text = name
|
||||||
|
image?.let {
|
||||||
|
binding.extensionIconImageView.setImageDrawable(it)
|
||||||
|
}
|
||||||
|
binding.extensionCheckBox.setOnCheckedChangeListener(null)
|
||||||
|
binding.extensionCheckBox.isChecked = isSelected
|
||||||
|
binding.extensionCheckBox.setOnCheckedChangeListener { _, isChecked ->
|
||||||
|
isSelected = isChecked
|
||||||
|
selectCallback(name, isChecked)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getLayout(): Int {
|
||||||
|
return R.layout.item_extension_select
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun initializeViewBinding(view: View): ItemExtensionSelectBinding {
|
||||||
|
return ItemExtensionSelectBinding.bind(view)
|
||||||
|
}
|
||||||
|
}
|
367
app/src/main/java/ani/dantotsu/parsers/ExtensionTestItem.kt
Normal file
367
app/src/main/java/ani/dantotsu/parsers/ExtensionTestItem.kt
Normal file
|
@ -0,0 +1,367 @@
|
||||||
|
package ani.dantotsu.parsers
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.view.View
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import ani.dantotsu.R
|
||||||
|
import ani.dantotsu.databinding.ItemExtensionTestBinding
|
||||||
|
import ani.dantotsu.getThemeColor
|
||||||
|
import com.xwray.groupie.viewbinding.BindableItem
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
|
class ExtensionTestItem(
|
||||||
|
private var extensionType: String,
|
||||||
|
private var testType: String,
|
||||||
|
private var extension: BaseParser,
|
||||||
|
private var searchString: String = "Chainsaw Man"
|
||||||
|
) : BindableItem<ItemExtensionTestBinding>() {
|
||||||
|
private lateinit var binding: ItemExtensionTestBinding
|
||||||
|
private lateinit var context: Context
|
||||||
|
private var job: Job? = null
|
||||||
|
private var isRunning = false
|
||||||
|
private var pingResult: Triple<Int, Int?, String>? = null
|
||||||
|
private var searchResultSize: Int? = null
|
||||||
|
private var episodeResultSize: Int? = null
|
||||||
|
private var serverResultSize: Int? = null
|
||||||
|
|
||||||
|
override fun bind(viewBinding: ItemExtensionTestBinding, position: Int) {
|
||||||
|
binding = viewBinding
|
||||||
|
context = binding.root.context
|
||||||
|
binding.extensionIconImageView.setImageDrawable(extension.icon)
|
||||||
|
binding.extensionNameTextView.text = extension.name
|
||||||
|
binding.extensionLoading.isVisible = isRunning
|
||||||
|
hideAllResults()
|
||||||
|
|
||||||
|
pingResult()
|
||||||
|
searchResult()
|
||||||
|
episodeResult()
|
||||||
|
serverResult()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getLayout(): Int {
|
||||||
|
return R.layout.item_extension_test
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun initializeViewBinding(view: View): ItemExtensionTestBinding {
|
||||||
|
return ItemExtensionTestBinding.bind(view)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun hideAllResults() {
|
||||||
|
if (::binding.isInitialized.not()) return
|
||||||
|
binding.searchResultText.isVisible = false
|
||||||
|
binding.episodeResultText.isVisible = false
|
||||||
|
binding.serverResultText.isVisible = false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun cancelJob() {
|
||||||
|
job?.cancel()
|
||||||
|
job = null
|
||||||
|
binding.extensionLoading.isVisible = false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun startTest() {
|
||||||
|
pingResult = null
|
||||||
|
searchResultSize = null
|
||||||
|
episodeResultSize = null
|
||||||
|
serverResultSize = null
|
||||||
|
isRunning = true
|
||||||
|
hideAllResults()
|
||||||
|
job?.cancel()
|
||||||
|
job = Job()
|
||||||
|
CoroutineScope(Dispatchers.IO + job!!).launch {
|
||||||
|
when (extensionType) {
|
||||||
|
"anime" -> {
|
||||||
|
val extension = extension as AnimeParser
|
||||||
|
runAnimeTest(extension)
|
||||||
|
}
|
||||||
|
|
||||||
|
"manga" -> {
|
||||||
|
val extension = extension as MangaParser
|
||||||
|
runMangaTest(extension)
|
||||||
|
}
|
||||||
|
|
||||||
|
"novel" -> {
|
||||||
|
val extension = extension as NovelParser
|
||||||
|
runNovelTest(extension)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun runAnimeTest(extension: AnimeParser) {
|
||||||
|
pingResult = extension.ping()
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
pingResult()
|
||||||
|
}
|
||||||
|
if (testType == "ping") {
|
||||||
|
done()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val searchResult = extension.search(searchString)
|
||||||
|
searchResultSize = searchResult.size
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
searchResult()
|
||||||
|
}
|
||||||
|
if (searchResultSize == 0 || testType == "basic") {
|
||||||
|
done()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val episodeResult = extension.loadEpisodes("", null, searchResult.first().sAnime!!)
|
||||||
|
episodeResultSize = episodeResult.size
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
episodeResult()
|
||||||
|
}
|
||||||
|
if (episodeResultSize == 0) {
|
||||||
|
done()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val serverResult = extension.loadVideoServers("", null, episodeResult.first().sEpisode!!)
|
||||||
|
serverResultSize = serverResult.size
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
serverResult()
|
||||||
|
}
|
||||||
|
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun runMangaTest(extension: MangaParser) {
|
||||||
|
pingResult = extension.ping()
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
pingResult()
|
||||||
|
}
|
||||||
|
if (testType == "ping") {
|
||||||
|
done()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val searchResult = extension.search(searchString)
|
||||||
|
searchResultSize = searchResult.size
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
searchResult()
|
||||||
|
}
|
||||||
|
if (searchResultSize == 0 || testType == "basic") {
|
||||||
|
done()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val chapterResult = extension.loadChapters("", null, searchResult.first().sManga!!)
|
||||||
|
episodeResultSize = chapterResult.size
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
episodeResult()
|
||||||
|
}
|
||||||
|
if (episodeResultSize == 0) {
|
||||||
|
done()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val serverResult = extension.loadImages("", chapterResult.first().sChapter)
|
||||||
|
serverResultSize = serverResult.size
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
serverResult()
|
||||||
|
}
|
||||||
|
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
if (::binding.isInitialized )
|
||||||
|
binding.extensionLoading.isVisible = false
|
||||||
|
isRunning = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun runNovelTest(extension: NovelParser) {
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
pingResult()
|
||||||
|
}
|
||||||
|
if (testType == "ping") {
|
||||||
|
done()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val searchResult = extension.search(searchString)
|
||||||
|
searchResultSize = searchResult.size
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
searchResult()
|
||||||
|
}
|
||||||
|
if (searchResultSize == 0 || testType == "basic") {
|
||||||
|
done()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val chapterResult = extension.loadBook(searchResult.first().link, null)
|
||||||
|
episodeResultSize = chapterResult.links.size
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
episodeResult()
|
||||||
|
serverResult()
|
||||||
|
}
|
||||||
|
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
if (::binding.isInitialized )
|
||||||
|
binding.extensionLoading.isVisible = false
|
||||||
|
isRunning = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun done() {
|
||||||
|
if (::binding.isInitialized.not()) return
|
||||||
|
binding.extensionLoading.isVisible = false
|
||||||
|
isRunning = false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun pingResult() {
|
||||||
|
if (::binding.isInitialized.not()) return
|
||||||
|
if (extensionType == "novel") {
|
||||||
|
binding.pingResultText.isVisible = true
|
||||||
|
binding.pingResultText.text = context.getString(R.string.test_not_supported)
|
||||||
|
binding.pingResultText.setCompoundDrawablesWithIntrinsicBounds(
|
||||||
|
R.drawable.ic_round_info_24, 0, 0, 0
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (pingResult == null) {
|
||||||
|
binding.pingResultText.isVisible = false
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
binding.pingResultText.isVisible = true
|
||||||
|
}
|
||||||
|
binding.pingResultText.setTextColor(
|
||||||
|
context.getThemeColor(com.google.android.material.R.attr.colorPrimary)
|
||||||
|
)
|
||||||
|
val (code, time, message) = pingResult!!
|
||||||
|
if (code == 200) {
|
||||||
|
binding.pingResultText.text = context.getString(R.string.ping_success, time.toString())
|
||||||
|
binding.pingResultText.setCompoundDrawablesWithIntrinsicBounds(
|
||||||
|
R.drawable.ic_circle_check, 0, 0, 0
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
binding.pingResultText.text =
|
||||||
|
context.getString(R.string.ping_error, code.toString(), message)
|
||||||
|
binding.pingResultText.setCompoundDrawablesWithIntrinsicBounds(
|
||||||
|
R.drawable.ic_circle_cancel, 0, 0, 0
|
||||||
|
)
|
||||||
|
binding.pingResultText.setTextColor(
|
||||||
|
context.getThemeColor(com.google.android.material.R.attr.colorError)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun searchResult() {
|
||||||
|
if (::binding.isInitialized.not()) return
|
||||||
|
if (searchResultSize == null) {
|
||||||
|
binding.searchResultText.isVisible = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
binding.searchResultText.setTextColor(
|
||||||
|
context.getThemeColor(com.google.android.material.R.attr.colorPrimary)
|
||||||
|
)
|
||||||
|
binding.searchResultText.isVisible = true
|
||||||
|
if (searchResultSize == 0) {
|
||||||
|
val text = context.getString(R.string.title_search_test,
|
||||||
|
context.getString(R.string.no_results_found))
|
||||||
|
binding.searchResultText.text = text
|
||||||
|
binding.searchResultText.setCompoundDrawablesWithIntrinsicBounds(
|
||||||
|
R.drawable.ic_circle_cancel, 0, 0, 0
|
||||||
|
)
|
||||||
|
binding.searchResultText.setTextColor(
|
||||||
|
context.getThemeColor(com.google.android.material.R.attr.colorError)
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val text = context.getString(R.string.title_search_test,
|
||||||
|
context.getString(R.string.results_found, searchResultSize.toString()))
|
||||||
|
binding.searchResultText.text = text
|
||||||
|
binding.searchResultText.setCompoundDrawablesWithIntrinsicBounds(
|
||||||
|
R.drawable.ic_circle_check, 0, 0, 0
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun episodeResult() {
|
||||||
|
if (::binding.isInitialized.not()) return
|
||||||
|
if (episodeResultSize == null) {
|
||||||
|
binding.episodeResultText.isVisible = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
binding.episodeResultText.setTextColor(
|
||||||
|
context.getThemeColor(com.google.android.material.R.attr.colorPrimary)
|
||||||
|
)
|
||||||
|
binding.episodeResultText.isVisible = true
|
||||||
|
if (episodeResultSize == 0) {
|
||||||
|
val text = when(extensionType) {
|
||||||
|
"anime" -> context.getString(R.string.episode_search_test,
|
||||||
|
context.getString(R.string.no_results_found))
|
||||||
|
"manga" -> context.getString(R.string.chapter_search_test,
|
||||||
|
context.getString(R.string.no_results_found))
|
||||||
|
else -> context.getString(R.string.book_search_test,
|
||||||
|
context.getString(R.string.no_results_found))
|
||||||
|
}
|
||||||
|
binding.episodeResultText.text = text
|
||||||
|
binding.episodeResultText.setCompoundDrawablesWithIntrinsicBounds(
|
||||||
|
R.drawable.ic_circle_cancel, 0, 0, 0
|
||||||
|
)
|
||||||
|
binding.episodeResultText.setTextColor(
|
||||||
|
context.getThemeColor(com.google.android.material.R.attr.colorError)
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val text = when(extensionType) {
|
||||||
|
"anime" -> context.getString(R.string.episode_search_test,
|
||||||
|
context.getString(R.string.results_found, episodeResultSize.toString()))
|
||||||
|
"manga" -> context.getString(R.string.chapter_search_test,
|
||||||
|
context.getString(R.string.results_found, episodeResultSize.toString()))
|
||||||
|
else -> context.getString(R.string.book_search_test,
|
||||||
|
context.getString(R.string.results_found, episodeResultSize.toString()))
|
||||||
|
}
|
||||||
|
binding.episodeResultText.text = text
|
||||||
|
binding.episodeResultText.setCompoundDrawablesWithIntrinsicBounds(
|
||||||
|
R.drawable.ic_circle_check, 0, 0, 0
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun serverResult() {
|
||||||
|
if (::binding.isInitialized.not()) return
|
||||||
|
if (extensionType == "novel") {
|
||||||
|
binding.pingResultText.isVisible = true
|
||||||
|
binding.pingResultText.text = context.getString(R.string.test_not_supported)
|
||||||
|
binding.pingResultText.setCompoundDrawablesWithIntrinsicBounds(
|
||||||
|
R.drawable.ic_round_info_24, 0, 0, 0
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (serverResultSize == null) {
|
||||||
|
binding.serverResultText.isVisible = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
binding.serverResultText.setTextColor(
|
||||||
|
context.getThemeColor(com.google.android.material.R.attr.colorPrimary)
|
||||||
|
)
|
||||||
|
binding.serverResultText.isVisible = true
|
||||||
|
if (serverResultSize == 0) {
|
||||||
|
val text = when(extensionType) {
|
||||||
|
"anime" -> context.getString(R.string.video_search_test,
|
||||||
|
context.getString(R.string.no_results_found))
|
||||||
|
"manga" -> context.getString(R.string.image_search_test,
|
||||||
|
context.getString(R.string.no_results_found))
|
||||||
|
else -> context.getString(R.string.book_search_test,
|
||||||
|
context.getString(R.string.no_results_found))
|
||||||
|
}
|
||||||
|
binding.serverResultText.text = text
|
||||||
|
binding.serverResultText.setCompoundDrawablesWithIntrinsicBounds(
|
||||||
|
R.drawable.ic_circle_cancel, 0, 0, 0
|
||||||
|
)
|
||||||
|
binding.serverResultText.setTextColor(
|
||||||
|
context.getThemeColor(com.google.android.material.R.attr.colorError)
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val text = when(extensionType) {
|
||||||
|
"anime" -> context.getString(R.string.video_search_test,
|
||||||
|
context.getString(R.string.results_found, serverResultSize.toString()))
|
||||||
|
"manga" -> context.getString(R.string.image_search_test,
|
||||||
|
context.getString(R.string.results_found, serverResultSize.toString()))
|
||||||
|
else -> context.getString(R.string.book_search_test,
|
||||||
|
context.getString(R.string.results_found, serverResultSize.toString()))
|
||||||
|
}
|
||||||
|
binding.serverResultText.text = text
|
||||||
|
binding.serverResultText.setCompoundDrawablesWithIntrinsicBounds(
|
||||||
|
R.drawable.ic_circle_check, 0, 0, 0
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,117 @@
|
||||||
|
package ani.dantotsu.parsers
|
||||||
|
|
||||||
|
import android.graphics.drawable.Drawable
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import ani.dantotsu.BottomSheetDialogFragment
|
||||||
|
import ani.dantotsu.databinding.BottomSheetExtensionTestSettingsBinding
|
||||||
|
import ani.dantotsu.parsers.novel.NovelExtensionManager
|
||||||
|
import com.xwray.groupie.GroupieAdapter
|
||||||
|
import eu.kanade.tachiyomi.extension.anime.AnimeExtensionManager
|
||||||
|
import eu.kanade.tachiyomi.extension.manga.MangaExtensionManager
|
||||||
|
import uy.kohesive.injekt.Injekt
|
||||||
|
import uy.kohesive.injekt.api.get
|
||||||
|
|
||||||
|
class ExtensionTestSettingsBottomDialog : BottomSheetDialogFragment() {
|
||||||
|
private var _binding: BottomSheetExtensionTestSettingsBinding? = null
|
||||||
|
private val binding get() = _binding!!
|
||||||
|
private val adapter: GroupieAdapter = GroupieAdapter()
|
||||||
|
private val animeExtension: AnimeExtensionManager = Injekt.get()
|
||||||
|
private val mangaExtensions: MangaExtensionManager = Injekt.get()
|
||||||
|
private val novelExtensions: NovelExtensionManager = Injekt.get()
|
||||||
|
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater,
|
||||||
|
container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View? {
|
||||||
|
_binding = BottomSheetExtensionTestSettingsBinding.inflate(inflater, container, false)
|
||||||
|
return _binding?.root
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
binding.extensionSelectionRecyclerView.adapter = adapter
|
||||||
|
binding.extensionSelectionRecyclerView.layoutManager = LinearLayoutManager(
|
||||||
|
context,
|
||||||
|
LinearLayoutManager.VERTICAL,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
binding.animeRadioButton.setOnCheckedChangeListener { _, b ->
|
||||||
|
if (b) {
|
||||||
|
extensionType = "anime"
|
||||||
|
extensionsToTest.clear()
|
||||||
|
setupAdapter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding.mangaRadioButton.setOnCheckedChangeListener { _, b ->
|
||||||
|
if (b) {
|
||||||
|
extensionType = "manga"
|
||||||
|
extensionsToTest.clear()
|
||||||
|
setupAdapter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding.novelsRadioButton.setOnCheckedChangeListener { _, b ->
|
||||||
|
if (b) {
|
||||||
|
extensionType = "novel"
|
||||||
|
extensionsToTest.clear()
|
||||||
|
setupAdapter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding.pingRadioButton.setOnCheckedChangeListener { _, b ->
|
||||||
|
if (b) {
|
||||||
|
testType = "ping"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding.basicRadioButton.setOnCheckedChangeListener { _, b ->
|
||||||
|
if (b) {
|
||||||
|
testType = "basic"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding.fullRadioButton.setOnCheckedChangeListener { _, b ->
|
||||||
|
if (b) {
|
||||||
|
testType = "full"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setupAdapter()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
_binding = null
|
||||||
|
super.onDestroyView()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupAdapter() {
|
||||||
|
val namesAndUrls: Map<String,Drawable?> = when (extensionType) {
|
||||||
|
"anime" -> animeExtension.installedExtensionsFlow.value.associate { it.name to it.icon }
|
||||||
|
"manga" -> mangaExtensions.installedExtensionsFlow.value.associate { it.name to it.icon }
|
||||||
|
"novel" -> novelExtensions.installedExtensionsFlow.value.associate { it.name to it.icon }
|
||||||
|
else -> emptyMap()
|
||||||
|
}
|
||||||
|
adapter.clear()
|
||||||
|
namesAndUrls.forEach { (name, icon) ->
|
||||||
|
val isSelected = extensionsToTest.contains(name)
|
||||||
|
adapter.add(ExtensionSelectItem(name, icon, isSelected, ::selectedCallback))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun selectedCallback(name: String, isSelected: Boolean) {
|
||||||
|
if (isSelected) {
|
||||||
|
extensionsToTest.add(name)
|
||||||
|
} else {
|
||||||
|
extensionsToTest.remove(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun newInstance(): ExtensionTestSettingsBottomDialog {
|
||||||
|
return ExtensionTestSettingsBottomDialog()
|
||||||
|
}
|
||||||
|
|
||||||
|
var extensionType = "anime"
|
||||||
|
var testType = "ping"
|
||||||
|
var extensionsToTest: MutableList<String> = mutableListOf()
|
||||||
|
}
|
||||||
|
}
|
112
app/src/main/java/ani/dantotsu/parsers/ParserTestActivity.kt
Normal file
112
app/src/main/java/ani/dantotsu/parsers/ParserTestActivity.kt
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
package ani.dantotsu.parsers
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.core.view.updateLayoutParams
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import ani.dantotsu.R
|
||||||
|
import ani.dantotsu.databinding.ActivityParserTestBinding
|
||||||
|
import ani.dantotsu.initActivity
|
||||||
|
import ani.dantotsu.navBarHeight
|
||||||
|
import ani.dantotsu.statusBarHeight
|
||||||
|
import ani.dantotsu.themes.ThemeManager
|
||||||
|
import ani.dantotsu.toast
|
||||||
|
import com.xwray.groupie.GroupieAdapter
|
||||||
|
|
||||||
|
class ParserTestActivity : AppCompatActivity() {
|
||||||
|
private lateinit var binding: ActivityParserTestBinding
|
||||||
|
val adapter = GroupieAdapter()
|
||||||
|
val extensionsToTest: MutableList<ExtensionTestItem> = mutableListOf()
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
ThemeManager(this).applyTheme()
|
||||||
|
initActivity(this)
|
||||||
|
binding = ActivityParserTestBinding.inflate(layoutInflater)
|
||||||
|
binding.toolbar.updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
||||||
|
topMargin = statusBarHeight
|
||||||
|
}
|
||||||
|
binding.extensionResultsRecyclerView.updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
||||||
|
bottomMargin = navBarHeight
|
||||||
|
}
|
||||||
|
setContentView(binding.root)
|
||||||
|
|
||||||
|
binding.extensionResultsRecyclerView.adapter = adapter
|
||||||
|
binding.extensionResultsRecyclerView.layoutManager = LinearLayoutManager(
|
||||||
|
this,
|
||||||
|
LinearLayoutManager.VERTICAL,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
binding.backButton.setOnClickListener {
|
||||||
|
onBackPressedDispatcher.onBackPressed()
|
||||||
|
}
|
||||||
|
binding.optionsLayout.setOnClickListener {
|
||||||
|
ExtensionTestSettingsBottomDialog.newInstance()
|
||||||
|
.show(supportFragmentManager, "extension_test_settings")
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.startButton.setOnClickListener {
|
||||||
|
if (ExtensionTestSettingsBottomDialog.extensionsToTest.isEmpty()) {
|
||||||
|
toast(R.string.no_extensions_selected)
|
||||||
|
return@setOnClickListener
|
||||||
|
}
|
||||||
|
extensionsToTest.forEach {
|
||||||
|
it.cancelJob()
|
||||||
|
}
|
||||||
|
extensionsToTest.clear()
|
||||||
|
adapter.clear()
|
||||||
|
when (ExtensionTestSettingsBottomDialog.extensionType) {
|
||||||
|
"anime" -> {
|
||||||
|
ExtensionTestSettingsBottomDialog.extensionsToTest.forEach { name ->
|
||||||
|
val extension =
|
||||||
|
AnimeSources.list.find { source -> source.name == name }?.get?.value
|
||||||
|
extension?.let {
|
||||||
|
extensionsToTest.add(
|
||||||
|
ExtensionTestItem(
|
||||||
|
"anime",
|
||||||
|
ExtensionTestSettingsBottomDialog.testType,
|
||||||
|
it
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"manga" -> {
|
||||||
|
ExtensionTestSettingsBottomDialog.extensionsToTest.forEach { name ->
|
||||||
|
val extension =
|
||||||
|
MangaSources.list.find { source -> source.name == name }?.get?.value
|
||||||
|
extension?.let {
|
||||||
|
extensionsToTest.add(
|
||||||
|
ExtensionTestItem(
|
||||||
|
"manga",
|
||||||
|
ExtensionTestSettingsBottomDialog.testType,
|
||||||
|
it
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"novel" -> {
|
||||||
|
ExtensionTestSettingsBottomDialog.extensionsToTest.forEach { name ->
|
||||||
|
val extension =
|
||||||
|
NovelSources.list.find { source -> source.name == name }?.get?.value
|
||||||
|
extension?.let {
|
||||||
|
extensionsToTest.add(
|
||||||
|
ExtensionTestItem(
|
||||||
|
"novel",
|
||||||
|
ExtensionTestSettingsBottomDialog.testType,
|
||||||
|
it
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
extensionsToTest.forEach {
|
||||||
|
adapter.add(it)
|
||||||
|
it.startTest()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
package ani.dantotsu.settings
|
package ani.dantotsu.settings
|
||||||
|
|
||||||
import android.app.AlertDialog
|
import android.app.AlertDialog
|
||||||
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.Editable
|
import android.text.Editable
|
||||||
import android.text.TextWatcher
|
import android.text.TextWatcher
|
||||||
|
@ -13,6 +14,7 @@ import android.view.inputmethod.EditorInfo
|
||||||
import android.widget.AutoCompleteTextView
|
import android.widget.AutoCompleteTextView
|
||||||
import android.widget.EditText
|
import android.widget.EditText
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.view.updateLayoutParams
|
import androidx.core.view.updateLayoutParams
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.viewpager2.adapter.FragmentStateAdapter
|
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||||
|
@ -28,6 +30,7 @@ import ani.dantotsu.media.MediaType
|
||||||
import ani.dantotsu.navBarHeight
|
import ani.dantotsu.navBarHeight
|
||||||
import ani.dantotsu.others.AndroidBug5497Workaround
|
import ani.dantotsu.others.AndroidBug5497Workaround
|
||||||
import ani.dantotsu.others.LanguageMapper
|
import ani.dantotsu.others.LanguageMapper
|
||||||
|
import ani.dantotsu.parsers.ParserTestActivity
|
||||||
import ani.dantotsu.settings.saving.PrefManager
|
import ani.dantotsu.settings.saving.PrefManager
|
||||||
import ani.dantotsu.settings.saving.PrefName
|
import ani.dantotsu.settings.saving.PrefName
|
||||||
import ani.dantotsu.statusBarHeight
|
import ani.dantotsu.statusBarHeight
|
||||||
|
@ -70,6 +73,14 @@ class ExtensionsActivity : AppCompatActivity() {
|
||||||
bottomMargin = statusBarHeight + navBarHeight
|
bottomMargin = statusBarHeight + navBarHeight
|
||||||
}
|
}
|
||||||
|
|
||||||
|
binding.testButton.setOnClickListener {
|
||||||
|
ContextCompat.startActivity(
|
||||||
|
this,
|
||||||
|
Intent(this, ParserTestActivity::class.java),
|
||||||
|
null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
val tabLayout = findViewById<TabLayout>(R.id.tabLayout)
|
val tabLayout = findViewById<TabLayout>(R.id.tabLayout)
|
||||||
val viewPager = findViewById<ViewPager2>(R.id.viewPager)
|
val viewPager = findViewById<ViewPager2>(R.id.viewPager)
|
||||||
viewPager.offscreenPageLimit = 1
|
viewPager.offscreenPageLimit = 1
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package ani.dantotsu.settings
|
package ani.dantotsu.settings
|
||||||
|
|
||||||
import android.app.AlertDialog
|
import android.app.AlertDialog
|
||||||
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.HapticFeedbackConstants
|
import android.view.HapticFeedbackConstants
|
||||||
import android.view.KeyEvent
|
import android.view.KeyEvent
|
||||||
|
@ -9,6 +10,7 @@ import android.view.ViewGroup
|
||||||
import android.view.inputmethod.EditorInfo
|
import android.view.inputmethod.EditorInfo
|
||||||
import android.widget.EditText
|
import android.widget.EditText
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.core.view.updateLayoutParams
|
import androidx.core.view.updateLayoutParams
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
@ -20,6 +22,7 @@ import ani.dantotsu.databinding.ItemRepositoryBinding
|
||||||
import ani.dantotsu.initActivity
|
import ani.dantotsu.initActivity
|
||||||
import ani.dantotsu.media.MediaType
|
import ani.dantotsu.media.MediaType
|
||||||
import ani.dantotsu.navBarHeight
|
import ani.dantotsu.navBarHeight
|
||||||
|
import ani.dantotsu.parsers.ParserTestActivity
|
||||||
import ani.dantotsu.settings.saving.PrefManager
|
import ani.dantotsu.settings.saving.PrefManager
|
||||||
import ani.dantotsu.settings.saving.PrefName
|
import ani.dantotsu.settings.saving.PrefName
|
||||||
import ani.dantotsu.statusBarHeight
|
import ani.dantotsu.statusBarHeight
|
||||||
|
@ -232,6 +235,20 @@ class SettingsExtensionsActivity : AppCompatActivity() {
|
||||||
setExtensionOutput(it.attachView, MediaType.MANGA)
|
setExtensionOutput(it.attachView, MediaType.MANGA)
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
|
Settings(
|
||||||
|
type = 1,
|
||||||
|
name = getString(R.string.extension_test),
|
||||||
|
desc = getString(R.string.extension_test_desc),
|
||||||
|
icon = R.drawable.ic_round_search_sources_24,
|
||||||
|
isActivity = true,
|
||||||
|
onClick = {
|
||||||
|
ContextCompat.startActivity(
|
||||||
|
context,
|
||||||
|
Intent(context, ParserTestActivity::class.java),
|
||||||
|
null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
),
|
||||||
Settings(
|
Settings(
|
||||||
type = 1,
|
type = 1,
|
||||||
name = getString(R.string.user_agent),
|
name = getString(R.string.user_agent),
|
||||||
|
|
|
@ -41,6 +41,15 @@
|
||||||
android:layout_marginHorizontal="16dp"
|
android:layout_marginHorizontal="16dp"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/testButton"
|
||||||
|
android:layout_width="48dp"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:contentDescription="@string/sort_by"
|
||||||
|
app:srcCompat="@drawable/ic_round_search_sources_24"
|
||||||
|
app:tint="?attr/colorOnBackground" />
|
||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
android:id="@+id/openSettingsButton"
|
android:id="@+id/openSettingsButton"
|
||||||
android:layout_width="48dp"
|
android:layout_width="48dp"
|
||||||
|
|
109
app/src/main/res/layout/activity_parser_test.xml
Normal file
109
app/src/main/res/layout/activity_parser_test.xml
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:context=".settings.SettingsNotificationActivity">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/toolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/backButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="start|center_vertical"
|
||||||
|
android:layout_marginStart="12dp"
|
||||||
|
android:src="@drawable/ic_round_arrow_back_ios_new_24"
|
||||||
|
app:tint="?attr/colorOnBackground"
|
||||||
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:layout_marginStart="44dp"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:fontFamily="@font/poppins_bold"
|
||||||
|
android:gravity="center|start"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:textAppearance="@style/TextAppearance.Widget.AppCompat.Toolbar.Title"
|
||||||
|
android:textColor="?attr/colorOnBackground"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:text="@string/extension_test" />
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/optionsLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="16dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:layout_marginVertical="16dp"
|
||||||
|
android:layout_marginEnd="24dp"
|
||||||
|
app:srcCompat="@drawable/ic_round_filter_24"
|
||||||
|
app:tint="?attr/colorPrimary"
|
||||||
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:fontFamily="@font/poppins_bold"
|
||||||
|
android:text="@string/view_options"
|
||||||
|
android:textColor="?attr/colorOnSurface"
|
||||||
|
android:textSize="16sp" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_marginVertical="16dp"
|
||||||
|
android:rotation="180"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:srcCompat="@drawable/ic_round_arrow_back_ios_new_24"
|
||||||
|
app:tint="?attr/colorPrimary"
|
||||||
|
tools:ignore="ContentDescription"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/startButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:layout_marginVertical="16dp"
|
||||||
|
android:backgroundTint="?attr/colorPrimaryContainer"
|
||||||
|
android:fontFamily="@font/poppins_bold"
|
||||||
|
android:text="@string/start_test"
|
||||||
|
android:textColor="?attr/colorOnPrimaryContainer"
|
||||||
|
app:cornerRadius="12dp"
|
||||||
|
app:iconTint="?attr/colorOnPrimaryContainer" />
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/extensionResultsRecyclerView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:nestedScrollingEnabled="false"
|
||||||
|
android:paddingStart="16dp"
|
||||||
|
android:paddingEnd="16dp"
|
||||||
|
android:paddingBottom="16dp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</androidx.core.widget.NestedScrollView>
|
100
app/src/main/res/layout/bottom_sheet_extension_test_settings.xml
Normal file
100
app/src/main/res/layout/bottom_sheet_extension_test_settings.xml
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_marginVertical="16dp"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical|center_horizontal"
|
||||||
|
android:fontFamily="@font/poppins_bold"
|
||||||
|
android:text="@string/extension_type"
|
||||||
|
android:textAlignment="center"
|
||||||
|
android:textSize="16sp" />
|
||||||
|
|
||||||
|
<RadioGroup
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<com.google.android.material.radiobutton.MaterialRadioButton
|
||||||
|
android:id="@+id/animeRadioButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:checked="true"
|
||||||
|
android:text="@string/anime"
|
||||||
|
android:textSize="16sp" />
|
||||||
|
|
||||||
|
<com.google.android.material.radiobutton.MaterialRadioButton
|
||||||
|
android:id="@+id/mangaRadioButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:text="@string/manga"
|
||||||
|
android:textSize="16sp" />
|
||||||
|
|
||||||
|
<com.google.android.material.radiobutton.MaterialRadioButton
|
||||||
|
android:id="@+id/novelsRadioButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/novels"
|
||||||
|
android:textSize="16sp" />
|
||||||
|
|
||||||
|
</RadioGroup>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical|center_horizontal"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:fontFamily="@font/poppins_bold"
|
||||||
|
android:text="@string/test_type"
|
||||||
|
android:textAlignment="center"
|
||||||
|
android:textSize="16sp" />
|
||||||
|
|
||||||
|
<RadioGroup
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<com.google.android.material.radiobutton.MaterialRadioButton
|
||||||
|
android:id="@+id/pingRadioButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:checked="true"
|
||||||
|
android:text="@string/ping"
|
||||||
|
android:textSize="16sp" />
|
||||||
|
|
||||||
|
<com.google.android.material.radiobutton.MaterialRadioButton
|
||||||
|
android:id="@+id/basicRadioButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:text="@string/basic"
|
||||||
|
android:textSize="16sp" />
|
||||||
|
|
||||||
|
<com.google.android.material.radiobutton.MaterialRadioButton
|
||||||
|
android:id="@+id/fullRadioButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/full"
|
||||||
|
android:textSize="16sp" />
|
||||||
|
|
||||||
|
</RadioGroup>
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/extensionSelectionRecyclerView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:paddingStart="16dp"
|
||||||
|
android:paddingEnd="16dp"
|
||||||
|
android:paddingBottom="16dp"
|
||||||
|
tools:listitem="@layout/item_extension_select"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
40
app/src/main/res/layout/item_extension_select.xml
Normal file
40
app/src/main/res/layout/item_extension_select.xml
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/extensionCardView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?attr/colorSurface"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:paddingTop="10dp"
|
||||||
|
android:paddingBottom="10dp">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/extensionIconImageView"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:layout_marginStart="10dp"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:layout_marginEnd="3dp"
|
||||||
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/extensionNameTextView"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="10dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:fontFamily="@font/poppins_semi_bold"
|
||||||
|
android:text="@string/extension_name"
|
||||||
|
android:textSize="15sp" />
|
||||||
|
|
||||||
|
<com.google.android.material.checkbox.MaterialCheckBox
|
||||||
|
android:id="@+id/extensionCheckBox"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical|end"
|
||||||
|
android:layout_marginStart="10dp"
|
||||||
|
android:layout_marginEnd="10dp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
111
app/src/main/res/layout/item_extension_test.xml
Normal file
111
app/src/main/res/layout/item_extension_test.xml
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/extensionCardView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?attr/colorSurface"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingTop="10dp"
|
||||||
|
android:paddingBottom="10dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
tools:ignore="UseCompoundDrawables">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/extensionIconImageView"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:layout_marginStart="10dp"
|
||||||
|
android:layout_marginEnd="3dp"
|
||||||
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/extensionNameTextView"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:layout_marginStart="10dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:fontFamily="@font/poppins_semi_bold"
|
||||||
|
android:text="@string/extension_name"
|
||||||
|
android:textSize="15sp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/resultLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/pingResultText"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:drawablePadding="10dp"
|
||||||
|
android:fontFamily="@font/poppins_semi_bold"
|
||||||
|
android:text="@string/placeholder"
|
||||||
|
android:textSize="13sp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:layout_marginStart="10dp"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
app:drawableStartCompat="@drawable/ic_round_help_24" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/searchResultText"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:drawablePadding="10dp"
|
||||||
|
android:fontFamily="@font/poppins_semi_bold"
|
||||||
|
android:text="@string/placeholder"
|
||||||
|
android:textSize="13sp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:layout_marginStart="10dp"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
app:drawableStartCompat="@drawable/ic_round_help_24" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/episodeResultText"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:drawablePadding="10dp"
|
||||||
|
android:fontFamily="@font/poppins_semi_bold"
|
||||||
|
android:text="@string/placeholder"
|
||||||
|
android:textSize="13sp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:layout_marginStart="10dp"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
app:drawableStartCompat="@drawable/ic_round_help_24" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/serverResultText"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:drawablePadding="10dp"
|
||||||
|
android:fontFamily="@font/poppins_semi_bold"
|
||||||
|
android:text="@string/placeholder"
|
||||||
|
android:textSize="13sp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:layout_marginStart="10dp"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
app:drawableStartCompat="@drawable/ic_round_help_24" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/extensionLoading"
|
||||||
|
style="?android:attr/progressBarStyle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:layout_marginVertical="10dp"
|
||||||
|
android:visibility="visible" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
|
@ -996,4 +996,25 @@ Non quae tempore quo provident laudantium qui illo dolor vel quia dolor et exerc
|
||||||
<string name="subscriptions">Subscriptions</string>
|
<string name="subscriptions">Subscriptions</string>
|
||||||
<string name="subscription_deleted">Subscription Deleted</string>
|
<string name="subscription_deleted">Subscription Deleted</string>
|
||||||
<string name="foreground_service_not_allowed">Cannot install when app is in background</string>
|
<string name="foreground_service_not_allowed">Cannot install when app is in background</string>
|
||||||
|
<string name="ping">Ping</string>
|
||||||
|
<string name="basic">Basic</string>
|
||||||
|
<string name="full">Full</string>
|
||||||
|
<string name="test_type">Test Type</string>
|
||||||
|
<string name="extension_type">Extension Type</string>
|
||||||
|
<string name="view_options">View Options</string>
|
||||||
|
<string name="extension_test">Extension Test</string>
|
||||||
|
<string name="extension_test_desc">Test if the extensions are working</string>
|
||||||
|
<string name="start_test">Start Test</string>
|
||||||
|
<string name="no_extensions_selected">No extensions selected</string>
|
||||||
|
<string name="ping_success">Ping successful: %1$s ms</string>
|
||||||
|
<string name="ping_error">Ping failed. Code: %1$s, Message: %2$s</string>
|
||||||
|
<string name="test_not_supported">Test not supported for this extension</string>
|
||||||
|
<string name="no_results_found">No results found. Extension may be broken</string>
|
||||||
|
<string name="results_found">%1$s results found</string>
|
||||||
|
<string name="title_search_test">Title Search Test: %1$s</string>
|
||||||
|
<string name="episode_search_test">Episode Search Test: %1$s</string>
|
||||||
|
<string name="chapter_search_test">Chapter Search Test: %1$s</string>
|
||||||
|
<string name="video_search_test">Video Search Test: %1$s</string>
|
||||||
|
<string name="image_search_test">Image Search Test: %1$s</string>
|
||||||
|
<string name="book_search_test">Book Search Test: %1$s</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue