forked from recloudstream/cloudstream
subs fix
This commit is contained in:
parent
517e77fdfb
commit
2932768891
9 changed files with 190 additions and 90 deletions
|
@ -7,7 +7,6 @@ import com.fasterxml.jackson.databind.DeserializationFeature
|
||||||
import com.fasterxml.jackson.databind.json.JsonMapper
|
import com.fasterxml.jackson.databind.json.JsonMapper
|
||||||
import com.fasterxml.jackson.module.kotlin.KotlinModule
|
import com.fasterxml.jackson.module.kotlin.KotlinModule
|
||||||
import com.lagradost.cloudstream3.animeproviders.*
|
import com.lagradost.cloudstream3.animeproviders.*
|
||||||
import com.lagradost.cloudstream3.metaproviders.TmdbProvider
|
|
||||||
import com.lagradost.cloudstream3.movieproviders.*
|
import com.lagradost.cloudstream3.movieproviders.*
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
|
@ -920,9 +920,9 @@ class PlayerFragment : Fragment() {
|
||||||
|
|
||||||
private var resizeMode = 0
|
private var resizeMode = 0
|
||||||
private var playbackSpeed = 0f
|
private var playbackSpeed = 0f
|
||||||
private var allEpisodes: HashMap<Int, ArrayList<ExtractorLink>> = HashMap()
|
private var allEpisodes: HashMap<Int, List<ExtractorLink>> = HashMap()
|
||||||
private var allEpisodesSubs: HashMap<Int, ArrayList<SubtitleFile>> = HashMap()
|
private var allEpisodesSubs: HashMap<Int, HashMap<String, SubtitleFile>> = HashMap()
|
||||||
private var episodes: List<ResultEpisode> = ArrayList()
|
private var episodes: List<ResultEpisode> = emptyList()
|
||||||
var currentPoster: String? = null
|
var currentPoster: String? = null
|
||||||
var currentHeaderName: String? = null
|
var currentHeaderName: String? = null
|
||||||
var currentIsMovie: Boolean? = null
|
var currentIsMovie: Boolean? = null
|
||||||
|
@ -1138,7 +1138,7 @@ class PlayerFragment : Fragment() {
|
||||||
context?.let { ctx ->
|
context?.let { ctx ->
|
||||||
//val isPlaying = exoPlayer.isPlaying
|
//val isPlaying = exoPlayer.isPlaying
|
||||||
exoPlayer.pause()
|
exoPlayer.pause()
|
||||||
val currentSubtitles = activeSubtitles
|
val currentSubtitles = context?.getSubs()?.map { it.lang } ?: activeSubtitles
|
||||||
|
|
||||||
val sourceBuilder = AlertDialog.Builder(ctx, R.style.AlertDialogCustomBlack)
|
val sourceBuilder = AlertDialog.Builder(ctx, R.style.AlertDialogCustomBlack)
|
||||||
.setView(R.layout.player_select_source_and_subs)
|
.setView(R.layout.player_select_source_and_subs)
|
||||||
|
@ -1189,8 +1189,8 @@ class PlayerFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
val startIndexFromMap =
|
val startIndexFromMap =
|
||||||
currentSubtitles.map { it.removeSuffix(" ") }
|
currentSubtitles.map { it.trimEnd() }
|
||||||
.indexOf(preferredSubtitles.removeSuffix(" ")) + 1
|
.indexOf(preferredSubtitles.trimEnd()) + 1
|
||||||
var subtitleIndex = startIndexFromMap
|
var subtitleIndex = startIndexFromMap
|
||||||
|
|
||||||
if (currentSubtitles.isEmpty()) {
|
if (currentSubtitles.isEmpty()) {
|
||||||
|
@ -1218,13 +1218,27 @@ class PlayerFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
applyButton.setOnClickListener {
|
applyButton.setOnClickListener {
|
||||||
|
if (this::exoPlayer.isInitialized) playbackPosition = exoPlayer.currentPosition
|
||||||
|
|
||||||
|
var init = false
|
||||||
if (sourceIndex != startSource) {
|
if (sourceIndex != startSource) {
|
||||||
playbackPosition = if (this::exoPlayer.isInitialized) exoPlayer.currentPosition else 0
|
|
||||||
setMirrorId(sources[sourceIndex].getId())
|
setMirrorId(sources[sourceIndex].getId())
|
||||||
initPlayer(getCurrentUrl())
|
init = true
|
||||||
}
|
}
|
||||||
if (subtitleIndex != startIndexFromMap) {
|
if (subtitleIndex != startIndexFromMap) {
|
||||||
setPreferredSubLanguage(if (subtitleIndex <= 0) null else currentSubtitles[subtitleIndex - 1])
|
if (subtitleIndex <= 0) {
|
||||||
|
setPreferredSubLanguage(null)
|
||||||
|
} else {
|
||||||
|
val langId = currentSubtitles[subtitleIndex - 1].trimEnd()
|
||||||
|
setPreferredSubLanguage(langId)
|
||||||
|
|
||||||
|
if (!activeSubtitles.any { it.trimEnd() == langId }) {
|
||||||
|
init = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (init) {
|
||||||
|
initPlayer(getCurrentUrl())
|
||||||
}
|
}
|
||||||
sourceDialog.dismiss()
|
sourceDialog.dismiss()
|
||||||
}
|
}
|
||||||
|
@ -1253,7 +1267,7 @@ class PlayerFragment : Fragment() {
|
||||||
|
|
||||||
private fun setPreferredSubLanguage(lang: String?) {
|
private fun setPreferredSubLanguage(lang: String?) {
|
||||||
//val textRendererIndex = getRendererIndex(C.TRACK_TYPE_TEXT) ?: return@setOnClickListener
|
//val textRendererIndex = getRendererIndex(C.TRACK_TYPE_TEXT) ?: return@setOnClickListener
|
||||||
val realLang = if (lang.isNullOrBlank()) "" else lang
|
val realLang = if (lang.isNullOrBlank()) "" else lang.trimEnd()
|
||||||
preferredSubtitles =
|
preferredSubtitles =
|
||||||
if (realLang.length == 2) SubtitleHelper.fromTwoLettersToLanguage(realLang) ?: realLang else realLang
|
if (realLang.length == 2) SubtitleHelper.fromTwoLettersToLanguage(realLang) ?: realLang else realLang
|
||||||
|
|
||||||
|
@ -1268,7 +1282,7 @@ class PlayerFragment : Fragment() {
|
||||||
} else {
|
} else {
|
||||||
trackSelector.setParameters(
|
trackSelector.setParameters(
|
||||||
trackSelector.buildUponParameters()
|
trackSelector.buildUponParameters()
|
||||||
.setPreferredTextLanguage(realLang)
|
.setPreferredTextLanguage("_$realLang")
|
||||||
//.setRendererDisabled(textRendererIndex, false)
|
//.setRendererDisabled(textRendererIndex, false)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1423,7 +1437,9 @@ class PlayerFragment : Fragment() {
|
||||||
player_media_route_button?.isVisible = !isDownloadedFile
|
player_media_route_button?.isVisible = !isDownloadedFile
|
||||||
if (savedInstanceState != null) {
|
if (savedInstanceState != null) {
|
||||||
currentWindow = savedInstanceState.getInt(STATE_RESUME_WINDOW)
|
currentWindow = savedInstanceState.getInt(STATE_RESUME_WINDOW)
|
||||||
|
if (playbackPosition <= 0) {
|
||||||
playbackPosition = savedInstanceState.getLong(STATE_RESUME_POSITION)
|
playbackPosition = savedInstanceState.getLong(STATE_RESUME_POSITION)
|
||||||
|
}
|
||||||
isFullscreen = savedInstanceState.getBoolean(STATE_PLAYER_FULLSCREEN)
|
isFullscreen = savedInstanceState.getBoolean(STATE_PLAYER_FULLSCREEN)
|
||||||
isPlayerPlaying = savedInstanceState.getBoolean(STATE_PLAYER_PLAYING)
|
isPlayerPlaying = savedInstanceState.getBoolean(STATE_PLAYER_PLAYING)
|
||||||
resizeMode = savedInstanceState.getInt(RESIZE_MODE_KEY)
|
resizeMode = savedInstanceState.getInt(RESIZE_MODE_KEY)
|
||||||
|
@ -1479,6 +1495,13 @@ class PlayerFragment : Fragment() {
|
||||||
|
|
||||||
observeDirectly(viewModel.allEpisodesSubs) { _allEpisodesSubs ->
|
observeDirectly(viewModel.allEpisodesSubs) { _allEpisodesSubs ->
|
||||||
allEpisodesSubs = _allEpisodesSubs
|
allEpisodesSubs = _allEpisodesSubs
|
||||||
|
if (preferredSubtitles != "" && !activeSubtitles.contains(preferredSubtitles) && allEpisodesSubs[getEpisode()?.id]?.containsKey(
|
||||||
|
preferredSubtitles
|
||||||
|
) == true
|
||||||
|
) {
|
||||||
|
if (this::exoPlayer.isInitialized) playbackPosition = exoPlayer.currentPosition
|
||||||
|
initPlayer(getCurrentUrl())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
observeDirectly(viewModel.resultResponse) { data ->
|
observeDirectly(viewModel.resultResponse) { data ->
|
||||||
|
@ -1495,6 +1518,8 @@ class PlayerFragment : Fragment() {
|
||||||
is Resource.Failure -> {
|
is Resource.Failure -> {
|
||||||
//WTF, HOW DID YOU EVEN GET HERE
|
//WTF, HOW DID YOU EVEN GET HERE
|
||||||
}
|
}
|
||||||
|
else -> {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1685,7 +1710,7 @@ class PlayerFragment : Fragment() {
|
||||||
}
|
}
|
||||||
return list
|
return list
|
||||||
} else {
|
} else {
|
||||||
allEpisodesSubs[getEpisode()?.id]
|
allEpisodesSubs[getEpisode()?.id]?.values?.toList()?.sortedBy { it.lang }
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
null
|
null
|
||||||
|
@ -1952,13 +1977,13 @@ class PlayerFragment : Fragment() {
|
||||||
val subItemsId = ArrayList<String>()
|
val subItemsId = ArrayList<String>()
|
||||||
|
|
||||||
for (sub in sortSubs(subs)) {
|
for (sub in sortSubs(subs)) {
|
||||||
val langId = sub.lang //SubtitleHelper.fromLanguageToTwoLetters(it.lang) ?: it.lang
|
val langId = sub.lang.trimEnd() //SubtitleHelper.fromLanguageToTwoLetters(it.lang) ?: it.lang
|
||||||
subItemsId.add(langId)
|
subItemsId.add(langId)
|
||||||
subItems.add(
|
subItems.add(
|
||||||
MediaItem.Subtitle(
|
MediaItem.Subtitle(
|
||||||
Uri.parse(sub.url),
|
Uri.parse(sub.url),
|
||||||
sub.url.toSubtitleMimeType(),
|
sub.url.toSubtitleMimeType(),
|
||||||
langId,
|
"_$langId",
|
||||||
C.SELECTION_FLAG_DEFAULT
|
C.SELECTION_FLAG_DEFAULT
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -2014,6 +2039,7 @@ class PlayerFragment : Fragment() {
|
||||||
databaseProvider
|
databaseProvider
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val cacheFactory = CacheDataSource.Factory().apply {
|
val cacheFactory = CacheDataSource.Factory().apply {
|
||||||
simpleCache?.let { setCache(it) }
|
simpleCache?.let { setCache(it) }
|
||||||
setUpstreamDataSourceFactory(getDataSourceFactory())
|
setUpstreamDataSourceFactory(getDataSourceFactory())
|
||||||
|
@ -2084,7 +2110,6 @@ class PlayerFragment : Fragment() {
|
||||||
|
|
||||||
player_view?.performClick()
|
player_view?.performClick()
|
||||||
|
|
||||||
//TODO FIX
|
|
||||||
video_title?.text = hName +
|
video_title?.text = hName +
|
||||||
if (isEpisodeBased)
|
if (isEpisodeBased)
|
||||||
if (epSeason == null)
|
if (epSeason == null)
|
||||||
|
@ -2199,7 +2224,7 @@ class PlayerFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPlayerError(error: PlaybackException) {
|
override fun onPlayerError(error: PlaybackException) {
|
||||||
println("CURRENT URL: " + currentUrl?.url)
|
println("CURRENT URL ERROR: " + currentUrl?.url)
|
||||||
// Lets pray this doesn't spam Toasts :)
|
// Lets pray this doesn't spam Toasts :)
|
||||||
val msg = error.message ?: ""
|
val msg = error.message ?: ""
|
||||||
val errorName = error.errorCodeName
|
val errorName = error.errorCodeName
|
||||||
|
|
|
@ -126,7 +126,7 @@ fun Context.buildResultEpisode(
|
||||||
id: Int,
|
id: Int,
|
||||||
index: Int,
|
index: Int,
|
||||||
rating: Int?,
|
rating: Int?,
|
||||||
descript: String?,
|
description: String?,
|
||||||
isFiller: Boolean?,
|
isFiller: Boolean?,
|
||||||
): ResultEpisode {
|
): ResultEpisode {
|
||||||
val posDur = getViewPos(id)
|
val posDur = getViewPos(id)
|
||||||
|
@ -142,7 +142,7 @@ fun Context.buildResultEpisode(
|
||||||
posDur?.position ?: 0,
|
posDur?.position ?: 0,
|
||||||
posDur?.duration ?: 0,
|
posDur?.duration ?: 0,
|
||||||
rating,
|
rating,
|
||||||
descript,
|
description,
|
||||||
isFiller
|
isFiller
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -167,8 +167,8 @@ class ResultFragment : Fragment() {
|
||||||
|
|
||||||
private var currentLoadingCount = 0 // THIS IS USED TO PREVENT LATE EVENTS, AFTER DISMISS WAS CLICKED
|
private var currentLoadingCount = 0 // THIS IS USED TO PREVENT LATE EVENTS, AFTER DISMISS WAS CLICKED
|
||||||
private val viewModel: ResultViewModel by activityViewModels()
|
private val viewModel: ResultViewModel by activityViewModels()
|
||||||
private var allEpisodes: HashMap<Int, ArrayList<ExtractorLink>> = HashMap()
|
private var allEpisodes: HashMap<Int, List<ExtractorLink>> = HashMap()
|
||||||
private var allEpisodesSubs: HashMap<Int, ArrayList<SubtitleFile>> = HashMap()
|
private var allEpisodesSubs: HashMap<Int, HashMap<String, SubtitleFile>> = HashMap()
|
||||||
private var currentHeaderName: String? = null
|
private var currentHeaderName: String? = null
|
||||||
private var currentType: TvType? = null
|
private var currentType: TvType? = null
|
||||||
private var currentEpisodes: List<ResultEpisode>? = null
|
private var currentEpisodes: List<ResultEpisode>? = null
|
||||||
|
@ -352,8 +352,8 @@ class ResultFragment : Fragment() {
|
||||||
val index = episodeClick.data.index
|
val index = episodeClick.data.index
|
||||||
val buildInPlayer = true
|
val buildInPlayer = true
|
||||||
currentLoadingCount++
|
currentLoadingCount++
|
||||||
var currentLinks: ArrayList<ExtractorLink>? = null
|
var currentLinks: List<ExtractorLink>? = null
|
||||||
var currentSubs: ArrayList<SubtitleFile>? = null
|
var currentSubs: HashMap<String, SubtitleFile>? = null
|
||||||
|
|
||||||
val showTitle =
|
val showTitle =
|
||||||
episodeClick.data.name ?: getString(R.string.episode_name_format).format(
|
episodeClick.data.name ?: getString(R.string.episode_name_format).format(
|
||||||
|
@ -443,7 +443,7 @@ class ResultFragment : Fragment() {
|
||||||
episodeClick.data.index,
|
episodeClick.data.index,
|
||||||
eps,
|
eps,
|
||||||
sortUrls(currentLinks ?: return),
|
sortUrls(currentLinks ?: return),
|
||||||
currentSubs ?: ArrayList(),
|
currentSubs?.values?.toList() ?: emptyList(),
|
||||||
startTime = episodeClick.data.getRealPosition(),
|
startTime = episodeClick.data.getRealPosition(),
|
||||||
startIndex = startIndex
|
startIndex = startIndex
|
||||||
)
|
)
|
||||||
|
@ -673,7 +673,7 @@ class ResultFragment : Fragment() {
|
||||||
}
|
}
|
||||||
var text = "#EXTM3U"
|
var text = "#EXTM3U"
|
||||||
if (subs != null) {
|
if (subs != null) {
|
||||||
for (sub in subs) {
|
for (sub in subs.values) {
|
||||||
text += "\n#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID=\"subs\",NAME=\"${sub.lang}\",DEFAULT=NO,AUTOSELECT=NO,FORCED=NO,LANGUAGE=\"${sub.lang}\",URI=\"${sub.url}\""
|
text += "\n#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID=\"subs\",NAME=\"${sub.lang}\",DEFAULT=NO,AUTOSELECT=NO,FORCED=NO,LANGUAGE=\"${sub.lang}\",URI=\"${sub.url}\""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -731,7 +731,7 @@ class ResultFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
ACTION_DOWNLOAD_EPISODE -> {
|
ACTION_DOWNLOAD_EPISODE -> {
|
||||||
startDownload(currentLinks ?: return@main, currentSubs)
|
startDownload(currentLinks ?: return@main, currentSubs?.values?.toList() ?: emptyList())
|
||||||
}
|
}
|
||||||
|
|
||||||
ACTION_DOWNLOAD_MIRROR -> {
|
ACTION_DOWNLOAD_MIRROR -> {
|
||||||
|
@ -740,7 +740,7 @@ class ResultFragment : Fragment() {
|
||||||
links,//(currentLinks ?: return@main).filter { !it.isM3u8 },
|
links,//(currentLinks ?: return@main).filter { !it.isM3u8 },
|
||||||
getString(R.string.episode_action_download_mirror)
|
getString(R.string.episode_action_download_mirror)
|
||||||
) { link ->
|
) { link ->
|
||||||
startDownload(listOf(link), currentSubs)
|
startDownload(listOf(link), currentSubs?.values?.toList() ?: emptyList())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1064,6 +1064,12 @@ class ResultFragment : Fragment() {
|
||||||
return@setOnLongClickListener true
|
return@setOnLongClickListener true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result_download_movie?.setOnLongClickListener {
|
||||||
|
val card = currentEpisodes?.firstOrNull() ?: return@setOnLongClickListener true
|
||||||
|
handleAction(EpisodeClickEvent(ACTION_SHOW_OPTIONS, card))
|
||||||
|
return@setOnLongClickListener true
|
||||||
|
}
|
||||||
|
|
||||||
// result_options.setOnClickListener {
|
// result_options.setOnClickListener {
|
||||||
// val card = currentEpisodes?.first() ?: return@setOnClickListener
|
// val card = currentEpisodes?.first() ?: return@setOnClickListener
|
||||||
// handleAction(EpisodeClickEvent(ACTION_SHOW_OPTIONS, card))
|
// handleAction(EpisodeClickEvent(ACTION_SHOW_OPTIONS, card))
|
||||||
|
|
|
@ -12,9 +12,8 @@ import com.lagradost.cloudstream3.mvvm.Resource
|
||||||
import com.lagradost.cloudstream3.mvvm.safeApiCall
|
import com.lagradost.cloudstream3.mvvm.safeApiCall
|
||||||
import com.lagradost.cloudstream3.ui.APIRepository
|
import com.lagradost.cloudstream3.ui.APIRepository
|
||||||
import com.lagradost.cloudstream3.ui.WatchType
|
import com.lagradost.cloudstream3.ui.WatchType
|
||||||
import com.lagradost.cloudstream3.utils.DOWNLOAD_HEADER_CACHE
|
import com.lagradost.cloudstream3.utils.*
|
||||||
import com.lagradost.cloudstream3.utils.DataStore.setKey
|
import com.lagradost.cloudstream3.utils.DataStore.setKey
|
||||||
import com.lagradost.cloudstream3.utils.DataStoreHelper
|
|
||||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.getBookmarkedData
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.getBookmarkedData
|
||||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.getResultSeason
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.getResultSeason
|
||||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.getResultWatchState
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.getResultWatchState
|
||||||
|
@ -25,9 +24,7 @@ import com.lagradost.cloudstream3.utils.DataStoreHelper.setLastWatched
|
||||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.setResultSeason
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.setResultSeason
|
||||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.setResultWatchState
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.setResultWatchState
|
||||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.setViewPos
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.setViewPos
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
|
||||||
import com.lagradost.cloudstream3.utils.FillerEpisodeCheck.getFillerEpisodes
|
import com.lagradost.cloudstream3.utils.FillerEpisodeCheck.getFillerEpisodes
|
||||||
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
@ -133,7 +130,7 @@ class ResultViewModel : ViewModel() {
|
||||||
val seasons = seasonTypes.toList().map { it.first }.sortedBy { it }
|
val seasons = seasonTypes.toList().map { it.first }.sortedBy { it }
|
||||||
seasonSelections.postValue(seasons)
|
seasonSelections.postValue(seasons)
|
||||||
if (seasons.isEmpty()) { // WHAT THE FUCK DID YOU DO????? HOW DID YOU DO THIS
|
if (seasons.isEmpty()) { // WHAT THE FUCK DID YOU DO????? HOW DID YOU DO THIS
|
||||||
_publicEpisodes.postValue(Resource.Success(ArrayList()))
|
_publicEpisodes.postValue(Resource.Success(emptyList()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -415,18 +412,18 @@ class ResultViewModel : ViewModel() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val _allEpisodes: MutableLiveData<HashMap<Int, ArrayList<ExtractorLink>>> =
|
private val _allEpisodes: MutableLiveData<HashMap<Int, List<ExtractorLink>>> =
|
||||||
MutableLiveData(HashMap()) // LOOKUP BY ID
|
MutableLiveData(HashMap()) // LOOKUP BY ID
|
||||||
private val _allEpisodesSubs: MutableLiveData<HashMap<Int, ArrayList<SubtitleFile>>> =
|
private val _allEpisodesSubs: MutableLiveData<HashMap<Int, HashMap<String, SubtitleFile>>> =
|
||||||
MutableLiveData(HashMap()) // LOOKUP BY ID
|
MutableLiveData(HashMap()) // LOOKUP BY ID
|
||||||
|
|
||||||
val allEpisodes: LiveData<HashMap<Int, ArrayList<ExtractorLink>>> get() = _allEpisodes
|
val allEpisodes: LiveData<HashMap<Int, List<ExtractorLink>>> get() = _allEpisodes
|
||||||
val allEpisodesSubs: LiveData<HashMap<Int, ArrayList<SubtitleFile>>> get() = _allEpisodesSubs
|
val allEpisodesSubs: LiveData<HashMap<Int, HashMap<String, SubtitleFile>>> get() = _allEpisodesSubs
|
||||||
|
|
||||||
private var _apiName: MutableLiveData<String> = MutableLiveData()
|
private var _apiName: MutableLiveData<String> = MutableLiveData()
|
||||||
val apiName: LiveData<String> get() = _apiName
|
val apiName: LiveData<String> get() = _apiName
|
||||||
|
|
||||||
data class EpisodeData(val links: ArrayList<ExtractorLink>, val subs: ArrayList<SubtitleFile>)
|
data class EpisodeData(val links: List<ExtractorLink>, val subs: HashMap<String, SubtitleFile>)
|
||||||
|
|
||||||
fun loadEpisode(
|
fun loadEpisode(
|
||||||
episode: ResultEpisode,
|
episode: ResultEpisode,
|
||||||
|
@ -452,11 +449,35 @@ class ResultViewModel : ViewModel() {
|
||||||
_allEpisodes.value?.remove(id)
|
_allEpisodes.value?.remove(id)
|
||||||
}
|
}
|
||||||
val links = ArrayList<ExtractorLink>()
|
val links = ArrayList<ExtractorLink>()
|
||||||
val subs = ArrayList<SubtitleFile>()
|
val subs = HashMap<String, SubtitleFile>()
|
||||||
return safeApiCall {
|
return safeApiCall {
|
||||||
repo?.loadLinks(data, isCasting, { subtitleFile ->
|
repo?.loadLinks(data, isCasting, { subtitleFile ->
|
||||||
if (!subs.any { it.url == subtitleFile.url }) {
|
if (!subs.values.any { it.url == subtitleFile.url }) {
|
||||||
subs.add(subtitleFile)
|
val langTrimmed = subtitleFile.lang.trimEnd()
|
||||||
|
|
||||||
|
val langId = if (langTrimmed.length == 2) {
|
||||||
|
SubtitleHelper.fromTwoLettersToLanguage(langTrimmed) ?: langTrimmed
|
||||||
|
} else {
|
||||||
|
langTrimmed
|
||||||
|
}
|
||||||
|
|
||||||
|
var title: String
|
||||||
|
var count = 0
|
||||||
|
while (true) {
|
||||||
|
title = "$langId${if (count == 0) "" else " ${count+1}"}"
|
||||||
|
count++
|
||||||
|
if(!subs.containsKey(title)) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val file =
|
||||||
|
subtitleFile.copy(
|
||||||
|
lang = title
|
||||||
|
)
|
||||||
|
|
||||||
|
subs[title] = file
|
||||||
|
|
||||||
_allEpisodesSubs.value?.set(id, subs)
|
_allEpisodesSubs.value?.set(id, subs)
|
||||||
_allEpisodesSubs.postValue(_allEpisodesSubs.value)
|
_allEpisodesSubs.postValue(_allEpisodesSubs.value)
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,10 @@ object SearchHelper {
|
||||||
activity.loadSearchResult(card, START_ACTION_LOAD_EP, card.id!!)
|
activity.loadSearchResult(card, START_ACTION_LOAD_EP, card.id!!)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
handleSearchClickCallback(activity, SearchClickCallback(SEARCH_ACTION_LOAD,callback.view,callback.card))
|
handleSearchClickCallback(
|
||||||
|
activity,
|
||||||
|
SearchClickCallback(SEARCH_ACTION_LOAD, callback.view, callback.card)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SEARCH_ACTION_SHOW_METADATA -> {
|
SEARCH_ACTION_SHOW_METADATA -> {
|
||||||
|
|
|
@ -216,12 +216,19 @@ class SubtitlesFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
subs_subtitle_elevation.setOnClickListener { textView ->
|
subs_subtitle_elevation.setOnClickListener { textView ->
|
||||||
|
val suffix = "dp"
|
||||||
val elevationTypes = listOf(
|
val elevationTypes = listOf(
|
||||||
Pair(0, "None"),
|
Pair(0, textView.context.getString(R.string.none)),
|
||||||
Pair(10, "10"),
|
Pair(10, "10$suffix"),
|
||||||
Pair(20, "20"),
|
Pair(20, "20$suffix"),
|
||||||
Pair(30, "30"),
|
Pair(30, "30$suffix"),
|
||||||
Pair(40, "40"),
|
Pair(40, "40$suffix"),
|
||||||
|
Pair(50, "50$suffix"),
|
||||||
|
Pair(60, "60$suffix"),
|
||||||
|
Pair(70, "70$suffix"),
|
||||||
|
Pair(80, "80$suffix"),
|
||||||
|
Pair(90, "90$suffix"),
|
||||||
|
Pair(100, "100$suffix"),
|
||||||
)
|
)
|
||||||
|
|
||||||
//showBottomDialog
|
//showBottomDialog
|
||||||
|
@ -248,11 +255,11 @@ class SubtitlesFragment : Fragment() {
|
||||||
|
|
||||||
subs_edge_type.setOnClickListener { textView ->
|
subs_edge_type.setOnClickListener { textView ->
|
||||||
val edgeTypes = listOf(
|
val edgeTypes = listOf(
|
||||||
Pair(CaptionStyleCompat.EDGE_TYPE_NONE, "None"),
|
Pair(CaptionStyleCompat.EDGE_TYPE_NONE, textView.context.getString(R.string.subtitles_none)),
|
||||||
Pair(CaptionStyleCompat.EDGE_TYPE_OUTLINE, "Outline"),
|
Pair(CaptionStyleCompat.EDGE_TYPE_OUTLINE, textView.context.getString(R.string.subtitles_outline)),
|
||||||
Pair(CaptionStyleCompat.EDGE_TYPE_DEPRESSED, "Depressed"),
|
Pair(CaptionStyleCompat.EDGE_TYPE_DEPRESSED, textView.context.getString(R.string.subtitles_depressed)),
|
||||||
Pair(CaptionStyleCompat.EDGE_TYPE_DROP_SHADOW, "Shadow"),
|
Pair(CaptionStyleCompat.EDGE_TYPE_DROP_SHADOW, textView.context.getString(R.string.subtitles_shadow)),
|
||||||
Pair(CaptionStyleCompat.EDGE_TYPE_RAISED, "Raised"),
|
Pair(CaptionStyleCompat.EDGE_TYPE_RAISED, textView.context.getString(R.string.subtitles_raised)),
|
||||||
)
|
)
|
||||||
|
|
||||||
//showBottomDialog
|
//showBottomDialog
|
||||||
|
@ -278,7 +285,7 @@ class SubtitlesFragment : Fragment() {
|
||||||
subs_font_size.setOnClickListener { textView ->
|
subs_font_size.setOnClickListener { textView ->
|
||||||
val suffix = "sp"
|
val suffix = "sp"
|
||||||
val fontSizes = listOf(
|
val fontSizes = listOf(
|
||||||
Pair(null, "Normal"),
|
Pair(null, textView.context.getString(R.string.normal)),
|
||||||
Pair(6f, "6$suffix"),
|
Pair(6f, "6$suffix"),
|
||||||
Pair(8f, "8$suffix"),
|
Pair(8f, "8$suffix"),
|
||||||
Pair(9f, "9$suffix"),
|
Pair(9f, "9$suffix"),
|
||||||
|
@ -328,7 +335,7 @@ class SubtitlesFragment : Fragment() {
|
||||||
|
|
||||||
subs_font.setOnClickListener { textView ->
|
subs_font.setOnClickListener { textView ->
|
||||||
val fontTypes = listOf(
|
val fontTypes = listOf(
|
||||||
Pair(null, "Normal"),
|
Pair(null, textView.context.getString(R.string.normal)),
|
||||||
Pair(R.font.trebuchet_ms, "Trebuchet MS"),
|
Pair(R.font.trebuchet_ms, "Trebuchet MS"),
|
||||||
Pair(R.font.netflix_sans, "Netflix Sans"),
|
Pair(R.font.netflix_sans, "Netflix Sans"),
|
||||||
Pair(R.font.google_sans, "Google Sans"),
|
Pair(R.font.google_sans, "Google Sans"),
|
||||||
|
@ -430,7 +437,7 @@ class SubtitlesFragment : Fragment() {
|
||||||
getPixels(TypedValue.COMPLEX_UNIT_SP, 25.0f).toFloat(),
|
getPixels(TypedValue.COMPLEX_UNIT_SP, 25.0f).toFloat(),
|
||||||
Cue.TEXT_SIZE_TYPE_ABSOLUTE
|
Cue.TEXT_SIZE_TYPE_ABSOLUTE
|
||||||
)
|
)
|
||||||
.setText("The quick brown fox jumps over the lazy dog").build()
|
.setText(subtitle_text.context.getString(R.string.subtitles_example_text)).build()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
package com.lagradost.cloudstream3.utils
|
package com.lagradost.cloudstream3.utils
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.network.get
|
|
||||||
import com.lagradost.cloudstream3.network.text
|
|
||||||
import org.jsoup.Jsoup
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
object SubtitleHelper {
|
object SubtitleHelper {
|
||||||
|
@ -52,16 +49,22 @@ object SubtitleHelper {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var ISO_639_1Map : HashMap<String, String> = hashMapOf()
|
||||||
|
private fun initISO6391Map() {
|
||||||
|
for (lang in languages) {
|
||||||
|
ISO_639_1Map[lang.ISO_639_1] = lang.languageName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** ISO_639_1 -> lang*/
|
/** ISO_639_1 -> lang*/
|
||||||
fun fromTwoLettersToLanguage(input: String): String? {
|
fun fromTwoLettersToLanguage(input: String): String? {
|
||||||
if (input.length != 2) return null
|
if (input.length != 2) return null
|
||||||
|
if(ISO_639_1Map.isEmpty()) {
|
||||||
|
initISO6391Map()
|
||||||
|
}
|
||||||
val comparison = input.toLowerCase(Locale.ROOT)
|
val comparison = input.toLowerCase(Locale.ROOT)
|
||||||
for (lang in languages) {
|
|
||||||
if (lang.ISO_639_1 == comparison) {
|
return ISO_639_1Map[comparison]
|
||||||
return lang.languageName
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**ISO_639_2_B or ISO_639_2_T or ISO_639_3-> lang*/
|
/**ISO_639_2_B or ISO_639_2_T or ISO_639_3-> lang*/
|
||||||
|
|
|
@ -213,4 +213,26 @@
|
||||||
<string name="source_error">Källfel</string>
|
<string name="source_error">Källfel</string>
|
||||||
<string name="remote_error">Fjärrfel</string>
|
<string name="remote_error">Fjärrfel</string>
|
||||||
<string name="render_error">Renderingsfel</string>
|
<string name="render_error">Renderingsfel</string>
|
||||||
|
<string name="subtitles_example_text">Flygande bäckasiner söka hwila på mjuka tuvor</string>
|
||||||
|
<string name="subtitles_shadow">Skugga</string>
|
||||||
|
<string name="subtitles_outline">Kontur</string>
|
||||||
|
<string name="subtitles_depressed">Nedsänkt</string>
|
||||||
|
<string name="subtitles_raised">Upphöjd</string>
|
||||||
|
<string name="none">Ingen</string>
|
||||||
|
<string name="normal">Normal</string>
|
||||||
|
<string name="all">Allt</string>
|
||||||
|
<string name="max">Min</string>
|
||||||
|
<string name="min">Max</string>
|
||||||
|
<string name="add_account">Lägg till konto</string>
|
||||||
|
<string name="switch_account">Byt konto</string>
|
||||||
|
<string name="login">Logga in</string>
|
||||||
|
<string name="logout">Logga ut</string>
|
||||||
|
<string name="account">konto</string>
|
||||||
|
<string name="download_path_pref">Nerladdningsplats</string>
|
||||||
|
<string name="type_re_watching">Kollar om</string>
|
||||||
|
<string name="automatic">Automatisk</string>
|
||||||
|
<string name="dns_pref">DNS över HTTPS</string>
|
||||||
|
<string name="dns_pref_summary">" "</string>
|
||||||
|
<string name="app_theme_settings">Appens tema</string>
|
||||||
|
<string name="app_dub_sub_episode_text_format">%s A%d</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -333,5 +333,19 @@
|
||||||
<string name="switch_account">Switch account</string>
|
<string name="switch_account">Switch account</string>
|
||||||
<string name="add_account">Add account</string>
|
<string name="add_account">Add account</string>
|
||||||
<!-- ============ -->
|
<!-- ============ -->
|
||||||
|
<string name="none">None</string>
|
||||||
|
<string name="normal">Normal</string>
|
||||||
|
<string name="all">All</string>
|
||||||
|
<string name="max">Max</string>
|
||||||
|
<string name="min">Min</string>
|
||||||
|
<string name="subtitles_none" translatable="false">@string/none</string>
|
||||||
|
<string name="subtitles_outline">Outline</string>
|
||||||
|
<string name="subtitles_depressed">Depressed</string>
|
||||||
|
<string name="subtitles_shadow">Shadow</string>
|
||||||
|
<string name="subtitles_raised">Raised</string>
|
||||||
|
<!--
|
||||||
|
Example text does not need to be translated and if you do translate include all the letters in the alphabet,
|
||||||
|
see https://en.wikipedia.org/wiki/The_quick_brown_fox_jumps_over_the_lazy_dog
|
||||||
|
-->
|
||||||
|
<string name="subtitles_example_text">The quick brown fox jumps over the lazy dog</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
Loading…
Reference in a new issue