diff --git a/app/src/main/java/org/mosad/teapod/ui/activity/main/MainActivity.kt b/app/src/main/java/org/mosad/teapod/ui/activity/main/MainActivity.kt index e4003f3..26b4aae 100644 --- a/app/src/main/java/org/mosad/teapod/ui/activity/main/MainActivity.kt +++ b/app/src/main/java/org/mosad/teapod/ui/activity/main/MainActivity.kt @@ -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 */ diff --git a/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/HomeFragment.kt b/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/HomeFragment.kt index a0f3ae4..2ceb9ab 100644 --- a/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/HomeFragment.kt +++ b/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/HomeFragment.kt @@ -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 diff --git a/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/MediaFragment.kt b/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/MediaFragment.kt index c05ba1d..7ebed88 100644 --- a/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/MediaFragment.kt +++ b/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/MediaFragment.kt @@ -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() 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") } /** diff --git a/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/MediaFragmentEpisodes.kt b/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/MediaFragmentEpisodes.kt index 91aeb6d..3e3307d 100644 --- a/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/MediaFragmentEpisodes.kt +++ b/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/MediaFragmentEpisodes.kt @@ -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 - } - } \ No newline at end of file diff --git a/app/src/main/java/org/mosad/teapod/ui/activity/main/viewmodel/HomeViewModel.kt b/app/src/main/java/org/mosad/teapod/ui/activity/main/viewmodel/HomeViewModel.kt index 9b9f483..72ccf1a 100644 --- a/app/src/main/java/org/mosad/teapod/ui/activity/main/viewmodel/HomeViewModel.kt +++ b/app/src/main/java/org/mosad/teapod/ui/activity/main/viewmodel/HomeViewModel.kt @@ -33,6 +33,8 @@ import kotlin.random.Random class HomeViewModel : ViewModel() { + private val WATCHLIST_LENGTH = 50 + private val uiState = MutableStateFlow(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() { } } -} \ No newline at end of file + /** + * 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 + } + } + } + } + +} diff --git a/app/src/main/java/org/mosad/teapod/ui/activity/player/PlayerActivity.kt b/app/src/main/java/org/mosad/teapod/ui/activity/player/PlayerActivity.kt index 48068f4..952ffb0 100644 --- a/app/src/main/java/org/mosad/teapod/ui/activity/player/PlayerActivity.kt +++ b/app/src/main/java/org/mosad/teapod/ui/activity/player/PlayerActivity.kt @@ -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 */ diff --git a/app/src/main/java/org/mosad/teapod/util/ActivityUtils.kt b/app/src/main/java/org/mosad/teapod/util/ActivityUtils.kt index d26fa69..668e7eb 100644 --- a/app/src/main/java/org/mosad/teapod/util/ActivityUtils.kt +++ b/app/src/main/java/org/mosad/teapod/util/ActivityUtils.kt @@ -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 */ diff --git a/app/src/main/java/org/mosad/teapod/util/Utils.kt b/app/src/main/java/org/mosad/teapod/util/Utils.kt index f999fc8..b8f2953 100644 --- a/app/src/main/java/org/mosad/teapod/util/Utils.kt +++ b/app/src/main/java/org/mosad/teapod/util/Utils.kt @@ -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) }