package dev.jdtech.jellyfin import android.os.Bundle import android.view.View import android.view.WindowManager import androidx.appcompat.app.AppCompatActivity import androidx.core.view.WindowCompat import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsControllerCompat import androidx.core.view.updatePadding import androidx.media3.exoplayer.trackselection.MappingTrackSelector import androidx.media3.session.MediaSession import dev.jdtech.jellyfin.viewmodels.PlayerActivityViewModel abstract class BasePlayerActivity : AppCompatActivity() { abstract val viewModel: PlayerActivityViewModel private lateinit var mediaSession: MediaSession private var wasPip: Boolean = false override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) WindowCompat.setDecorFitsSystemWindows(window, false) } override fun onStart() { super.onStart() mediaSession = MediaSession.Builder(this, viewModel.player).build() } override fun onResume() { super.onResume() if (wasPip) { wasPip = false } else { viewModel.player.playWhenReady = viewModel.playWhenReady } hideSystemUI() } override fun onPause() { super.onPause() if (isInPictureInPictureMode) { wasPip = true } else { viewModel.playWhenReady = viewModel.player.playWhenReady == true viewModel.player.playWhenReady = false } } override fun onStop() { super.onStop() mediaSession.release() if (wasPip) { finish() } } protected fun hideSystemUI() { WindowCompat.getInsetsController(window, window.decorView).apply { systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE hide(WindowInsetsCompat.Type.systemBars()) } window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES } protected fun isRendererType( mappedTrackInfo: MappingTrackSelector.MappedTrackInfo, rendererIndex: Int, type: Int, ): Boolean { val trackGroupArray = mappedTrackInfo.getTrackGroups(rendererIndex) if (trackGroupArray.length == 0) { return false } val trackType = mappedTrackInfo.getRendererType(rendererIndex) return type == trackType } protected fun configureInsets(playerControls: View) { playerControls.setOnApplyWindowInsetsListener { _, windowInsets -> val cutout = windowInsets.displayCutout playerControls.updatePadding( left = cutout?.safeInsetLeft ?: 0, top = cutout?.safeInsetTop ?: 0, right = cutout?.safeInsetRight ?: 0, bottom = cutout?.safeInsetBottom ?: 0, ) return@setOnApplyWindowInsetsListener windowInsets } } }