mirror of
				https://github.com/TeamNewPipe/NewPipe
				synced 2025-10-31 07:13: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
	 Stypox
					Stypox