mirror of
https://gitlab.futo.org/videostreaming/grayjay.git
synced 2025-09-12 20:42:27 +00:00
casting: undo formatting to VideoDetailView
This commit is contained in:
parent
e79e1fd108
commit
feeba10429
1 changed files with 87 additions and 88 deletions
|
@ -576,7 +576,9 @@ class VideoDetailView : ConstraintLayout {
|
||||||
if(chapter?.type == ChapterType.SKIPPABLE) {
|
if(chapter?.type == ChapterType.SKIPPABLE) {
|
||||||
_layoutSkip.visibility = VISIBLE;
|
_layoutSkip.visibility = VISIBLE;
|
||||||
} else if(chapter?.type == ChapterType.SKIP || chapter?.type == ChapterType.SKIPONCE) {
|
} else if(chapter?.type == ChapterType.SKIP || chapter?.type == ChapterType.SKIPONCE) {
|
||||||
if (!StateCasting.instance.videoSeekTo(chapter.timeEnd)) {
|
if (StateCasting.instance.activeDevice != null) {
|
||||||
|
StateCasting.instance.videoSeekTo(chapter.timeEnd)
|
||||||
|
} else {
|
||||||
_player.seekTo((chapter.timeEnd * 1000).toLong());
|
_player.seekTo((chapter.timeEnd * 1000).toLong());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -680,7 +682,9 @@ class VideoDetailView : ConstraintLayout {
|
||||||
}
|
}
|
||||||
else -> {}
|
else -> {}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
updatePillButtonVisibilities();
|
||||||
|
|
||||||
StateCasting.instance.onActiveDevicePlayChanged.subscribe(this) {
|
StateCasting.instance.onActiveDevicePlayChanged.subscribe(this) {
|
||||||
val activeDevice = StateCasting.instance.activeDevice;
|
val activeDevice = StateCasting.instance.activeDevice;
|
||||||
|
@ -704,8 +708,6 @@ class VideoDetailView : ConstraintLayout {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
updatePillButtonVisibilities();
|
|
||||||
|
|
||||||
_cast.onTimeJobTimeChanged_s.subscribe {
|
_cast.onTimeJobTimeChanged_s.subscribe {
|
||||||
if (_isCasting) {
|
if (_isCasting) {
|
||||||
setLastPositionMilliseconds((it * 1000.0).toLong(), true);
|
setLastPositionMilliseconds((it * 1000.0).toLong(), true);
|
||||||
|
@ -883,7 +885,7 @@ class VideoDetailView : ConstraintLayout {
|
||||||
if (ad != null) {
|
if (ad != null) {
|
||||||
val currentChapter = _cast.getCurrentChapter((ad.time * 1000).toLong());
|
val currentChapter = _cast.getCurrentChapter((ad.time * 1000).toLong());
|
||||||
if(currentChapter?.type == ChapterType.SKIPPABLE) {
|
if(currentChapter?.type == ChapterType.SKIPPABLE) {
|
||||||
ad.seekTo(currentChapter.timeEnd);
|
StateCasting.instance.videoSeekTo(currentChapter.timeEnd);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
val currentChapter = _player.getCurrentChapter(_player.position);
|
val currentChapter = _player.getCurrentChapter(_player.position);
|
||||||
|
@ -1002,6 +1004,17 @@ class VideoDetailView : ConstraintLayout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_slideUpOverlay?.hide();
|
_slideUpOverlay?.hide();
|
||||||
|
} else if(video is JSVideoDetails && (video as JSVideoDetails).hasVODEvents())
|
||||||
|
RoundButton(context, R.drawable.ic_chat, context.getString(R.string.vod_chat), TAG_VODCHAT) {
|
||||||
|
video?.let {
|
||||||
|
try {
|
||||||
|
loadVODChat(it);
|
||||||
|
}
|
||||||
|
catch(ex: Throwable) {
|
||||||
|
Logger.e(TAG, "Failed to reopen vod chat", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_slideUpOverlay?.hide();
|
||||||
} else null,
|
} else null,
|
||||||
if (!isLimitedVersion) RoundButton(context, R.drawable.ic_screen_share, if (isAudioOnlyUserAction) context.getString(R.string.background_revert) else context.getString(R.string.background), TAG_BACKGROUND) {
|
if (!isLimitedVersion) RoundButton(context, R.drawable.ic_screen_share, if (isAudioOnlyUserAction) context.getString(R.string.background_revert) else context.getString(R.string.background), TAG_BACKGROUND) {
|
||||||
if (!isAudioOnlyUserAction) {
|
if (!isAudioOnlyUserAction) {
|
||||||
|
@ -1126,19 +1139,23 @@ class VideoDetailView : ConstraintLayout {
|
||||||
|
|
||||||
|
|
||||||
//Lifecycle
|
//Lifecycle
|
||||||
|
var isLoginStop = false; //TODO: This is a bit jank, but easiest solution for now without reworking flow. (Alternatively, fix MainActivity getting stopped/disposing video)
|
||||||
fun onResume() {
|
fun onResume() {
|
||||||
Logger.v(TAG, "onResume");
|
Logger.v(TAG, "onResume");
|
||||||
_onPauseCalled = false;
|
_onPauseCalled = false;
|
||||||
|
|
||||||
|
val wasLoginCall = isLoginStop;
|
||||||
|
isLoginStop = false;
|
||||||
|
|
||||||
Logger.i(TAG, "_video: ${video?.name ?: "no video"}");
|
Logger.i(TAG, "_video: ${video?.name ?: "no video"}");
|
||||||
Logger.i(TAG, "_didStop: $_didStop");
|
Logger.i(TAG, "_didStop: $_didStop");
|
||||||
|
|
||||||
//Recover cancelled loads
|
//Recover cancelled loads
|
||||||
if(video == null) {
|
if(video == null) {
|
||||||
val t = (lastPositionMilliseconds / 1000.0f).roundToLong();
|
val t = (lastPositionMilliseconds / 1000.0f).roundToLong();
|
||||||
if(_searchVideo != null)
|
if(_searchVideo != null && !wasLoginCall)
|
||||||
setVideoOverview(_searchVideo!!, true, t);
|
setVideoOverview(_searchVideo!!, true, t);
|
||||||
else if(_url != null)
|
else if(_url != null && !wasLoginCall)
|
||||||
setVideo(_url!!, t, _playWhenReady);
|
setVideo(_url!!, t, _playWhenReady);
|
||||||
}
|
}
|
||||||
else if(_didStop) {
|
else if(_didStop) {
|
||||||
|
@ -1155,6 +1172,9 @@ class VideoDetailView : ConstraintLayout {
|
||||||
isAudioOnlyUserAction = false;
|
isAudioOnlyUserAction = false;
|
||||||
_buttonPins.getButtonByTag(TAG_BACKGROUND)?.text?.text = resources.getString(R.string.background);
|
_buttonPins.getButtonByTag(TAG_BACKGROUND)?.text?.text = resources.getString(R.string.background);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
_buttonPins.getButtonByTag(TAG_BACKGROUND)?.text?.text = resources.getString(R.string.video);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(!_player.isFitMode && !_player.isFullScreen && !fragment.isInPictureInPicture)
|
if(!_player.isFitMode && !_player.isFullScreen && !fragment.isInPictureInPicture)
|
||||||
_player.fitHeight();
|
_player.fitHeight();
|
||||||
|
@ -1200,6 +1220,7 @@ class VideoDetailView : ConstraintLayout {
|
||||||
_taskLoadVideo.cancel();
|
_taskLoadVideo.cancel();
|
||||||
handleStop();
|
handleStop();
|
||||||
_didStop = true;
|
_didStop = true;
|
||||||
|
onShouldEnterPictureInPictureChanged.emit()
|
||||||
Logger.i(TAG, "_didStop set to true");
|
Logger.i(TAG, "_didStop set to true");
|
||||||
|
|
||||||
StatePlayer.instance.rotationLock = false;
|
StatePlayer.instance.rotationLock = false;
|
||||||
|
@ -1952,7 +1973,8 @@ class VideoDetailView : ConstraintLayout {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!StateCasting.instance.isCasting) {
|
val isCasting = StateCasting.instance.isCasting
|
||||||
|
if (!isCasting) {
|
||||||
setCastEnabled(false);
|
setCastEnabled(false);
|
||||||
|
|
||||||
val isLimitedVersion = StatePlatform.instance.getContentClientOrNull(video.url)?.let {
|
val isLimitedVersion = StatePlatform.instance.getContentClientOrNull(video.url)?.let {
|
||||||
|
@ -2227,9 +2249,7 @@ class VideoDetailView : ConstraintLayout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val currentPlaybackRate = (if (_isCasting) {
|
val currentPlaybackRate = (if (_isCasting) StateCasting.instance.activeDevice?.speed else _player.getPlaybackRate()) ?: 1.0
|
||||||
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())
|
||||||
};
|
};
|
||||||
|
@ -2347,12 +2367,8 @@ class VideoDetailView : ConstraintLayout {
|
||||||
?.distinct()
|
?.distinct()
|
||||||
?.toList() ?: listOf() else audioSources?.toList() ?: listOf();
|
?.toList() ?: listOf() else audioSources?.toList() ?: listOf();
|
||||||
|
|
||||||
val canSetSpeed = !_isCasting || StateCasting.instance.activeDevice?.canSetSpeed() ?: false
|
val canSetSpeed = !_isCasting || StateCasting.instance.activeDevice?.canSetSpeed() == true
|
||||||
val currentPlaybackRate = if (_isCasting) {
|
val currentPlaybackRate = if (_isCasting) StateCasting.instance.activeDevice?.speed else _player.getPlaybackRate()
|
||||||
StateCasting.instance.activeDevice?.speed
|
|
||||||
} else {
|
|
||||||
_player.getPlaybackRate()
|
|
||||||
}
|
|
||||||
val qualityPlaybackSpeedTitle = if (canSetSpeed) SlideUpMenuTitle(this.context).apply { setTitle(context.getString(R.string.playback_rate) + " (${String.format("%.2f", currentPlaybackRate)})"); } else null;
|
val qualityPlaybackSpeedTitle = if (canSetSpeed) SlideUpMenuTitle(this.context).apply { setTitle(context.getString(R.string.playback_rate) + " (${String.format("%.2f", currentPlaybackRate)})"); } else null;
|
||||||
_overlay_quality_selector = SlideUpMenuOverlay(this.context, _overlay_quality_container, context.getString(
|
_overlay_quality_selector = SlideUpMenuOverlay(this.context, _overlay_quality_container, context.getString(
|
||||||
R.string.quality), null, true,
|
R.string.quality), null, true,
|
||||||
|
@ -2366,9 +2382,7 @@ class VideoDetailView : ConstraintLayout {
|
||||||
|
|
||||||
setButtons(playbackLabels, String.format(Locale.US, format, currentPlaybackRate));
|
setButtons(playbackLabels, String.format(Locale.US, format, currentPlaybackRate));
|
||||||
onClick.subscribe { v ->
|
onClick.subscribe { v ->
|
||||||
val currentPlaybackSpeed = if (_isCasting) {
|
val currentPlaybackSpeed = if (_isCasting) StateCasting.instance.activeDevice?.speed else _player.getPlaybackRate();
|
||||||
StateCasting.instance.activeDevice?.speed
|
|
||||||
} else _player.getPlaybackRate();
|
|
||||||
var playbackSpeedString = v;
|
var playbackSpeedString = v;
|
||||||
val stepSpeed = Settings.instance.playback.getPlaybackSpeedStep();
|
val stepSpeed = Settings.instance.playback.getPlaybackSpeedStep();
|
||||||
if(v == "+")
|
if(v == "+")
|
||||||
|
@ -2376,9 +2390,14 @@ class VideoDetailView : ConstraintLayout {
|
||||||
else if(v == "-")
|
else if(v == "-")
|
||||||
playbackSpeedString = String.format(Locale.US, "%.2f", Math.max(0.1, (currentPlaybackSpeed?.toDouble() ?: 1.0) - stepSpeed)).toString();
|
playbackSpeedString = String.format(Locale.US, "%.2f", Math.max(0.1, (currentPlaybackSpeed?.toDouble() ?: 1.0) - stepSpeed)).toString();
|
||||||
val newPlaybackSpeed = playbackSpeedString.toDouble();
|
val newPlaybackSpeed = playbackSpeedString.toDouble();
|
||||||
if (_isCasting && StateCasting.instance.activeDevice?.canSetSpeed() ?: false) {
|
if (_isCasting) {
|
||||||
|
val ad = StateCasting.instance.activeDevice ?: return@subscribe
|
||||||
|
if (!ad.canSetSpeed()) {
|
||||||
|
return@subscribe
|
||||||
|
}
|
||||||
|
|
||||||
qualityPlaybackSpeedTitle?.setTitle(context.getString(R.string.playback_rate) + " (${String.format(Locale.US, "%.2f", newPlaybackSpeed)})");
|
qualityPlaybackSpeedTitle?.setTitle(context.getString(R.string.playback_rate) + " (${String.format(Locale.US, "%.2f", newPlaybackSpeed)})");
|
||||||
StateCasting.instance.changeSpeed(newPlaybackSpeed)
|
ad.changeSpeed(newPlaybackSpeed)
|
||||||
setSelected(playbackSpeedString);
|
setSelected(playbackSpeedString);
|
||||||
} else {
|
} else {
|
||||||
qualityPlaybackSpeedTitle?.setTitle(context.getString(R.string.playback_rate) + " (${String.format(Locale.US, "%.2f", newPlaybackSpeed)})");
|
qualityPlaybackSpeedTitle?.setTitle(context.getString(R.string.playback_rate) + " (${String.format(Locale.US, "%.2f", newPlaybackSpeed)})");
|
||||||
|
@ -2495,8 +2514,9 @@ class VideoDetailView : ConstraintLayout {
|
||||||
private fun handlePlay() {
|
private fun handlePlay() {
|
||||||
Logger.i(TAG, "handlePlay")
|
Logger.i(TAG, "handlePlay")
|
||||||
if (!StateCasting.instance.resumeVideo()) {
|
if (!StateCasting.instance.resumeVideo()) {
|
||||||
_player.play()
|
_player.play();
|
||||||
}
|
}
|
||||||
|
onShouldEnterPictureInPictureChanged.emit()
|
||||||
|
|
||||||
//TODO: This was needed because handleLowerVolume was done.
|
//TODO: This was needed because handleLowerVolume was done.
|
||||||
//_player.setVolume(1.0f);
|
//_player.setVolume(1.0f);
|
||||||
|
@ -2511,26 +2531,28 @@ class VideoDetailView : ConstraintLayout {
|
||||||
private fun handlePause() {
|
private fun handlePause() {
|
||||||
Logger.i(TAG, "handlePause")
|
Logger.i(TAG, "handlePause")
|
||||||
if (!StateCasting.instance.pauseVideo()) {
|
if (!StateCasting.instance.pauseVideo()) {
|
||||||
_player.pause()
|
_player.pause();
|
||||||
}
|
}
|
||||||
|
onShouldEnterPictureInPictureChanged.emit()
|
||||||
}
|
}
|
||||||
private fun handleSeek(ms: Long) {
|
private fun handleSeek(ms: Long) {
|
||||||
Logger.i(TAG, "handleSeek(ms=$ms)")
|
Logger.i(TAG, "handleSeek(ms=$ms)")
|
||||||
if (!StateCasting.instance.videoSeekTo(ms.toDouble() / 1000.0)) {
|
if (!StateCasting.instance.videoSeekTo(ms.toDouble() / 1000.0)) {
|
||||||
_player.seekTo(ms)
|
_player.seekTo(ms);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private fun handleStop() {
|
private fun handleStop() {
|
||||||
Logger.i(TAG, "handleStop")
|
Logger.i(TAG, "handleStop")
|
||||||
if (!StateCasting.instance.stopVideo()) {
|
if (!StateCasting.instance.stopVideo()) {
|
||||||
_player.stop()
|
_player.stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handlePlayChanged(playing: Boolean) {
|
private fun handlePlayChanged(playing: Boolean) {
|
||||||
Logger.i(TAG, "handlePlayChanged(playing=$playing)")
|
Logger.i(TAG, "handlePlayChanged(playing=$playing)")
|
||||||
|
|
||||||
if (StateCasting.instance.isCasting) {
|
val ad = StateCasting.instance.activeDevice;
|
||||||
|
if (ad != null) {
|
||||||
_cast.setIsPlaying(playing);
|
_cast.setIsPlaying(playing);
|
||||||
} else {
|
} else {
|
||||||
StatePlayer.instance.updateMediaSession( null);
|
StatePlayer.instance.updateMediaSession( null);
|
||||||
|
@ -2572,21 +2594,11 @@ class VideoDetailView : ConstraintLayout {
|
||||||
|
|
||||||
fragment.lifecycleScope.launch(Dispatchers.Main) {
|
fragment.lifecycleScope.launch(Dispatchers.Main) {
|
||||||
try {
|
try {
|
||||||
if (StateCasting.instance.activeDevice != null) {
|
val d = StateCasting.instance.activeDevice;
|
||||||
val expectedCurrentTime = StateCasting.instance.activeDevice?.expectedCurrentTime ?: 0.0
|
if (d != null && d.connectionState == CastConnectionState.CONNECTED)
|
||||||
val speed = StateCasting.instance.activeDevice?.speed ?: 1.0
|
castIfAvailable(context.contentResolver, video, videoSource, _lastAudioSource, _lastSubtitleSource, (d.expectedCurrentTime * 1000.0).toLong(), d.speed);
|
||||||
castIfAvailable(
|
else if(!_player.swapSources(videoSource, _lastAudioSource, true, true, true))
|
||||||
context.contentResolver,
|
|
||||||
video,
|
|
||||||
videoSource,
|
|
||||||
_lastAudioSource,
|
|
||||||
_lastSubtitleSource,
|
|
||||||
(expectedCurrentTime * 1000.0).toLong(),
|
|
||||||
speed
|
|
||||||
)
|
|
||||||
} else if(!_player.swapSources(videoSource, _lastAudioSource, true, true, true)) {
|
|
||||||
_player.hideControls(false); //TODO: Disable player?
|
_player.hideControls(false); //TODO: Disable player?
|
||||||
}
|
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
Logger.e(TAG, "handleSelectVideoTrack failed", e)
|
Logger.e(TAG, "handleSelectVideoTrack failed", e)
|
||||||
}
|
}
|
||||||
|
@ -2603,21 +2615,11 @@ class VideoDetailView : ConstraintLayout {
|
||||||
|
|
||||||
fragment.lifecycleScope.launch(Dispatchers.Main) {
|
fragment.lifecycleScope.launch(Dispatchers.Main) {
|
||||||
try {
|
try {
|
||||||
if (StateCasting.instance.activeDevice != null) {
|
val d = StateCasting.instance.activeDevice;
|
||||||
val expectedCurrentTime = StateCasting.instance.activeDevice?.expectedCurrentTime ?: 0.0
|
if (d != null && d.connectionState == CastConnectionState.CONNECTED)
|
||||||
val speed = StateCasting.instance.activeDevice?.speed ?: 1.0
|
castIfAvailable(context.contentResolver, video, _lastVideoSource, audioSource, _lastSubtitleSource, (d.expectedCurrentTime * 1000.0).toLong(), d.speed)
|
||||||
castIfAvailable(
|
else if (!_player.swapSources(_lastVideoSource, audioSource, true, true, true))
|
||||||
context.contentResolver,
|
|
||||||
video,
|
|
||||||
_lastVideoSource,
|
|
||||||
audioSource,
|
|
||||||
_lastSubtitleSource,
|
|
||||||
(expectedCurrentTime * 1000.0).toLong(),
|
|
||||||
speed
|
|
||||||
)
|
|
||||||
} else if (!_player.swapSources(_lastVideoSource, audioSource, true, true, true)) {
|
|
||||||
_player.hideControls(false); //TODO: Disable player?
|
_player.hideControls(false); //TODO: Disable player?
|
||||||
}
|
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
Logger.e(TAG, "handleSelectAudioTrack failed", e)
|
Logger.e(TAG, "handleSelectAudioTrack failed", e)
|
||||||
}
|
}
|
||||||
|
@ -2635,19 +2637,10 @@ class VideoDetailView : ConstraintLayout {
|
||||||
|
|
||||||
fragment.lifecycleScope.launch(Dispatchers.Main) {
|
fragment.lifecycleScope.launch(Dispatchers.Main) {
|
||||||
try {
|
try {
|
||||||
if (StateCasting.instance.activeDevice != null) {
|
val d = StateCasting.instance.activeDevice;
|
||||||
val expectedCurrentTime = StateCasting.instance.activeDevice?.expectedCurrentTime ?: 0.0
|
if (d != null && d.connectionState == CastConnectionState.CONNECTED)
|
||||||
val speed = StateCasting.instance.activeDevice?.speed ?: 1.0
|
castIfAvailable(context.contentResolver, video, _lastVideoSource, _lastAudioSource, toSet, (d.expectedCurrentTime * 1000.0).toLong(), d.speed);
|
||||||
castIfAvailable(
|
else {
|
||||||
context.contentResolver,
|
|
||||||
video,
|
|
||||||
_lastVideoSource,
|
|
||||||
_lastAudioSource,
|
|
||||||
toSet,
|
|
||||||
(expectedCurrentTime * 1000.0).toLong(),
|
|
||||||
speed
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
_player.swapSubtitles(toSet);
|
_player.swapSubtitles(toSet);
|
||||||
}
|
}
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
|
@ -3287,9 +3280,14 @@ class VideoDetailView : ConstraintLayout {
|
||||||
val id = e.config.let { if(it is SourcePluginConfig) it.id else null };
|
val id = e.config.let { if(it is SourcePluginConfig) it.id else null };
|
||||||
val didLogin = if(id == null)
|
val didLogin = if(id == null)
|
||||||
false
|
false
|
||||||
else StatePlugins.instance.loginPlugin(context, id) {
|
else {
|
||||||
|
isLoginStop = true;
|
||||||
|
StatePlugins.instance.loginPlugin(context, id) {
|
||||||
|
fragment.lifecycleScope.launch(Dispatchers.Main) {
|
||||||
fetchVideo();
|
fetchVideo();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if(!didLogin)
|
if(!didLogin)
|
||||||
UIDialogs.showDialogOk(context, R.drawable.ic_error_pred, "Failed to login");
|
UIDialogs.showDialogOk(context, R.drawable.ic_error_pred, "Failed to login");
|
||||||
}, UIDialogs.ActionStyle.PRIMARY));
|
}, UIDialogs.ActionStyle.PRIMARY));
|
||||||
|
@ -3466,6 +3464,7 @@ class VideoDetailView : ConstraintLayout {
|
||||||
const val TAG_SHARE = "share";
|
const val TAG_SHARE = "share";
|
||||||
const val TAG_OVERLAY = "overlay";
|
const val TAG_OVERLAY = "overlay";
|
||||||
const val TAG_LIVECHAT = "livechat";
|
const val TAG_LIVECHAT = "livechat";
|
||||||
|
const val TAG_VODCHAT = "vodchat";
|
||||||
const val TAG_CHAPTERS = "chapters";
|
const val TAG_CHAPTERS = "chapters";
|
||||||
const val TAG_OPEN = "open";
|
const val TAG_OPEN = "open";
|
||||||
const val TAG_SEND_TO_DEVICE = "send_to_device";
|
const val TAG_SEND_TO_DEVICE = "send_to_device";
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue