various fixes and updates
This commit is contained in:
parent
da81646297
commit
d1270c7c83
21 changed files with 487 additions and 162 deletions
|
@ -97,6 +97,9 @@ dependencies {
|
||||||
implementation 'com.alexvasilkov:gesture-views:2.8.3'
|
implementation 'com.alexvasilkov:gesture-views:2.8.3'
|
||||||
implementation 'com.github.VipulOG:ebook-reader:0.1.6'
|
implementation 'com.github.VipulOG:ebook-reader:0.1.6'
|
||||||
|
|
||||||
|
// string matching
|
||||||
|
implementation 'me.xdrop:fuzzywuzzy:1.4.0'
|
||||||
|
|
||||||
// Aniyomi
|
// Aniyomi
|
||||||
implementation 'io.reactivex:rxjava:1.3.8'
|
implementation 'io.reactivex:rxjava:1.3.8'
|
||||||
implementation 'io.reactivex:rxandroid:1.2.1'
|
implementation 'io.reactivex:rxandroid:1.2.1'
|
||||||
|
|
|
@ -11,6 +11,7 @@ import ani.dantotsu.aniyomi.anime.custom.PreferenceModule
|
||||||
import eu.kanade.tachiyomi.data.notification.Notifications
|
import eu.kanade.tachiyomi.data.notification.Notifications
|
||||||
import tachiyomi.core.util.system.logcat
|
import tachiyomi.core.util.system.logcat
|
||||||
import ani.dantotsu.others.DisabledReports
|
import ani.dantotsu.others.DisabledReports
|
||||||
|
import com.google.android.material.color.DynamicColors
|
||||||
import com.google.firebase.crashlytics.ktx.crashlytics
|
import com.google.firebase.crashlytics.ktx.crashlytics
|
||||||
import com.google.firebase.ktx.Firebase
|
import com.google.firebase.ktx.Firebase
|
||||||
import logcat.AndroidLogcatLogger
|
import logcat.AndroidLogcatLogger
|
||||||
|
@ -33,6 +34,11 @@ class App : MultiDexApplication() {
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
|
val sharedPreferences = getSharedPreferences("Dantotsu", Context.MODE_PRIVATE)
|
||||||
|
val useMaterialYou = sharedPreferences.getBoolean("use_material_you", false)
|
||||||
|
if(useMaterialYou) {
|
||||||
|
DynamicColors.applyToActivitiesIfAvailable(this)
|
||||||
|
}
|
||||||
registerActivityLifecycleCallbacks(mFTActivityLifecycleCallbacks)
|
registerActivityLifecycleCallbacks(mFTActivityLifecycleCallbacks)
|
||||||
|
|
||||||
Firebase.crashlytics.setCrashlyticsCollectionEnabled(!DisabledReports)
|
Firebase.crashlytics.setCrashlyticsCollectionEnabled(!DisabledReports)
|
||||||
|
|
|
@ -10,6 +10,7 @@ import eu.kanade.domain.source.service.SourcePreferences
|
||||||
import eu.kanade.tachiyomi.core.preference.AndroidPreferenceStore
|
import eu.kanade.tachiyomi.core.preference.AndroidPreferenceStore
|
||||||
import eu.kanade.tachiyomi.extension.manga.MangaExtensionManager
|
import eu.kanade.tachiyomi.extension.manga.MangaExtensionManager
|
||||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||||
|
import eu.kanade.tachiyomi.network.NetworkPreferences
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import uy.kohesive.injekt.api.InjektModule
|
import uy.kohesive.injekt.api.InjektModule
|
||||||
import uy.kohesive.injekt.api.InjektRegistrar
|
import uy.kohesive.injekt.api.InjektRegistrar
|
||||||
|
@ -21,7 +22,7 @@ class AppModule(val app: Application) : InjektModule {
|
||||||
override fun InjektRegistrar.registerInjectables() {
|
override fun InjektRegistrar.registerInjectables() {
|
||||||
addSingleton(app)
|
addSingleton(app)
|
||||||
|
|
||||||
addSingletonFactory { NetworkHelper(app) }
|
addSingletonFactory { NetworkHelper(app, get()) }
|
||||||
|
|
||||||
addSingletonFactory { AnimeExtensionManager(app) }
|
addSingletonFactory { AnimeExtensionManager(app) }
|
||||||
|
|
||||||
|
@ -44,6 +45,13 @@ class PreferenceModule(val application: Application) : InjektModule {
|
||||||
AndroidPreferenceStore(application)
|
AndroidPreferenceStore(application)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addSingletonFactory {
|
||||||
|
NetworkPreferences(
|
||||||
|
preferenceStore = get(),
|
||||||
|
verboseLogging = false,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
addSingletonFactory {
|
addSingletonFactory {
|
||||||
SourcePreferences(get())
|
SourcePreferences(get())
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,25 +50,14 @@ class MediaDetailsViewModel : ViewModel() {
|
||||||
|
|
||||||
fun loadSelected(media: Media): Selected {
|
fun loadSelected(media: Media): Selected {
|
||||||
val data = loadData<Selected>("${media.id}-select") ?: Selected().let {
|
val data = loadData<Selected>("${media.id}-select") ?: Selected().let {
|
||||||
it.source = if (media.isAdult) "" else when (media.anime != null) {
|
it.sourceIndex = if (media.isAdult) 0 else when (media.anime != null) {
|
||||||
true -> loadData("settings_def_anime_source") ?: ""
|
true -> loadData("settings_def_anime_source_s_r") ?: 0
|
||||||
else -> loadData("settings_def_manga_source") ?: ""
|
else -> loadData("settings_def_manga_source_s_r") ?: 0
|
||||||
}
|
}
|
||||||
it.preferDub = loadData("settings_prefer_dub") ?: false
|
it.preferDub = loadData("settings_prefer_dub") ?: false
|
||||||
it.sourceIndex = loadSelectedStringLocation(it.source)
|
|
||||||
saveSelected(media.id, it)
|
saveSelected(media.id, it)
|
||||||
it
|
it
|
||||||
}
|
}
|
||||||
if (media.anime != null) {
|
|
||||||
val sources = if (media.isAdult) HAnimeSources else AnimeSources
|
|
||||||
data.sourceIndex = sources.list.indexOfFirst { it.name == data.source }
|
|
||||||
} else {
|
|
||||||
val sources = if (media.isAdult) HMangaSources else MangaSources
|
|
||||||
data.sourceIndex = sources.list.indexOfFirst { it.name == data.source }
|
|
||||||
}
|
|
||||||
if (data.sourceIndex == -1) {
|
|
||||||
data.sourceIndex = 0
|
|
||||||
}
|
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,8 +183,8 @@ class MediaDetailsViewModel : ViewModel() {
|
||||||
val server = selected.server ?: return false
|
val server = selected.server ?: return false
|
||||||
val link = ep.link ?: return false
|
val link = ep.link ?: return false
|
||||||
|
|
||||||
ep.extractors = mutableListOf(watchSources?.get(loadSelectedStringLocation(selected.source))?.let {
|
ep.extractors = mutableListOf(watchSources?.get(selected.sourceIndex)?.let {
|
||||||
selected.sourceIndex = loadSelectedStringLocation(selected.source)
|
selected.sourceIndex = selected.sourceIndex
|
||||||
if (!post && !it.allowsPreloading) null
|
if (!post && !it.allowsPreloading) null
|
||||||
else ep.sEpisode?.let { it1 ->
|
else ep.sEpisode?.let { it1 ->
|
||||||
it.loadSingleVideoServer(server, link, ep.extra,
|
it.loadSingleVideoServer(server, link, ep.extra,
|
||||||
|
@ -266,7 +255,7 @@ class MediaDetailsViewModel : ViewModel() {
|
||||||
suspend fun loadMangaChapterImages(chapter: MangaChapter, selected: Selected, post: Boolean = true): Boolean {
|
suspend fun loadMangaChapterImages(chapter: MangaChapter, selected: Selected, post: Boolean = true): Boolean {
|
||||||
return tryWithSuspend(true) {
|
return tryWithSuspend(true) {
|
||||||
chapter.addImages(
|
chapter.addImages(
|
||||||
mangaReadSources?.get(loadSelectedStringLocation(selected.source))?.loadImages(chapter.link, chapter.sChapter) ?: return@tryWithSuspend false
|
mangaReadSources?.get(selected.sourceIndex)?.loadImages(chapter.link, chapter.sChapter) ?: return@tryWithSuspend false
|
||||||
)
|
)
|
||||||
if (post) mangaChapter.postValue(chapter)
|
if (post) mangaChapter.postValue(chapter)
|
||||||
true
|
true
|
||||||
|
@ -289,7 +278,7 @@ class MediaDetailsViewModel : ViewModel() {
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun autoSearchNovels(media: Media) {
|
suspend fun autoSearchNovels(media: Media) {
|
||||||
val source = novelSources[loadSelectedStringLocation(media.selected?.source?:"")]
|
val source = novelSources[media.selected?.sourceIndex?:0]
|
||||||
tryWithSuspend(post = true) {
|
tryWithSuspend(post = true) {
|
||||||
if (source != null) {
|
if (source != null) {
|
||||||
novelResponses.postValue(source.sortedSearch(media))
|
novelResponses.postValue(source.sortedSearch(media))
|
||||||
|
|
|
@ -7,7 +7,7 @@ data class Selected(
|
||||||
var recyclerStyle: Int? = null,
|
var recyclerStyle: Int? = null,
|
||||||
var recyclerReversed: Boolean = false,
|
var recyclerReversed: Boolean = false,
|
||||||
var chip: Int = 0,
|
var chip: Int = 0,
|
||||||
var source: String = "",
|
//var source: String = "",
|
||||||
var sourceIndex: Int = 0,
|
var sourceIndex: Int = 0,
|
||||||
var preferDub: Boolean = false,
|
var preferDub: Boolean = false,
|
||||||
var server: String? = null,
|
var server: String? = null,
|
||||||
|
|
|
@ -1,22 +1,33 @@
|
||||||
package ani.dantotsu.media.manga
|
package ani.dantotsu.media.manga
|
||||||
|
|
||||||
|
import android.content.ContentResolver
|
||||||
|
import android.content.ContentValues
|
||||||
|
import android.content.Context
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Build
|
||||||
|
import android.os.Environment
|
||||||
|
import android.provider.MediaStore
|
||||||
import android.util.LruCache
|
import android.util.LruCache
|
||||||
import eu.kanade.tachiyomi.source.model.Page
|
import eu.kanade.tachiyomi.source.model.Page
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
import java.io.File
|
||||||
|
import java.io.FileOutputStream
|
||||||
|
|
||||||
data class ImageData(
|
data class ImageData(
|
||||||
val page: Page,
|
val page: Page,
|
||||||
val source: HttpSource,
|
val source: HttpSource
|
||||||
){
|
){
|
||||||
suspend fun fetchAndProcessImage(page: Page, httpSource: HttpSource): Bitmap? {
|
suspend fun fetchAndProcessImage(page: Page, httpSource: HttpSource, context: Context): Bitmap? {
|
||||||
return withContext(Dispatchers.IO) {
|
return withContext(Dispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
// Fetch the image
|
// Fetch the image
|
||||||
val response = httpSource.getImage(page)
|
val response = httpSource.getImage(page)
|
||||||
|
println("Response: ${response.code}")
|
||||||
|
println("Response: ${response.message}")
|
||||||
|
|
||||||
// Convert the Response to an InputStream
|
// Convert the Response to an InputStream
|
||||||
val inputStream = response.body?.byteStream()
|
val inputStream = response.body?.byteStream()
|
||||||
|
@ -25,6 +36,7 @@ data class ImageData(
|
||||||
val bitmap = BitmapFactory.decodeStream(inputStream)
|
val bitmap = BitmapFactory.decodeStream(inputStream)
|
||||||
|
|
||||||
inputStream?.close()
|
inputStream?.close()
|
||||||
|
saveImage(bitmap, context.contentResolver, page.imageUrl!!, Bitmap.CompressFormat.JPEG, 100)
|
||||||
|
|
||||||
return@withContext bitmap
|
return@withContext bitmap
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
@ -36,6 +48,39 @@ data class ImageData(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun saveImage(bitmap: Bitmap, contentResolver: ContentResolver, filename: String, format: Bitmap.CompressFormat, quality: Int) {
|
||||||
|
try {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||||
|
val contentValues = ContentValues().apply {
|
||||||
|
put(MediaStore.MediaColumns.DISPLAY_NAME, filename)
|
||||||
|
put(MediaStore.MediaColumns.MIME_TYPE, "image/${format.name.lowercase()}")
|
||||||
|
put(MediaStore.MediaColumns.RELATIVE_PATH, "${Environment.DIRECTORY_DOWNLOADS}/Dantotsu/Manga")
|
||||||
|
}
|
||||||
|
|
||||||
|
val uri: Uri? = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
|
||||||
|
|
||||||
|
uri?.let {
|
||||||
|
contentResolver.openOutputStream(it)?.use { os ->
|
||||||
|
bitmap.compress(format, quality, os)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val directory = File("${Environment.getExternalStorageDirectory()}${File.separator}Dantotsu${File.separator}Anime")
|
||||||
|
if (!directory.exists()) {
|
||||||
|
directory.mkdirs()
|
||||||
|
}
|
||||||
|
|
||||||
|
val file = File(directory, filename)
|
||||||
|
FileOutputStream(file).use { outputStream ->
|
||||||
|
bitmap.compress(format, quality, outputStream)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
// Handle exception here
|
||||||
|
println("Exception while saving image: ${e.message}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class MangaCache() {
|
class MangaCache() {
|
||||||
private val maxMemory = (Runtime.getRuntime().maxMemory() / 1024 / 2).toInt()
|
private val maxMemory = (Runtime.getRuntime().maxMemory() / 1024 / 2).toInt()
|
||||||
private val cache = LruCache<String, ImageData>(maxMemory)
|
private val cache = LruCache<String, ImageData>(maxMemory)
|
||||||
|
|
|
@ -161,7 +161,7 @@ abstract class BaseImageAdapter(
|
||||||
println(mangaCache.get(link.url))
|
println(mangaCache.get(link.url))
|
||||||
println("cache size: ${mangaCache.size()}")
|
println("cache size: ${mangaCache.size()}")
|
||||||
mangaCache.get(link.url)?.let { imageData ->
|
mangaCache.get(link.url)?.let { imageData ->
|
||||||
val bitmap = imageData.fetchAndProcessImage(imageData.page, imageData.source)
|
val bitmap = imageData.fetchAndProcessImage(imageData.page, imageData.source, context = this@loadBitmap)
|
||||||
it.load(bitmap)
|
it.load(bitmap)
|
||||||
.skipMemoryCache(true)
|
.skipMemoryCache(true)
|
||||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||||
|
|
|
@ -2,6 +2,7 @@ package ani.dantotsu.parsers
|
||||||
|
|
||||||
import android.content.ContentResolver
|
import android.content.ContentResolver
|
||||||
import android.content.ContentValues
|
import android.content.ContentValues
|
||||||
|
import android.content.Context
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
@ -199,12 +200,14 @@ class DynamicMangaParser(extension: MangaExtension.Installed) : MangaParser() {
|
||||||
|
|
||||||
return coroutineScope {
|
return coroutineScope {
|
||||||
try {
|
try {
|
||||||
|
println("source.name " + source.name)
|
||||||
val res = source.getPageList(sChapter)
|
val res = source.getPageList(sChapter)
|
||||||
val reIndexedPages = res.mapIndexed { index, page -> Page(index, page.url, page.imageUrl, page.uri) }
|
val reIndexedPages = res.mapIndexed { index, page -> Page(index, page.url, page.imageUrl, page.uri) }
|
||||||
|
|
||||||
val deferreds = reIndexedPages.map { page ->
|
val deferreds = reIndexedPages.map { page ->
|
||||||
async(Dispatchers.IO) {
|
async(Dispatchers.IO) {
|
||||||
mangaCache.put(page.imageUrl ?: "", ImageData(page, source))
|
mangaCache.put(page.imageUrl ?: "", ImageData(page, source))
|
||||||
|
logger("put page: ${page.imageUrl}")
|
||||||
pageToMangaImage(page)
|
pageToMangaImage(page)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -212,11 +215,44 @@ class DynamicMangaParser(extension: MangaExtension.Installed) : MangaParser() {
|
||||||
deferreds.awaitAll()
|
deferreds.awaitAll()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
logger("loadImages Exception: $e")
|
logger("loadImages Exception: $e")
|
||||||
|
Toast.makeText(currContext(), "Failed to load images: $e", Toast.LENGTH_SHORT).show()
|
||||||
emptyList()
|
emptyList()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun fetchAndProcessImage(page: Page, httpSource: HttpSource, context: Context): Bitmap? {
|
||||||
|
return withContext(Dispatchers.IO) {
|
||||||
|
try {
|
||||||
|
// Fetch the image
|
||||||
|
val response = httpSource.getImage(page)
|
||||||
|
println("Response: ${response.code}")
|
||||||
|
println("Response: ${response.message}")
|
||||||
|
|
||||||
|
// Convert the Response to an InputStream
|
||||||
|
val inputStream = response.body?.byteStream()
|
||||||
|
|
||||||
|
// Convert InputStream to Bitmap
|
||||||
|
val bitmap = BitmapFactory.decodeStream(inputStream)
|
||||||
|
|
||||||
|
inputStream?.close()
|
||||||
|
ani.dantotsu.media.manga.saveImage(
|
||||||
|
bitmap,
|
||||||
|
context.contentResolver,
|
||||||
|
page.imageUrl!!,
|
||||||
|
Bitmap.CompressFormat.JPEG,
|
||||||
|
100
|
||||||
|
)
|
||||||
|
|
||||||
|
return@withContext bitmap
|
||||||
|
} catch (e: Exception) {
|
||||||
|
// Handle any exceptions
|
||||||
|
println("An error occurred: ${e.message}")
|
||||||
|
return@withContext null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fun fetchAndSaveImage(page: Page, httpSource: HttpSource, contentResolver: ContentResolver) {
|
fun fetchAndSaveImage(page: Page, httpSource: HttpSource, contentResolver: ContentResolver) {
|
||||||
|
|
|
@ -7,6 +7,8 @@ import eu.kanade.tachiyomi.source.model.SManga
|
||||||
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 me.xdrop.fuzzywuzzy.FuzzySearch
|
||||||
|
|
||||||
|
|
||||||
abstract class BaseParser {
|
abstract class BaseParser {
|
||||||
|
|
||||||
|
@ -55,21 +57,41 @@ abstract class BaseParser {
|
||||||
setUserText("Searching : ${mediaObj.mainName()}")
|
setUserText("Searching : ${mediaObj.mainName()}")
|
||||||
val results = search(mediaObj.mainName())
|
val results = search(mediaObj.mainName())
|
||||||
val sortedResults = if (results.isNotEmpty()) {
|
val sortedResults = if (results.isNotEmpty()) {
|
||||||
StringMatcher.closestShowMovedToTop(mediaObj.mainName(), results)
|
results.sortedByDescending { FuzzySearch.ratio(it.name, mediaObj.mainName()) }
|
||||||
} else {
|
} else {
|
||||||
emptyList()
|
emptyList()
|
||||||
}
|
}
|
||||||
response = sortedResults.firstOrNull()
|
response = sortedResults.firstOrNull()
|
||||||
|
|
||||||
if (response == null) {
|
if (response == null || FuzzySearch.ratio(response.name, mediaObj.mainName()) < 100) {
|
||||||
setUserText("Searching : ${mediaObj.nameRomaji}")
|
setUserText("Searching : ${mediaObj.nameRomaji}")
|
||||||
val romajiResults = search(mediaObj.nameRomaji)
|
val romajiResults = search(mediaObj.nameRomaji)
|
||||||
val sortedRomajiResults = if (romajiResults.isNotEmpty()) {
|
val sortedRomajiResults = if (romajiResults.isNotEmpty()) {
|
||||||
StringMatcher.closestShowMovedToTop(mediaObj.nameRomaji, romajiResults)
|
romajiResults.sortedByDescending { FuzzySearch.ratio(it.name, mediaObj.nameRomaji) }
|
||||||
} else {
|
} else {
|
||||||
emptyList()
|
emptyList()
|
||||||
}
|
}
|
||||||
response = sortedRomajiResults.firstOrNull()
|
val closestRomaji = sortedRomajiResults.firstOrNull()
|
||||||
|
logger("Closest match from RomajiResults: ${closestRomaji?.name ?: "None"}")
|
||||||
|
|
||||||
|
response = if (response == null) {
|
||||||
|
logger("No exact match found in results. Using closest match from RomajiResults.")
|
||||||
|
closestRomaji
|
||||||
|
} else {
|
||||||
|
val romajiRatio = FuzzySearch.ratio(closestRomaji?.name ?: "", mediaObj.nameRomaji)
|
||||||
|
val mainNameRatio = FuzzySearch.ratio(response.name, mediaObj.mainName())
|
||||||
|
logger("Fuzzy ratio for closest match in results: $mainNameRatio")
|
||||||
|
logger("Fuzzy ratio for closest match in RomajiResults: $romajiRatio")
|
||||||
|
|
||||||
|
if (romajiRatio > mainNameRatio) {
|
||||||
|
logger("RomajiResults has a closer match. Replacing response.")
|
||||||
|
closestRomaji
|
||||||
|
} else {
|
||||||
|
logger("Results has a closer or equal match. Keeping existing response.")
|
||||||
|
response
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
saveShowResponse(mediaObj.id, response)
|
saveShowResponse(mediaObj.id, response)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package ani.dantotsu.parsers
|
package ani.dantotsu.parsers
|
||||||
|
|
||||||
|
import ani.dantotsu.logger
|
||||||
|
|
||||||
class StringMatcher {
|
class StringMatcher {
|
||||||
companion object {
|
companion object {
|
||||||
private fun levenshteinDistance(s1: String, s2: String): Int {
|
private fun levenshteinDistance(s1: String, s2: String): Int {
|
||||||
|
@ -52,8 +54,10 @@ class StringMatcher {
|
||||||
val closestShowAndIndex = closestShow(target, shows)
|
val closestShowAndIndex = closestShow(target, shows)
|
||||||
val closestIndex = closestShowAndIndex.second
|
val closestIndex = closestShowAndIndex.second
|
||||||
if (closestIndex == -1) {
|
if (closestIndex == -1) {
|
||||||
|
logger("No closest show found for $target")
|
||||||
return shows // Return original list if no closest show found
|
return shows // Return original list if no closest show found
|
||||||
}
|
}
|
||||||
|
logger("Closest show found for $target is ${closestShowAndIndex.first.name}")
|
||||||
return listOf(shows[closestIndex]) + shows.subList(0, closestIndex) + shows.subList(closestIndex + 1, shows.size)
|
return listOf(shows[closestIndex]) + shows.subList(0, closestIndex) + shows.subList(closestIndex + 1, shows.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ import android.view.ViewGroup
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.content.ContextCompat.getSystemService
|
import androidx.core.content.ContextCompat.getSystemService
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
@ -18,6 +19,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import ani.dantotsu.R
|
import ani.dantotsu.R
|
||||||
import ani.dantotsu.databinding.FragmentAnimeExtensionsBinding
|
import ani.dantotsu.databinding.FragmentAnimeExtensionsBinding
|
||||||
|
import ani.dantotsu.loadData
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import eu.kanade.tachiyomi.data.notification.Notifications
|
import eu.kanade.tachiyomi.data.notification.Notifications
|
||||||
import eu.kanade.tachiyomi.extension.anime.AnimeExtensionManager
|
import eu.kanade.tachiyomi.extension.anime.AnimeExtensionManager
|
||||||
|
@ -35,13 +37,57 @@ class AnimeExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
private var _binding: FragmentAnimeExtensionsBinding? = null
|
private var _binding: FragmentAnimeExtensionsBinding? = null
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
|
val skipIcons = loadData("skip_extension_icons") ?: false
|
||||||
|
|
||||||
private lateinit var extensionsRecyclerView: RecyclerView
|
private lateinit var extensionsRecyclerView: RecyclerView
|
||||||
private lateinit var allextenstionsRecyclerView: RecyclerView
|
private lateinit var allextenstionsRecyclerView: RecyclerView
|
||||||
private val animeExtensionManager: AnimeExtensionManager = Injekt.get<AnimeExtensionManager>()
|
private val animeExtensionManager: AnimeExtensionManager = Injekt.get<AnimeExtensionManager>()
|
||||||
private val extensionsAdapter = AnimeExtensionsAdapter { pkgName ->
|
private val extensionsAdapter = AnimeExtensionsAdapter ({ pkg ->
|
||||||
animeExtensionManager.uninstallExtension(pkgName)
|
if(pkg.hasUpdate){
|
||||||
}
|
val notificationManager =
|
||||||
private val allExtensionsAdapter = AllAnimeExtensionsAdapter(lifecycleScope) { pkgName ->
|
requireContext().getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||||
|
animeExtensionManager.updateExtension(pkg)
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(
|
||||||
|
{ installStep ->
|
||||||
|
val builder = NotificationCompat.Builder(
|
||||||
|
requireContext(),
|
||||||
|
Notifications.CHANNEL_DOWNLOADER_PROGRESS
|
||||||
|
)
|
||||||
|
.setSmallIcon(R.drawable.ic_round_sync_24)
|
||||||
|
.setContentTitle("Updating extension")
|
||||||
|
.setContentText("Step: $installStep")
|
||||||
|
.setPriority(NotificationCompat.PRIORITY_LOW)
|
||||||
|
notificationManager.notify(1, builder.build())
|
||||||
|
},
|
||||||
|
{ error ->
|
||||||
|
val builder = NotificationCompat.Builder(
|
||||||
|
requireContext(),
|
||||||
|
Notifications.CHANNEL_DOWNLOADER_ERROR
|
||||||
|
)
|
||||||
|
.setSmallIcon(R.drawable.ic_round_info_24)
|
||||||
|
.setContentTitle("Update failed")
|
||||||
|
.setContentText("Error: ${error.message}")
|
||||||
|
.setPriority(NotificationCompat.PRIORITY_HIGH)
|
||||||
|
notificationManager.notify(1, builder.build())
|
||||||
|
},
|
||||||
|
{
|
||||||
|
val builder = NotificationCompat.Builder(
|
||||||
|
requireContext(),
|
||||||
|
Notifications.CHANNEL_DOWNLOADER_PROGRESS
|
||||||
|
)
|
||||||
|
.setSmallIcon(androidx.media3.ui.R.drawable.exo_ic_check)
|
||||||
|
.setContentTitle("Update complete")
|
||||||
|
.setContentText("The extension has been successfully updated.")
|
||||||
|
.setPriority(NotificationCompat.PRIORITY_LOW)
|
||||||
|
notificationManager.notify(1, builder.build())
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}else {
|
||||||
|
animeExtensionManager.uninstallExtension(pkg.pkgName)
|
||||||
|
}
|
||||||
|
}, skipIcons)
|
||||||
|
private val allExtensionsAdapter = AllAnimeExtensionsAdapter(lifecycleScope, { pkgName ->
|
||||||
|
|
||||||
val notificationManager =
|
val notificationManager =
|
||||||
requireContext().getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
requireContext().getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||||
|
@ -84,7 +130,7 @@ class AnimeExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
notificationManager.notify(1, builder.build())
|
notificationManager.notify(1, builder.build())
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}, skipIcons)
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||||
_binding = FragmentAnimeExtensionsBinding.inflate(inflater, container, false)
|
_binding = FragmentAnimeExtensionsBinding.inflate(inflater, container, false)
|
||||||
|
|
||||||
|
@ -136,9 +182,10 @@ class AnimeExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private class AnimeExtensionsAdapter(private val onUninstallClicked: (String) -> Unit) : RecyclerView.Adapter<AnimeExtensionsAdapter.ViewHolder>() {
|
private class AnimeExtensionsAdapter(private val onUninstallClicked: (AnimeExtension.Installed) -> Unit, skipIcons: Boolean) : RecyclerView.Adapter<AnimeExtensionsAdapter.ViewHolder>() {
|
||||||
|
|
||||||
private var extensions: List<AnimeExtension.Installed> = emptyList()
|
private var extensions: List<AnimeExtension.Installed> = emptyList()
|
||||||
|
val skipIcons = skipIcons
|
||||||
|
|
||||||
fun updateData(newExtensions: List<AnimeExtension.Installed>) {
|
fun updateData(newExtensions: List<AnimeExtension.Installed>) {
|
||||||
extensions = newExtensions
|
extensions = newExtensions
|
||||||
|
@ -154,10 +201,17 @@ class AnimeExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||||
val extension = extensions[position]
|
val extension = extensions[position]
|
||||||
holder.extensionNameTextView.text = extension.name
|
holder.extensionNameTextView.text = extension.name
|
||||||
holder.extensionIconImageView.setImageDrawable(extension.icon)
|
if (!skipIcons) {
|
||||||
holder.closeTextView.text = "Uninstall"
|
holder.extensionIconImageView.setImageDrawable(extension.icon)
|
||||||
|
}
|
||||||
|
if(extension.hasUpdate){
|
||||||
|
holder.closeTextView.text = "Update"
|
||||||
|
holder.closeTextView.setTextColor(ContextCompat.getColor(holder.itemView.context, R.color.warning))
|
||||||
|
}else{
|
||||||
|
holder.closeTextView.text = "Uninstall"
|
||||||
|
}
|
||||||
holder.closeTextView.setOnClickListener {
|
holder.closeTextView.setOnClickListener {
|
||||||
onUninstallClicked(extension.pkgName)
|
onUninstallClicked(extension)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,8 +225,9 @@ class AnimeExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AllAnimeExtensionsAdapter(private val coroutineScope: CoroutineScope,
|
private class AllAnimeExtensionsAdapter(private val coroutineScope: CoroutineScope,
|
||||||
private val onButtonClicked: (AnimeExtension.Available) -> Unit) : RecyclerView.Adapter<AllAnimeExtensionsAdapter.ViewHolder>() {
|
private val onButtonClicked: (AnimeExtension.Available) -> Unit, skipIcons: Boolean) : RecyclerView.Adapter<AllAnimeExtensionsAdapter.ViewHolder>() {
|
||||||
private var extensions: List<AnimeExtension.Available> = emptyList()
|
private var extensions: List<AnimeExtension.Available> = emptyList()
|
||||||
|
val skipIcons = skipIcons
|
||||||
|
|
||||||
fun updateData(newExtensions: List<AnimeExtension.Available>, installedExtensions: List<AnimeExtension.Installed> = emptyList()) {
|
fun updateData(newExtensions: List<AnimeExtension.Available>, installedExtensions: List<AnimeExtension.Installed> = emptyList()) {
|
||||||
val installedPkgNames = installedExtensions.map { it.pkgName }.toSet()
|
val installedPkgNames = installedExtensions.map { it.pkgName }.toSet()
|
||||||
|
@ -190,9 +245,11 @@ class AnimeExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||||
val extension = filteredExtensions[position]
|
val extension = filteredExtensions[position]
|
||||||
holder.extensionNameTextView.text = extension.name
|
holder.extensionNameTextView.text = extension.name
|
||||||
coroutineScope.launch {
|
if (!skipIcons) {
|
||||||
val drawable = urlToDrawable(holder.itemView.context, extension.iconUrl)
|
coroutineScope.launch {
|
||||||
holder.extensionIconImageView.setImageDrawable(drawable)
|
val drawable = urlToDrawable(holder.itemView.context, extension.iconUrl)
|
||||||
|
holder.extensionIconImageView.setImageDrawable(drawable)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
holder.closeTextView.text = "Install"
|
holder.closeTextView.text = "Install"
|
||||||
holder.closeTextView.setOnClickListener {
|
holder.closeTextView.setOnClickListener {
|
||||||
|
|
|
@ -10,6 +10,7 @@ import android.view.ViewGroup
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
@ -17,6 +18,7 @@ import androidx.recyclerview.widget.RecyclerView
|
||||||
import ani.dantotsu.R
|
import ani.dantotsu.R
|
||||||
import ani.dantotsu.databinding.FragmentMangaBinding
|
import ani.dantotsu.databinding.FragmentMangaBinding
|
||||||
import ani.dantotsu.databinding.FragmentMangaExtensionsBinding
|
import ani.dantotsu.databinding.FragmentMangaExtensionsBinding
|
||||||
|
import ani.dantotsu.loadData
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import eu.kanade.tachiyomi.data.notification.Notifications
|
import eu.kanade.tachiyomi.data.notification.Notifications
|
||||||
import eu.kanade.tachiyomi.extension.manga.MangaExtensionManager
|
import eu.kanade.tachiyomi.extension.manga.MangaExtensionManager
|
||||||
|
@ -34,14 +36,58 @@ class MangaExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
private var _binding: FragmentMangaExtensionsBinding? = null
|
private var _binding: FragmentMangaExtensionsBinding? = null
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
|
val skipIcons = loadData("skip_extension_icons") ?: false
|
||||||
|
|
||||||
private lateinit var extensionsRecyclerView: RecyclerView
|
private lateinit var extensionsRecyclerView: RecyclerView
|
||||||
private lateinit var allextenstionsRecyclerView: RecyclerView
|
private lateinit var allextenstionsRecyclerView: RecyclerView
|
||||||
private val mangaExtensionManager:MangaExtensionManager = Injekt.get<MangaExtensionManager>()
|
private val mangaExtensionManager:MangaExtensionManager = Injekt.get<MangaExtensionManager>()
|
||||||
private val extensionsAdapter = MangaExtensionsAdapter { pkgName ->
|
private val extensionsAdapter = MangaExtensionsAdapter ({ pkg ->
|
||||||
mangaExtensionManager.uninstallExtension(pkgName)
|
if(pkg.hasUpdate){
|
||||||
}
|
val notificationManager =
|
||||||
|
requireContext().getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||||
|
mangaExtensionManager.updateExtension(pkg)
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(
|
||||||
|
{ installStep ->
|
||||||
|
val builder = NotificationCompat.Builder(
|
||||||
|
requireContext(),
|
||||||
|
Notifications.CHANNEL_DOWNLOADER_PROGRESS
|
||||||
|
)
|
||||||
|
.setSmallIcon(R.drawable.ic_round_sync_24)
|
||||||
|
.setContentTitle("Updating extension")
|
||||||
|
.setContentText("Step: $installStep")
|
||||||
|
.setPriority(NotificationCompat.PRIORITY_LOW)
|
||||||
|
notificationManager.notify(1, builder.build())
|
||||||
|
},
|
||||||
|
{ error ->
|
||||||
|
val builder = NotificationCompat.Builder(
|
||||||
|
requireContext(),
|
||||||
|
Notifications.CHANNEL_DOWNLOADER_ERROR
|
||||||
|
)
|
||||||
|
.setSmallIcon(R.drawable.ic_round_info_24)
|
||||||
|
.setContentTitle("Update failed")
|
||||||
|
.setContentText("Error: ${error.message}")
|
||||||
|
.setPriority(NotificationCompat.PRIORITY_HIGH)
|
||||||
|
notificationManager.notify(1, builder.build())
|
||||||
|
},
|
||||||
|
{
|
||||||
|
val builder = NotificationCompat.Builder(
|
||||||
|
requireContext(),
|
||||||
|
Notifications.CHANNEL_DOWNLOADER_PROGRESS
|
||||||
|
)
|
||||||
|
.setSmallIcon(androidx.media3.ui.R.drawable.exo_ic_check)
|
||||||
|
.setContentTitle("Update complete")
|
||||||
|
.setContentText("The extension has been successfully updated.")
|
||||||
|
.setPriority(NotificationCompat.PRIORITY_LOW)
|
||||||
|
notificationManager.notify(1, builder.build())
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}else {
|
||||||
|
mangaExtensionManager.uninstallExtension(pkg.pkgName)
|
||||||
|
}
|
||||||
|
}, skipIcons)
|
||||||
private val allExtensionsAdapter =
|
private val allExtensionsAdapter =
|
||||||
AllMangaExtensionsAdapter(lifecycleScope) { pkgName ->
|
AllMangaExtensionsAdapter(lifecycleScope, { pkgName ->
|
||||||
|
|
||||||
val notificationManager =
|
val notificationManager =
|
||||||
requireContext().getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
requireContext().getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||||
|
@ -84,7 +130,8 @@ class MangaExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
notificationManager.notify(1, builder.build())
|
notificationManager.notify(1, builder.build())
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}, skipIcons)
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||||
_binding = FragmentMangaExtensionsBinding.inflate(inflater, container, false)
|
_binding = FragmentMangaExtensionsBinding.inflate(inflater, container, false)
|
||||||
|
|
||||||
|
@ -134,9 +181,10 @@ class MangaExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
super.onDestroyView();_binding = null
|
super.onDestroyView();_binding = null
|
||||||
}
|
}
|
||||||
|
|
||||||
private class MangaExtensionsAdapter(private val onUninstallClicked: (String) -> Unit) : RecyclerView.Adapter<MangaExtensionsAdapter.ViewHolder>() {
|
private class MangaExtensionsAdapter(private val onUninstallClicked: (MangaExtension.Installed) -> Unit, skipIcons: Boolean) : RecyclerView.Adapter<MangaExtensionsAdapter.ViewHolder>() {
|
||||||
|
|
||||||
private var extensions: List<MangaExtension.Installed> = emptyList()
|
private var extensions: List<MangaExtension.Installed> = emptyList()
|
||||||
|
val skipIcons = skipIcons
|
||||||
|
|
||||||
fun updateData(newExtensions: List<MangaExtension.Installed>) {
|
fun updateData(newExtensions: List<MangaExtension.Installed>) {
|
||||||
extensions = newExtensions
|
extensions = newExtensions
|
||||||
|
@ -152,10 +200,17 @@ class MangaExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||||
val extension = extensions[position]
|
val extension = extensions[position]
|
||||||
holder.extensionNameTextView.text = extension.name
|
holder.extensionNameTextView.text = extension.name
|
||||||
holder.extensionIconImageView.setImageDrawable(extension.icon)
|
if(!skipIcons) {
|
||||||
holder.closeTextView.text = "Uninstall"
|
holder.extensionIconImageView.setImageDrawable(extension.icon)
|
||||||
|
}
|
||||||
|
if(extension.hasUpdate){
|
||||||
|
holder.closeTextView.text = "Update"
|
||||||
|
holder.closeTextView.setTextColor(ContextCompat.getColor(holder.itemView.context, R.color.warning))
|
||||||
|
}else{
|
||||||
|
holder.closeTextView.text = "Uninstall"
|
||||||
|
}
|
||||||
holder.closeTextView.setOnClickListener {
|
holder.closeTextView.setOnClickListener {
|
||||||
onUninstallClicked(extension.pkgName)
|
onUninstallClicked(extension)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,8 +224,9 @@ class MangaExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AllMangaExtensionsAdapter(private val coroutineScope: CoroutineScope,
|
private class AllMangaExtensionsAdapter(private val coroutineScope: CoroutineScope,
|
||||||
private val onButtonClicked: (MangaExtension.Available) -> Unit) : RecyclerView.Adapter<AllMangaExtensionsAdapter.ViewHolder>() {
|
private val onButtonClicked: (MangaExtension.Available) -> Unit, skipIcons: Boolean) : RecyclerView.Adapter<AllMangaExtensionsAdapter.ViewHolder>() {
|
||||||
private var extensions: List<MangaExtension.Available> = emptyList()
|
private var extensions: List<MangaExtension.Available> = emptyList()
|
||||||
|
val skipIcons = skipIcons
|
||||||
|
|
||||||
fun updateData(newExtensions: List<MangaExtension.Available>, installedExtensions: List<MangaExtension.Installed> = emptyList()) {
|
fun updateData(newExtensions: List<MangaExtension.Available>, installedExtensions: List<MangaExtension.Installed> = emptyList()) {
|
||||||
val installedPkgNames = installedExtensions.map { it.pkgName }.toSet()
|
val installedPkgNames = installedExtensions.map { it.pkgName }.toSet()
|
||||||
|
@ -188,9 +244,11 @@ class MangaExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||||
val extension = filteredExtensions[position]
|
val extension = filteredExtensions[position]
|
||||||
holder.extensionNameTextView.text = extension.name
|
holder.extensionNameTextView.text = extension.name
|
||||||
coroutineScope.launch {
|
if (!skipIcons) {
|
||||||
val drawable = urlToDrawable(holder.itemView.context, extension.iconUrl)
|
coroutineScope.launch {
|
||||||
holder.extensionIconImageView.setImageDrawable(drawable)
|
val drawable = urlToDrawable(holder.itemView.context, extension.iconUrl)
|
||||||
|
holder.extensionIconImageView.setImageDrawable(drawable)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
holder.closeTextView.text = "Install"
|
holder.closeTextView.text = "Install"
|
||||||
holder.closeTextView.setOnClickListener {
|
holder.closeTextView.setOnClickListener {
|
||||||
|
|
|
@ -2,6 +2,7 @@ package ani.dantotsu.settings
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.app.AlertDialog
|
import android.app.AlertDialog
|
||||||
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.graphics.drawable.Animatable
|
import android.graphics.drawable.Animatable
|
||||||
import android.os.Build.*
|
import android.os.Build.*
|
||||||
|
@ -31,6 +32,7 @@ import ani.dantotsu.subcriptions.Subscription.Companion.defaultTime
|
||||||
import ani.dantotsu.subcriptions.Subscription.Companion.startSubscription
|
import ani.dantotsu.subcriptions.Subscription.Companion.startSubscription
|
||||||
import ani.dantotsu.subcriptions.Subscription.Companion.timeMinutes
|
import ani.dantotsu.subcriptions.Subscription.Companion.timeMinutes
|
||||||
import eu.kanade.domain.base.BasePreferences
|
import eu.kanade.domain.base.BasePreferences
|
||||||
|
import eu.kanade.tachiyomi.network.NetworkPreferences
|
||||||
import io.noties.markwon.Markwon
|
import io.noties.markwon.Markwon
|
||||||
import io.noties.markwon.SoftBreakAddsNewLinePlugin
|
import io.noties.markwon.SoftBreakAddsNewLinePlugin
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
@ -47,6 +49,7 @@ class SettingsActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
lateinit var binding: ActivitySettingsBinding
|
lateinit var binding: ActivitySettingsBinding
|
||||||
private val extensionInstaller = Injekt.get<BasePreferences>().extensionInstaller()
|
private val extensionInstaller = Injekt.get<BasePreferences>().extensionInstaller()
|
||||||
|
private val networkPreferences = Injekt.get<NetworkPreferences>()
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
@ -92,18 +95,21 @@ OS Version: $CODENAME $RELEASE ($SDK_INT)
|
||||||
onBackPressedDispatcher.onBackPressed()
|
onBackPressedDispatcher.onBackPressed()
|
||||||
}
|
}
|
||||||
|
|
||||||
val animeSourceName = loadData<String>("settings_def_anime_source") ?: AnimeSources.names[0]
|
binding.settingsUseMaterialYou.isChecked = getSharedPreferences("Dantotsu", Context.MODE_PRIVATE).getBoolean("use_material_you", false)
|
||||||
// Set the dropdown item in the UI if the name exists in the list.
|
binding.settingsUseMaterialYou.setOnCheckedChangeListener { _, isChecked ->
|
||||||
if (AnimeSources.names.contains(animeSourceName)) {
|
getSharedPreferences("Dantotsu", Context.MODE_PRIVATE).edit().putBoolean("use_material_you", isChecked).apply()
|
||||||
binding.animeSource.setText(animeSourceName, false)
|
}
|
||||||
|
|
||||||
|
val animeSource = loadData<Int>("settings_def_anime_source_s")?.let { if (it >= AnimeSources.names.size) 0 else it } ?: 0
|
||||||
|
if (MangaSources.names.isNotEmpty() && animeSource in 0 until MangaSources.names.size) {
|
||||||
|
binding.mangaSource.setText(MangaSources.names[animeSource], false)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.animeSource.setAdapter(ArrayAdapter(this, R.layout.item_dropdown, AnimeSources.names))
|
binding.animeSource.setAdapter(ArrayAdapter(this, R.layout.item_dropdown, AnimeSources.names))
|
||||||
// Set up the item click listener for the dropdown.
|
|
||||||
binding.animeSource.setOnItemClickListener { _, _, i, _ ->
|
binding.animeSource.setOnItemClickListener { _, _, i, _ ->
|
||||||
val selectedName = AnimeSources.names[i]
|
saveData("settings_def_anime_source_s", i)
|
||||||
// Save the string name of the selected item.
|
|
||||||
saveData("settings_def_anime_source", selectedName)
|
|
||||||
binding.animeSource.clearFocus()
|
binding.animeSource.clearFocus()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,6 +137,17 @@ OS Version: $CODENAME $RELEASE ($SDK_INT)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
binding.skipExtensionIcons.isChecked = loadData("skip_extension_icons") ?: false
|
||||||
|
binding.skipExtensionIcons.setOnCheckedChangeListener { _, isChecked ->
|
||||||
|
saveData("skip_extension_icons", isChecked)
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.userAgent.setText(networkPreferences.defaultUserAgent().get())
|
||||||
|
binding.userAgent.setOnEditorActionListener { _, _, _ ->
|
||||||
|
networkPreferences.defaultUserAgent().set(binding.userAgent.text.toString())
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
binding.settingsDownloadInSd.isChecked = loadData("sd_dl") ?: false
|
binding.settingsDownloadInSd.isChecked = loadData("sd_dl") ?: false
|
||||||
binding.settingsDownloadInSd.setOnCheckedChangeListener { _, isChecked ->
|
binding.settingsDownloadInSd.setOnCheckedChangeListener { _, isChecked ->
|
||||||
if (isChecked) {
|
if (isChecked) {
|
||||||
|
@ -169,12 +186,9 @@ OS Version: $CODENAME $RELEASE ($SDK_INT)
|
||||||
saveData("settings_prefer_dub", isChecked)
|
saveData("settings_prefer_dub", isChecked)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the saved manga source name from data storage.
|
val mangaSource = loadData<Int>("settings_def_manga_source_s")?.let { if (it >= MangaSources.names.size) 0 else it } ?: 0
|
||||||
val mangaSourceName = loadData<String>("settings_def_manga_source") ?: MangaSources.names[0]
|
if (MangaSources.names.isNotEmpty() && mangaSource in 0 until MangaSources.names.size) {
|
||||||
|
binding.mangaSource.setText(MangaSources.names[mangaSource], false)
|
||||||
// Set the dropdown item in the UI if the name exists in the list.
|
|
||||||
if (MangaSources.names.contains(mangaSourceName)) {
|
|
||||||
binding.mangaSource.setText(mangaSourceName, false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up the dropdown adapter.
|
// Set up the dropdown adapter.
|
||||||
|
@ -182,9 +196,7 @@ OS Version: $CODENAME $RELEASE ($SDK_INT)
|
||||||
|
|
||||||
// Set up the item click listener for the dropdown.
|
// Set up the item click listener for the dropdown.
|
||||||
binding.mangaSource.setOnItemClickListener { _, _, i, _ ->
|
binding.mangaSource.setOnItemClickListener { _, _, i, _ ->
|
||||||
val selectedName = MangaSources.names[i]
|
saveData("settings_def_manga_source_s", i)
|
||||||
// Save the string name of the selected item.
|
|
||||||
saveData("settings_def_manga_source", selectedName)
|
|
||||||
binding.mangaSource.clearFocus()
|
binding.mangaSource.clearFocus()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,21 +15,13 @@ class SubscriptionHelper {
|
||||||
companion object {
|
companion object {
|
||||||
private fun loadSelected(context: Context, mediaId: Int, isAdult: Boolean, isAnime: Boolean): Selected {
|
private fun loadSelected(context: Context, mediaId: Int, isAdult: Boolean, isAnime: Boolean): Selected {
|
||||||
val data = loadData<Selected>("${mediaId}-select", context) ?: Selected().let {
|
val data = loadData<Selected>("${mediaId}-select", context) ?: Selected().let {
|
||||||
it.source =
|
it.sourceIndex =
|
||||||
if (isAdult) ""
|
if (isAdult) 0
|
||||||
else if (isAnime) {loadData("settings_def_anime_source", context) ?: ""}
|
else if (isAnime) {loadData("settings_def_anime_source_s_r", context) ?: 0}
|
||||||
else loadData("settings_def_manga_source", context) ?: ""
|
else loadData("settings_def_manga_source_s_r", context) ?: 0
|
||||||
it.preferDub = loadData("settings_prefer_dub", context) ?: false
|
it.preferDub = loadData("settings_prefer_dub", context) ?: false
|
||||||
it
|
it
|
||||||
}
|
}
|
||||||
if (isAnime){
|
|
||||||
val sources = if (isAdult) HAnimeSources else AnimeSources
|
|
||||||
data.sourceIndex = sources.list.indexOfFirst { it.name == data.source }
|
|
||||||
}else{
|
|
||||||
val sources = if (isAdult) HMangaSources else MangaSources
|
|
||||||
data.sourceIndex = sources.list.indexOfFirst { it.name == data.source }
|
|
||||||
}
|
|
||||||
if (data.sourceIndex == -1) {data.sourceIndex = 0}
|
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,9 +32,7 @@ class SubscriptionHelper {
|
||||||
fun getAnimeParser(context: Context, isAdult: Boolean, id: Int): AnimeParser {
|
fun getAnimeParser(context: Context, isAdult: Boolean, id: Int): AnimeParser {
|
||||||
val sources = if (isAdult) HAnimeSources else AnimeSources
|
val sources = if (isAdult) HAnimeSources else AnimeSources
|
||||||
val selected = loadSelected(context, id, isAdult, true)
|
val selected = loadSelected(context, id, isAdult, true)
|
||||||
var location = sources.list.indexOfFirst { it.name == selected.source }
|
val parser = sources[selected.sourceIndex]
|
||||||
if (location == -1) {location = 0}
|
|
||||||
val parser = sources[location]
|
|
||||||
parser.selectDub = selected.preferDub
|
parser.selectDub = selected.preferDub
|
||||||
return parser
|
return parser
|
||||||
}
|
}
|
||||||
|
@ -69,9 +59,7 @@ class SubscriptionHelper {
|
||||||
fun getMangaParser(context: Context, isAdult: Boolean, id: Int): MangaParser {
|
fun getMangaParser(context: Context, isAdult: Boolean, id: Int): MangaParser {
|
||||||
val sources = if (isAdult) HMangaSources else MangaSources
|
val sources = if (isAdult) HMangaSources else MangaSources
|
||||||
val selected = loadSelected(context, id, isAdult, false)
|
val selected = loadSelected(context, id, isAdult, false)
|
||||||
var location = sources.list.indexOfFirst { it.name == selected.source }
|
return sources[selected.sourceIndex]
|
||||||
if (location == -1) {location = 0}
|
|
||||||
return sources[location]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getChapter(context: Context, parser: MangaParser, id: Int, isAdult: Boolean): MangaChapter? {
|
suspend fun getChapter(context: Context, parser: MangaParser, id: Int, isAdult: Boolean): MangaChapter? {
|
||||||
|
|
|
@ -11,11 +11,13 @@ import eu.kanade.tachiyomi.network.interceptor.UncaughtExceptionInterceptor
|
||||||
import eu.kanade.tachiyomi.network.interceptor.UserAgentInterceptor
|
import eu.kanade.tachiyomi.network.interceptor.UserAgentInterceptor
|
||||||
import okhttp3.Cache
|
import okhttp3.Cache
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
|
import okhttp3.logging.HttpLoggingInterceptor
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
class NetworkHelper(
|
class NetworkHelper(
|
||||||
context: Context,
|
context: Context,
|
||||||
|
private val preferences: NetworkPreferences,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
private val cacheDir = File(context.cacheDir, "network_cache")
|
private val cacheDir = File(context.cacheDir, "network_cache")
|
||||||
|
@ -40,18 +42,17 @@ class NetworkHelper(
|
||||||
.addInterceptor(UncaughtExceptionInterceptor())
|
.addInterceptor(UncaughtExceptionInterceptor())
|
||||||
.addInterceptor(userAgentInterceptor)
|
.addInterceptor(userAgentInterceptor)
|
||||||
|
|
||||||
/*if (preferences.verboseLogging().get()) {
|
if (preferences.verboseLogging().get()) {
|
||||||
val httpLoggingInterceptor = HttpLoggingInterceptor().apply {
|
val httpLoggingInterceptor = HttpLoggingInterceptor().apply {
|
||||||
level = HttpLoggingInterceptor.Level.HEADERS
|
level = HttpLoggingInterceptor.Level.HEADERS
|
||||||
}
|
}
|
||||||
builder.addNetworkInterceptor(httpLoggingInterceptor)
|
builder.addNetworkInterceptor(httpLoggingInterceptor)
|
||||||
}*/
|
}
|
||||||
|
|
||||||
//when (preferences.dohProvider().get()) {
|
when (preferences.dohProvider().get()) {
|
||||||
when (PREF_DOH_CLOUDFLARE) {
|
|
||||||
PREF_DOH_CLOUDFLARE -> builder.dohCloudflare()
|
PREF_DOH_CLOUDFLARE -> builder.dohCloudflare()
|
||||||
PREF_DOH_GOOGLE -> builder.dohGoogle()
|
PREF_DOH_GOOGLE -> builder.dohGoogle()
|
||||||
/*PREF_DOH_ADGUARD -> builder.dohAdGuard()
|
PREF_DOH_ADGUARD -> builder.dohAdGuard()
|
||||||
PREF_DOH_QUAD9 -> builder.dohQuad9()
|
PREF_DOH_QUAD9 -> builder.dohQuad9()
|
||||||
PREF_DOH_ALIDNS -> builder.dohAliDNS()
|
PREF_DOH_ALIDNS -> builder.dohAliDNS()
|
||||||
PREF_DOH_DNSPOD -> builder.dohDNSPod()
|
PREF_DOH_DNSPOD -> builder.dohDNSPod()
|
||||||
|
@ -60,7 +61,7 @@ class NetworkHelper(
|
||||||
PREF_DOH_MULLVAD -> builder.dohMullvad()
|
PREF_DOH_MULLVAD -> builder.dohMullvad()
|
||||||
PREF_DOH_CONTROLD -> builder.dohControlD()
|
PREF_DOH_CONTROLD -> builder.dohControlD()
|
||||||
PREF_DOH_NJALLA -> builder.dohNajalla()
|
PREF_DOH_NJALLA -> builder.dohNajalla()
|
||||||
PREF_DOH_SHECAN -> builder.dohShecan()*/
|
PREF_DOH_SHECAN -> builder.dohShecan()
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder
|
return builder
|
||||||
|
@ -75,5 +76,5 @@ class NetworkHelper(
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun defaultUserAgentProvider() = "Mozilla/5.0 (Linux; Android %s; %s) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36"//preferences.defaultUserAgent().get().trim()
|
fun defaultUserAgentProvider() = preferences.defaultUserAgent().get().trim()
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
package eu.kanade.tachiyomi.network
|
||||||
|
|
||||||
|
import tachiyomi.core.preference.Preference
|
||||||
|
import tachiyomi.core.preference.PreferenceStore
|
||||||
|
|
||||||
|
class NetworkPreferences(
|
||||||
|
private val preferenceStore: PreferenceStore,
|
||||||
|
private val verboseLogging: Boolean = false,
|
||||||
|
) {
|
||||||
|
|
||||||
|
fun verboseLogging(): Preference<Boolean> {
|
||||||
|
return preferenceStore.getBoolean("verbose_logging", verboseLogging)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun dohProvider(): Preference<Int> {
|
||||||
|
return preferenceStore.getInt("doh_provider", 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun defaultUserAgent(): Preference<String> {
|
||||||
|
return preferenceStore.getString("default_user_agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:110.0) Gecko/20100101 Firefox/110.0")
|
||||||
|
}
|
||||||
|
}
|
|
@ -74,77 +74,110 @@
|
||||||
android:paddingStart="32dp"
|
android:paddingStart="32dp"
|
||||||
android:paddingEnd="32dp">
|
android:paddingEnd="32dp">
|
||||||
|
|
||||||
<LinearLayout
|
<ani.dantotsu.others.Xpandable
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="8dp"
|
android:orientation="vertical">
|
||||||
android:gravity="center"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="0dp"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="64dp"
|
||||||
android:layout_weight="1"
|
|
||||||
android:fontFamily="@font/poppins_bold"
|
android:fontFamily="@font/poppins_bold"
|
||||||
|
android:gravity="center_vertical"
|
||||||
android:text="@string/theme"
|
android:text="@string/theme"
|
||||||
android:textColor="?attr/colorSecondary" />
|
android:textColor="?attr/colorSecondary"
|
||||||
|
app:drawableEndCompat="@drawable/ic_round_arrow_drop_down_24"
|
||||||
|
tools:ignore="TextContrastCheck" />
|
||||||
|
|
||||||
<androidx.cardview.widget.CardView
|
<LinearLayout
|
||||||
android:layout_width="wrap_content"
|
android:id="@+id/settingsThemeContainer"
|
||||||
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:cardBackgroundColor="@color/nav_bg_inv"
|
android:orientation="horizontal">
|
||||||
app:cardCornerRadius="16dp"
|
|
||||||
app:cardElevation="0dp">
|
|
||||||
|
|
||||||
<ImageButton
|
<LinearLayout
|
||||||
android:id="@+id/settingsUiLight"
|
android:layout_width="match_parent"
|
||||||
android:layout_width="48dp"
|
android:layout_height="match_parent"
|
||||||
android:layout_height="64dp"
|
android:layout_marginTop="8dp"
|
||||||
android:alpha="0.33"
|
android:gravity="center"
|
||||||
android:background="?android:attr/selectableItemBackground"
|
android:orientation="horizontal">
|
||||||
android:src="@drawable/ic_round_brightness_high_24"
|
|
||||||
app:tint="@color/bg_opp"
|
|
||||||
tools:ignore="ContentDescription,SpeakableTextPresentCheck,ImageContrastCheck,DuplicateSpeakableTextCheck" />
|
|
||||||
</androidx.cardview.widget.CardView>
|
|
||||||
|
|
||||||
<androidx.cardview.widget.CardView
|
|
||||||
android:layout_width="wrap_content"
|
<androidx.cardview.widget.CardView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:cardBackgroundColor="@color/nav_bg_inv"
|
||||||
|
app:cardCornerRadius="16dp"
|
||||||
|
app:cardElevation="0dp">
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/settingsUiLight"
|
||||||
|
android:layout_width="48dp"
|
||||||
|
android:layout_height="64dp"
|
||||||
|
android:alpha="0.33"
|
||||||
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:src="@drawable/ic_round_brightness_high_24"
|
||||||
|
app:tint="@color/bg_opp"
|
||||||
|
tools:ignore="ContentDescription,SpeakableTextPresentCheck,ImageContrastCheck,DuplicateSpeakableTextCheck" />
|
||||||
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
|
<androidx.cardview.widget.CardView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:cardBackgroundColor="@color/nav_bg_inv"
|
||||||
|
app:cardCornerRadius="16dp"
|
||||||
|
app:cardElevation="0dp">
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/settingsUiDark"
|
||||||
|
android:layout_width="48dp"
|
||||||
|
android:layout_height="64dp"
|
||||||
|
android:alpha="0.33"
|
||||||
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:scaleX="-1"
|
||||||
|
android:src="@drawable/ic_round_brightness_4_24"
|
||||||
|
app:tint="@color/bg_opp"
|
||||||
|
tools:ignore="ContentDescription,SpeakableTextPresentCheck,ImageContrastCheck" />
|
||||||
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
|
<androidx.cardview.widget.CardView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:cardBackgroundColor="@color/nav_bg_inv"
|
||||||
|
app:cardCornerRadius="16dp"
|
||||||
|
app:cardElevation="0dp">
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/settingsUiAuto"
|
||||||
|
android:layout_width="48dp"
|
||||||
|
android:layout_height="64dp"
|
||||||
|
android:alpha="0.33"
|
||||||
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:src="@drawable/ic_round_brightness_auto_24"
|
||||||
|
app:tint="@color/bg_opp"
|
||||||
|
tools:ignore="ContentDescription,SpeakableTextPresentCheck,ImageContrastCheck" />
|
||||||
|
</androidx.cardview.widget.CardView>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||||
|
android:id="@+id/settingsUseMaterialYou"
|
||||||
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:cardBackgroundColor="@color/nav_bg_inv"
|
android:checked="false"
|
||||||
app:cardCornerRadius="16dp"
|
android:drawableStart="@drawable/ic_round_new_releases_24"
|
||||||
app:cardElevation="0dp">
|
android:drawablePadding="16dp"
|
||||||
|
android:elegantTextHeight="true"
|
||||||
<ImageButton
|
android:fontFamily="@font/poppins_bold"
|
||||||
android:id="@+id/settingsUiDark"
|
android:minHeight="64dp"
|
||||||
android:layout_width="48dp"
|
android:text="@string/use_material_you"
|
||||||
android:layout_height="64dp"
|
android:textAlignment="viewStart"
|
||||||
android:alpha="0.33"
|
android:textColor="@color/bg_opp"
|
||||||
android:background="?android:attr/selectableItemBackground"
|
app:cornerRadius="0dp"
|
||||||
android:scaleX="-1"
|
app:drawableTint="?attr/colorPrimary"
|
||||||
android:src="@drawable/ic_round_brightness_4_24"
|
app:showText="false"
|
||||||
app:tint="@color/bg_opp"
|
app:thumbTint="@color/button_switch_track" />
|
||||||
tools:ignore="ContentDescription,SpeakableTextPresentCheck,ImageContrastCheck" />
|
</ani.dantotsu.others.Xpandable>
|
||||||
</androidx.cardview.widget.CardView>
|
|
||||||
|
|
||||||
<androidx.cardview.widget.CardView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:cardBackgroundColor="@color/nav_bg_inv"
|
|
||||||
app:cardCornerRadius="16dp"
|
|
||||||
app:cardElevation="0dp">
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/settingsUiAuto"
|
|
||||||
android:layout_width="48dp"
|
|
||||||
android:layout_height="64dp"
|
|
||||||
android:alpha="0.33"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:src="@drawable/ic_round_brightness_auto_24"
|
|
||||||
app:tint="@color/bg_opp"
|
|
||||||
tools:ignore="ContentDescription,SpeakableTextPresentCheck,ImageContrastCheck" />
|
|
||||||
</androidx.cardview.widget.CardView>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<ani.dantotsu.others.Xpandable
|
<ani.dantotsu.others.Xpandable
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -429,6 +462,44 @@
|
||||||
app:showText="false"
|
app:showText="false"
|
||||||
app:thumbTint="@color/button_switch_track" />
|
app:thumbTint="@color/button_switch_track" />
|
||||||
|
|
||||||
|
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||||
|
android:id="@+id/skipExtensionIcons"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:checked="false"
|
||||||
|
android:drawableStart="@drawable/ic_round_new_releases_24"
|
||||||
|
android:drawablePadding="16dp"
|
||||||
|
android:elegantTextHeight="true"
|
||||||
|
android:fontFamily="@font/poppins_bold"
|
||||||
|
android:minHeight="64dp"
|
||||||
|
android:text="@string/skip_loading_extension_icons"
|
||||||
|
android:textAlignment="viewStart"
|
||||||
|
android:textColor="@color/bg_opp"
|
||||||
|
app:cornerRadius="0dp"
|
||||||
|
app:drawableTint="?attr/colorPrimary"
|
||||||
|
app:showText="false"
|
||||||
|
app:thumbTint="@color/button_switch_track" />
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="16dp">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/userAgent"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:hint="user agent"
|
||||||
|
app:boxCornerRadiusBottomEnd="8dp"
|
||||||
|
app:boxCornerRadiusBottomStart="8dp"
|
||||||
|
app:boxCornerRadiusTopEnd="8dp"
|
||||||
|
app:boxCornerRadiusTopStart="8dp"
|
||||||
|
app:hintAnimationEnabled="true" />
|
||||||
|
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
|
||||||
</ani.dantotsu.others.Xpandable>
|
</ani.dantotsu.others.Xpandable>
|
||||||
|
|
||||||
<ani.dantotsu.others.Xpandable
|
<ani.dantotsu.others.Xpandable
|
||||||
|
@ -698,8 +769,8 @@
|
||||||
style="@style/Widget.Material3.Button.TextButton"
|
style="@style/Widget.Material3.Button.TextButton"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="64dp"
|
android:layout_height="64dp"
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:layout_marginStart="-12dp"
|
android:layout_marginStart="-12dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
android:fontFamily="@font/poppins_bold"
|
android:fontFamily="@font/poppins_bold"
|
||||||
android:insetTop="0dp"
|
android:insetTop="0dp"
|
||||||
android:insetBottom="0dp"
|
android:insetBottom="0dp"
|
||||||
|
@ -1222,11 +1293,11 @@
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingTop="16dp"
|
|
||||||
android:paddingBottom="16dp"
|
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal"
|
||||||
|
android:paddingTop="16dp"
|
||||||
|
android:paddingBottom="16dp">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/settingBuyMeCoffee"
|
android:id="@+id/settingBuyMeCoffee"
|
||||||
|
|
|
@ -28,6 +28,6 @@
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:text="Uninstall"
|
android:text="Uninstall"
|
||||||
android:textColor="@color/fav"
|
android:textColor="@color/pink_500"
|
||||||
android:textSize="14sp"/>
|
android:textSize="14sp"/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
|
@ -28,6 +28,6 @@
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:text="Install"
|
android:text="Install"
|
||||||
android:textColor="@color/fav"
|
android:textColor="@color/pink_500"
|
||||||
android:textSize="14sp"/>
|
android:textSize="14sp"/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
|
@ -21,4 +21,5 @@
|
||||||
<color name="nav_status">#80FFFFFF</color>
|
<color name="nav_status">#80FFFFFF</color>
|
||||||
<color name="fav">#ad5edd</color>
|
<color name="fav">#ad5edd</color>
|
||||||
<color name="filler">#54FF8400</color>
|
<color name="filler">#54FF8400</color>
|
||||||
|
<color name="warning">#FF0000</color>
|
||||||
</resources>
|
</resources>
|
|
@ -624,5 +624,7 @@
|
||||||
<string name="view_manga">View Manga</string>
|
<string name="view_manga">View Manga</string>
|
||||||
<string name="force_legacy_installer">Force Legacy Installer</string>
|
<string name="force_legacy_installer">Force Legacy Installer</string>
|
||||||
<string name="extensions_settings">Extensions</string>
|
<string name="extensions_settings">Extensions</string>
|
||||||
|
<string name="skip_loading_extension_icons">skip loading extension icons</string>
|
||||||
|
<string name="use_material_you">Use Material You</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue