use the epsidoeId for the next epsiode in PlayerViewModel

This commit is contained in:
Jannik 2021-09-05 11:54:55 +02:00
parent 8753d4f36f
commit eeb1c33e43
Signed by: Seil0
GPG Key ID: E8459F3723C52C24
3 changed files with 36 additions and 33 deletions

View File

@ -118,13 +118,13 @@ class PlayerActivity : AppCompatActivity() {
override fun onNewIntent(intent: Intent?) { override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent) super.onNewIntent(intent)
// when the intent changed, lead the new media and play it // when the intent changed, load the new media and play it
intent?.let { intent?.let {
model.loadMedia( model.loadMedia(
it.getIntExtra(getString(R.string.intent_media_id), 0), it.getIntExtra(getString(R.string.intent_media_id), 0),
it.getIntExtra(getString(R.string.intent_episode_id), 0) it.getIntExtra(getString(R.string.intent_episode_id), 0)
) )
model.playEpisode(model.currentEpisode, replace = true) model.playEpisode(model.currentEpisode.mediaId, replace = true)
} }
} }
@ -206,14 +206,14 @@ class PlayerActivity : AppCompatActivity() {
else -> View.VISIBLE else -> View.VISIBLE
} }
if (state == ExoPlayer.STATE_ENDED && model.nextEpisode != null && Preferences.autoplay) { if (state == ExoPlayer.STATE_ENDED && model.nextEpisodeId != null && Preferences.autoplay) {
playNextEpisode() playNextEpisode()
} }
} }
}) })
// start playing the current episode, after all needed player components have been initialized // start playing the current episode, after all needed player components have been initialized
model.playEpisode(model.currentEpisode, true) model.playEpisode(model.currentEpisode.mediaId, true)
} }
@SuppressLint("ClickableViewAccessibility") @SuppressLint("ClickableViewAccessibility")
@ -277,7 +277,7 @@ class PlayerActivity : AppCompatActivity() {
// if remaining time < 20 sec, a next ep is set, autoplay is enabled and not in pip: // if remaining time < 20 sec, a next ep is set, autoplay is enabled and not in pip:
// show next ep button // show next ep button
if (remainingTime in 1..20000) { if (remainingTime in 1..20000) {
if (!btnNextEpIsVisible && model.nextEpisode != null && Preferences.autoplay && !isInPiPMode()) { if (!btnNextEpIsVisible && model.nextEpisodeId != null && Preferences.autoplay && !isInPiPMode()) {
showButtonNextEp() showButtonNextEp()
} }
} else if (btnNextEpIsVisible) { } else if (btnNextEpIsVisible) {
@ -335,7 +335,7 @@ class PlayerActivity : AppCompatActivity() {
exo_text_title.text = model.getMediaTitle() exo_text_title.text = model.getMediaTitle()
// hide the next ep button, if there is none // hide the next ep button, if there is none
button_next_ep_c.visibility = if (model.nextEpisode == null) { button_next_ep_c.visibility = if (model.nextEpisodeId == null) {
View.GONE View.GONE
} else { } else {
View.VISIBLE View.VISIBLE

View File

@ -29,9 +29,6 @@ import kotlin.collections.ArrayList
* PlayerViewModel handles all stuff related to media/episodes. * PlayerViewModel handles all stuff related to media/episodes.
* When currentEpisode is changed the player will start playing it (not initial media), * When currentEpisode is changed the player will start playing it (not initial media),
* the next episode will be update and the callback is handled. * the next episode will be update and the callback is handled.
*
* TODO rework don't use episodes for everything, use media instead
* this is a major rework of the AoDParser/Player/Media architecture
*/ */
class PlayerViewModel(application: Application) : AndroidViewModel(application) { class PlayerViewModel(application: Application) : AndroidViewModel(application) {
@ -44,16 +41,16 @@ class PlayerViewModel(application: Application) : AndroidViewModel(application)
var media: AoDMedia = AoDMediaNone var media: AoDMedia = AoDMediaNone
internal set internal set
var currentEpisode = AoDEpisodeNone var mediaMeta: Meta? = null
internal set
var nextEpisode: AoDEpisode? = null
internal set internal set
var tmdbTVSeason: TMDBTVSeason? =null var tmdbTVSeason: TMDBTVSeason? =null
internal set internal set
var mediaMeta: Meta? = null var currentEpisode = AoDEpisodeNone
internal set internal set
var currentEpisodeMeta: EpisodeMeta? = null var currentEpisodeMeta: EpisodeMeta? = null
internal set internal set
var nextEpisodeId: Int? = null
internal set
var currentLanguage: Locale = Locale.ROOT var currentLanguage: Locale = Locale.ROOT
internal set internal set
@ -97,7 +94,7 @@ class PlayerViewModel(application: Application) : AndroidViewModel(application)
} }
currentEpisode = media.getEpisodeById(episodeId) currentEpisode = media.getEpisodeById(episodeId)
nextEpisode = selectNextEpisode() nextEpisodeId = selectNextEpisode()
currentEpisodeMeta = getEpisodeMetaByAoDMediaId(currentEpisode.mediaId) currentEpisodeMeta = getEpisodeMetaByAoDMediaId(currentEpisode.mediaId)
currentLanguage = currentEpisode.getPreferredStream(preferredLanguage).language currentLanguage = currentEpisode.getPreferredStream(preferredLanguage).language
} }
@ -125,33 +122,37 @@ class PlayerViewModel(application: Application) : AndroidViewModel(application)
/** /**
* play the next episode, if nextEpisode is not null * play the next episode, if nextEpisode is not null
*/ */
fun playNextEpisode() = nextEpisode?.let { it -> fun playNextEpisode() = nextEpisodeId?.let { it ->
playEpisode(it, replace = true) playEpisode(it, replace = true)
} }
/** /**
* set currentEpisode to the param episode and start playing it * Set currentEpisode and start playing it.
* update nextEpisode to reflect the change * Update nextEpisode to reflect the change and update
* the watched state for the now playing episode.
* *
* updateWatchedState for the next (now current) episode * @param episodeId The aod media id of the episode to play.
* @param replace (default = false)
* @param seekPosition The seek position for the episode (default = 0).
*/ */
fun playEpisode(episode: AoDEpisode, replace: Boolean = false, seekPosition: Long = 0) { fun playEpisode(episodeId: Int, replace: Boolean = false, seekPosition: Long = 0) {
val preferredStream = episode.getPreferredStream(currentLanguage) currentEpisode = media.getEpisodeById(episodeId)
currentLanguage = preferredStream.language // update current language, since it may have changed currentLanguage = currentEpisode.getPreferredStream(currentLanguage).language
currentEpisode = episode currentEpisodeMeta = getEpisodeMetaByAoDMediaId(currentEpisode.mediaId)
nextEpisode = selectNextEpisode() nextEpisodeId = selectNextEpisode()
currentEpisodeMeta = getEpisodeMetaByAoDMediaId(episode.mediaId)
currentEpisodeChangedListener.forEach { it() } // update player gui (title) // update player gui (title, next ep button) after nextEpisodeId has been set
currentEpisodeChangedListener.forEach { it() }
val mediaSource = HlsMediaSource.Factory(dataSourceFactory).createMediaSource( val mediaSource = HlsMediaSource.Factory(dataSourceFactory).createMediaSource(
MediaItem.fromUri(Uri.parse(preferredStream.url)) MediaItem.fromUri(Uri.parse(currentEpisode.getPreferredStream(currentLanguage).url))
) )
playMedia(mediaSource, replace, seekPosition) playMedia(mediaSource, replace, seekPosition)
// if episodes has not been watched, mark as watched // if episodes has not been watched, mark as watched
if (!episode.watched) { if (!currentEpisode.watched) {
viewModelScope.launch { viewModelScope.launch {
AoDParser.markAsWatched(media.aodId, episode.mediaId) AoDParser.markAsWatched(media.aodId, currentEpisode.mediaId)
} }
} }
} }
@ -198,11 +199,13 @@ class PlayerViewModel(application: Application) : AndroidViewModel(application)
} }
/** /**
* Based on the current episodeId, get the next episode. If there is no next * Based on the current episodes index, get the next episode.
* episode, return null * @return The next episode or null if there is none.
*/ */
private fun selectNextEpisode(): AoDEpisode? { private fun selectNextEpisode(): Int? {
return media.playlist.firstOrNull { it.index > media.getEpisodeById(currentEpisode.mediaId).index } return media.playlist.firstOrNull {
it.index > media.getEpisodeById(currentEpisode.mediaId).index
}?.mediaId
} }
} }

View File

@ -31,7 +31,7 @@ class EpisodesListPlayer @JvmOverloads constructor(
adapterRecEpisodes = PlayerEpisodeItemAdapter(model.media.playlist, model.tmdbTVSeason?.episodes) adapterRecEpisodes = PlayerEpisodeItemAdapter(model.media.playlist, model.tmdbTVSeason?.episodes)
adapterRecEpisodes.onImageClick = { _, position -> adapterRecEpisodes.onImageClick = { _, position ->
(this.parent as ViewGroup).removeView(this) (this.parent as ViewGroup).removeView(this)
model.playEpisode(model.media.playlist[position], replace = true) model.playEpisode(model.media.playlist[position].mediaId, replace = true)
} }
adapterRecEpisodes.currentSelected = model.currentEpisode.index adapterRecEpisodes.currentSelected = model.currentEpisode.index