fix: subtitles not showing

This commit is contained in:
rebel onion 2025-05-15 01:13:47 -05:00
parent 7d0894cd92
commit afd9f6b884
5 changed files with 152 additions and 120 deletions

View file

@ -48,6 +48,10 @@ android {
manifestPlaceholders.icon_placeholder_round = "@mipmap/ic_launcher_alpha_round" manifestPlaceholders.icon_placeholder_round = "@mipmap/ic_launcher_alpha_round"
debuggable System.getenv("CI") == null debuggable System.getenv("CI") == null
isDefault true isDefault true
debuggable true
jniDebuggable true
minifyEnabled false
shrinkResources false
} }
debug { debug {
applicationIdSuffix ".beta" applicationIdSuffix ".beta"
@ -81,25 +85,26 @@ android {
dependencies { dependencies {
// FireBase // FireBase
googleImplementation platform('com.google.firebase:firebase-bom:33.0.0') googleImplementation platform('com.google.firebase:firebase-bom:33.13.0')
googleImplementation 'com.google.firebase:firebase-analytics-ktx:22.0.0' googleImplementation 'com.google.firebase:firebase-analytics-ktx:22.4.0'
googleImplementation 'com.google.firebase:firebase-crashlytics-ktx:19.0.0' googleImplementation 'com.google.firebase:firebase-crashlytics-ktx:19.4.3'
// Core // Core
implementation 'androidx.appcompat:appcompat:1.6.1' implementation 'androidx.appcompat:appcompat:1.7.0'
implementation 'androidx.browser:browser:1.8.0' implementation 'androidx.browser:browser:1.8.0'
implementation 'androidx.core:core-ktx:1.13.1' implementation 'androidx.core:core-ktx:1.16.0'
implementation 'androidx.fragment:fragment-ktx:1.6.2' implementation 'androidx.fragment:fragment-ktx:1.8.6'
implementation 'androidx.activity:activity-ktx:1.10.1'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
implementation 'androidx.legacy:legacy-support-v4:1.0.0' implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.multidex:multidex:2.0.1' implementation 'androidx.multidex:multidex:2.0.1'
implementation "androidx.work:work-runtime-ktx:2.9.0" implementation "androidx.work:work-runtime-ktx:2.10.1"
implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.google.code.gson:gson:2.10.1' implementation 'com.google.code.gson:gson:2.10.1'
implementation 'com.github.Blatzar:NiceHttp:0.4.4' implementation 'com.github.Blatzar:NiceHttp:0.4.4'
implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3' implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3'
implementation 'androidx.preference:preference-ktx:1.2.1' implementation 'androidx.preference:preference-ktx:1.2.1'
implementation 'androidx.webkit:webkit:1.11.0' implementation 'androidx.webkit:webkit:1.13.0'
implementation "com.anggrayudi:storage:1.5.5" implementation "com.anggrayudi:storage:1.5.5"
implementation "androidx.biometric:biometric:1.1.0" implementation "androidx.biometric:biometric:1.1.0"
@ -113,7 +118,7 @@ dependencies {
implementation 'jp.wasabeef:glide-transformations:4.3.0' implementation 'jp.wasabeef:glide-transformations:4.3.0'
// Exoplayer // Exoplayer
ext.exo_version = '1.5.1' ext.exo_version = '1.6.1'
implementation "androidx.media3:media3-exoplayer:$exo_version" implementation "androidx.media3:media3-exoplayer:$exo_version"
implementation "androidx.media3:media3-ui:$exo_version" implementation "androidx.media3:media3-ui:$exo_version"
implementation "androidx.media3:media3-exoplayer-hls:$exo_version" implementation "androidx.media3:media3-exoplayer-hls:$exo_version"
@ -133,7 +138,7 @@ dependencies {
implementation 'com.davemorrissey.labs:subsampling-scale-image-view-androidx:3.10.0' implementation 'com.davemorrissey.labs:subsampling-scale-image-view-androidx:3.10.0'
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'
implementation 'androidx.paging:paging-runtime-ktx:3.2.1' implementation 'androidx.paging:paging-runtime-ktx:3.3.6'
implementation 'com.github.eltos:simpledialogfragments:v3.7' implementation 'com.github.eltos:simpledialogfragments:v3.7'
implementation 'com.github.AAChartModel:AAChartCore-Kotlin:7.2.3' implementation 'com.github.AAChartModel:AAChartCore-Kotlin:7.2.3'
@ -162,13 +167,13 @@ dependencies {
implementation 'ca.gosyer:voyager-navigator:1.0.0-rc07' implementation 'ca.gosyer:voyager-navigator:1.0.0-rc07'
implementation 'com.squareup.logcat:logcat:0.1' implementation 'com.squareup.logcat:logcat:0.1'
implementation 'uy.kohesive.injekt:injekt-core:1.16.+' implementation 'uy.kohesive.injekt:injekt-core:1.16.+'
implementation 'com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.12' implementation 'com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.14'
implementation 'com.squareup.okhttp3:okhttp:5.0.0-alpha.12' implementation 'com.squareup.okhttp3:okhttp:5.0.0-alpha.14'
implementation 'com.squareup.okhttp3:okhttp-dnsoverhttps' implementation 'com.squareup.okhttp3:okhttp-dnsoverhttps'
implementation 'com.squareup.okio:okio:3.8.0' implementation 'com.squareup.okio:okio:3.9.1'
implementation 'com.squareup.okhttp3:okhttp-brotli:5.0.0-alpha.12' implementation 'com.squareup.okhttp3:okhttp-brotli:5.0.0-alpha.14'
implementation 'org.jsoup:jsoup:1.16.1' implementation 'org.jsoup:jsoup:1.18.1'
implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json-okio:1.6.3' implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json-okio:1.7.3'
implementation 'com.jakewharton.rxrelay:rxrelay:1.2.0' implementation 'com.jakewharton.rxrelay:rxrelay:1.2.0'
implementation 'com.github.tachiyomiorg:unifile:17bec43' implementation 'com.github.tachiyomiorg:unifile:17bec43'
implementation 'com.github.gpanther:java-nat-sort:natural-comparator-1.1' implementation 'com.github.gpanther:java-nat-sort:natural-comparator-1.1'

View file

@ -4,6 +4,7 @@ import android.animation.ObjectAnimator
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Intent import android.content.Intent
import android.content.res.Configuration import android.content.res.Configuration
import android.graphics.Color
import android.os.Bundle import android.os.Bundle
import android.text.SpannableStringBuilder import android.text.SpannableStringBuilder
import android.view.GestureDetector import android.view.GestureDetector
@ -12,6 +13,8 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.animation.AccelerateDecelerateInterpolator import android.view.animation.AccelerateDecelerateInterpolator
import android.widget.ImageView import android.widget.ImageView
import androidx.activity.SystemBarStyle
import androidx.activity.enableEdgeToEdge
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
@ -19,8 +22,10 @@ import androidx.appcompat.content.res.AppCompatResources
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.text.bold import androidx.core.text.bold
import androidx.core.text.color import androidx.core.text.color
import androidx.core.view.WindowInsetsControllerCompat
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.core.view.marginBottom import androidx.core.view.marginBottom
import androidx.core.view.setPadding
import androidx.core.view.updateLayoutParams import androidx.core.view.updateLayoutParams
import androidx.core.view.updateMargins import androidx.core.view.updateMargins
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
@ -79,6 +84,7 @@ class MediaDetailsActivity : AppCompatActivity(), AppBarLayout.OnOffsetChangedLi
@SuppressLint("ClickableViewAccessibility") @SuppressLint("ClickableViewAccessibility")
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
var media: Media = intent.getSerialized("media") ?: mediaSingleton ?: emptyMedia() var media: Media = intent.getSerialized("media") ?: mediaSingleton ?: emptyMedia()
val id = intent.getIntExtra("mediaId", -1) val id = intent.getIntExtra("mediaId", -1)
@ -109,6 +115,7 @@ class MediaDetailsActivity : AppCompatActivity(), AppBarLayout.OnOffsetChangedLi
// Ui init // Ui init
initActivity(this) initActivity(this)
binding.mediaViewPager.updateLayoutParams<ViewGroup.MarginLayoutParams> { binding.mediaViewPager.updateLayoutParams<ViewGroup.MarginLayoutParams> {
bottomMargin = navBarHeight bottomMargin = navBarHeight
} }
@ -132,10 +139,12 @@ class MediaDetailsActivity : AppCompatActivity(), AppBarLayout.OnOffsetChangedLi
val navBarBottomMargin = if (resources.configuration.orientation == val navBarBottomMargin = if (resources.configuration.orientation ==
Configuration.ORIENTATION_LANDSCAPE Configuration.ORIENTATION_LANDSCAPE
) 0 else navBarHeight ) 0 else navBarHeight
navBar.updateLayoutParams<ViewGroup.MarginLayoutParams> { navBar.setPadding(
rightMargin = navBarRightMargin navBar.paddingLeft,
bottomMargin = navBarBottomMargin navBar.paddingTop,
} navBar.paddingRight + navBarRightMargin,
navBar.paddingBottom + navBarBottomMargin
)
binding.mediaBanner.updateLayoutParams { height += statusBarHeight } binding.mediaBanner.updateLayoutParams { height += statusBarHeight }
binding.mediaBannerNoKen.updateLayoutParams { height += statusBarHeight } binding.mediaBannerNoKen.updateLayoutParams { height += statusBarHeight }
binding.mediaClose.updateLayoutParams<ViewGroup.MarginLayoutParams> { topMargin += statusBarHeight } binding.mediaClose.updateLayoutParams<ViewGroup.MarginLayoutParams> { topMargin += statusBarHeight }

View file

@ -1,6 +1,8 @@
package ani.dantotsu.media package ani.dantotsu.media
import android.content.Context import android.content.Context
import androidx.core.net.toFile
import androidx.core.net.toUri
import ani.dantotsu.download.DownloadedType import ani.dantotsu.download.DownloadedType
import ani.dantotsu.download.DownloadsManager import ani.dantotsu.download.DownloadsManager
import ani.dantotsu.parsers.SubtitleType import ani.dantotsu.parsers.SubtitleType
@ -21,28 +23,32 @@ class SubtitleDownloader {
suspend fun loadSubtitleType(url: String): SubtitleType = suspend fun loadSubtitleType(url: String): SubtitleType =
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
return@withContext try { return@withContext try {
// Initialize the NetworkHelper instance. Replace this line based on how you usually initialize it if (!url.startsWith("file")) {
val networkHelper = Injekt.get<NetworkHelper>() // Initialize the NetworkHelper instance. Replace this line based on how you usually initialize it
val request = Request.Builder() val networkHelper = Injekt.get<NetworkHelper>()
.url(url) val request = Request.Builder()
.build() .url(url)
.build()
val response = networkHelper.client.newCall(request).execute() val response = networkHelper.client.newCall(request).execute()
// Check if response is successful // Check if response is successful
if (response.isSuccessful) { if (response.isSuccessful) {
val responseBody = response.body.string() val responseBody = response.body.string()
val subtitleType = when { val subtitleType = getType(responseBody)
responseBody.contains("[Script Info]") -> SubtitleType.ASS
responseBody.contains("WEBVTT") -> SubtitleType.VTT subtitleType
else -> SubtitleType.SRT } else {
SubtitleType.UNKNOWN
} }
subtitleType
} else { } else {
SubtitleType.UNKNOWN val uri = url.toUri()
val file = uri.toFile()
val fileBody = file.readText()
val subtitleType = getType(fileBody)
subtitleType
} }
} catch (e: Exception) { } catch (e: Exception) {
Logger.log(e) Logger.log(e)
@ -50,6 +56,15 @@ class SubtitleDownloader {
} }
} }
private fun getType(content: String): SubtitleType {
return when {
content.contains("[Script Info]") -> SubtitleType.ASS
content.contains("WEBVTT") -> SubtitleType.VTT
content.contains("SRT") -> SubtitleType.SRT
else -> SubtitleType.UNKNOWN
}
}
//actually downloads lol //actually downloads lol
@Deprecated("handled externally") @Deprecated("handled externally")
suspend fun downloadSubtitle( suspend fun downloadSubtitle(

View file

@ -2,7 +2,6 @@ package ani.dantotsu.media.anime
import android.animation.ObjectAnimator import android.animation.ObjectAnimator
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.AlertDialog
import android.app.Dialog import android.app.Dialog
import android.app.PictureInPictureParams import android.app.PictureInPictureParams
import android.app.PictureInPictureUiState import android.app.PictureInPictureUiState
@ -19,7 +18,6 @@ import android.media.AudioManager.AUDIOFOCUS_GAIN
import android.media.AudioManager.AUDIOFOCUS_LOSS import android.media.AudioManager.AUDIOFOCUS_LOSS
import android.media.AudioManager.AUDIOFOCUS_LOSS_TRANSIENT import android.media.AudioManager.AUDIOFOCUS_LOSS_TRANSIENT
import android.media.AudioManager.STREAM_MUSIC import android.media.AudioManager.STREAM_MUSIC
import android.net.Uri
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.os.CountDownTimer import android.os.CountDownTimer
@ -75,9 +73,7 @@ import androidx.media3.common.TrackSelectionOverride
import androidx.media3.common.Tracks import androidx.media3.common.Tracks
import androidx.media3.common.text.CueGroup import androidx.media3.common.text.CueGroup
import androidx.media3.common.util.UnstableApi import androidx.media3.common.util.UnstableApi
import androidx.media3.datasource.DataSource
import androidx.media3.datasource.DefaultDataSource import androidx.media3.datasource.DefaultDataSource
import androidx.media3.datasource.HttpDataSource
import androidx.media3.datasource.cache.CacheDataSource 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
@ -175,10 +171,10 @@ import java.util.Timer
import java.util.TimerTask import java.util.TimerTask
import java.util.concurrent.Executors import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import kotlin.collections.set
import kotlin.math.max import kotlin.math.max
import kotlin.math.min import kotlin.math.min
import kotlin.math.roundToInt import kotlin.math.roundToInt
import androidx.core.net.toUri
@UnstableApi @UnstableApi
@SuppressLint("ClickableViewAccessibility") @SuppressLint("ClickableViewAccessibility")
@ -427,7 +423,8 @@ class ExoplayerView :
false -> 0f false -> 0f
} }
val textElevation = PrefManager.getVal<Float>(PrefName.SubBottomMargin) / 50 * resources.displayMetrics.heightPixels val textElevation =
PrefManager.getVal<Float>(PrefName.SubBottomMargin) / 50 * resources.displayMetrics.heightPixels
textView.translationY = -textElevation textView.translationY = -textElevation
} }
@ -606,9 +603,9 @@ class ExoplayerView :
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
pipEnabled = pipEnabled =
packageManager.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE) && packageManager.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE) &&
PrefManager.getVal( PrefManager.getVal(
PrefName.Pip, PrefName.Pip,
) )
if (pipEnabled) { if (pipEnabled) {
exoPip.visibility = View.VISIBLE exoPip.visibility = View.VISIBLE
exoPip.setOnClickListener { exoPip.setOnClickListener {
@ -1044,7 +1041,8 @@ class ExoplayerView :
} }
} }
override fun onSingleClick(event: MotionEvent) = if (isSeeking) doubleTap(false, event) else handleController() override fun onSingleClick(event: MotionEvent) =
if (isSeeking) doubleTap(false, event) else handleController()
}, },
) )
val rewindArea = playerView.findViewById<View>(R.id.exo_rewind_area) val rewindArea = playerView.findViewById<View>(R.id.exo_rewind_area)
@ -1079,7 +1077,8 @@ class ExoplayerView :
} }
} }
override fun onSingleClick(event: MotionEvent) = if (isSeeking) doubleTap(true, event) else handleController() override fun onSingleClick(event: MotionEvent) =
if (isSeeking) doubleTap(true, event) else handleController()
}, },
) )
val forwardArea = playerView.findViewById<View>(R.id.exo_forward_area) val forwardArea = playerView.findViewById<View>(R.id.exo_forward_area)
@ -1449,7 +1448,8 @@ class ExoplayerView :
else -> mutableListOf() else -> mutableListOf()
} }
val startTimestamp = Calendar.getInstance() val startTimestamp = Calendar.getInstance()
val durationInSeconds = if (exoPlayer.duration != C.TIME_UNSET) (exoPlayer.duration / 1000).toInt() else 1440 val durationInSeconds =
if (exoPlayer.duration != C.TIME_UNSET) (exoPlayer.duration / 1000).toInt() else 1440
val endTimestamp = val endTimestamp =
Calendar.getInstance().apply { Calendar.getInstance().apply {
@ -1502,12 +1502,12 @@ class ExoplayerView :
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
val list = val list =
( (
PrefManager.getNullableCustomVal( PrefManager.getNullableCustomVal(
"continueAnimeList", "continueAnimeList",
listOf<Int>(), listOf<Int>(),
List::class.java, List::class.java,
) as List<Int> ) as List<Int>
).toMutableList() ).toMutableList()
if (list.contains(media.id)) list.remove(media.id) if (list.contains(media.id)) list.remove(media.id)
list.add(media.id) list.add(media.id)
PrefManager.setCustomVal("continueAnimeList", list) PrefManager.setCustomVal("continueAnimeList", list)
@ -1567,7 +1567,11 @@ class ExoplayerView :
subtitle = intent.getSerialized("subtitle") subtitle = intent.getSerialized("subtitle")
?: when ( ?: when (
val subLang: String? = val subLang: String? =
PrefManager.getNullableCustomVal("subLang_${media.id}", null, String::class.java) PrefManager.getNullableCustomVal(
"subLang_${media.id}",
null,
String::class.java
)
) { ) {
null -> { null -> {
when (episode.selectedSubtitle) { when (episode.selectedSubtitle) {
@ -1575,8 +1579,12 @@ class ExoplayerView :
-1 -> -1 ->
ext.subtitles.find { ext.subtitles.find {
it.language.contains(lang, ignoreCase = true) || it.language.contains(lang, ignoreCase = true) ||
it.language.contains(getLanguageCode(lang), ignoreCase = true) it.language.contains(
getLanguageCode(lang),
ignoreCase = true
)
} }
else -> ext.subtitles.getOrNull(episode.selectedSubtitle!!) else -> ext.subtitles.getOrNull(episode.selectedSubtitle!!)
} }
} }
@ -1597,29 +1605,27 @@ class ExoplayerView :
emptyList<MediaItem.SubtitleConfiguration>().toMutableList() emptyList<MediaItem.SubtitleConfiguration>().toMutableList()
ext.subtitles.forEach { subtitle -> ext.subtitles.forEach { subtitle ->
val subtitleUrl = if (!hasExtSubtitles) video!!.file.url else subtitle.file.url val subtitleUrl = if (!hasExtSubtitles) video!!.file.url else subtitle.file.url
// var localFile: String? = null
if (subtitle.type == SubtitleType.UNKNOWN) { if (subtitle.type == SubtitleType.UNKNOWN) {
runBlocking { runBlocking {
val type = SubtitleDownloader.loadSubtitleType(subtitleUrl) val type = SubtitleDownloader.loadSubtitleType(subtitleUrl)
val fileUri = Uri.parse(subtitleUrl) val fileUri = (subtitleUrl).toUri()
sub += sub +=
MediaItem.SubtitleConfiguration MediaItem.SubtitleConfiguration
.Builder(fileUri) .Builder(fileUri)
.setSelectionFlags(C.SELECTION_FLAG_DEFAULT) .setSelectionFlags(C.SELECTION_FLAG_DEFAULT)
.setMimeType( .setMimeType(
when (type) { when (type) {
SubtitleType.VTT -> MimeTypes.TEXT_SSA SubtitleType.VTT -> MimeTypes.TEXT_VTT
SubtitleType.ASS -> MimeTypes.TEXT_SSA SubtitleType.ASS -> MimeTypes.TEXT_SSA
SubtitleType.SRT -> MimeTypes.TEXT_SSA SubtitleType.SRT -> MimeTypes.APPLICATION_SUBRIP
else -> MimeTypes.TEXT_SSA else -> MimeTypes.TEXT_UNKNOWN
}, },
).setId("69") ).setId("69")
.setLanguage(subtitle.language) .setLanguage(subtitle.language)
.build() .build()
} }
println("sub: $sub")
} else { } else {
val subUri = Uri.parse(subtitleUrl) val subUri = subtitleUrl.toUri()
sub += sub +=
MediaItem.SubtitleConfiguration MediaItem.SubtitleConfiguration
.Builder(subUri) .Builder(subUri)
@ -1649,26 +1655,18 @@ class ExoplayerView :
followRedirects(true) followRedirects(true)
followSslRedirects(true) followSslRedirects(true)
}.build() }.build()
val dataSourceFactory = val httpDataSourceFactory =
DataSource.Factory { OkHttpDataSource.Factory(httpClient).apply {
val dataSource: HttpDataSource = OkHttpDataSource.Factory(httpClient).createDataSource() setDefaultRequestProperties(defaultHeaders)
defaultHeaders.forEach { video?.file?.headers?.let {
dataSource.setRequestProperty(it.key, it.value) setDefaultRequestProperties(it)
} }
video?.file?.headers?.forEach {
dataSource.setRequestProperty(it.key, it.value)
}
dataSource
} }
val dafuckDataSourceFactory = DefaultDataSource.Factory(this) val defaultDataSourceFactory = DefaultDataSource.Factory(this, httpDataSourceFactory)
cacheFactory = cacheFactory =
CacheDataSource.Factory().apply { CacheDataSource.Factory().apply {
setCache(VideoCache.getInstance(this@ExoplayerView)) setCache(VideoCache.getInstance(this@ExoplayerView))
if (ext.server.offline) { setUpstreamDataSourceFactory(defaultDataSourceFactory)
setUpstreamDataSourceFactory(dafuckDataSourceFactory)
} else {
setUpstreamDataSourceFactory(dataSourceFactory)
}
setCacheWriteDataSinkFactory(null) setCacheWriteDataSinkFactory(null)
} }
@ -1717,16 +1715,18 @@ class ExoplayerView :
val docFile = val docFile =
directory.listFiles().firstOrNull { directory.listFiles().firstOrNull {
it.name?.endsWith(".mp4") == true || it.name?.endsWith(".mp4") == true ||
it.name?.endsWith(".mkv") == true || it.name?.endsWith(".mkv") == true ||
it.name?.endsWith( it.name?.endsWith(
".${Injekt ".${
.get<DownloadAddonManager>() Injekt
.extension .get<DownloadAddonManager>()
?.extension .extension
?.getFileExtension() ?.extension
?.first ?: "ts"}", ?.getFileExtension()
) == ?.first ?: "ts"
true }",
) ==
true
} }
if (docFile != null) { if (docFile != null) {
val uri = docFile.uri val uri = docFile.uri
@ -1840,30 +1840,30 @@ class ExoplayerView :
"%02d:%02d:%02d", "%02d:%02d:%02d",
TimeUnit.MILLISECONDS.toHours(playbackPosition), TimeUnit.MILLISECONDS.toHours(playbackPosition),
TimeUnit.MILLISECONDS.toMinutes(playbackPosition) - TimeUnit.MILLISECONDS.toMinutes(playbackPosition) -
TimeUnit.HOURS.toMinutes( TimeUnit.HOURS.toMinutes(
TimeUnit.MILLISECONDS.toHours( TimeUnit.MILLISECONDS.toHours(
playbackPosition, playbackPosition,
),
), ),
),
TimeUnit.MILLISECONDS.toSeconds(playbackPosition) - TimeUnit.MILLISECONDS.toSeconds(playbackPosition) -
TimeUnit.MINUTES.toSeconds( TimeUnit.MINUTES.toSeconds(
TimeUnit.MILLISECONDS.toMinutes( TimeUnit.MILLISECONDS.toMinutes(
playbackPosition, playbackPosition,
),
), ),
),
) )
customAlertDialog().apply { customAlertDialog().apply {
setTitle(getString(R.string.continue_from, time)) setTitle(getString(R.string.continue_from, time))
setCancelable(false) setCancelable(false)
setPosButton(getString(R.string.yes)) { setPosButton(getString(R.string.yes)) {
buildExoplayer() buildExoplayer()
}
setNegButton(getString(R.string.no)) {
playbackPosition = 0L
buildExoplayer()
}
show()
} }
setNegButton(getString(R.string.no)) {
playbackPosition = 0L
buildExoplayer()
}
show()
}
} else { } else {
buildExoplayer() buildExoplayer()
} }
@ -1940,7 +1940,9 @@ class ExoplayerView :
val currentPosition = exoPlayer.currentPosition val currentPosition = exoPlayer.currentPosition
if ((lastSubtitle?.length ?: 0) < 20 || (lastPosition != 0L && currentPosition - lastPosition > 1500)) { if ((lastSubtitle?.length
?: 0) < 20 || (lastPosition != 0L && currentPosition - lastPosition > 1500)
) {
activeSubtitles.clear() activeSubtitles.clear()
} }
@ -2187,7 +2189,7 @@ class ExoplayerView :
currentTimeStamp = currentTimeStamp =
model.timeStamps.value?.find { timestamp -> model.timeStamps.value?.find { timestamp ->
timestamp.interval.startTime < playerCurrentTime && timestamp.interval.startTime < playerCurrentTime &&
playerCurrentTime < (timestamp.interval.endTime - 1) playerCurrentTime < (timestamp.interval.endTime - 1)
} }
val new = currentTimeStamp val new = currentTimeStamp
@ -2213,7 +2215,8 @@ class ExoplayerView :
override fun onTick(millisUntilFinished: Long) { override fun onTick(millisUntilFinished: Long) {
if (new == null) { if (new == null) {
skipTimeButton.visibility = View.GONE skipTimeButton.visibility = View.GONE
exoSkip.isVisible = PrefManager.getVal<Int>(PrefName.SkipTime) > 0 exoSkip.isVisible =
PrefManager.getVal<Int>(PrefName.SkipTime) > 0
disappeared = false disappeared = false
functionstarted = false functionstarted = false
cancelTimer() cancelTimer()
@ -2222,7 +2225,8 @@ class ExoplayerView :
override fun onFinish() { override fun onFinish() {
skipTimeButton.visibility = View.GONE skipTimeButton.visibility = View.GONE
exoSkip.isVisible = PrefManager.getVal<Int>(PrefName.SkipTime) > 0 exoSkip.isVisible =
PrefManager.getVal<Int>(PrefName.SkipTime) > 0
disappeared = true disappeared = true
functionstarted = false functionstarted = false
cancelTimer() cancelTimer()
@ -2310,7 +2314,7 @@ class ExoplayerView :
tracks.groups.forEach { tracks.groups.forEach {
println( println(
"Track__: $it\nTrack__: ${it.length}\nTrack__: ${it.isSelected}\n" + "Track__: $it\nTrack__: ${it.length}\nTrack__: ${it.isSelected}\n" +
"Track__: ${it.type}\nTrack__: ${it.mediaTrackGroup.id}", "Track__: ${it.type}\nTrack__: ${it.mediaTrackGroup.id}",
) )
when (it.type) { when (it.type) {
TRACK_TYPE_AUDIO -> { TRACK_TYPE_AUDIO -> {
@ -2365,7 +2369,7 @@ class ExoplayerView :
when (error.errorCode) { when (error.errorCode) {
PlaybackException.ERROR_CODE_IO_BAD_HTTP_STATUS, PlaybackException.ERROR_CODE_IO_BAD_HTTP_STATUS,
PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED, PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED,
-> { -> {
toast("Source Exception : ${error.message}") toast("Source Exception : ${error.message}")
isPlayerPlaying = true isPlayerPlaying = true
sourceClick() sourceClick()
@ -2403,9 +2407,9 @@ class ExoplayerView :
val incognito: Boolean = PrefManager.getVal(PrefName.Incognito) val incognito: Boolean = PrefManager.getVal(PrefName.Incognito)
val episodeEnd = val episodeEnd =
exoPlayer.currentPosition / episodeLength > exoPlayer.currentPosition / episodeLength >
PrefManager.getVal<Float>( PrefManager.getVal<Float>(
PrefName.WatchPercentage, PrefName.WatchPercentage,
) )
val episode0 = currentEpisodeIndex == 0 && PrefManager.getVal(PrefName.ChapterZeroPlayer) val episode0 = currentEpisodeIndex == 0 && PrefManager.getVal(PrefName.ChapterZeroPlayer)
if (!incognito && (episodeEnd || episode0) && Anilist.userid != null if (!incognito && (episodeEnd || episode0) && Anilist.userid != null
) { ) {
@ -2484,7 +2488,7 @@ class ExoplayerView :
val videoURL = video?.file?.url ?: return val videoURL = video?.file?.url ?: return
val subtitleUrl = if (!hasExtSubtitles) video!!.file.url else subtitle!!.file.url val subtitleUrl = if (!hasExtSubtitles) video!!.file.url else subtitle!!.file.url
val shareVideo = Intent(Intent.ACTION_VIEW) val shareVideo = Intent(Intent.ACTION_VIEW)
shareVideo.setDataAndType(Uri.parse(videoURL), "video/*") shareVideo.setDataAndType(videoURL.toUri(), "video/*")
shareVideo.setPackage("com.instantbits.cast.webvideo") shareVideo.setPackage("com.instantbits.cast.webvideo")
if (subtitle != null) shareVideo.putExtra("subtitle", subtitleUrl) if (subtitle != null) shareVideo.putExtra("subtitle", subtitleUrl)
shareVideo.putExtra( shareVideo.putExtra(
@ -2506,7 +2510,7 @@ class ExoplayerView :
} catch (ex: ActivityNotFoundException) { } catch (ex: ActivityNotFoundException) {
val intent = Intent(Intent.ACTION_VIEW) val intent = Intent(Intent.ACTION_VIEW)
val uriString = "market://details?id=com.instantbits.cast.webvideo" val uriString = "market://details?id=com.instantbits.cast.webvideo"
intent.data = Uri.parse(uriString) intent.data = uriString.toUri()
startActivity(intent) startActivity(intent)
} }
} }

View file

@ -646,7 +646,6 @@ class VideoServerPassthrough(private val videoServer: VideoServer) : VideoExtrac
} }
private fun trackToSubtitle(track: Track): Subtitle { private fun trackToSubtitle(track: Track): Subtitle {
//use Dispatchers.IO to make a HTTP request to determine the subtitle type
var type: SubtitleType? var type: SubtitleType?
runBlocking { runBlocking {
type = findSubtitleType(track.url) type = findSubtitleType(track.url)