rework the player activity starting behaviour
* add callbacks on player finish to update episode watch head progress in gui * directly start the player from the fragment and not from MainActivity
This commit is contained in:
parent
a95813e91e
commit
f49b5a2730
|
@ -43,7 +43,6 @@ import org.mosad.teapod.ui.activity.main.fragments.HomeFragment
|
|||
import org.mosad.teapod.ui.activity.main.fragments.LibraryFragment
|
||||
import org.mosad.teapod.ui.activity.main.fragments.SearchFragment
|
||||
import org.mosad.teapod.ui.activity.onboarding.OnboardingActivity
|
||||
import org.mosad.teapod.ui.activity.player.PlayerActivity
|
||||
import org.mosad.teapod.util.DataTypes
|
||||
import org.mosad.teapod.util.metadb.MetaDBController
|
||||
import java.util.*
|
||||
|
@ -190,17 +189,6 @@ class MainActivity : AppCompatActivity(), NavigationBarView.OnItemSelectedListen
|
|||
finish()
|
||||
}
|
||||
|
||||
/**
|
||||
* start the player as new activity
|
||||
*/
|
||||
fun startPlayer(seasonId: String, episodeId: String) {
|
||||
val intent = Intent(this, PlayerActivity::class.java).apply {
|
||||
putExtra(getString(R.string.intent_season_id), seasonId)
|
||||
putExtra(getString(R.string.intent_episode_id), episodeId)
|
||||
}
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
/**
|
||||
* use custom restart instead of recreate(), since it has animations
|
||||
*/
|
||||
|
|
|
@ -27,6 +27,7 @@ import android.util.Log
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.core.view.children
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.Fragment
|
||||
|
@ -40,13 +41,10 @@ import kotlinx.coroutines.launch
|
|||
import org.mosad.teapod.R
|
||||
import org.mosad.teapod.databinding.FragmentHomeBinding
|
||||
import org.mosad.teapod.ui.activity.main.viewmodel.HomeViewModel
|
||||
import org.mosad.teapod.util.*
|
||||
import org.mosad.teapod.util.adapter.MediaEpisodeListAdapter
|
||||
import org.mosad.teapod.util.adapter.MediaItemListAdapter
|
||||
import org.mosad.teapod.util.decoration.MediaItemDecoration
|
||||
import org.mosad.teapod.util.setDrawableTop
|
||||
import org.mosad.teapod.util.showFragment
|
||||
import org.mosad.teapod.util.startPlayer
|
||||
import org.mosad.teapod.util.toItemMediaList
|
||||
|
||||
class HomeFragment : Fragment() {
|
||||
|
||||
|
@ -54,6 +52,10 @@ class HomeFragment : Fragment() {
|
|||
private val model: HomeViewModel by viewModels()
|
||||
private lateinit var binding: FragmentHomeBinding
|
||||
|
||||
private val playerResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||
model.updateUpNextItems()
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||
binding = FragmentHomeBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
|
@ -70,7 +72,7 @@ class HomeFragment : Fragment() {
|
|||
|
||||
binding.recyclerUpNext.adapter = MediaEpisodeListAdapter(
|
||||
MediaEpisodeListAdapter.OnClickListener {
|
||||
activity?.startPlayer(it.panel.episodeMetadata.seasonId, it.panel.id)
|
||||
playerResult.launch(playerIntent(it.panel.episodeMetadata.seasonId, it.panel.id))
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -154,7 +156,7 @@ class HomeFragment : Fragment() {
|
|||
|
||||
binding.buttonPlayHighlight.setOnClickListener {
|
||||
val panel = uiState.highlightItemUpNext.panel
|
||||
activity?.startPlayer(panel.episodeMetadata.seasonId, panel.id)
|
||||
playerResult.launch(playerIntent(panel.episodeMetadata.seasonId, panel.id))
|
||||
}
|
||||
|
||||
// disable the shimmer effect
|
||||
|
|
|
@ -7,6 +7,7 @@ import android.util.Log
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
|
@ -20,8 +21,8 @@ import kotlinx.coroutines.launch
|
|||
import org.mosad.teapod.R
|
||||
import org.mosad.teapod.databinding.FragmentMediaBinding
|
||||
import org.mosad.teapod.parser.crunchyroll.NoneUpNextSeriesItem
|
||||
import org.mosad.teapod.ui.activity.main.MainActivity
|
||||
import org.mosad.teapod.ui.activity.main.viewmodel.MediaFragmentViewModel
|
||||
import org.mosad.teapod.util.playerIntent
|
||||
import org.mosad.teapod.util.tmdb.TMDBApiController
|
||||
import org.mosad.teapod.util.tmdb.TMDBMovie
|
||||
import org.mosad.teapod.util.tmdb.TMDBTVShow
|
||||
|
@ -40,7 +41,10 @@ class MediaFragment(private val mediaIdStr: String) : Fragment() {
|
|||
|
||||
private val fragments = arrayListOf<Fragment>()
|
||||
private var watchlistJobRunning = false
|
||||
private var runOnResume = false
|
||||
|
||||
private val playerResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||
playerFinishedCallback()
|
||||
}
|
||||
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||
|
@ -74,33 +78,6 @@ class MediaFragment(private val mediaIdStr: String) : Fragment() {
|
|||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
|
||||
if (runOnResume) {
|
||||
/**
|
||||
* FIXME
|
||||
* this is currently also run on back press when multiple MediaFragments have
|
||||
* been open and closed via similar tab
|
||||
*/
|
||||
|
||||
lifecycleScope.launch {
|
||||
model.updateOnResume()
|
||||
|
||||
if (model.upNextSeries != NoneUpNextSeriesItem) {
|
||||
binding.textTitle.text = model.upNextSeries.panel.title
|
||||
}
|
||||
|
||||
// needs to be called after model.updateOnResume()
|
||||
if (fragments.elementAtOrNull(0) is MediaFragmentEpisodes) {
|
||||
(fragments[0] as MediaFragmentEpisodes).updateWatchedState()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
runOnResume = true
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* if tmdb data is present, use it, else use the aod data
|
||||
*/
|
||||
|
@ -218,15 +195,25 @@ class MediaFragment(private val mediaIdStr: String) : Fragment() {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* play the current episode
|
||||
* TODO this is also used in MediaFragmentEpisode, we should only have on implementation
|
||||
*/
|
||||
private fun playEpisode(seasonId: String, episodeId: String) {
|
||||
(activity as MainActivity).startPlayer(seasonId, episodeId)
|
||||
Log.d(javaClass.name, "Started Player with episodeId: $episodeId")
|
||||
private fun playerFinishedCallback() = lifecycleScope.launch {
|
||||
model.updateOnResume()
|
||||
|
||||
//model.updateNextEpisode(episodeId) // set the correct next episode
|
||||
if (model.upNextSeries != NoneUpNextSeriesItem) {
|
||||
binding.textTitle.text = model.upNextSeries.panel.title
|
||||
}
|
||||
|
||||
// needs to be called after model.updateOnResume()
|
||||
(fragments.elementAtOrNull(0) as? MediaFragmentEpisodes)?.updateWatchedState()
|
||||
|
||||
Log.d(javaClass.name, "Updated model and gui after player closed")
|
||||
}
|
||||
|
||||
/**
|
||||
* play a episode, also runs callback on player result return
|
||||
*/
|
||||
fun playEpisode(seasonId: String, episodeId: String) {
|
||||
playerResult.launch(playerIntent(seasonId, episodeId))
|
||||
Log.d(javaClass.name, "Started Player with episodeId: $episodeId")
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -2,7 +2,6 @@ package org.mosad.teapod.ui.activity.main.fragments
|
|||
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
@ -13,7 +12,6 @@ import androidx.lifecycle.lifecycleScope
|
|||
import kotlinx.coroutines.launch
|
||||
import org.mosad.teapod.R
|
||||
import org.mosad.teapod.databinding.FragmentMediaEpisodesBinding
|
||||
import org.mosad.teapod.ui.activity.main.MainActivity
|
||||
import org.mosad.teapod.ui.activity.main.viewmodel.MediaFragmentViewModel
|
||||
import org.mosad.teapod.util.adapter.EpisodeItemAdapter
|
||||
|
||||
|
@ -37,7 +35,7 @@ class MediaFragmentEpisodes : Fragment() {
|
|||
model.tmdbTVSeason.episodes,
|
||||
model.currentPlayheads,
|
||||
EpisodeItemAdapter.OnClickListener { episode ->
|
||||
playEpisode(episode.seasonId, episode.id)
|
||||
(requireParentFragment() as? MediaFragment)?.playEpisode(episode.seasonId, episode.id)
|
||||
},
|
||||
EpisodeItemAdapter.ViewType.MEDIA_FRAGMENT
|
||||
)
|
||||
|
@ -106,11 +104,4 @@ class MediaFragmentEpisodes : Fragment() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun playEpisode(seasonId: String, episodeId: String) {
|
||||
(activity as MainActivity).startPlayer(seasonId, episodeId)
|
||||
Log.d(javaClass.name, "Started Player with episodeId: $episodeId")
|
||||
|
||||
//model.updateNextEpisode(episodeId) // set the correct next episode
|
||||
}
|
||||
|
||||
}
|
|
@ -33,6 +33,8 @@ import kotlin.random.Random
|
|||
|
||||
class HomeViewModel : ViewModel() {
|
||||
|
||||
private val WATCHLIST_LENGTH = 50
|
||||
|
||||
private val uiState = MutableStateFlow<UiState>(UiState.Loading)
|
||||
|
||||
sealed class UiState {
|
||||
|
@ -64,7 +66,7 @@ class HomeViewModel : ViewModel() {
|
|||
try {
|
||||
// run the loading in parallel to speed up the process
|
||||
val upNextJob = viewModelScope.async { Crunchyroll.upNextAccount().items }
|
||||
val watchlistJob = viewModelScope.async { Crunchyroll.watchlist(50).items }
|
||||
val watchlistJob = viewModelScope.async { Crunchyroll.watchlist(WATCHLIST_LENGTH).items }
|
||||
val recommendationsJob = viewModelScope.async {
|
||||
Crunchyroll.recommendations(20).items
|
||||
}
|
||||
|
@ -111,7 +113,7 @@ class HomeViewModel : ViewModel() {
|
|||
}
|
||||
|
||||
// update the watchlist after a item has been added/removed
|
||||
val watchlistItems = Crunchyroll.watchlist(50).items
|
||||
val watchlistItems = Crunchyroll.watchlist(WATCHLIST_LENGTH).items
|
||||
|
||||
currentUiState.copy(
|
||||
watchlistItems = watchlistItems,
|
||||
|
@ -123,4 +125,20 @@ class HomeViewModel : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* Update the up next list. To be used on player result callbacks.
|
||||
*/
|
||||
fun updateUpNextItems() {
|
||||
viewModelScope.launch {
|
||||
uiState.update { currentUiState ->
|
||||
if (currentUiState is UiState.Normal) {
|
||||
val upNextItems = Crunchyroll.upNextAccount().items
|
||||
currentUiState.copy(upNextItems = upNextItems)
|
||||
} else {
|
||||
currentUiState
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -142,14 +142,6 @@ class PlayerActivity : AppCompatActivity() {
|
|||
if (isInPiPMode()) { finishAndRemoveTask() }
|
||||
}
|
||||
|
||||
// override fun onDestroy() {
|
||||
// super.onDestroy()
|
||||
//
|
||||
// if (isFinishing) {
|
||||
// // TODO notify about player finishing
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* used, when the player is in pip and the user selects a new media
|
||||
*/
|
||||
|
|
|
@ -9,7 +9,6 @@ import androidx.fragment.app.Fragment
|
|||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.fragment.app.commit
|
||||
import org.mosad.teapod.R
|
||||
import org.mosad.teapod.ui.activity.player.PlayerActivity
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
/**
|
||||
|
@ -25,20 +24,6 @@ fun FragmentActivity.showFragment(fragment: Fragment) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the player as new activity.
|
||||
*
|
||||
* @param seasonId The ID of the season the episode to be played is in
|
||||
* @param episodeId The ID of the episode to play
|
||||
*/
|
||||
fun Activity.startPlayer(seasonId: String, episodeId: String) {
|
||||
val intent = Intent(this, PlayerActivity::class.java).apply {
|
||||
putExtra(getString(R.string.intent_season_id), seasonId)
|
||||
putExtra(getString(R.string.intent_episode_id), episodeId)
|
||||
}
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
/**
|
||||
* hide the status and navigation bar
|
||||
*/
|
||||
|
|
|
@ -1,16 +1,31 @@
|
|||
package org.mosad.teapod.util
|
||||
|
||||
import android.content.Intent
|
||||
import android.view.View
|
||||
import android.view.Window
|
||||
import android.widget.TextView
|
||||
import androidx.core.view.WindowCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.core.view.WindowInsetsControllerCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import org.mosad.teapod.R
|
||||
import org.mosad.teapod.parser.crunchyroll.Collection
|
||||
import org.mosad.teapod.parser.crunchyroll.ContinueWatchingItem
|
||||
import org.mosad.teapod.parser.crunchyroll.Item
|
||||
import org.mosad.teapod.ui.activity.player.PlayerActivity
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Create a Intent for PlayerActivity with season and episode id.
|
||||
*
|
||||
* @param seasonId The ID of the season the episode to be played is in
|
||||
* @param episodeId The ID of the episode to play
|
||||
*/
|
||||
fun Fragment.playerIntent(seasonId: String, episodeId: String) = Intent(context, PlayerActivity::class.java).apply {
|
||||
putExtra(getString(R.string.intent_season_id), seasonId)
|
||||
putExtra(getString(R.string.intent_episode_id), episodeId)
|
||||
}
|
||||
|
||||
fun TextView.setDrawableTop(drawable: Int) {
|
||||
this.setCompoundDrawablesWithIntrinsicBounds(0, drawable, 0, 0)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue