feat: multi stream audio support

This commit is contained in:
rebelonion 2024-05-06 21:30:26 -05:00
parent abcf9fcbef
commit 636a56fb7f
15 changed files with 195 additions and 144 deletions

View file

@ -489,7 +489,7 @@ class AnimeWatchAdapter(
val adapter = ArrayAdapter( val adapter = ArrayAdapter(
fragment.requireContext(), fragment.requireContext(),
R.layout.item_dropdown, R.layout.item_dropdown,
parser.extension.sources.map { LanguageMapper.mapLanguageCodeToName(it.lang) } parser.extension.sources.map { LanguageMapper.getLanguageCode(it.lang) }
) )
val items = adapter.count val items = adapter.count

View file

@ -371,7 +371,7 @@ class AnimeWatchFragment : Fragment() {
var selectedSetting = allSettings[0] var selectedSetting = allSettings[0]
if (allSettings.size > 1) { if (allSettings.size > 1) {
val names = val names =
allSettings.map { LanguageMapper.mapLanguageCodeToName(it.lang) }.toTypedArray() allSettings.map { LanguageMapper.getLanguageCode(it.lang) }.toTypedArray()
val dialog = AlertDialog.Builder(requireContext(), R.style.MyPopup) val dialog = AlertDialog.Builder(requireContext(), R.style.MyPopup)
.setTitle("Select a Source") .setTitle("Select a Source")
.setSingleChoiceItems(names, -1) { dialog, which -> .setSingleChoiceItems(names, -1) { dialog, which ->

View file

@ -82,7 +82,9 @@ import androidx.media3.datasource.cache.CacheDataSource
import androidx.media3.datasource.okhttp.OkHttpDataSource import androidx.media3.datasource.okhttp.OkHttpDataSource
import androidx.media3.exoplayer.DefaultLoadControl import androidx.media3.exoplayer.DefaultLoadControl
import androidx.media3.exoplayer.ExoPlayer import androidx.media3.exoplayer.ExoPlayer
import androidx.media3.exoplayer.hls.HlsMediaSource
import androidx.media3.exoplayer.source.DefaultMediaSourceFactory import androidx.media3.exoplayer.source.DefaultMediaSourceFactory
import androidx.media3.exoplayer.source.MergingMediaSource
import androidx.media3.exoplayer.trackselection.DefaultTrackSelector import androidx.media3.exoplayer.trackselection.DefaultTrackSelector
import androidx.media3.exoplayer.util.EventLogger import androidx.media3.exoplayer.util.EventLogger
import androidx.media3.session.MediaSession import androidx.media3.session.MediaSession
@ -126,6 +128,7 @@ import ani.dantotsu.media.SubtitleDownloader
import ani.dantotsu.okHttpClient import ani.dantotsu.okHttpClient
import ani.dantotsu.others.AniSkip import ani.dantotsu.others.AniSkip
import ani.dantotsu.others.AniSkip.getType import ani.dantotsu.others.AniSkip.getType
import ani.dantotsu.others.LanguageMapper
import ani.dantotsu.others.ResettableTimer import ani.dantotsu.others.ResettableTimer
import ani.dantotsu.others.getSerialized import ani.dantotsu.others.getSerialized
import ani.dantotsu.parsers.AnimeSources import ani.dantotsu.parsers.AnimeSources
@ -190,6 +193,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
private lateinit var cacheFactory: CacheDataSource.Factory private lateinit var cacheFactory: CacheDataSource.Factory
private lateinit var playbackParameters: PlaybackParameters private lateinit var playbackParameters: PlaybackParameters
private lateinit var mediaItem: MediaItem private lateinit var mediaItem: MediaItem
private lateinit var mediaSource: MergingMediaSource
private var mediaSession: MediaSession? = null private var mediaSession: MediaSession? = null
private lateinit var binding: ActivityExoplayerBinding private lateinit var binding: ActivityExoplayerBinding
@ -223,6 +227,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
private var downloadId: String? = null private var downloadId: String? = null
private var hasExtSubtitles = false private var hasExtSubtitles = false
private var audioLanguages = mutableListOf<String>()
companion object { companion object {
var initialized = false var initialized = false
@ -1484,9 +1489,9 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
val titleName = ext.server.name.split("/").first() val titleName = ext.server.name.split("/").first()
val episodeName = ext.server.name.split("/").last() val episodeName = ext.server.name.split("/").last()
downloadId = PrefManager.getAnimeDownloadPreferences() downloadId = PrefManager.getAnimeDownloadPreferences()
.getString("$titleName - $episodeName", null) ?: .getString("$titleName - $episodeName", null)
PrefManager.getAnimeDownloadPreferences() ?: PrefManager.getAnimeDownloadPreferences()
.getString(ext.server.name, null) .getString(ext.server.name, null)
val exoItem = if (downloadId != null) { val exoItem = if (downloadId != null) {
Helper.downloadManager(this) Helper.downloadManager(this)
.downloadIndex.getDownload(downloadId!!)?.request?.toMediaItem() .downloadIndex.getDownload(downloadId!!)?.request?.toMediaItem()
@ -1540,6 +1545,32 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
} }
} }
val audioMediaItem = mutableListOf<MediaItem>()
audioLanguages.clear()
ext.audioTracks.forEach {
val code = LanguageMapper.getLanguageCode(it.lang)
audioLanguages.add(code)
audioMediaItem.add(
MediaItem.Builder()
.setUri(it.url)
.setMimeType(MimeTypes.AUDIO_UNKNOWN)
.setTag(code)
.build()
)
}
val audioSources = audioMediaItem.map { mediaItem ->
if (mediaItem.localConfiguration?.uri.toString().endsWith(".m3u8")) {
HlsMediaSource.Factory(cacheFactory).createMediaSource(mediaItem)
} else {
DefaultMediaSourceFactory(cacheFactory).createMediaSource(mediaItem)
}
}.toTypedArray()
val videoMediaSource = DefaultMediaSourceFactory(cacheFactory)
.createMediaSource(mediaItem)
mediaSource = MergingMediaSource(videoMediaSource, *audioSources)
//Source //Source
exoSource.setOnClickListener { exoSource.setOnClickListener {
sourceClick() sourceClick()
@ -1615,7 +1646,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
.build().apply { .build().apply {
playWhenReady = true playWhenReady = true
this.playbackParameters = this@ExoplayerView.playbackParameters this.playbackParameters = this@ExoplayerView.playbackParameters
setMediaItem(mediaItem) setMediaSource(mediaSource)
prepare() prepare()
PrefManager.getCustomVal( PrefManager.getCustomVal(
"${media.id}_${media.anime!!.selectedEpisode}_max", "${media.id}_${media.anime!!.selectedEpisode}_max",
@ -1953,7 +1984,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
} }
exoAudioTrack.isVisible = audioTracks.size > 1 exoAudioTrack.isVisible = audioTracks.size > 1
exoAudioTrack.setOnClickListener { exoAudioTrack.setOnClickListener {
TrackGroupDialogFragment(this, audioTracks, TRACK_TYPE_AUDIO) TrackGroupDialogFragment(this, audioTracks, TRACK_TYPE_AUDIO, audioLanguages)
.show(supportFragmentManager, "dialog") .show(supportFragmentManager, "dialog")
} }
if (!hasExtSubtitles) { if (!hasExtSubtitles) {

View file

@ -19,19 +19,13 @@ import java.util.Locale
@OptIn(UnstableApi::class) @OptIn(UnstableApi::class)
class TrackGroupDialogFragment( class TrackGroupDialogFragment(
instance: ExoplayerView, trackGroups: ArrayList<Tracks.Group>, type: @TrackType Int private var instance: ExoplayerView,
private var trackGroups: ArrayList<Tracks.Group>,
private var type: @TrackType Int,
private var overrideTrackNames: List<String>? = null
) : BottomSheetDialogFragment() { ) : BottomSheetDialogFragment() {
private var _binding: BottomSheetSubtitlesBinding? = null private var _binding: BottomSheetSubtitlesBinding? = null
private val binding get() = _binding!! private val binding get() = _binding!!
private var instance: ExoplayerView
private var trackGroups: ArrayList<Tracks.Group>
private var type: @TrackType Int
init {
this.instance = instance
this.trackGroups = trackGroups
this.type = type
}
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
@ -67,7 +61,8 @@ class TrackGroupDialogFragment(
override fun onBindViewHolder(holder: StreamViewHolder, position: Int) { override fun onBindViewHolder(holder: StreamViewHolder, position: Int) {
val binding = holder.binding val binding = holder.binding
trackGroups[position].let { trackGroup -> trackGroups[position].let { trackGroup ->
when (val language = trackGroup.getTrackFormat(0).language?.lowercase()) { when (val language = overrideTrackNames?.getOrNull(position)
?: trackGroup.getTrackFormat(0).language?.lowercase()) {
null -> { null -> {
binding.subtitleTitle.text = binding.subtitleTitle.text =
getString(R.string.unknown_track, "Track $position") getString(R.string.unknown_track, "Track $position")
@ -94,7 +89,6 @@ class TrackGroupDialogFragment(
} }
binding.subtitleTitle.text = locale?.let { binding.subtitleTitle.text = locale?.let {
"[${it.language}] ${it.displayName}" "[${it.language}] ${it.displayName}"
} ?: getString(R.string.unknown_track, language) } ?: getString(R.string.unknown_track, language)
} }
} }

View file

@ -548,7 +548,7 @@ class MangaReadAdapter(
val adapter = ArrayAdapter( val adapter = ArrayAdapter(
fragment.requireContext(), fragment.requireContext(),
R.layout.item_dropdown, R.layout.item_dropdown,
parser.extension.sources.map { LanguageMapper.mapLanguageCodeToName(it.lang) } parser.extension.sources.map { LanguageMapper.getLanguageCode(it.lang) }
) )
val items = adapter.count val items = adapter.count
binding?.animeSourceLanguageContainer?.isVisible = items > 1 binding?.animeSourceLanguageContainer?.isVisible = items > 1

View file

@ -385,7 +385,7 @@ open class MangaReadFragment : Fragment(), ScanlatorSelectionListener {
var selectedSetting = allSettings[0] var selectedSetting = allSettings[0]
if (allSettings.size > 1) { if (allSettings.size > 1) {
val names = val names =
allSettings.map { LanguageMapper.mapLanguageCodeToName(it.lang) }.toTypedArray() allSettings.map { LanguageMapper.getLanguageCode(it.lang) }.toTypedArray()
val dialog = AlertDialog.Builder(requireContext(), R.style.MyPopup) val dialog = AlertDialog.Builder(requireContext(), R.style.MyPopup)
.setTitle("Select a Source") .setTitle("Select a Source")
.setSingleChoiceItems(names, -1) { dialog, which -> .setSingleChoiceItems(names, -1) { dialog, which ->

View file

@ -1,124 +1,145 @@
package ani.dantotsu.others package ani.dantotsu.others
import java.util.Locale
class LanguageMapper { class LanguageMapper {
companion object { companion object {
fun mapLanguageCodeToName(code: String): String { private val codeMap: Map<String, String> = mapOf(
return when (code) { "all" to "Multi",
"all" -> "Multi" "af" to "Afrikaans",
"af" -> "Afrikaans" "am" to "Amharic",
"am" -> "Amharic" "ar" to "Arabic",
"ar" -> "Arabic" "as" to "Assamese",
"as" -> "Assamese" "az" to "Azerbaijani",
"az" -> "Azerbaijani" "be" to "Belarusian",
"be" -> "Belarusian" "bg" to "Bulgarian",
"bg" -> "Bulgarian" "bn" to "Bengali",
"bn" -> "Bengali" "bs" to "Bosnian",
"bs" -> "Bosnian" "ca" to "Catalan",
"ca" -> "Catalan" "ceb" to "Cebuano",
"ceb" -> "Cebuano" "cs" to "Czech",
"cs" -> "Czech" "da" to "Danish",
"da" -> "Danish" "de" to "German",
"de" -> "German" "el" to "Greek",
"el" -> "Greek" "en" to "English",
"en" -> "English" "en-Us" to "English (United States)",
"en-Us" -> "English (United States)" "eo" to "Esperanto",
"eo" -> "Esperanto" "es" to "Spanish",
"es" -> "Spanish" "es-419" to "Spanish (Latin America)",
"es-419" -> "Spanish (Latin America)" "es-ES" to "Spanish (Spain)",
"et" -> "Estonian" "et" to "Estonian",
"eu" -> "Basque" "eu" to "Basque",
"fa" -> "Persian" "fa" to "Persian",
"fi" -> "Finnish" "fi" to "Finnish",
"fil" -> "Filipino" "fil" to "Filipino",
"fo" -> "Faroese" "fo" to "Faroese",
"fr" -> "French" "fr" to "French",
"ga" -> "Irish" "ga" to "Irish",
"gn" -> "Guarani" "gn" to "Guarani",
"gu" -> "Gujarati" "gu" to "Gujarati",
"ha" -> "Hausa" "ha" to "Hausa",
"he" -> "Hebrew" "he" to "Hebrew",
"hi" -> "Hindi" "hi" to "Hindi",
"hr" -> "Croatian" "hr" to "Croatian",
"ht" -> "Haitian Creole" "ht" to "Haitian Creole",
"hu" -> "Hungarian" "hu" to "Hungarian",
"hy" -> "Armenian" "hy" to "Armenian",
"id" -> "Indonesian" "id" to "Indonesian",
"ig" -> "Igbo" "ig" to "Igbo",
"is" -> "Icelandic" "is" to "Icelandic",
"it" -> "Italian" "it" to "Italian",
"ja" -> "Japanese" "ja" to "Japanese",
"jv" -> "Javanese" "jv" to "Javanese",
"ka" -> "Georgian" "ka" to "Georgian",
"kk" -> "Kazakh" "kk" to "Kazakh",
"km" -> "Khmer" "km" to "Khmer",
"kn" -> "Kannada" "kn" to "Kannada",
"ko" -> "Korean" "ko" to "Korean",
"ku" -> "Kurdish" "ku" to "Kurdish",
"ky" -> "Kyrgyz" "ky" to "Kyrgyz",
"la" -> "Latin" "la" to "Latin",
"lb" -> "Luxembourgish" "lb" to "Luxembourgish",
"lo" -> "Lao" "lo" to "Lao",
"lt" -> "Lithuanian" "lt" to "Lithuanian",
"lv" -> "Latvian" "lv" to "Latvian",
"mg" -> "Malagasy" "mg" to "Malagasy",
"mi" -> "Maori" "mi" to "Maori",
"mk" -> "Macedonian" "mk" to "Macedonian",
"ml" -> "Malayalam" "ml" to "Malayalam",
"mn" -> "Mongolian" "mn" to "Mongolian",
"mo" -> "Moldovan" "mo" to "Moldovan",
"mr" -> "Marathi" "mr" to "Marathi",
"ms" -> "Malay" "ms" to "Malay",
"mt" -> "Maltese" "mt" to "Maltese",
"my" -> "Burmese" "my" to "Burmese",
"ne" -> "Nepali" "ne" to "Nepali",
"nl" -> "Dutch" "nl" to "Dutch",
"no" -> "Norwegian" "no" to "Norwegian",
"ny" -> "Chichewa" "ny" to "Chichewa",
"pl" -> "Polish" "pl" to "Polish",
"pt" -> "Portuguese" "pt" to "Portuguese",
"pt-BR" -> "Portuguese (Brazil)" "pt-BR" to "Portuguese (Brazil)",
"pt-PT" -> "Portuguese (Portugal)" "pt-PT" to "Portuguese (Portugal)",
"ps" -> "Pashto" "ps" to "Pashto",
"ro" -> "Romanian" "ro" to "Romanian",
"rm" -> "Romansh" "rm" to "Romansh",
"ru" -> "Russian" "ru" to "Russian",
"sd" -> "Sindhi" "sd" to "Sindhi",
"sh" -> "Serbo-Croatian" "sh" to "Serbo-Croatian",
"si" -> "Sinhala" "si" to "Sinhala",
"sk" -> "Slovak" "sk" to "Slovak",
"sl" -> "Slovenian" "sl" to "Slovenian",
"sm" -> "Samoan" "sm" to "Samoan",
"sn" -> "Shona" "sn" to "Shona",
"so" -> "Somali" "so" to "Somali",
"sq" -> "Albanian" "sq" to "Albanian",
"sr" -> "Serbian" "sr" to "Serbian",
"st" -> "Southern Sotho" "st" to "Southern Sotho",
"sv" -> "Swedish" "sv" to "Swedish",
"sw" -> "Swahili" "sw" to "Swahili",
"ta" -> "Tamil" "ta" to "Tamil",
"te" -> "Telugu" "te" to "Telugu",
"tg" -> "Tajik" "tg" to "Tajik",
"th" -> "Thai" "th" to "Thai",
"ti" -> "Tigrinya" "ti" to "Tigrinya",
"tk" -> "Turkmen" "tk" to "Turkmen",
"tl" -> "Tagalog" "tl" to "Tagalog",
"to" -> "Tongan" "to" to "Tongan",
"tr" -> "Turkish" "tr" to "Turkish",
"uk" -> "Ukrainian" "uk" to "Ukrainian",
"ur" -> "Urdu" "ur" to "Urdu",
"uz" -> "Uzbek" "uz" to "Uzbek",
"vi" -> "Vietnamese" "vi" to "Vietnamese",
"yo" -> "Yoruba" "yo" to "Yoruba",
"zh" -> "Chinese" "zh" to "Chinese",
"zh-Hans" -> "Chinese (Simplified)" "zh-Hans" to "Chinese (Simplified)",
"zh-Hant" -> "Chinese (Traditional)" "zh-Hant" to "Chinese (Traditional)",
"zh-Habt" -> "Chinese (Hakka)" "zh-Habt" to "Chinese (Hakka)",
"zu" -> "Zulu" "zu" to "Zulu"
else -> code )
fun getLanguage(code: String): String {
return if (code.contains("-")) {
try {
val parts = code.split("-")
Locale(parts[0], parts[1]).displayName
} catch (ignored: Exception) {
code
}
} else {
try {
Locale(code).displayName
} catch (ignored: Exception) {
code
}
} }
} }
fun getLanguageCode(language: String): String {
return codeMap.filterValues { it.lowercase() == language.lowercase() }.keys.firstOrNull() ?: "all"
}
enum class Language(val code: String) { enum class Language(val code: String) {
ALL("all"), ALL("all"),
ARABIC("ar"), ARABIC("ar"),

View file

@ -511,9 +511,10 @@ class VideoServerPassthrough(private val videoServer: VideoServer) : VideoExtrac
override suspend fun extract(): VideoContainer { override suspend fun extract(): VideoContainer {
val vidList = listOfNotNull(videoServer.video?.let { aniVideoToSaiVideo(it) }) val vidList = listOfNotNull(videoServer.video?.let { aniVideoToSaiVideo(it) })
val subList = videoServer.video?.subtitleTracks?.map { trackToSubtitle(it) } ?: emptyList() val subList = videoServer.video?.subtitleTracks?.map { trackToSubtitle(it) } ?: emptyList()
val audioList = videoServer.video?.audioTracks ?: emptyList()
return if (vidList.isNotEmpty()) { return if (vidList.isNotEmpty()) {
VideoContainer(vidList, subList) VideoContainer(vidList, subList, audioList)
} else { } else {
throw Exception("No videos found") throw Exception("No videos found")
} }

View file

@ -1,6 +1,7 @@
package ani.dantotsu.parsers package ani.dantotsu.parsers
import ani.dantotsu.FileUrl import ani.dantotsu.FileUrl
import eu.kanade.tachiyomi.animesource.model.Track
import java.io.Serializable import java.io.Serializable
/** /**
@ -12,6 +13,7 @@ abstract class VideoExtractor : Serializable {
abstract val server: VideoServer abstract val server: VideoServer
var videos: List<Video> = listOf() var videos: List<Video> = listOf()
var subtitles: List<Subtitle> = listOf() var subtitles: List<Subtitle> = listOf()
var audioTracks: List<Track> = listOf()
/** /**
* Extracts videos & subtitles from the `embed` * Extracts videos & subtitles from the `embed`
@ -29,6 +31,7 @@ abstract class VideoExtractor : Serializable {
extract().also { extract().also {
videos = it.videos videos = it.videos
subtitles = it.subtitles subtitles = it.subtitles
audioTracks = it.audioTracks
return this return this
} }
} }
@ -80,7 +83,8 @@ data class VideoServer(
* **/ * **/
data class VideoContainer( data class VideoContainer(
val videos: List<Video>, val videos: List<Video>,
val subtitles: List<Subtitle> = listOf() val subtitles: List<Subtitle> = listOf(),
val audioTracks: List<Track> = listOf(),
) : Serializable ) : Serializable
/** /**

View file

@ -72,7 +72,7 @@ class InstalledAnimeExtensionsFragment : Fragment(), SearchQueryHandler {
if (allSettings.isNotEmpty()) { if (allSettings.isNotEmpty()) {
var selectedSetting = allSettings[0] var selectedSetting = allSettings[0]
if (allSettings.size > 1) { if (allSettings.size > 1) {
val names = allSettings.map { LanguageMapper.mapLanguageCodeToName(it.lang) } val names = allSettings.map { LanguageMapper.getLanguageCode(it.lang) }
.toTypedArray() .toTypedArray()
var selectedIndex = 0 var selectedIndex = 0
val dialog = AlertDialog.Builder(requireContext(), R.style.MyPopup) val dialog = AlertDialog.Builder(requireContext(), R.style.MyPopup)
@ -295,7 +295,7 @@ class InstalledAnimeExtensionsFragment : Fragment(), SearchQueryHandler {
override fun onBindViewHolder(holder: ViewHolder, position: Int) { override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val extension = getItem(position) val extension = getItem(position)
val nsfw = if (extension.isNsfw) "(18+)" else "" val nsfw = if (extension.isNsfw) "(18+)" else ""
val lang = LanguageMapper.mapLanguageCodeToName(extension.lang) val lang = LanguageMapper.getLanguageCode(extension.lang)
holder.extensionNameTextView.text = extension.name holder.extensionNameTextView.text = extension.name
val versionText = "$lang ${extension.versionName} $nsfw" val versionText = "$lang ${extension.versionName} $nsfw"
holder.extensionVersionTextView.text = versionText holder.extensionVersionTextView.text = versionText

View file

@ -71,7 +71,7 @@ class InstalledMangaExtensionsFragment : Fragment(), SearchQueryHandler {
if (allSettings.isNotEmpty()) { if (allSettings.isNotEmpty()) {
var selectedSetting = allSettings[0] var selectedSetting = allSettings[0]
if (allSettings.size > 1) { if (allSettings.size > 1) {
val names = allSettings.map { LanguageMapper.mapLanguageCodeToName(it.lang) } val names = allSettings.map { LanguageMapper.getLanguageCode(it.lang) }
.toTypedArray() .toTypedArray()
var selectedIndex = 0 var selectedIndex = 0
val dialog = AlertDialog.Builder(requireContext(), R.style.MyPopup) val dialog = AlertDialog.Builder(requireContext(), R.style.MyPopup)
@ -293,7 +293,7 @@ class InstalledMangaExtensionsFragment : Fragment(), SearchQueryHandler {
override fun onBindViewHolder(holder: ViewHolder, position: Int) { override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val extension = getItem(position) // Use getItem() from ListAdapter val extension = getItem(position) // Use getItem() from ListAdapter
val nsfw = if (extension.isNsfw) "(18+)" else "" val nsfw = if (extension.isNsfw) "(18+)" else ""
val lang = LanguageMapper.mapLanguageCodeToName(extension.lang) val lang = LanguageMapper.getLanguageCode(extension.lang)
holder.extensionNameTextView.text = extension.name holder.extensionNameTextView.text = extension.name
val versionText = "$lang ${extension.versionName} $nsfw" val versionText = "$lang ${extension.versionName} $nsfw"
holder.extensionVersionTextView.text = versionText holder.extensionVersionTextView.text = versionText

View file

@ -222,7 +222,7 @@ class InstalledNovelExtensionsFragment : Fragment(), SearchQueryHandler {
override fun onBindViewHolder(holder: ViewHolder, position: Int) { override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val extension = getItem(position) // Use getItem() from ListAdapter val extension = getItem(position) // Use getItem() from ListAdapter
val nsfw = "" val nsfw = ""
val lang = LanguageMapper.mapLanguageCodeToName("all") val lang = LanguageMapper.getLanguageCode("all")
holder.extensionNameTextView.text = extension.name holder.extensionNameTextView.text = extension.name
val versionText = "$lang ${extension.versionName} $nsfw" val versionText = "$lang ${extension.versionName} $nsfw"
holder.extensionVersionTextView.text = versionText holder.extensionVersionTextView.text = versionText

View file

@ -203,7 +203,7 @@ class AnimeExtensionAdapter(private val clickListener: OnAnimeInstallClickListen
fun bind(extension: AnimeExtension.Available) { fun bind(extension: AnimeExtension.Available) {
val nsfw = if (extension.isNsfw) "(18+)" else "" val nsfw = if (extension.isNsfw) "(18+)" else ""
val lang = LanguageMapper.mapLanguageCodeToName(extension.lang) val lang = LanguageMapper.getLanguageCode(extension.lang)
binding.extensionNameTextView.text = extension.name binding.extensionNameTextView.text = extension.name
val versionText = "$lang ${extension.versionName} $nsfw" val versionText = "$lang ${extension.versionName} $nsfw"
binding.extensionVersionTextView.text = versionText binding.extensionVersionTextView.text = versionText

View file

@ -201,7 +201,7 @@ class MangaExtensionAdapter(private val clickListener: OnMangaInstallClickListen
fun bind(extension: MangaExtension.Available) { fun bind(extension: MangaExtension.Available) {
val nsfw = if (extension.isNsfw) "(18+)" else "" val nsfw = if (extension.isNsfw) "(18+)" else ""
val lang = LanguageMapper.mapLanguageCodeToName(extension.lang) val lang = LanguageMapper.getLanguageCode(extension.lang)
binding.extensionNameTextView.text = extension.name binding.extensionNameTextView.text = extension.name
val versionText = "$lang ${extension.versionName} $nsfw" val versionText = "$lang ${extension.versionName} $nsfw"
binding.extensionVersionTextView.text = versionText binding.extensionVersionTextView.text = versionText

View file

@ -202,7 +202,7 @@ class NovelExtensionAdapter(private val clickListener: OnNovelInstallClickListen
val extensionIconImageView: ImageView = binding.extensionIconImageView val extensionIconImageView: ImageView = binding.extensionIconImageView
fun bind(extension: NovelExtension.Available) { fun bind(extension: NovelExtension.Available) {
val nsfw = "" val nsfw = ""
val lang = LanguageMapper.mapLanguageCodeToName("all") val lang = LanguageMapper.getLanguageCode("all")
binding.extensionNameTextView.text = extension.name binding.extensionNameTextView.text = extension.name
binding.extensionVersionTextView.text = "$lang ${extension.versionName} $nsfw" binding.extensionVersionTextView.text = "$lang ${extension.versionName} $nsfw"
} }