mirror of
https://gitlab.futo.org/videostreaming/grayjay.git
synced 2025-05-01 23:24:34 +02:00
Merge branch 'master' of gitlab.futo.org:videostreaming/grayjay
This commit is contained in:
commit
4826b40136
11
app/src/main/assets/scripts/JSDOM.js
Normal file
11
app/src/main/assets/scripts/JSDOM.js
Normal file
File diff suppressed because one or more lines are too long
@ -32,6 +32,7 @@ import com.futo.platformplayer.engine.internal.V8Converter
|
|||||||
import com.futo.platformplayer.engine.packages.PackageBridge
|
import com.futo.platformplayer.engine.packages.PackageBridge
|
||||||
import com.futo.platformplayer.engine.packages.PackageDOMParser
|
import com.futo.platformplayer.engine.packages.PackageDOMParser
|
||||||
import com.futo.platformplayer.engine.packages.PackageHttp
|
import com.futo.platformplayer.engine.packages.PackageHttp
|
||||||
|
import com.futo.platformplayer.engine.packages.PackageJSDOM
|
||||||
import com.futo.platformplayer.engine.packages.PackageUtilities
|
import com.futo.platformplayer.engine.packages.PackageUtilities
|
||||||
import com.futo.platformplayer.engine.packages.V8Package
|
import com.futo.platformplayer.engine.packages.V8Package
|
||||||
import com.futo.platformplayer.getOrThrow
|
import com.futo.platformplayer.getOrThrow
|
||||||
@ -264,6 +265,7 @@ class V8Plugin {
|
|||||||
"DOMParser" -> PackageDOMParser(this)
|
"DOMParser" -> PackageDOMParser(this)
|
||||||
"Http" -> PackageHttp(this, config)
|
"Http" -> PackageHttp(this, config)
|
||||||
"Utilities" -> PackageUtilities(this, config)
|
"Utilities" -> PackageUtilities(this, config)
|
||||||
|
"JSDOM" -> PackageJSDOM(this, config)
|
||||||
else -> if(allowNull) null else throw ScriptCompilationException(config, "Unknown package [${packageName}] required for plugin ${config.name}");
|
else -> if(allowNull) null else throw ScriptCompilationException(config, "Unknown package [${packageName}] required for plugin ${config.name}");
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,20 @@
|
|||||||
|
package com.futo.platformplayer.engine.packages
|
||||||
|
|
||||||
|
import com.futo.platformplayer.engine.IV8PluginConfig
|
||||||
|
import com.futo.platformplayer.engine.V8Plugin
|
||||||
|
import com.futo.platformplayer.states.StateApp
|
||||||
|
|
||||||
|
|
||||||
|
class PackageJSDOM : V8Package {
|
||||||
|
@Transient
|
||||||
|
private val _config: IV8PluginConfig;
|
||||||
|
|
||||||
|
override val name: String get() = "JSDOM";
|
||||||
|
override val variableName: String get() = "packageJSDOM";
|
||||||
|
|
||||||
|
constructor(plugin: V8Plugin, config: IV8PluginConfig): super(plugin) {
|
||||||
|
_config = config;
|
||||||
|
plugin.withDependency(StateApp.instance.contextOrNull ?: return, "scripts/JSDOM.js");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -476,8 +476,13 @@ class ChannelFragment : MainFragment() {
|
|||||||
R.string.subscribers
|
R.string.subscribers
|
||||||
).lowercase() else ""
|
).lowercase() else ""
|
||||||
|
|
||||||
val supportsPlaylists =
|
var supportsPlaylists = false;
|
||||||
StatePlatform.instance.getChannelClient(channel.url).capabilities.hasGetChannelPlaylists
|
try {
|
||||||
|
supportsPlaylists = StatePlatform.instance.getChannelClient(channel.url).capabilities.hasGetChannelPlaylists
|
||||||
|
} catch (ex: Throwable) {
|
||||||
|
//Ignore error
|
||||||
|
Logger.e(TAG, "Failed to check if supports playlists", ex);
|
||||||
|
}
|
||||||
val playlistPosition = 1
|
val playlistPosition = 1
|
||||||
if (supportsPlaylists && !(_viewPager.adapter as ChannelViewPagerAdapter).containsItem(
|
if (supportsPlaylists && !(_viewPager.adapter as ChannelViewPagerAdapter).containsItem(
|
||||||
ChannelTab.PLAYLISTS.ordinal.toLong()
|
ChannelTab.PLAYLISTS.ordinal.toLong()
|
||||||
|
@ -233,8 +233,8 @@ class DownloadsFragment : MainFragment() {
|
|||||||
vidsToReturn = when(ordering){
|
vidsToReturn = when(ordering){
|
||||||
"downloadDateAsc" -> vidsToReturn.sortedBy { it.downloadDate ?: OffsetDateTime.MAX };
|
"downloadDateAsc" -> vidsToReturn.sortedBy { it.downloadDate ?: OffsetDateTime.MAX };
|
||||||
"downloadDateDesc" -> vidsToReturn.sortedByDescending { it.downloadDate ?: OffsetDateTime.MIN };
|
"downloadDateDesc" -> vidsToReturn.sortedByDescending { it.downloadDate ?: OffsetDateTime.MIN };
|
||||||
"nameAsc" -> vidsToReturn.sortedBy { it.name }
|
"nameAsc" -> vidsToReturn.sortedBy { it.name.lowercase() }
|
||||||
"nameDesc" -> vidsToReturn.sortedByDescending { it.name }
|
"nameDesc" -> vidsToReturn.sortedByDescending { it.name.lowercase() }
|
||||||
"releasedAsc" -> vidsToReturn.sortedBy { it.datetime ?: OffsetDateTime.MAX }
|
"releasedAsc" -> vidsToReturn.sortedBy { it.datetime ?: OffsetDateTime.MAX }
|
||||||
"releasedDesc" -> vidsToReturn.sortedByDescending { it.datetime ?: OffsetDateTime.MIN }
|
"releasedDesc" -> vidsToReturn.sortedByDescending { it.datetime ?: OffsetDateTime.MIN }
|
||||||
else -> vidsToReturn
|
else -> vidsToReturn
|
||||||
|
@ -204,8 +204,10 @@ class SubscriptionsFeedFragment : MainFragment() {
|
|||||||
val feed = StateSubscriptions.instance.getFeed(group?.id);
|
val feed = StateSubscriptions.instance.getFeed(group?.id);
|
||||||
|
|
||||||
val currentExs = feed?.exceptions ?: listOf();
|
val currentExs = feed?.exceptions ?: listOf();
|
||||||
if(currentExs != _lastExceptions && currentExs.any())
|
if(currentExs != _lastExceptions && currentExs.any()) {
|
||||||
handleExceptions(currentExs);
|
handleExceptions(currentExs)
|
||||||
|
feed?.exceptions = listOf()
|
||||||
|
}
|
||||||
|
|
||||||
return@TaskHandler resp;
|
return@TaskHandler resp;
|
||||||
})
|
})
|
||||||
|
@ -11,12 +11,14 @@ import android.os.Handler
|
|||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.OrientationEventListener
|
import android.view.OrientationEventListener
|
||||||
|
import android.view.Surface
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.view.WindowInsets
|
import android.view.WindowInsets
|
||||||
import android.view.WindowInsetsController
|
import android.view.WindowInsetsController
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import androidx.constraintlayout.motion.widget.MotionLayout
|
import androidx.constraintlayout.motion.widget.MotionLayout
|
||||||
|
import androidx.core.view.ViewCompat.getDisplay
|
||||||
import androidx.core.view.WindowCompat
|
import androidx.core.view.WindowCompat
|
||||||
import androidx.media3.common.util.UnstableApi
|
import androidx.media3.common.util.UnstableApi
|
||||||
import com.futo.platformplayer.R
|
import com.futo.platformplayer.R
|
||||||
@ -37,7 +39,7 @@ import kotlinx.coroutines.CoroutineScope
|
|||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlin.math.min
|
|
||||||
|
|
||||||
//region Fragment
|
//region Fragment
|
||||||
@UnstableApi
|
@UnstableApi
|
||||||
@ -205,7 +207,37 @@ class VideoDetailFragment() : MainFragment() {
|
|||||||
} else if (rotationLock) {
|
} else if (rotationLock) {
|
||||||
_portraitOrientationListener?.disableListener()
|
_portraitOrientationListener?.disableListener()
|
||||||
_landscapeOrientationListener?.disableListener()
|
_landscapeOrientationListener?.disableListener()
|
||||||
a.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LOCKED
|
val display = getDisplay(_viewDetail!!)
|
||||||
|
val rotation = display!!.rotation
|
||||||
|
val orientation = resources.configuration.orientation
|
||||||
|
|
||||||
|
a.requestedOrientation = when (orientation) {
|
||||||
|
Configuration.ORIENTATION_PORTRAIT -> {
|
||||||
|
if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) {
|
||||||
|
if (rotation == Surface.ROTATION_0) {
|
||||||
|
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
||||||
|
} else {
|
||||||
|
ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Configuration.ORIENTATION_LANDSCAPE -> {
|
||||||
|
if (rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) {
|
||||||
|
if (rotation == Surface.ROTATION_90) {
|
||||||
|
ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
|
||||||
|
} else {
|
||||||
|
ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
_portraitOrientationListener?.disableListener()
|
_portraitOrientationListener?.disableListener()
|
||||||
_landscapeOrientationListener?.disableListener()
|
_landscapeOrientationListener?.disableListener()
|
||||||
|
@ -171,7 +171,6 @@ import kotlinx.coroutines.withContext
|
|||||||
import userpackage.Protocol
|
import userpackage.Protocol
|
||||||
import java.time.OffsetDateTime
|
import java.time.OffsetDateTime
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
import kotlin.math.max
|
|
||||||
import kotlin.math.roundToLong
|
import kotlin.math.roundToLong
|
||||||
|
|
||||||
@UnstableApi
|
@UnstableApi
|
||||||
@ -870,14 +869,12 @@ class VideoDetailView : ConstraintLayout {
|
|||||||
}
|
}
|
||||||
_slideUpOverlay?.hide();
|
_slideUpOverlay?.hide();
|
||||||
} else null,
|
} else null,
|
||||||
if(!isLimitedVersion)
|
if (!isLimitedVersion) RoundButton(context, R.drawable.ic_screen_share, if (allowBackground) context.getString(R.string.background_revert) else context.getString(R.string.background), TAG_BACKGROUND) {
|
||||||
RoundButton(context, R.drawable.ic_screen_share, context.getString(R.string.background), TAG_BACKGROUND) {
|
if (!allowBackground) {
|
||||||
if(!allowBackground) {
|
|
||||||
_player.switchToAudioMode();
|
_player.switchToAudioMode();
|
||||||
allowBackground = true;
|
allowBackground = true;
|
||||||
it.text.text = resources.getString(R.string.background_revert);
|
it.text.text = resources.getString(R.string.background_revert);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
_player.switchToVideoMode();
|
_player.switchToVideoMode();
|
||||||
allowBackground = false;
|
allowBackground = false;
|
||||||
it.text.text = resources.getString(R.string.background);
|
it.text.text = resources.getString(R.string.background);
|
||||||
@ -1901,13 +1898,45 @@ class VideoDetailView : ConstraintLayout {
|
|||||||
return super.onInterceptTouchEvent(ev);
|
return super.onInterceptTouchEvent(ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//Actions
|
//Actions
|
||||||
private fun showVideoSettings() {
|
private fun showVideoSettings() {
|
||||||
Logger.i(TAG, "showVideoSettings")
|
Logger.i(TAG, "showVideoSettings")
|
||||||
_overlay_quality_selector?.selectOption("video", _lastVideoSource);
|
_overlay_quality_selector?.selectOption("video", _lastVideoSource);
|
||||||
_overlay_quality_selector?.selectOption("audio", _lastAudioSource);
|
_overlay_quality_selector?.selectOption("audio", _lastAudioSource);
|
||||||
_overlay_quality_selector?.selectOption("subtitles", _lastSubtitleSource);
|
_overlay_quality_selector?.selectOption("subtitles", _lastSubtitleSource);
|
||||||
|
|
||||||
|
if (_lastVideoSource is IDashManifestSource || _lastVideoSource is IHLSManifestSource) {
|
||||||
|
|
||||||
|
val videoTracks =
|
||||||
|
_player.exoPlayer?.player?.currentTracks?.groups?.firstOrNull { it.mediaTrackGroup.type == C.TRACK_TYPE_VIDEO }
|
||||||
|
|
||||||
|
var selectedQuality: Format? = null
|
||||||
|
|
||||||
|
if (videoTracks != null) {
|
||||||
|
for (i in 0 until videoTracks.mediaTrackGroup.length) {
|
||||||
|
if (videoTracks.mediaTrackGroup.getFormat(i).height == _player.targetTrackVideoHeight) {
|
||||||
|
selectedQuality = videoTracks.mediaTrackGroup.getFormat(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var videoMenuGroup: SlideUpMenuGroup? = null
|
||||||
|
for (view in _overlay_quality_selector!!.groupItems) {
|
||||||
|
if (view is SlideUpMenuGroup && view.groupTag == "video") {
|
||||||
|
videoMenuGroup = view
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedQuality != null) {
|
||||||
|
videoMenuGroup?.getItem("auto")?.setSubText("")
|
||||||
|
_overlay_quality_selector?.selectOption("video", selectedQuality)
|
||||||
|
} else {
|
||||||
|
videoMenuGroup?.getItem("auto")
|
||||||
|
?.setSubText("${_player.exoPlayer?.player?.videoFormat?.width}x${_player.exoPlayer?.player?.videoFormat?.height}")
|
||||||
|
_overlay_quality_selector?.selectOption("video", "auto")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val currentPlaybackRate = (if (_isCasting) StateCasting.instance.activeDevice?.speed else _player.getPlaybackRate()) ?: 1.0
|
val currentPlaybackRate = (if (_isCasting) StateCasting.instance.activeDevice?.speed else _player.getPlaybackRate()) ?: 1.0
|
||||||
_overlay_quality_selector?.groupItems?.firstOrNull { it is SlideUpMenuButtonList && it.id == "playback_rate" }?.let {
|
_overlay_quality_selector?.groupItems?.firstOrNull { it is SlideUpMenuButtonList && it.id == "playback_rate" }?.let {
|
||||||
(it as SlideUpMenuButtonList).setSelected(currentPlaybackRate.toString())
|
(it as SlideUpMenuButtonList).setSelected(currentPlaybackRate.toString())
|
||||||
@ -2081,17 +2110,15 @@ class VideoDetailView : ConstraintLayout {
|
|||||||
call = { handleSelectSubtitleTrack(it) })
|
call = { handleSelectSubtitleTrack(it) })
|
||||||
}.toList().toTypedArray())
|
}.toList().toTypedArray())
|
||||||
else null,
|
else null,
|
||||||
if(liveStreamVideoFormats?.isEmpty() == false)
|
if (liveStreamVideoFormats?.isEmpty() == false) SlideUpMenuGroup(
|
||||||
SlideUpMenuGroup(this.context, context.getString(R.string.stream_video), "video",
|
this.context, context.getString(R.string.stream_video), "video", (listOf(
|
||||||
*liveStreamVideoFormats
|
SlideUpMenuItem(this.context, R.drawable.ic_movie, "Auto", tag = "auto", call = { _player.selectVideoTrack(-1) })
|
||||||
.map {
|
) + (liveStreamVideoFormats.map {
|
||||||
SlideUpMenuItem(this.context,
|
SlideUpMenuItem(this.context, R.drawable.ic_movie, it.label
|
||||||
R.drawable.ic_movie,
|
?: it.containerMimeType
|
||||||
it.label ?: it.containerMimeType ?: it.bitrate.toString(),
|
?: it.bitrate.toString(), "${it.width}x${it.height}", tag = it, call = { _player.selectVideoTrack(it.height) });
|
||||||
"${it.width}x${it.height}",
|
}))
|
||||||
tag = it,
|
)
|
||||||
call = { _player.selectVideoTrack(it.height) });
|
|
||||||
}.toList().toTypedArray())
|
|
||||||
else null,
|
else null,
|
||||||
if(liveStreamAudioFormats?.isEmpty() == false)
|
if(liveStreamAudioFormats?.isEmpty() == false)
|
||||||
SlideUpMenuGroup(this.context, context.getString(R.string.stream_audio), "audio",
|
SlideUpMenuGroup(this.context, context.getString(R.string.stream_audio), "audio",
|
||||||
|
@ -755,10 +755,6 @@ class GestureControlView : LinearLayout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Settings.instance.gestureControls.useSystemBrightness) {
|
|
||||||
_brightnessFactor = 1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Settings.instance.gestureControls.useSystemVolume) {
|
if (Settings.instance.gestureControls.useSystemVolume) {
|
||||||
val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
||||||
val currentVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC)
|
val currentVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC)
|
||||||
|
@ -61,6 +61,15 @@ class SlideUpMenuGroup : LinearLayout {
|
|||||||
return didSelect;
|
return didSelect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getItem(tag: Any?): SlideUpMenuItem? {
|
||||||
|
for(item in items) {
|
||||||
|
if(item.itemTag == tag){
|
||||||
|
return item
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
private fun addItems(items: List<SlideUpMenuItem>) {
|
private fun addItems(items: List<SlideUpMenuItem>) {
|
||||||
for (item in items) {
|
for (item in items) {
|
||||||
item.setParentClickListener { parentClickListener?.invoke() }
|
item.setParentClickListener { parentClickListener?.invoke() }
|
||||||
|
@ -82,6 +82,10 @@ class SlideUpMenuItem : ConstraintLayout {
|
|||||||
return isSelected;
|
return isSelected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun setSubText(subText: String) {
|
||||||
|
_subtext.text = subText
|
||||||
|
}
|
||||||
|
|
||||||
fun setParentClickListener(listener: (()->Unit)?) {
|
fun setParentClickListener(listener: (()->Unit)?) {
|
||||||
_parentClickListener = listener;
|
_parentClickListener = listener;
|
||||||
}
|
}
|
||||||
|
@ -110,8 +110,10 @@ abstract class FutoVideoPlayerBase : RelativeLayout {
|
|||||||
private var _didCallSourceChange = false;
|
private var _didCallSourceChange = false;
|
||||||
private var _lastState: Int = -1;
|
private var _lastState: Int = -1;
|
||||||
|
|
||||||
private var _targetTrackVideoHeight = -1;
|
|
||||||
private var _targetTrackAudioBitrate = -1;
|
var targetTrackVideoHeight = -1
|
||||||
|
private set
|
||||||
|
private var _targetTrackAudioBitrate = -1
|
||||||
|
|
||||||
private var _toResume = false;
|
private var _toResume = false;
|
||||||
|
|
||||||
@ -278,7 +280,7 @@ abstract class FutoVideoPlayerBase : RelativeLayout {
|
|||||||
|
|
||||||
//TODO: Temporary solution, Implement custom track selector without using constraints
|
//TODO: Temporary solution, Implement custom track selector without using constraints
|
||||||
fun selectVideoTrack(height: Int) {
|
fun selectVideoTrack(height: Int) {
|
||||||
_targetTrackVideoHeight = height;
|
targetTrackVideoHeight = height;
|
||||||
updateTrackSelector();
|
updateTrackSelector();
|
||||||
}
|
}
|
||||||
fun selectAudioTrack(bitrate: Int) {
|
fun selectAudioTrack(bitrate: Int) {
|
||||||
@ -288,16 +290,22 @@ abstract class FutoVideoPlayerBase : RelativeLayout {
|
|||||||
@OptIn(UnstableApi::class)
|
@OptIn(UnstableApi::class)
|
||||||
private fun updateTrackSelector() {
|
private fun updateTrackSelector() {
|
||||||
var builder = DefaultTrackSelector.Parameters.Builder(context);
|
var builder = DefaultTrackSelector.Parameters.Builder(context);
|
||||||
if(_targetTrackVideoHeight > 0) {
|
if(targetTrackVideoHeight > 0) {
|
||||||
builder = builder
|
builder = builder
|
||||||
.setMinVideoSize(0, _targetTrackVideoHeight - 10)
|
.setMinVideoSize(0, targetTrackVideoHeight - 10)
|
||||||
.setMaxVideoSize(9999, _targetTrackVideoHeight + 10);
|
.setMaxVideoSize(9999, targetTrackVideoHeight + 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(_targetTrackAudioBitrate > 0) {
|
if(_targetTrackAudioBitrate > 0) {
|
||||||
builder = builder.setMaxAudioBitrate(_targetTrackAudioBitrate);
|
builder = builder.setMaxAudioBitrate(_targetTrackAudioBitrate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
builder = if (isAudioMode) {
|
||||||
|
builder.setTrackTypeDisabled(C.TRACK_TYPE_VIDEO, true)
|
||||||
|
} else {
|
||||||
|
builder.setTrackTypeDisabled(C.TRACK_TYPE_VIDEO, false)
|
||||||
|
}
|
||||||
|
|
||||||
val trackSelector = exoPlayer?.player?.trackSelector;
|
val trackSelector = exoPlayer?.player?.trackSelector;
|
||||||
if(trackSelector != null) {
|
if(trackSelector != null) {
|
||||||
trackSelector.parameters = builder.build();
|
trackSelector.parameters = builder.build();
|
||||||
@ -737,6 +745,7 @@ abstract class FutoVideoPlayerBase : RelativeLayout {
|
|||||||
val sourceAudio = _lastAudioMediaSource;
|
val sourceAudio = _lastAudioMediaSource;
|
||||||
val sourceSubs = _lastSubtitleMediaSource;
|
val sourceSubs = _lastSubtitleMediaSource;
|
||||||
|
|
||||||
|
updateTrackSelector()
|
||||||
|
|
||||||
beforeSourceChanged();
|
beforeSourceChanged();
|
||||||
|
|
||||||
|
@ -959,12 +959,12 @@
|
|||||||
<item>Watchtime Descending</item>
|
<item>Watchtime Descending</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="downloads_sortby_array">
|
<string-array name="downloads_sortby_array">
|
||||||
<item>Name Ascending</item>
|
<item>Name (Ascending)</item>
|
||||||
<item>Name Descending</item>
|
<item>Name (Descending)</item>
|
||||||
<item>Downloaded Ascending</item>
|
<item>Download Date (Oldest)</item>
|
||||||
<item>Downloaded Descending</item>
|
<item>Download Date (Newest)</item>
|
||||||
<item>Released Ascending</item>
|
<item>Release Date (Oldest)</item>
|
||||||
<item>Released Descending</item>
|
<item>Release Date (Newest)</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="feed_style">
|
<string-array name="feed_style">
|
||||||
<item>Preview</item>
|
<item>Preview</item>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user