mirror of
https://github.com/TeamNewPipe/NewPipe
synced 2025-09-09 14:26:00 +00:00
More improve Kotlin converted from java in various places
This commit is contained in:
@@ -7,7 +7,6 @@ import android.content.BroadcastReceiver
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.IntentFilter
|
import android.content.IntentFilter
|
||||||
import android.content.SharedPreferences
|
|
||||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener
|
import android.content.SharedPreferences.OnSharedPreferenceChangeListener
|
||||||
import android.content.pm.ActivityInfo
|
import android.content.pm.ActivityInfo
|
||||||
import android.database.ContentObserver
|
import android.database.ContentObserver
|
||||||
@@ -18,7 +17,6 @@ import android.os.Bundle
|
|||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
import android.text.TextUtils
|
|
||||||
import android.util.DisplayMetrics
|
import android.util.DisplayMetrics
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.util.TypedValue
|
import android.util.TypedValue
|
||||||
@@ -44,14 +42,14 @@ import androidx.core.content.ContextCompat
|
|||||||
import androidx.core.content.edit
|
import androidx.core.content.edit
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import androidx.core.os.postDelayed
|
import androidx.core.os.postDelayed
|
||||||
|
import androidx.core.view.isGone
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import coil3.util.CoilUtils.dispose
|
import coil3.util.CoilUtils
|
||||||
import com.evernote.android.state.State
|
import com.evernote.android.state.State
|
||||||
import com.google.android.exoplayer2.PlaybackException
|
import com.google.android.exoplayer2.PlaybackException
|
||||||
import com.google.android.exoplayer2.PlaybackParameters
|
import com.google.android.exoplayer2.PlaybackParameters
|
||||||
import com.google.android.material.appbar.AppBarLayout
|
import com.google.android.material.appbar.AppBarLayout
|
||||||
import com.google.android.material.appbar.AppBarLayout.OnOffsetChangedListener
|
|
||||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||||
import com.google.android.material.bottomsheet.BottomSheetBehavior.BottomSheetCallback
|
import com.google.android.material.bottomsheet.BottomSheetBehavior.BottomSheetCallback
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||||
@@ -115,17 +113,15 @@ import org.schabi.newpipe.util.StreamTypeUtil
|
|||||||
import org.schabi.newpipe.util.ThemeHelper
|
import org.schabi.newpipe.util.ThemeHelper
|
||||||
import org.schabi.newpipe.util.external_communication.KoreUtils
|
import org.schabi.newpipe.util.external_communication.KoreUtils
|
||||||
import org.schabi.newpipe.util.external_communication.ShareUtils
|
import org.schabi.newpipe.util.external_communication.ShareUtils
|
||||||
import org.schabi.newpipe.util.image.CoilHelper.loadAvatar
|
import org.schabi.newpipe.util.image.CoilHelper
|
||||||
import org.schabi.newpipe.util.image.CoilHelper.loadDetailsThumbnail
|
|
||||||
import java.util.LinkedList
|
import java.util.LinkedList
|
||||||
import java.util.Objects
|
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
|
||||||
class VideoDetailFragment :
|
class VideoDetailFragment :
|
||||||
BaseStateFragment<StreamInfo?>(),
|
BaseStateFragment<StreamInfo>(),
|
||||||
BackPressable,
|
BackPressable,
|
||||||
PlayerServiceExtendedEventListener,
|
PlayerServiceExtendedEventListener,
|
||||||
OnKeyDownListener {
|
OnKeyDownListener {
|
||||||
@@ -160,15 +156,15 @@ class VideoDetailFragment :
|
|||||||
private var lastAppBarVerticalOffset = Int.Companion.MAX_VALUE // prevents useless updates
|
private var lastAppBarVerticalOffset = Int.Companion.MAX_VALUE // prevents useless updates
|
||||||
|
|
||||||
private val preferenceChangeListener =
|
private val preferenceChangeListener =
|
||||||
OnSharedPreferenceChangeListener { sharedPreferences: SharedPreferences?, key: String? ->
|
OnSharedPreferenceChangeListener { sharedPreferences, key ->
|
||||||
if (getString(R.string.show_comments_key) == key) {
|
if (getString(R.string.show_comments_key) == key) {
|
||||||
showComments = sharedPreferences!!.getBoolean(key, true)
|
showComments = sharedPreferences.getBoolean(key, true)
|
||||||
tabSettingsChanged = true
|
tabSettingsChanged = true
|
||||||
} else if (getString(R.string.show_next_video_key) == key) {
|
} else if (getString(R.string.show_next_video_key) == key) {
|
||||||
showRelatedItems = sharedPreferences!!.getBoolean(key, true)
|
showRelatedItems = sharedPreferences.getBoolean(key, true)
|
||||||
tabSettingsChanged = true
|
tabSettingsChanged = true
|
||||||
} else if (getString(R.string.show_description_key) == key) {
|
} else if (getString(R.string.show_description_key) == key) {
|
||||||
showDescription = sharedPreferences!!.getBoolean(key, true)
|
showDescription = sharedPreferences.getBoolean(key, true)
|
||||||
tabSettingsChanged = true
|
tabSettingsChanged = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -198,11 +194,11 @@ class VideoDetailFragment :
|
|||||||
// It will do nothing if the player is not in fullscreen mode
|
// It will do nothing if the player is not in fullscreen mode
|
||||||
hideSystemUiIfNeeded()
|
hideSystemUiIfNeeded()
|
||||||
|
|
||||||
val mainUi = player?.UIs()?.get(MainPlayerUi::class)
|
|
||||||
if (player?.videoPlayerSelected() != true && !playAfterConnect) {
|
if (player?.videoPlayerSelected() != true && !playAfterConnect) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val mainUi = player?.UIs()?.get(MainPlayerUi::class)
|
||||||
if (DeviceUtils.isLandscape(requireContext())) {
|
if (DeviceUtils.isLandscape(requireContext())) {
|
||||||
// If the video is playing but orientation changed
|
// If the video is playing but orientation changed
|
||||||
// let's make the video in fullscreen again
|
// let's make the video in fullscreen again
|
||||||
@@ -252,7 +248,7 @@ class VideoDetailFragment :
|
|||||||
|
|
||||||
setupBroadcastReceiver()
|
setupBroadcastReceiver()
|
||||||
|
|
||||||
settingsContentObserver = object : ContentObserver(Handler()) {
|
settingsContentObserver = object : ContentObserver(Handler(Looper.getMainLooper())) {
|
||||||
override fun onChange(selfChange: Boolean) {
|
override fun onChange(selfChange: Boolean) {
|
||||||
if (activity != null && !PlayerHelper.globalScreenOrientationLocked(activity)) {
|
if (activity != null && !PlayerHelper.globalScreenOrientationLocked(activity)) {
|
||||||
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)
|
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)
|
||||||
@@ -277,9 +273,7 @@ class VideoDetailFragment :
|
|||||||
|
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
super.onPause()
|
super.onPause()
|
||||||
if (currentWorker != null) {
|
currentWorker?.dispose()
|
||||||
currentWorker!!.dispose()
|
|
||||||
}
|
|
||||||
restoreDefaultBrightness()
|
restoreDefaultBrightness()
|
||||||
PreferenceManager.getDefaultSharedPreferences(requireContext()).edit {
|
PreferenceManager.getDefaultSharedPreferences(requireContext()).edit {
|
||||||
putString(
|
putString(
|
||||||
@@ -304,9 +298,7 @@ class VideoDetailFragment :
|
|||||||
if (tabSettingsChanged) {
|
if (tabSettingsChanged) {
|
||||||
tabSettingsChanged = false
|
tabSettingsChanged = false
|
||||||
initTabs()
|
initTabs()
|
||||||
if (currentInfo != null) {
|
currentInfo?.let { updateTabs(it) }
|
||||||
updateTabs(currentInfo!!)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if it was loading when the fragment was stopped/paused
|
// Check if it was loading when the fragment was stopped/paused
|
||||||
@@ -339,12 +331,8 @@ class VideoDetailFragment :
|
|||||||
activity.unregisterReceiver(broadcastReceiver)
|
activity.unregisterReceiver(broadcastReceiver)
|
||||||
activity.contentResolver.unregisterContentObserver(settingsContentObserver!!)
|
activity.contentResolver.unregisterContentObserver(settingsContentObserver!!)
|
||||||
|
|
||||||
if (positionSubscriber != null) {
|
positionSubscriber?.dispose()
|
||||||
positionSubscriber!!.dispose()
|
currentWorker?.dispose()
|
||||||
}
|
|
||||||
if (currentWorker != null) {
|
|
||||||
currentWorker!!.dispose()
|
|
||||||
}
|
|
||||||
disposables.clear()
|
disposables.clear()
|
||||||
positionSubscriber = null
|
positionSubscriber = null
|
||||||
currentWorker = null
|
currentWorker = null
|
||||||
@@ -353,7 +341,7 @@ class VideoDetailFragment :
|
|||||||
if (activity.isFinishing) {
|
if (activity.isFinishing) {
|
||||||
playQueue = null
|
playQueue = null
|
||||||
currentInfo = null
|
currentInfo = null
|
||||||
stack = LinkedList<StackItem?>()
|
stack = LinkedList<StackItem>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -367,8 +355,7 @@ class VideoDetailFragment :
|
|||||||
if (requestCode == ReCaptchaActivity.RECAPTCHA_REQUEST) {
|
if (requestCode == ReCaptchaActivity.RECAPTCHA_REQUEST) {
|
||||||
if (resultCode == Activity.RESULT_OK) {
|
if (resultCode == Activity.RESULT_OK) {
|
||||||
NavigationHelper.openVideoDetailFragment(
|
NavigationHelper.openVideoDetailFragment(
|
||||||
requireContext(), getFM(),
|
requireContext(), getFM(), serviceId, url, title, null, false
|
||||||
serviceId, url, title, null, false
|
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
Log.e(TAG, "ReCaptcha failed")
|
Log.e(TAG, "ReCaptcha failed")
|
||||||
@@ -385,11 +372,11 @@ class VideoDetailFragment :
|
|||||||
binding.detailTitleRootLayout.setOnClickListener { toggleTitleAndSecondaryControls() }
|
binding.detailTitleRootLayout.setOnClickListener { toggleTitleAndSecondaryControls() }
|
||||||
binding.detailUploaderRootLayout.setOnClickListener(
|
binding.detailUploaderRootLayout.setOnClickListener(
|
||||||
makeOnClickListener { info ->
|
makeOnClickListener { info ->
|
||||||
if (TextUtils.isEmpty(info.subChannelUrl)) {
|
if (info.subChannelUrl.isEmpty()) {
|
||||||
if (!TextUtils.isEmpty(info.uploaderUrl)) {
|
if (info.uploaderUrl.isNotEmpty()) {
|
||||||
openChannel(info.uploaderUrl, info.uploaderName, info.serviceId)
|
openChannel(info.uploaderUrl, info.uploaderName, info.serviceId)
|
||||||
} else if (DEBUG) {
|
} else if (DEBUG) {
|
||||||
Log.i(TAG, "Can't open sub-channel because we got no channel URL")
|
Log.w(TAG, "Can't open sub-channel because we got no channel URL")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
openChannel(info.subChannelUrl, info.subChannelName, info.serviceId)
|
openChannel(info.subChannelUrl, info.subChannelName, info.serviceId)
|
||||||
@@ -495,7 +482,7 @@ class VideoDetailFragment :
|
|||||||
}
|
}
|
||||||
binding.detailUploaderRootLayout.setOnLongClickListener(
|
binding.detailUploaderRootLayout.setOnLongClickListener(
|
||||||
makeOnLongClickListener { info ->
|
makeOnLongClickListener { info ->
|
||||||
if (TextUtils.isEmpty(info.subChannelUrl)) {
|
if (info.subChannelUrl.isEmpty()) {
|
||||||
Log.w(TAG, "Can't open parent channel because we got no parent channel URL")
|
Log.w(TAG, "Can't open parent channel because we got no parent channel URL")
|
||||||
} else {
|
} else {
|
||||||
openChannel(info.uploaderUrl, info.uploaderName, info.serviceId)
|
openChannel(info.uploaderUrl, info.uploaderName, info.serviceId)
|
||||||
@@ -541,7 +528,7 @@ class VideoDetailFragment :
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun toggleTitleAndSecondaryControls() {
|
private fun toggleTitleAndSecondaryControls() {
|
||||||
if (binding.detailSecondaryControlPanel.visibility == View.GONE) {
|
if (binding.detailSecondaryControlPanel.isGone) {
|
||||||
binding.detailVideoTitleView.setMaxLines(10)
|
binding.detailVideoTitleView.setMaxLines(10)
|
||||||
binding.detailToggleSecondaryControlsView
|
binding.detailToggleSecondaryControlsView
|
||||||
.animateRotation(VideoPlayerUi.DEFAULT_CONTROLS_DURATION, 180)
|
.animateRotation(VideoPlayerUi.DEFAULT_CONTROLS_DURATION, 180)
|
||||||
@@ -569,18 +556,12 @@ class VideoDetailFragment :
|
|||||||
|
|
||||||
binding.detailThumbnailRootLayout.requestFocus()
|
binding.detailThumbnailRootLayout.requestFocus()
|
||||||
|
|
||||||
binding.detailControlsPlayWithKodi.visibility =
|
binding.detailControlsPlayWithKodi.isVisible =
|
||||||
if (KoreUtils.shouldShowPlayWithKodi(requireContext(), serviceId))
|
KoreUtils.shouldShowPlayWithKodi(requireContext(), serviceId)
|
||||||
View.VISIBLE
|
binding.detailControlsCrashThePlayer.isVisible =
|
||||||
else
|
DEBUG && PreferenceManager.getDefaultSharedPreferences(requireContext())
|
||||||
View.GONE
|
.getBoolean(getString(R.string.show_crash_the_player_key), false)
|
||||||
binding.detailControlsCrashThePlayer.visibility =
|
|
||||||
if (DEBUG && PreferenceManager.getDefaultSharedPreferences(requireContext())
|
|
||||||
.getBoolean(getString(R.string.show_crash_the_player_key), false)
|
|
||||||
)
|
|
||||||
View.VISIBLE
|
|
||||||
else
|
|
||||||
View.GONE
|
|
||||||
accommodateForTvAndDesktopMode()
|
accommodateForTvAndDesktopMode()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -591,8 +572,8 @@ class VideoDetailFragment :
|
|||||||
setOnClickListeners()
|
setOnClickListeners()
|
||||||
setOnLongClickListeners()
|
setOnLongClickListeners()
|
||||||
|
|
||||||
val controlsTouchListener = OnTouchListener { view: View?, motionEvent: MotionEvent? ->
|
val controlsTouchListener = OnTouchListener { view, motionEvent ->
|
||||||
if (motionEvent!!.action == MotionEvent.ACTION_DOWN &&
|
if (motionEvent.action == MotionEvent.ACTION_DOWN &&
|
||||||
PlayButtonHelper.shouldShowHoldToAppendTip(activity)
|
PlayButtonHelper.shouldShowHoldToAppendTip(activity)
|
||||||
) {
|
) {
|
||||||
binding.touchAppendDetail.animate(true, 250, AnimationType.ALPHA, 0) {
|
binding.touchAppendDetail.animate(true, 250, AnimationType.ALPHA, 0) {
|
||||||
@@ -604,16 +585,14 @@ class VideoDetailFragment :
|
|||||||
binding.detailControlsBackground.setOnTouchListener(controlsTouchListener)
|
binding.detailControlsBackground.setOnTouchListener(controlsTouchListener)
|
||||||
binding.detailControlsPopup.setOnTouchListener(controlsTouchListener)
|
binding.detailControlsPopup.setOnTouchListener(controlsTouchListener)
|
||||||
|
|
||||||
binding.appBarLayout.addOnOffsetChangedListener(
|
binding.appBarLayout.addOnOffsetChangedListener { layout, verticalOffset ->
|
||||||
OnOffsetChangedListener { layout: AppBarLayout?, verticalOffset: Int ->
|
// prevent useless updates to tab layout visibility if nothing changed
|
||||||
// prevent useless updates to tab layout visibility if nothing changed
|
if (verticalOffset != lastAppBarVerticalOffset) {
|
||||||
if (verticalOffset != lastAppBarVerticalOffset) {
|
lastAppBarVerticalOffset = verticalOffset
|
||||||
lastAppBarVerticalOffset = verticalOffset
|
// the view was scrolled
|
||||||
// the view was scrolled
|
updateTabLayoutVisibility()
|
||||||
updateTabLayoutVisibility()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
|
|
||||||
setupBottomPlayer()
|
setupBottomPlayer()
|
||||||
if (!PlayerHolder.isBound) {
|
if (!PlayerHolder.isBound) {
|
||||||
@@ -656,7 +635,7 @@ class VideoDetailFragment :
|
|||||||
// Remove top
|
// Remove top
|
||||||
stack.pop()
|
stack.pop()
|
||||||
// Get stack item from the new top
|
// Get stack item from the new top
|
||||||
setupFromHistoryItem(Objects.requireNonNull<StackItem?>(stack.peek()))
|
setupFromHistoryItem(stack.peek()!!)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -688,10 +667,9 @@ class VideoDetailFragment :
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
currentInfo?.let { info ->
|
when (val info = currentInfo) {
|
||||||
prepareAndHandleInfoIfNeededAfterDelay(info, false, 50)
|
null -> prepareAndLoadInfo()
|
||||||
} ?: {
|
else -> prepareAndHandleInfoIfNeededAfterDelay(info, false, 50)
|
||||||
prepareAndLoadInfo()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -756,9 +734,7 @@ class VideoDetailFragment :
|
|||||||
|
|
||||||
initTabs()
|
initTabs()
|
||||||
currentInfo = null
|
currentInfo = null
|
||||||
if (currentWorker != null) {
|
currentWorker?.dispose()
|
||||||
currentWorker!!.dispose()
|
|
||||||
}
|
|
||||||
|
|
||||||
runWorker(forceLoad, addToBackStack ?: stack.isEmpty())
|
runWorker(forceLoad, addToBackStack ?: stack.isEmpty())
|
||||||
}
|
}
|
||||||
@@ -783,7 +759,7 @@ class VideoDetailFragment :
|
|||||||
if (playQueue == null) {
|
if (playQueue == null) {
|
||||||
playQueue = SinglePlayQueue(result)
|
playQueue = SinglePlayQueue(result)
|
||||||
}
|
}
|
||||||
if (stack.isEmpty() || stack.peek()!!.playQueue != playQueue) {
|
if (stack.peek()?.playQueue != playQueue) { // also if stack empty (!)
|
||||||
stack.push(StackItem(serviceId, url, title, playQueue))
|
stack.push(StackItem(serviceId, url, title, playQueue))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -866,13 +842,14 @@ class VideoDetailFragment :
|
|||||||
|
|
||||||
private fun updateTabs(info: StreamInfo) {
|
private fun updateTabs(info: StreamInfo) {
|
||||||
if (showRelatedItems) {
|
if (showRelatedItems) {
|
||||||
if (binding.relatedItemsLayout == null) { // phone
|
when (val relatedItemsLayout = binding.relatedItemsLayout) {
|
||||||
pageAdapter.updateItem(RELATED_TAB_TAG, getInstance(info))
|
null -> pageAdapter.updateItem(RELATED_TAB_TAG, getInstance(info)) // phone
|
||||||
} else { // tablet + TV
|
else -> { // tablet + TV
|
||||||
getChildFragmentManager().beginTransaction()
|
getChildFragmentManager().beginTransaction()
|
||||||
.replace(R.id.relatedItemsLayout, getInstance(info))
|
.replace(R.id.relatedItemsLayout, getInstance(info))
|
||||||
.commitAllowingStateLoss()
|
.commitAllowingStateLoss()
|
||||||
binding.relatedItemsLayout!!.isVisible = !this.isFullscreen
|
relatedItemsLayout.isVisible = !this.isFullscreen
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -909,8 +886,7 @@ class VideoDetailFragment :
|
|||||||
// call `post()` to be sure `viewPager.getHitRect()`
|
// call `post()` to be sure `viewPager.getHitRect()`
|
||||||
// is up to date and not being currently recomputed
|
// is up to date and not being currently recomputed
|
||||||
binding.tabLayout.post {
|
binding.tabLayout.post {
|
||||||
val activity = getActivity()
|
getActivity()?.let { activity ->
|
||||||
if (activity != null) {
|
|
||||||
val pagerHitRect = Rect()
|
val pagerHitRect = Rect()
|
||||||
binding.viewPager.getHitRect(pagerHitRect)
|
binding.viewPager.getHitRect(pagerHitRect)
|
||||||
|
|
||||||
@@ -1056,7 +1032,7 @@ class VideoDetailFragment :
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun openMainPlayer() {
|
private fun openMainPlayer() {
|
||||||
if (noPlayerServiceAvailable()) {
|
if (playerService == null) {
|
||||||
PlayerHolder.startService(autoPlayEnabled, this)
|
PlayerHolder.startService(autoPlayEnabled, this)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -1082,13 +1058,13 @@ class VideoDetailFragment :
|
|||||||
*/
|
*/
|
||||||
private fun hideMainPlayerOnLoadingNewStream() {
|
private fun hideMainPlayerOnLoadingNewStream() {
|
||||||
val root = this.root
|
val root = this.root
|
||||||
if (noPlayerServiceAvailable() || root == null || !player!!.videoPlayerSelected()) {
|
if (root == null || playerService == null || player?.videoPlayerSelected() != true) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
removeVideoPlayerView()
|
removeVideoPlayerView()
|
||||||
if (this.isAutoplayEnabled) {
|
if (this.isAutoplayEnabled) {
|
||||||
playerService!!.stopForImmediateReusing()
|
playerService?.stopForImmediateReusing()
|
||||||
root.visibility = View.GONE
|
root.visibility = View.GONE
|
||||||
} else {
|
} else {
|
||||||
PlayerHolder.stopService()
|
PlayerHolder.stopService()
|
||||||
@@ -1127,8 +1103,11 @@ class VideoDetailFragment :
|
|||||||
|
|
||||||
val recordManager = HistoryRecordManager(requireContext())
|
val recordManager = HistoryRecordManager(requireContext())
|
||||||
disposables.add(
|
disposables.add(
|
||||||
recordManager.onViewed(info).onErrorComplete()
|
recordManager.onViewed(info)
|
||||||
.subscribe({ }, { throwable -> Log.e(TAG, "Register view failure: ", throwable) })
|
.subscribe(
|
||||||
|
{ /* successful */ },
|
||||||
|
{ throwable -> Log.e(TAG, "Register view failure: ", throwable) }
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1157,8 +1136,10 @@ class VideoDetailFragment :
|
|||||||
if (player == null || view == null) {
|
if (player == null || view == null) {
|
||||||
return@post
|
return@post
|
||||||
}
|
}
|
||||||
|
|
||||||
// setup the surface view height, so that it fits the video correctly
|
// setup the surface view height, so that it fits the video correctly
|
||||||
setHeightThumbnail()
|
setHeightThumbnail()
|
||||||
|
|
||||||
player?.UIs()?.get(MainPlayerUi::class)?.let { playerUi ->
|
player?.UIs()?.get(MainPlayerUi::class)?.let { playerUi ->
|
||||||
// sometimes binding would be null here, even though getView() != null above u.u
|
// sometimes binding would be null here, even though getView() != null above u.u
|
||||||
nullableBinding?.let { b ->
|
nullableBinding?.let { b ->
|
||||||
@@ -1186,13 +1167,13 @@ class VideoDetailFragment :
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val preDrawListener: OnPreDrawListener = OnPreDrawListener {
|
private val preDrawListener: OnPreDrawListener = OnPreDrawListener {
|
||||||
if (view != null) {
|
view?.let { view ->
|
||||||
val decorView = if (DeviceUtils.isInMultiWindow(activity))
|
val decorView = if (DeviceUtils.isInMultiWindow(activity))
|
||||||
requireView()
|
view
|
||||||
else
|
else
|
||||||
activity.window.decorView
|
activity.window.decorView
|
||||||
setHeightThumbnail(decorView.height, resources.displayMetrics)
|
setHeightThumbnail(decorView.height, resources.displayMetrics)
|
||||||
requireView().getViewTreeObserver().removeOnPreDrawListener(preDrawListener)
|
view.getViewTreeObserver().removeOnPreDrawListener(preDrawListener)
|
||||||
}
|
}
|
||||||
return@OnPreDrawListener false
|
return@OnPreDrawListener false
|
||||||
}
|
}
|
||||||
@@ -1366,20 +1347,20 @@ class VideoDetailFragment :
|
|||||||
|
|
||||||
binding.relatedItemsLayout?.isVisible = showRelatedItems && !this.isFullscreen
|
binding.relatedItemsLayout?.isVisible = showRelatedItems && !this.isFullscreen
|
||||||
|
|
||||||
dispose(binding.detailThumbnailImageView)
|
CoilUtils.dispose(binding.detailThumbnailImageView)
|
||||||
dispose(binding.detailSubChannelThumbnailView)
|
CoilUtils.dispose(binding.detailSubChannelThumbnailView)
|
||||||
dispose(binding.overlayThumbnail)
|
CoilUtils.dispose(binding.overlayThumbnail)
|
||||||
dispose(binding.detailUploaderThumbnailView)
|
CoilUtils.dispose(binding.detailUploaderThumbnailView)
|
||||||
|
|
||||||
binding.detailThumbnailImageView.setImageBitmap(null)
|
binding.detailThumbnailImageView.setImageBitmap(null)
|
||||||
binding.detailSubChannelThumbnailView.setImageBitmap(null)
|
binding.detailSubChannelThumbnailView.setImageBitmap(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun handleResult(info: StreamInfo?) {
|
override fun handleResult(info: StreamInfo) {
|
||||||
super.handleResult(info)
|
super.handleResult(info)
|
||||||
|
|
||||||
currentInfo = info
|
currentInfo = info
|
||||||
setInitialData(info!!.serviceId, info.originalUrl, info.name, playQueue)
|
setInitialData(info.serviceId, info.originalUrl, info.name, playQueue)
|
||||||
|
|
||||||
updateTabs(info)
|
updateTabs(info)
|
||||||
|
|
||||||
@@ -1388,10 +1369,10 @@ class VideoDetailFragment :
|
|||||||
|
|
||||||
binding.detailSubChannelThumbnailView.visibility = View.GONE
|
binding.detailSubChannelThumbnailView.visibility = View.GONE
|
||||||
|
|
||||||
if (!TextUtils.isEmpty(info.subChannelName)) {
|
if (info.subChannelName.isEmpty()) {
|
||||||
displayBothUploaderAndSubChannel(info)
|
|
||||||
} else {
|
|
||||||
displayUploaderAsSubChannel(info)
|
displayUploaderAsSubChannel(info)
|
||||||
|
} else {
|
||||||
|
displayBothUploaderAndSubChannel(info)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info.viewCount >= 0) {
|
if (info.viewCount >= 0) {
|
||||||
@@ -1459,10 +1440,7 @@ class VideoDetailFragment :
|
|||||||
binding.detailSecondaryControlPanel.visibility = View.GONE
|
binding.detailSecondaryControlPanel.visibility = View.GONE
|
||||||
|
|
||||||
checkUpdateProgressInfo(info)
|
checkUpdateProgressInfo(info)
|
||||||
loadDetailsThumbnail(
|
CoilHelper.loadDetailsThumbnail(binding.detailThumbnailImageView, info.thumbnails)
|
||||||
binding.detailThumbnailImageView,
|
|
||||||
info.thumbnails
|
|
||||||
)
|
|
||||||
ExtractorHelper.showMetaInfoInTextView(
|
ExtractorHelper.showMetaInfoInTextView(
|
||||||
info.metaInfo, binding.detailMetaInfoTextView,
|
info.metaInfo, binding.detailMetaInfoTextView,
|
||||||
binding.detailMetaInfoSeparator, disposables
|
binding.detailMetaInfoSeparator, disposables
|
||||||
@@ -1475,12 +1453,8 @@ class VideoDetailFragment :
|
|||||||
if (!info.errors.isEmpty()) {
|
if (!info.errors.isEmpty()) {
|
||||||
// Bandcamp fan pages are not yet supported and thus a ContentNotAvailableException is
|
// Bandcamp fan pages are not yet supported and thus a ContentNotAvailableException is
|
||||||
// thrown. This is not an error and thus should not be shown to the user.
|
// thrown. This is not an error and thus should not be shown to the user.
|
||||||
for (throwable in info.errors) {
|
info.errors.removeIf {
|
||||||
if (throwable is ContentNotSupportedException &&
|
it is ContentNotSupportedException && "Fan pages are not supported" == it.message
|
||||||
"Fan pages are not supported" == throwable.message
|
|
||||||
) {
|
|
||||||
info.errors.remove(throwable)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!info.errors.isEmpty()) {
|
if (!info.errors.isEmpty()) {
|
||||||
@@ -1490,8 +1464,9 @@ class VideoDetailFragment :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val hasAudioStreams = info.videoStreams.isNotEmpty() || info.audioStreams.isNotEmpty()
|
|
||||||
binding.detailControlsDownload.isVisible = !StreamTypeUtil.isLiveStream(info.streamType)
|
binding.detailControlsDownload.isVisible = !StreamTypeUtil.isLiveStream(info.streamType)
|
||||||
|
|
||||||
|
val hasAudioStreams = info.videoStreams.isNotEmpty() || info.audioStreams.isNotEmpty()
|
||||||
binding.detailControlsBackground.isVisible = hasAudioStreams
|
binding.detailControlsBackground.isVisible = hasAudioStreams
|
||||||
|
|
||||||
val hasVideoStreams = info.videoStreams.isNotEmpty() || info.videoOnlyStreams.isNotEmpty()
|
val hasVideoStreams = info.videoStreams.isNotEmpty() || info.videoOnlyStreams.isNotEmpty()
|
||||||
@@ -1514,7 +1489,7 @@ class VideoDetailFragment :
|
|||||||
binding.detailUploaderTextView.visibility = View.GONE
|
binding.detailUploaderTextView.visibility = View.GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
loadAvatar(binding.detailSubChannelThumbnailView, info.uploaderAvatars)
|
CoilHelper.loadAvatar(binding.detailSubChannelThumbnailView, info.uploaderAvatars)
|
||||||
binding.detailSubChannelThumbnailView.visibility = View.VISIBLE
|
binding.detailSubChannelThumbnailView.visibility = View.VISIBLE
|
||||||
binding.detailUploaderThumbnailView.visibility = View.GONE
|
binding.detailUploaderThumbnailView.visibility = View.GONE
|
||||||
}
|
}
|
||||||
@@ -1525,8 +1500,8 @@ class VideoDetailFragment :
|
|||||||
binding.detailSubChannelTextView.setSelected(true)
|
binding.detailSubChannelTextView.setSelected(true)
|
||||||
|
|
||||||
val subText = StringBuilder()
|
val subText = StringBuilder()
|
||||||
if (!TextUtils.isEmpty(info.uploaderName)) {
|
if (info.uploaderName.isNotEmpty()) {
|
||||||
subText.append(String.format(getString(R.string.video_detail_by), info.uploaderName))
|
subText.append(getString(R.string.video_detail_by, info.uploaderName))
|
||||||
}
|
}
|
||||||
if (info.uploaderSubscriberCount > -1) {
|
if (info.uploaderSubscriberCount > -1) {
|
||||||
if (subText.isNotEmpty()) {
|
if (subText.isNotEmpty()) {
|
||||||
@@ -1545,26 +1520,22 @@ class VideoDetailFragment :
|
|||||||
binding.detailUploaderTextView.setSelected(true)
|
binding.detailUploaderTextView.setSelected(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
loadAvatar(binding.detailSubChannelThumbnailView, info.subChannelAvatars)
|
CoilHelper.loadAvatar(binding.detailSubChannelThumbnailView, info.subChannelAvatars)
|
||||||
binding.detailSubChannelThumbnailView.visibility = View.VISIBLE
|
binding.detailSubChannelThumbnailView.visibility = View.VISIBLE
|
||||||
loadAvatar(binding.detailUploaderThumbnailView, info.uploaderAvatars)
|
CoilHelper.loadAvatar(binding.detailUploaderThumbnailView, info.uploaderAvatars)
|
||||||
binding.detailUploaderThumbnailView.visibility = View.VISIBLE
|
binding.detailUploaderThumbnailView.visibility = View.VISIBLE
|
||||||
}
|
}
|
||||||
|
|
||||||
fun openDownloadDialog() {
|
fun openDownloadDialog() {
|
||||||
if (currentInfo == null) {
|
val info = currentInfo ?: return
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val downloadDialog = DownloadDialog(activity, currentInfo!!)
|
val downloadDialog = DownloadDialog(activity, info)
|
||||||
downloadDialog.show(activity.supportFragmentManager, "downloadDialog")
|
downloadDialog.show(activity.supportFragmentManager, "downloadDialog")
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
showSnackbar(
|
showSnackbar(
|
||||||
activity,
|
activity,
|
||||||
ErrorInfo(
|
ErrorInfo(e, UserAction.DOWNLOAD_OPEN_DIALOG, "Showing download dialog", info)
|
||||||
e, UserAction.DOWNLOAD_OPEN_DIALOG, "Showing download dialog", currentInfo
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1586,7 +1557,7 @@ class VideoDetailFragment :
|
|||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(
|
.subscribe(
|
||||||
{ state -> updatePlaybackProgress(state.progressMillis, info.duration * 1000) },
|
{ state -> updatePlaybackProgress(state.progressMillis, info.duration * 1000) },
|
||||||
{ throwable -> /* ignore errors */ },
|
{ throwable -> /* impossible due to the onErrorComplete() */ },
|
||||||
{ /* onComplete */
|
{ /* onComplete */
|
||||||
binding.positionView.visibility = View.GONE
|
binding.positionView.visibility = View.GONE
|
||||||
binding.detailPositionView.visibility = View.GONE
|
binding.detailPositionView.visibility = View.GONE
|
||||||
@@ -1600,11 +1571,10 @@ class VideoDetailFragment :
|
|||||||
}
|
}
|
||||||
val progressSeconds = TimeUnit.MILLISECONDS.toSeconds(progress).toInt()
|
val progressSeconds = TimeUnit.MILLISECONDS.toSeconds(progress).toInt()
|
||||||
val durationSeconds = TimeUnit.MILLISECONDS.toSeconds(duration).toInt()
|
val durationSeconds = TimeUnit.MILLISECONDS.toSeconds(duration).toInt()
|
||||||
|
binding.positionView.setMax(durationSeconds)
|
||||||
// If the old and the new progress values have a big difference then use animation.
|
// If the old and the new progress values have a big difference then use animation.
|
||||||
// Otherwise don't because it affects CPU
|
// Otherwise don't because it affects CPU
|
||||||
val progressDifference = abs(binding.positionView.progress - progressSeconds)
|
if (abs(binding.positionView.progress - progressSeconds) > 2) {
|
||||||
binding.positionView.setMax(durationSeconds)
|
|
||||||
if (progressDifference > 2) {
|
|
||||||
binding.positionView.setProgressAnimated(progressSeconds)
|
binding.positionView.setProgressAnimated(progressSeconds)
|
||||||
} else {
|
} else {
|
||||||
binding.positionView.progress = progressSeconds
|
binding.positionView.progress = progressSeconds
|
||||||
@@ -1637,15 +1607,15 @@ class VideoDetailFragment :
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Register broadcast receiver to listen to playQueue changes
|
// Register broadcast receiver to listen to playQueue changes
|
||||||
// and hide the overlayPlayQueueButton when the playQueue is empty / destroyed.
|
// and hide the overlayPlayQueueButton when the playQueue is empty / destroyed.7
|
||||||
playQueue?.broadcastReceiver?.subscribe { updateOverlayPlayQueueButtonVisibility() }
|
playQueue?.broadcastReceiver?.subscribe { updateOverlayPlayQueueButtonVisibility() }
|
||||||
|
?.let { disposables.add(it) }
|
||||||
|
|
||||||
// This should be the only place where we push data to stack.
|
// This should be the only place where we push data to stack.
|
||||||
// It will allow to have live instance of PlayQueue with actual information about
|
// It will allow to have live instance of PlayQueue with actual information about
|
||||||
// deleted/added items inside Channel/Playlist queue and makes possible to have
|
// deleted/added items inside Channel/Playlist queue and makes possible to have
|
||||||
// a history of played items
|
// a history of played items
|
||||||
val stackPeek: StackItem? = stack.peek()
|
if (stack.peek()?.playQueue?.equals(queue) == false) {
|
||||||
if (stackPeek != null && stackPeek.playQueue != queue) {
|
|
||||||
queue.item?.let { queueItem ->
|
queue.item?.let { queueItem ->
|
||||||
stack.push(StackItem(queueItem.serviceId, queueItem.url, queueItem.title, queue))
|
stack.push(StackItem(queueItem.serviceId, queueItem.url, queueItem.title, queue))
|
||||||
return@onQueueUpdate
|
return@onQueueUpdate
|
||||||
@@ -1703,7 +1673,7 @@ class VideoDetailFragment :
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateOverlayData(info.name, info.uploaderName, info.thumbnails)
|
updateOverlayData(info.name, info.uploaderName, info.thumbnails)
|
||||||
if (currentInfo?.url == info.url) {
|
if (info.url == currentInfo?.url) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1780,17 +1750,15 @@ class VideoDetailFragment :
|
|||||||
* Will scroll down to description view after long click on moreOptionsButton
|
* Will scroll down to description view after long click on moreOptionsButton
|
||||||
* */
|
* */
|
||||||
override fun onMoreOptionsLongClicked() {
|
override fun onMoreOptionsLongClicked() {
|
||||||
val params =
|
val params = binding.appBarLayout.layoutParams as CoordinatorLayout.LayoutParams
|
||||||
binding.appBarLayout.layoutParams as CoordinatorLayout.LayoutParams
|
|
||||||
val behavior = params.behavior as AppBarLayout.Behavior
|
val behavior = params.behavior as AppBarLayout.Behavior
|
||||||
val valueAnimator = ValueAnimator.ofInt(0, -binding.playerPlaceholder.height)
|
val valueAnimator = ValueAnimator.ofInt(0, -binding.playerPlaceholder.height)
|
||||||
valueAnimator.interpolator = DecelerateInterpolator()
|
|
||||||
valueAnimator.addUpdateListener { animation ->
|
valueAnimator.addUpdateListener { animation ->
|
||||||
behavior.setTopAndBottomOffset(animation.getAnimatedValue() as Int)
|
behavior.setTopAndBottomOffset(animation.getAnimatedValue() as Int)
|
||||||
binding.appBarLayout.requestLayout()
|
binding.appBarLayout.requestLayout()
|
||||||
}
|
}
|
||||||
valueAnimator.interpolator = DecelerateInterpolator()
|
valueAnimator.interpolator = DecelerateInterpolator()
|
||||||
valueAnimator.setDuration(500)
|
valueAnimator.duration = 500
|
||||||
valueAnimator.start()
|
valueAnimator.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1867,9 +1835,11 @@ class VideoDetailFragment :
|
|||||||
private val isFullscreen: Boolean
|
private val isFullscreen: Boolean
|
||||||
get() = player?.UIs()?.get(VideoPlayerUi::class)?.isFullscreen == true
|
get() = player?.UIs()?.get(VideoPlayerUi::class)?.isFullscreen == true
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if the player is null, or if the player is nonnull but is stopped.
|
||||||
|
*/
|
||||||
@Suppress("NullableBooleanElvis") // rewriting as "!= false" creates more confusion
|
@Suppress("NullableBooleanElvis") // rewriting as "!= false" creates more confusion
|
||||||
private val playerIsStopped
|
private val playerIsStopped
|
||||||
// returns true if the player is null, or if the player is nonnull but is stopped
|
|
||||||
get() = player?.isStopped ?: true
|
get() = player?.isStopped ?: true
|
||||||
|
|
||||||
private fun restoreDefaultBrightness() {
|
private fun restoreDefaultBrightness() {
|
||||||
@@ -2017,9 +1987,8 @@ class VideoDetailFragment :
|
|||||||
.map { it.getResolution() as CharSequence }
|
.map { it.getResolution() as CharSequence }
|
||||||
.toTypedArray()
|
.toTypedArray()
|
||||||
|
|
||||||
builder.setSingleChoiceItems(
|
builder
|
||||||
resolutions, selectedVideoStreamIndexForExternalPlayers, null
|
.setSingleChoiceItems(resolutions, selectedVideoStreamIndexForExternalPlayers, null)
|
||||||
)
|
|
||||||
builder.setNegativeButton(R.string.cancel, null)
|
builder.setNegativeButton(R.string.cancel, null)
|
||||||
builder.setPositiveButton(R.string.ok) { dialog, which ->
|
builder.setPositiveButton(R.string.ok) { dialog, which ->
|
||||||
val index = (dialog as AlertDialog).listView.getCheckedItemPosition()
|
val index = (dialog as AlertDialog).listView.getCheckedItemPosition()
|
||||||
@@ -2050,16 +2019,14 @@ class VideoDetailFragment :
|
|||||||
startOnExternalPlayer(activity, info, audioTracks[0])
|
startOnExternalPlayer(activity, info, audioTracks[0])
|
||||||
} else {
|
} else {
|
||||||
val selectedAudioStream = ListHelper.getDefaultAudioFormat(activity, audioTracks)
|
val selectedAudioStream = ListHelper.getDefaultAudioFormat(activity, audioTracks)
|
||||||
val trackNames = audioTracks
|
val trackNames = audioTracks.map { Localization.audioTrackName(activity, it) }
|
||||||
.map { Localization.audioTrackName(activity, it) }
|
|
||||||
.toTypedArray()
|
|
||||||
|
|
||||||
AlertDialog.Builder(activity)
|
AlertDialog.Builder(activity)
|
||||||
.setTitle(R.string.select_audio_track_external_players)
|
.setTitle(R.string.select_audio_track_external_players)
|
||||||
.setNeutralButton(R.string.open_in_browser) { dialog, which ->
|
.setNeutralButton(R.string.open_in_browser) { dialog, which ->
|
||||||
ShareUtils.openUrlInBrowser(requireActivity(), url)
|
ShareUtils.openUrlInBrowser(requireActivity(), url)
|
||||||
}
|
}
|
||||||
.setSingleChoiceItems(trackNames, selectedAudioStream, null)
|
.setSingleChoiceItems(trackNames.toTypedArray(), selectedAudioStream, null)
|
||||||
.setNegativeButton(R.string.cancel, null)
|
.setNegativeButton(R.string.cancel, null)
|
||||||
.setPositiveButton(R.string.ok) { dialog, which ->
|
.setPositiveButton(R.string.ok) { dialog, which ->
|
||||||
val index = (dialog as AlertDialog).listView.getCheckedItemPosition()
|
val index = (dialog as AlertDialog).listView.getCheckedItemPosition()
|
||||||
@@ -2079,7 +2046,7 @@ class VideoDetailFragment :
|
|||||||
PlayerHolder.stopService()
|
PlayerHolder.stopService()
|
||||||
setInitialData(0, null, "", null)
|
setInitialData(0, null, "", null)
|
||||||
currentInfo = null
|
currentInfo = null
|
||||||
updateOverlayData(null, null, mutableListOf<Image>())
|
updateOverlayData(null, null, listOf())
|
||||||
}
|
}
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
@@ -2145,8 +2112,8 @@ class VideoDetailFragment :
|
|||||||
val behavior = params.behavior as AppBarLayout.Behavior?
|
val behavior = params.behavior as AppBarLayout.Behavior?
|
||||||
|
|
||||||
val bottomSheetLayout = activity.findViewById<FrameLayout>(R.id.fragment_player_holder)
|
val bottomSheetLayout = activity.findViewById<FrameLayout>(R.id.fragment_player_holder)
|
||||||
bottomSheetBehavior = BottomSheetBehavior.from<FrameLayout?>(bottomSheetLayout)
|
bottomSheetBehavior = BottomSheetBehavior.from(bottomSheetLayout)
|
||||||
bottomSheetBehavior.setState(lastStableBottomSheetState)
|
bottomSheetBehavior.state = lastStableBottomSheetState
|
||||||
updateBottomSheetState(lastStableBottomSheetState)
|
updateBottomSheetState(lastStableBottomSheetState)
|
||||||
|
|
||||||
val peekHeight = resources.getDimensionPixelSize(R.dimen.mini_player_height)
|
val peekHeight = resources.getDimensionPixelSize(R.dimen.mini_player_height)
|
||||||
@@ -2154,9 +2121,9 @@ class VideoDetailFragment :
|
|||||||
manageSpaceAtTheBottom(false)
|
manageSpaceAtTheBottom(false)
|
||||||
bottomSheetBehavior.peekHeight = peekHeight
|
bottomSheetBehavior.peekHeight = peekHeight
|
||||||
if (bottomSheetState == BottomSheetBehavior.STATE_COLLAPSED) {
|
if (bottomSheetState == BottomSheetBehavior.STATE_COLLAPSED) {
|
||||||
binding.overlayLayout.setAlpha(MAX_OVERLAY_ALPHA)
|
binding.overlayLayout.alpha = MAX_OVERLAY_ALPHA
|
||||||
} else if (bottomSheetState == BottomSheetBehavior.STATE_EXPANDED) {
|
} else if (bottomSheetState == BottomSheetBehavior.STATE_EXPANDED) {
|
||||||
binding.overlayLayout.setAlpha(0f)
|
binding.overlayLayout.alpha = 0f
|
||||||
setOverlayElementsClickable(false)
|
setOverlayElementsClickable(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2189,7 +2156,7 @@ class VideoDetailFragment :
|
|||||||
!this@VideoDetailFragment.isFullscreen &&
|
!this@VideoDetailFragment.isFullscreen &&
|
||||||
!DeviceUtils.isTablet(activity)
|
!DeviceUtils.isTablet(activity)
|
||||||
) {
|
) {
|
||||||
player!!.UIs().get(MainPlayerUi::class)?.toggleFullscreen()
|
player?.UIs()?.get(MainPlayerUi::class)?.toggleFullscreen()
|
||||||
}
|
}
|
||||||
setOverlayLook(binding.appBarLayout, behavior, 1f)
|
setOverlayLook(binding.appBarLayout, behavior, 1f)
|
||||||
}
|
}
|
||||||
@@ -2238,18 +2205,18 @@ class VideoDetailFragment :
|
|||||||
|
|
||||||
private fun updateOverlayPlayQueueButtonVisibility() {
|
private fun updateOverlayPlayQueueButtonVisibility() {
|
||||||
// hide the button if the queue is empty; no player => no play queue :)
|
// hide the button if the queue is empty; no player => no play queue :)
|
||||||
nullableBinding?.overlayPlayQueueButton?.isVisible = player?.playQueue?.isEmpty != true
|
nullableBinding?.overlayPlayQueueButton?.isVisible = player?.playQueue?.isEmpty == false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateOverlayData(
|
private fun updateOverlayData(
|
||||||
overlayTitle: String?,
|
overlayTitle: String?,
|
||||||
uploader: String?,
|
uploader: String?,
|
||||||
thumbnails: MutableList<Image>
|
thumbnails: List<Image>
|
||||||
) {
|
) {
|
||||||
binding.overlayTitleTextView.text = overlayTitle ?: ""
|
binding.overlayTitleTextView.text = overlayTitle ?: ""
|
||||||
binding.overlayChannelTextView.text = uploader ?: ""
|
binding.overlayChannelTextView.text = uploader ?: ""
|
||||||
binding.overlayThumbnail.setImageDrawable(null)
|
binding.overlayThumbnail.setImageDrawable(null)
|
||||||
loadDetailsThumbnail(binding.overlayThumbnail, thumbnails)
|
CoilHelper.loadDetailsThumbnail(binding.overlayThumbnail, thumbnails)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setOverlayPlayPauseImage(playerIsPlaying: Boolean) {
|
private fun setOverlayPlayPauseImage(playerIsPlaying: Boolean) {
|
||||||
@@ -2267,12 +2234,7 @@ class VideoDetailFragment :
|
|||||||
if (behavior == null || slideOffset < 0) {
|
if (behavior == null || slideOffset < 0) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
binding.overlayLayout.setAlpha(
|
binding.overlayLayout.alpha = min(MAX_OVERLAY_ALPHA, 1 - slideOffset)
|
||||||
min(
|
|
||||||
MAX_OVERLAY_ALPHA.toDouble(),
|
|
||||||
(1 - slideOffset).toDouble()
|
|
||||||
).toFloat()
|
|
||||||
)
|
|
||||||
// These numbers are not special. They just do a cool transition
|
// These numbers are not special. They just do a cool transition
|
||||||
behavior.setTopAndBottomOffset(
|
behavior.setTopAndBottomOffset(
|
||||||
(-binding.detailThumbnailImageView.height * 2 * (1 - slideOffset) / 3).toInt()
|
(-binding.detailThumbnailImageView.height * 2 * (1 - slideOffset) / 3).toInt()
|
||||||
@@ -2291,10 +2253,6 @@ class VideoDetailFragment :
|
|||||||
binding.overlayCloseButton.isClickable = enable
|
binding.overlayCloseButton.isClickable = enable
|
||||||
}
|
}
|
||||||
|
|
||||||
fun noPlayerServiceAvailable(): Boolean {
|
|
||||||
return playerService == null
|
|
||||||
}
|
|
||||||
|
|
||||||
val root: View?
|
val root: View?
|
||||||
get() = player?.UIs()?.get(VideoPlayerUi::class)?.binding?.root
|
get() = player?.UIs()?.get(VideoPlayerUi::class)?.binding?.root
|
||||||
|
|
||||||
@@ -2356,6 +2314,6 @@ class VideoDetailFragment :
|
|||||||
* Stack that contains the "navigation history".<br></br>
|
* Stack that contains the "navigation history".<br></br>
|
||||||
* The peek is the current video.
|
* The peek is the current video.
|
||||||
*/
|
*/
|
||||||
private var stack = LinkedList<StackItem?>()
|
private var stack = LinkedList<StackItem>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -9,6 +9,7 @@ import android.support.v4.media.MediaDescriptionCompat
|
|||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.annotation.DrawableRes
|
import androidx.annotation.DrawableRes
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
|
import androidx.core.os.bundleOf
|
||||||
import androidx.media.MediaBrowserServiceCompat
|
import androidx.media.MediaBrowserServiceCompat
|
||||||
import androidx.media.MediaBrowserServiceCompat.Result
|
import androidx.media.MediaBrowserServiceCompat.Result
|
||||||
import androidx.media.utils.MediaConstants
|
import androidx.media.utils.MediaConstants
|
||||||
@@ -180,17 +181,16 @@ class MediaBrowserImpl(
|
|||||||
|
|
||||||
private fun createPlaylistMediaItem(playlist: PlaylistLocalItem): MediaBrowserCompat.MediaItem {
|
private fun createPlaylistMediaItem(playlist: PlaylistLocalItem): MediaBrowserCompat.MediaItem {
|
||||||
val builder = MediaDescriptionCompat.Builder()
|
val builder = MediaDescriptionCompat.Builder()
|
||||||
builder
|
|
||||||
.setMediaId(createMediaIdForInfoItem(playlist is PlaylistRemoteEntity, playlist.uid))
|
.setMediaId(createMediaIdForInfoItem(playlist is PlaylistRemoteEntity, playlist.uid))
|
||||||
.setTitle(playlist.orderingName)
|
.setTitle(playlist.orderingName)
|
||||||
.setIconUri(imageUriOrNullIfDisabled(playlist.thumbnailUrl))
|
.setIconUri(imageUriOrNullIfDisabled(playlist.thumbnailUrl))
|
||||||
|
.setExtras(
|
||||||
|
bundleOf(
|
||||||
|
MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE
|
||||||
|
to context.resources.getString(R.string.tab_bookmarks)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
val extras = Bundle()
|
|
||||||
extras.putString(
|
|
||||||
MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE,
|
|
||||||
context.resources.getString(R.string.tab_bookmarks),
|
|
||||||
)
|
|
||||||
builder.setExtras(extras)
|
|
||||||
return MediaBrowserCompat.MediaItem(
|
return MediaBrowserCompat.MediaItem(
|
||||||
builder.build(),
|
builder.build(),
|
||||||
MediaBrowserCompat.MediaItem.FLAG_BROWSABLE,
|
MediaBrowserCompat.MediaItem.FLAG_BROWSABLE,
|
||||||
@@ -199,7 +199,7 @@ class MediaBrowserImpl(
|
|||||||
|
|
||||||
private fun createInfoItemMediaItem(item: InfoItem): MediaBrowserCompat.MediaItem? {
|
private fun createInfoItemMediaItem(item: InfoItem): MediaBrowserCompat.MediaItem? {
|
||||||
val builder = MediaDescriptionCompat.Builder()
|
val builder = MediaDescriptionCompat.Builder()
|
||||||
builder.setMediaId(createMediaIdForInfoItem(item))
|
.setMediaId(createMediaIdForInfoItem(item))
|
||||||
.setTitle(item.name)
|
.setTitle(item.name)
|
||||||
.setIconUri(ImageStrategy.choosePreferredImage(item.thumbnails)?.toUri())
|
.setIconUri(ImageStrategy.choosePreferredImage(item.thumbnails)?.toUri())
|
||||||
|
|
||||||
@@ -250,7 +250,7 @@ class MediaBrowserImpl(
|
|||||||
index: Int,
|
index: Int,
|
||||||
): MediaBrowserCompat.MediaItem {
|
): MediaBrowserCompat.MediaItem {
|
||||||
val builder = MediaDescriptionCompat.Builder()
|
val builder = MediaDescriptionCompat.Builder()
|
||||||
builder.setMediaId(createMediaIdForPlaylistIndex(false, playlistId, index))
|
.setMediaId(createMediaIdForPlaylistIndex(false, playlistId, index))
|
||||||
.setTitle(item.streamEntity.title)
|
.setTitle(item.streamEntity.title)
|
||||||
.setSubtitle(item.streamEntity.uploader)
|
.setSubtitle(item.streamEntity.uploader)
|
||||||
.setIconUri(imageUriOrNullIfDisabled(item.streamEntity.thumbnailUrl))
|
.setIconUri(imageUriOrNullIfDisabled(item.streamEntity.thumbnailUrl))
|
||||||
|
Reference in New Issue
Block a user