From d73f9882ff1f6cca5904ea9d2a9ad6f467ce0fc7 Mon Sep 17 00:00:00 2001 From: Jannik Date: Fri, 29 Jan 2021 21:55:01 +0100 Subject: [PATCH 1/7] add tab layout to media fragment this is a rough first implementation of the tab layout to switch between episodes and similar titles --- .../teapod/activity/main/MainActivity.kt | 6 + .../main/fragments/MediaEpisodesFragment.kt | 51 +++++++ .../activity/main/fragments/MediaFragment.kt | 124 +++++++++--------- .../main/fragments/MediaFragmentViewModel.kt | 63 +++++++++ .../main/fragments/MediaSimilarFragment.kt | 18 +++ .../activity/onboarding/OnboardingActivity.kt | 3 +- .../java/org/mosad/teapod/parser/AoDParser.kt | 2 +- app/src/main/res/layout/fragment_media.xml | 21 ++- .../res/layout/fragment_media_episodes.xml | 20 +++ .../res/layout/fragment_media_similar.xml | 18 +++ app/src/main/res/values-de-rDE/strings.xml | 1 + app/src/main/res/values/strings.xml | 1 + 12 files changed, 254 insertions(+), 74 deletions(-) create mode 100644 app/src/main/java/org/mosad/teapod/activity/main/fragments/MediaEpisodesFragment.kt create mode 100644 app/src/main/java/org/mosad/teapod/activity/main/fragments/MediaFragmentViewModel.kt create mode 100644 app/src/main/java/org/mosad/teapod/activity/main/fragments/MediaSimilarFragment.kt create mode 100644 app/src/main/res/layout/fragment_media_episodes.xml create mode 100644 app/src/main/res/layout/fragment_media_similar.xml diff --git a/app/src/main/java/org/mosad/teapod/activity/main/MainActivity.kt b/app/src/main/java/org/mosad/teapod/activity/main/MainActivity.kt index c22a68b..1bd5b6d 100644 --- a/app/src/main/java/org/mosad/teapod/activity/main/MainActivity.kt +++ b/app/src/main/java/org/mosad/teapod/activity/main/MainActivity.kt @@ -31,6 +31,7 @@ import androidx.fragment.app.Fragment import androidx.fragment.app.commit import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.callbacks.onDismiss +import com.afollestad.materialdialogs.utils.MDUtil.isLandscape import com.google.android.material.bottomnavigation.BottomNavigationView import kotlinx.coroutines.joinAll import kotlinx.coroutines.runBlocking @@ -60,6 +61,11 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS companion object { var wasInitialized = false + lateinit var instance: MainActivity + } + + init { + instance = this } override fun onCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/java/org/mosad/teapod/activity/main/fragments/MediaEpisodesFragment.kt b/app/src/main/java/org/mosad/teapod/activity/main/fragments/MediaEpisodesFragment.kt new file mode 100644 index 0000000..9bbd93b --- /dev/null +++ b/app/src/main/java/org/mosad/teapod/activity/main/fragments/MediaEpisodesFragment.kt @@ -0,0 +1,51 @@ +package org.mosad.teapod.activity.main.fragments + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import androidx.fragment.app.activityViewModels +import org.mosad.teapod.databinding.FragmentMediaEpisodesBinding +import org.mosad.teapod.util.adapter.EpisodeItemAdapter + +class MediaEpisodesFragment : Fragment() { + + private lateinit var binding: FragmentMediaEpisodesBinding + private lateinit var adapterRecEpisodes: EpisodeItemAdapter + + private val model: MediaFragmentViewModel by activityViewModels() + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { + binding = FragmentMediaEpisodesBinding.inflate(inflater, container, false) + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + adapterRecEpisodes = EpisodeItemAdapter(model.media.episodes) + binding.recyclerEpisodes.adapter = adapterRecEpisodes + + println(model.media.episodes) + + // set onItemClick only in adapter is initialized + if (this::adapterRecEpisodes.isInitialized) { + adapterRecEpisodes.onImageClick = { _, position -> + model.playEpisode(model.media.episodes[position]) + } + } + } + + override fun onResume() { + super.onResume() + + if (this::adapterRecEpisodes.isInitialized) { + model.media.episodes.forEachIndexed { index, episode -> + adapterRecEpisodes.updateWatchedState(episode.watched, index) + } + adapterRecEpisodes.notifyDataSetChanged() + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/org/mosad/teapod/activity/main/fragments/MediaFragment.kt b/app/src/main/java/org/mosad/teapod/activity/main/fragments/MediaFragment.kt index ed3f42f..248d710 100644 --- a/app/src/main/java/org/mosad/teapod/activity/main/fragments/MediaFragment.kt +++ b/app/src/main/java/org/mosad/teapod/activity/main/fragments/MediaFragment.kt @@ -8,26 +8,30 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment +import androidx.fragment.app.FragmentActivity +import androidx.fragment.app.activityViewModels +import androidx.viewpager2.adapter.FragmentStateAdapter import com.bumptech.glide.Glide import com.bumptech.glide.request.RequestOptions +import com.google.android.material.tabs.TabLayoutMediator import jp.wasabeef.glide.transformations.BlurTransformation import kotlinx.coroutines.* import org.mosad.teapod.R -import org.mosad.teapod.activity.main.MainActivity import org.mosad.teapod.databinding.FragmentMediaBinding -import org.mosad.teapod.parser.AoDParser import org.mosad.teapod.util.* import org.mosad.teapod.util.DataTypes.MediaType -import org.mosad.teapod.util.adapter.EpisodeItemAdapter +/** + * TODO use a shared ViewModel for MediaFragment and it's sibling Fragments (episodes and similar) + */ class MediaFragment(private val mediaId: Int) : Fragment() { private lateinit var binding: FragmentMediaBinding - private lateinit var adapterRecEpisodes: EpisodeItemAdapter + private lateinit var pagerAdapter: FragmentStateAdapter - private lateinit var media: Media - private lateinit var tmdb: TMDBResponse - private lateinit var nextEpisode: Episode + private val fragments = arrayListOf() + + private val model: MediaFragmentViewModel by activityViewModels() override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { binding = FragmentMediaBinding.inflate(inflater, container, false) @@ -38,10 +42,19 @@ class MediaFragment(private val mediaId: Int) : Fragment() { super.onViewCreated(view, savedInstanceState) binding.frameLoading.visibility = View.VISIBLE + // tab layout and pager TODO + pagerAdapter = ScreenSlidePagerAdapter(requireActivity()) + binding.pagerEpisodesSimilar.adapter = pagerAdapter + TabLayoutMediator(binding.tabEpisodesSimilar, binding.pagerEpisodesSimilar) { tab, position -> + tab.text = if (model.media.type == MediaType.TVSHOW && position == 0) { + getString(R.string.episodes) + } else { + getString(R.string.similar_titles) + } + }.attach() + GlobalScope.launch(Dispatchers.Main) { - // load the streams for the selected media - media = AoDParser.getMediaById(mediaId) - tmdb = TMDBApiController().search(media.info.title, media.type) + model.load(mediaId) // load the streams and tmdb for the selected media if (this@MediaFragment.isAdded) { updateGUI() @@ -53,20 +66,14 @@ class MediaFragment(private val mediaId: Int) : Fragment() { override fun onResume() { super.onResume() - // only notify adapter, if initialized - if (this::adapterRecEpisodes.isInitialized) { - // TODO find a better solution for this - media.episodes.forEachIndexed { index, episode -> - adapterRecEpisodes.updateWatchedState(episode.watched, index) - } - adapterRecEpisodes.notifyDataSetChanged() - } + // update the next ep text, since it may have changed + binding.textTitle.text = model.nextEpisode.title } /** * if tmdb data is present, use it, else use the aod data */ - private fun updateGUI() = with(binding) { + private fun updateGUI() = with(model) { // generic gui val backdropUrl = if (tmdb.backdropUrl.isNotEmpty()) tmdb.backdropUrl else media.info.posterUrl val posterUrl = if (tmdb.posterUrl.isNotEmpty()) tmdb.posterUrl else media.info.posterUrl @@ -74,33 +81,23 @@ class MediaFragment(private val mediaId: Int) : Fragment() { Glide.with(requireContext()).load(backdropUrl) .apply(RequestOptions.placeholderOf(ColorDrawable(Color.DKGRAY))) .apply(RequestOptions.bitmapTransform(BlurTransformation(20, 3))) - .into(imageBackdrop) + .into(binding.imageBackdrop) Glide.with(requireContext()).load(posterUrl) - .into(imagePoster) + .into(binding.imagePoster) - textTitle.text = media.info.title - textYear.text = media.info.year.toString() - textAge.text = media.info.age.toString() - textOverview.text = media.info.shortDesc + binding.textTitle.text = media.info.title + binding.textYear.text = media.info.year.toString() + binding.textAge.text = media.info.age.toString() + binding.textOverview.text = media.info.shortDesc if (StorageController.myList.contains(media.id)) { - Glide.with(requireContext()).load(R.drawable.ic_baseline_check_24).into(imageMyListAction) + Glide.with(requireContext()).load(R.drawable.ic_baseline_check_24).into(binding.imageMyListAction) } else { - Glide.with(requireContext()).load(R.drawable.ic_baseline_add_24).into(imageMyListAction) + Glide.with(requireContext()).load(R.drawable.ic_baseline_add_24).into(binding.imageMyListAction) } // specific gui if (media.type == MediaType.TVSHOW) { - adapterRecEpisodes = EpisodeItemAdapter(media.episodes) - recyclerEpisodes.adapter = adapterRecEpisodes - - // episodes count - binding.textEpisodesOrRuntime.text = resources.getQuantityString( - R.plurals.text_episodes_count, - media.info.episodesCount, - media.info.episodesCount - ) - // get next episode nextEpisode = if (media.episodes.firstOrNull{ !it.watched } != null) { media.episodes.first{ !it.watched } @@ -109,25 +106,39 @@ class MediaFragment(private val mediaId: Int) : Fragment() { } // title is the next episodes title - textTitle.text = nextEpisode.title + binding.textTitle.text = nextEpisode.title + + // episodes count + binding.textEpisodesOrRuntime.text = resources.getQuantityString( + R.plurals.text_episodes_count, + media.info.episodesCount, + media.info.episodesCount + ) + + // episodes + fragments.add(MediaEpisodesFragment()) + pagerAdapter.notifyDataSetChanged() } else if (media.type == MediaType.MOVIE) { - recyclerEpisodes.visibility = View.GONE if (tmdb.runtime > 0) { - textEpisodesOrRuntime.text = resources.getQuantityString( + binding.textEpisodesOrRuntime.text = resources.getQuantityString( R.plurals.text_runtime, tmdb.runtime, tmdb.runtime ) } else { - textEpisodesOrRuntime.visibility = View.GONE + binding.textEpisodesOrRuntime.visibility = View.GONE } } - frameLoading.visibility = View.GONE // hide loading indicator + // if has similar titles + fragments.add(MediaSimilarFragment()) + pagerAdapter.notifyDataSetChanged() + + binding.frameLoading.visibility = View.GONE // hide loading indicator } - private fun initActions() { + private fun initActions() = with(model) { binding.buttonPlay.setOnClickListener { when (media.type) { MediaType.MOVIE -> playStream(media.episodes.first()) @@ -152,30 +163,15 @@ class MediaFragment(private val mediaId: Int) : Fragment() { (it as HomeFragment).updateMyListMedia() } } - - // set onItemClick only in adapter is initialized - if (this::adapterRecEpisodes.isInitialized) { - adapterRecEpisodes.onImageClick = { _, position -> - playEpisode(media.episodes[position]) - } - } } - private fun playEpisode(ep: Episode) { - playStream(ep) + /** + * A simple pager adapter + */ + private inner class ScreenSlidePagerAdapter(fa: FragmentActivity) : FragmentStateAdapter(fa) { + override fun getItemCount(): Int = fragments.size - // update nextEpisode - nextEpisode = if (media.episodes.firstOrNull{ !it.watched } != null) { - media.episodes.first{ !it.watched } - } else { - media.episodes.first() - } - binding.textTitle.text = nextEpisode.title - } - - private fun playStream(ep: Episode) { - Log.d(javaClass.name, "Starting Player with mediaId: ${media.id}") - (activity as MainActivity).startPlayer(media.id, ep.id) + override fun createFragment(position: Int): Fragment = fragments[position] } } \ No newline at end of file diff --git a/app/src/main/java/org/mosad/teapod/activity/main/fragments/MediaFragmentViewModel.kt b/app/src/main/java/org/mosad/teapod/activity/main/fragments/MediaFragmentViewModel.kt new file mode 100644 index 0000000..57cb71c --- /dev/null +++ b/app/src/main/java/org/mosad/teapod/activity/main/fragments/MediaFragmentViewModel.kt @@ -0,0 +1,63 @@ +package org.mosad.teapod.activity.main.fragments + +import android.app.Application +import android.util.Log +import androidx.lifecycle.AndroidViewModel +import org.mosad.teapod.activity.main.MainActivity +import org.mosad.teapod.parser.AoDParser +import org.mosad.teapod.util.* + +class MediaFragmentViewModel(application: Application) : AndroidViewModel(application) { + + var media = Media(-1, "", DataTypes.MediaType.OTHER) + internal set + var nextEpisode = Episode() + internal set + var tmdb = TMDBResponse() + internal set + + suspend fun load(mediaId: Int) { + media = AoDParser.getMediaById(mediaId) + tmdb = TMDBApiController().search(media.info.title, media.type) + + if (media.type == DataTypes.MediaType.TVSHOW) { + nextEpisode = if (media.episodes.firstOrNull{ !it.watched } != null) { + media.episodes.first{ !it.watched } + } else { + media.episodes.first() + } + } + } + + fun playEpisode(ep: Episode) { + playStream(ep) + + // update nextEpisode + val currentEpNumber = nextEpisode.number + nextEpisode = if (media.episodes.firstOrNull{ !it.watched } != null) { + media.episodes.first{ !it.watched && it.number > currentEpNumber } + } else { + media.episodes.first() + } + } + + fun playStream(ep: Episode) { + Log.d(javaClass.name, "Starting Player with mediaId: ${media.id}") + + // TODO somehow start the player ... + MainActivity.instance.startPlayer(media.id, ep.id) // this is just a workaround! + + // not working TODO once thsi is solved, use ViewModel instead of AndroidViewModel +// with(getApplication().baseContext) { +// val intent = Intent(this, PlayerActivity::class.java).apply { +// putExtra(getString(R.string.intent_media_id), media.id) +// putExtra(getString(R.string.intent_episode_id), ep.id) +// addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) +// } +// startActivity(intent) +// } + + //(activity as MainActivity).startPlayer(media.id, ep.id) + } + +} \ No newline at end of file diff --git a/app/src/main/java/org/mosad/teapod/activity/main/fragments/MediaSimilarFragment.kt b/app/src/main/java/org/mosad/teapod/activity/main/fragments/MediaSimilarFragment.kt new file mode 100644 index 0000000..8927642 --- /dev/null +++ b/app/src/main/java/org/mosad/teapod/activity/main/fragments/MediaSimilarFragment.kt @@ -0,0 +1,18 @@ +package org.mosad.teapod.activity.main.fragments + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import org.mosad.teapod.databinding.FragmentMediaSimilarBinding + +class MediaSimilarFragment : Fragment() { + + private lateinit var binding: FragmentMediaSimilarBinding + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { + binding = FragmentMediaSimilarBinding.inflate(inflater, container, false) + return binding.root + } +} \ No newline at end of file diff --git a/app/src/main/java/org/mosad/teapod/activity/onboarding/OnboardingActivity.kt b/app/src/main/java/org/mosad/teapod/activity/onboarding/OnboardingActivity.kt index 4493b82..3c4488b 100644 --- a/app/src/main/java/org/mosad/teapod/activity/onboarding/OnboardingActivity.kt +++ b/app/src/main/java/org/mosad/teapod/activity/onboarding/OnboardingActivity.kt @@ -67,8 +67,7 @@ class OnboardingActivity : AppCompatActivity() { } /** - * A simple pager adapter that represents 5 ScreenSlidePageFragment objects, in - * sequence. + * A simple pager adapter */ private inner class ScreenSlidePagerAdapter(fa: FragmentActivity) : FragmentStateAdapter(fa) { override fun getItemCount(): Int = fragments.size diff --git a/app/src/main/java/org/mosad/teapod/parser/AoDParser.kt b/app/src/main/java/org/mosad/teapod/parser/AoDParser.kt index 217708d..2362d9d 100644 --- a/app/src/main/java/org/mosad/teapod/parser/AoDParser.kt +++ b/app/src/main/java/org/mosad/teapod/parser/AoDParser.kt @@ -41,7 +41,7 @@ object AoDParser { private const val loginPath = "/users/sign_in" private const val libraryPath = "/animes" - private const val userAgent = "Mozilla/5.0 (X11; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.0" + private const val userAgent = "Mozilla/5.0 (X11; Linux x86_64; rv:84.0) Gecko/20100101 Firefox/84.0" private var sessionCookies = mutableMapOf() private var csrfToken: String = "" diff --git a/app/src/main/res/layout/fragment_media.xml b/app/src/main/res/layout/fragment_media.xml index ff4d7ad..ce972b9 100644 --- a/app/src/main/res/layout/fragment_media.xml +++ b/app/src/main/res/layout/fragment_media.xml @@ -148,17 +148,24 @@ - + app:tabMode="scrollable" + app:tabGravity="start" + app:tabSelectedTextColor="?textPrimary" + app:tabTextColor="?textSecondary" /> + + + diff --git a/app/src/main/res/layout/fragment_media_episodes.xml b/app/src/main/res/layout/fragment_media_episodes.xml new file mode 100644 index 0000000..21453fc --- /dev/null +++ b/app/src/main/res/layout/fragment_media_episodes.xml @@ -0,0 +1,20 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_media_similar.xml b/app/src/main/res/layout/fragment_media_similar.xml new file mode 100644 index 0000000..e3e23a0 --- /dev/null +++ b/app/src/main/res/layout/fragment_media_similar.xml @@ -0,0 +1,18 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/values-de-rDE/strings.xml b/app/src/main/res/values-de-rDE/strings.xml index d710961..c958865 100644 --- a/app/src/main/res/values-de-rDE/strings.xml +++ b/app/src/main/res/values-de-rDE/strings.xml @@ -27,6 +27,7 @@ %d Minute %d Minuten + Ähnliche Titel Flg. %1$d %2$s Flg. %1$d %2$s (OmU) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1c6411c..fe2da5e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -34,6 +34,7 @@ %d Minute %d Minutes + Similar titles Ep. %1$d %2$s Ep. %1$d %2$s (Sub) episode poster -- 2.44.0 From f44dc4ddac829e9dbf0d9fedeab119694e8394c8 Mon Sep 17 00:00:00 2001 From: Jannik Date: Sun, 31 Jan 2021 21:05:43 +0100 Subject: [PATCH 2/7] move startPlayer() call to the fragment --- .../activity/main/fragments/MediaFragment.kt | 17 ++++- ...esFragment.kt => MediaFragmentEpisodes.kt} | 18 ++++-- .../main/fragments/MediaFragmentViewModel.kt | 63 ------------------- .../main/viewmodel/MediaFragmentViewModel.kt | 49 +++++++++++++++ 4 files changed, 78 insertions(+), 69 deletions(-) rename app/src/main/java/org/mosad/teapod/activity/main/fragments/{MediaEpisodesFragment.kt => MediaFragmentEpisodes.kt} (71%) delete mode 100644 app/src/main/java/org/mosad/teapod/activity/main/fragments/MediaFragmentViewModel.kt create mode 100644 app/src/main/java/org/mosad/teapod/activity/main/viewmodel/MediaFragmentViewModel.kt diff --git a/app/src/main/java/org/mosad/teapod/activity/main/fragments/MediaFragment.kt b/app/src/main/java/org/mosad/teapod/activity/main/fragments/MediaFragment.kt index 248d710..6fda407 100644 --- a/app/src/main/java/org/mosad/teapod/activity/main/fragments/MediaFragment.kt +++ b/app/src/main/java/org/mosad/teapod/activity/main/fragments/MediaFragment.kt @@ -17,6 +17,8 @@ import com.google.android.material.tabs.TabLayoutMediator import jp.wasabeef.glide.transformations.BlurTransformation import kotlinx.coroutines.* import org.mosad.teapod.R +import org.mosad.teapod.activity.main.MainActivity +import org.mosad.teapod.activity.main.viewmodel.MediaFragmentViewModel import org.mosad.teapod.databinding.FragmentMediaBinding import org.mosad.teapod.util.* import org.mosad.teapod.util.DataTypes.MediaType @@ -116,7 +118,7 @@ class MediaFragment(private val mediaId: Int) : Fragment() { ) // episodes - fragments.add(MediaEpisodesFragment()) + fragments.add(MediaFragmentEpisodes()) pagerAdapter.notifyDataSetChanged() } else if (media.type == MediaType.MOVIE) { @@ -141,7 +143,7 @@ class MediaFragment(private val mediaId: Int) : Fragment() { private fun initActions() = with(model) { binding.buttonPlay.setOnClickListener { when (media.type) { - MediaType.MOVIE -> playStream(media.episodes.first()) + MediaType.MOVIE -> playEpisode(media.episodes.first()) MediaType.TVSHOW -> playEpisode(nextEpisode) else -> Log.e(javaClass.name, "Wrong Type: $media.type") } @@ -165,6 +167,17 @@ class MediaFragment(private val mediaId: Int) : Fragment() { } } + /** + * play the current episode + * TODO this is also used in MediaFragmentEpisode, we should only have on implementation + */ + private fun playEpisode(ep: Episode) { + (activity as MainActivity).startPlayer(model.media.id, ep.id) + Log.d(javaClass.name, "Started Player with episodeId: ${ep.id}") + + model.updateNextEpisode() // set the correct next episode + } + /** * A simple pager adapter */ diff --git a/app/src/main/java/org/mosad/teapod/activity/main/fragments/MediaEpisodesFragment.kt b/app/src/main/java/org/mosad/teapod/activity/main/fragments/MediaFragmentEpisodes.kt similarity index 71% rename from app/src/main/java/org/mosad/teapod/activity/main/fragments/MediaEpisodesFragment.kt rename to app/src/main/java/org/mosad/teapod/activity/main/fragments/MediaFragmentEpisodes.kt index 9bbd93b..d16a50e 100644 --- a/app/src/main/java/org/mosad/teapod/activity/main/fragments/MediaEpisodesFragment.kt +++ b/app/src/main/java/org/mosad/teapod/activity/main/fragments/MediaFragmentEpisodes.kt @@ -1,15 +1,19 @@ package org.mosad.teapod.activity.main.fragments import android.os.Bundle +import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels +import org.mosad.teapod.activity.main.MainActivity +import org.mosad.teapod.activity.main.viewmodel.MediaFragmentViewModel import org.mosad.teapod.databinding.FragmentMediaEpisodesBinding +import org.mosad.teapod.util.Episode import org.mosad.teapod.util.adapter.EpisodeItemAdapter -class MediaEpisodesFragment : Fragment() { +class MediaFragmentEpisodes : Fragment() { private lateinit var binding: FragmentMediaEpisodesBinding private lateinit var adapterRecEpisodes: EpisodeItemAdapter @@ -27,12 +31,10 @@ class MediaEpisodesFragment : Fragment() { adapterRecEpisodes = EpisodeItemAdapter(model.media.episodes) binding.recyclerEpisodes.adapter = adapterRecEpisodes - println(model.media.episodes) - // set onItemClick only in adapter is initialized if (this::adapterRecEpisodes.isInitialized) { adapterRecEpisodes.onImageClick = { _, position -> - model.playEpisode(model.media.episodes[position]) + playEpisode(model.media.episodes[position]) } } } @@ -40,6 +42,7 @@ class MediaEpisodesFragment : Fragment() { override fun onResume() { super.onResume() + // if adapterRecEpisodes is initialized, update the watched state for the episodes if (this::adapterRecEpisodes.isInitialized) { model.media.episodes.forEachIndexed { index, episode -> adapterRecEpisodes.updateWatchedState(episode.watched, index) @@ -48,4 +51,11 @@ class MediaEpisodesFragment : Fragment() { } } + private fun playEpisode(ep: Episode) { + (activity as MainActivity).startPlayer(model.media.id, ep.id) + Log.d(javaClass.name, "Started Player with episodeId: ${ep.id}") + + model.updateNextEpisode() // set the correct next episode + } + } \ No newline at end of file diff --git a/app/src/main/java/org/mosad/teapod/activity/main/fragments/MediaFragmentViewModel.kt b/app/src/main/java/org/mosad/teapod/activity/main/fragments/MediaFragmentViewModel.kt deleted file mode 100644 index 57cb71c..0000000 --- a/app/src/main/java/org/mosad/teapod/activity/main/fragments/MediaFragmentViewModel.kt +++ /dev/null @@ -1,63 +0,0 @@ -package org.mosad.teapod.activity.main.fragments - -import android.app.Application -import android.util.Log -import androidx.lifecycle.AndroidViewModel -import org.mosad.teapod.activity.main.MainActivity -import org.mosad.teapod.parser.AoDParser -import org.mosad.teapod.util.* - -class MediaFragmentViewModel(application: Application) : AndroidViewModel(application) { - - var media = Media(-1, "", DataTypes.MediaType.OTHER) - internal set - var nextEpisode = Episode() - internal set - var tmdb = TMDBResponse() - internal set - - suspend fun load(mediaId: Int) { - media = AoDParser.getMediaById(mediaId) - tmdb = TMDBApiController().search(media.info.title, media.type) - - if (media.type == DataTypes.MediaType.TVSHOW) { - nextEpisode = if (media.episodes.firstOrNull{ !it.watched } != null) { - media.episodes.first{ !it.watched } - } else { - media.episodes.first() - } - } - } - - fun playEpisode(ep: Episode) { - playStream(ep) - - // update nextEpisode - val currentEpNumber = nextEpisode.number - nextEpisode = if (media.episodes.firstOrNull{ !it.watched } != null) { - media.episodes.first{ !it.watched && it.number > currentEpNumber } - } else { - media.episodes.first() - } - } - - fun playStream(ep: Episode) { - Log.d(javaClass.name, "Starting Player with mediaId: ${media.id}") - - // TODO somehow start the player ... - MainActivity.instance.startPlayer(media.id, ep.id) // this is just a workaround! - - // not working TODO once thsi is solved, use ViewModel instead of AndroidViewModel -// with(getApplication().baseContext) { -// val intent = Intent(this, PlayerActivity::class.java).apply { -// putExtra(getString(R.string.intent_media_id), media.id) -// putExtra(getString(R.string.intent_episode_id), ep.id) -// addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) -// } -// startActivity(intent) -// } - - //(activity as MainActivity).startPlayer(media.id, ep.id) - } - -} \ No newline at end of file diff --git a/app/src/main/java/org/mosad/teapod/activity/main/viewmodel/MediaFragmentViewModel.kt b/app/src/main/java/org/mosad/teapod/activity/main/viewmodel/MediaFragmentViewModel.kt new file mode 100644 index 0000000..9352049 --- /dev/null +++ b/app/src/main/java/org/mosad/teapod/activity/main/viewmodel/MediaFragmentViewModel.kt @@ -0,0 +1,49 @@ +package org.mosad.teapod.activity.main.viewmodel + +import android.app.Application +import androidx.lifecycle.AndroidViewModel +import org.mosad.teapod.parser.AoDParser +import org.mosad.teapod.util.* +import org.mosad.teapod.util.DataTypes.MediaType + +/** + * handle media, next ep and tmdb + */ +class MediaFragmentViewModel(application: Application) : AndroidViewModel(application) { + + var media = Media(-1, "", MediaType.OTHER) + internal set + var nextEpisode = Episode() + internal set + var tmdb = TMDBResponse() + internal set + + suspend fun load(mediaId: Int) { + media = AoDParser.getMediaById(mediaId) + tmdb = TMDBApiController().search(media.info.title, media.type) + + if (media.type == MediaType.TVSHOW) { + nextEpisode = if (media.episodes.firstOrNull{ !it.watched } != null) { + media.episodes.first{ !it.watched } + } else { + media.episodes.first() + } + } + } + + /** + * based on watched state and current episode number set the next episode + * if no matching is found, use first episode + */ + fun updateNextEpisode() { + if (media.type == MediaType.MOVIE) return // return if movie + + val currentEpNumber = nextEpisode.number + nextEpisode = if (media.episodes.firstOrNull{ !it.watched } != null) { + media.episodes.first{ !it.watched && it.number > currentEpNumber } + } else { + media.episodes.first() + } + } + +} \ No newline at end of file -- 2.44.0 From a21ef195c9e067757fa0db7df3f3578097633e36 Mon Sep 17 00:00:00 2001 From: Jannik Date: Sun, 31 Jan 2021 22:11:08 +0100 Subject: [PATCH 3/7] add similar media to MediaFragment * parse similar media in AoDParser --- app/src/main/AndroidManifest.xml | 10 ++--- .../main/fragments/MediaSimilarFragment.kt | 18 --------- .../java/org/mosad/teapod/parser/AoDParser.kt | 18 ++++++++- .../{ => ui}/activity/SplashActivity.kt | 4 +- .../{ => ui}/activity/main/MainActivity.kt | 16 ++++---- .../activity/main/fragments/AboutFragment.kt | 2 +- .../main/fragments/AccountFragment.kt | 4 +- .../activity/main/fragments/HomeFragment.kt | 4 +- .../main/fragments/LibraryFragment.kt | 3 +- .../activity/main/fragments/MediaFragment.kt | 20 +++++++--- .../main/fragments/MediaFragmentEpisodes.kt | 6 +-- .../main/fragments/MediaFragmentSimilar.kt | 39 +++++++++++++++++++ .../activity/main/fragments/SearchFragment.kt | 3 +- .../main/viewmodel/MediaFragmentViewModel.kt | 5 ++- .../activity/onboarding/OnLoginFragment.kt | 2 +- .../activity/onboarding/OnWelcomeFragment.kt | 2 +- .../activity/onboarding/OnboardingActivity.kt | 4 +- .../activity/player/PlayerActivity.kt | 2 +- .../activity/player/PlayerViewModel.kt | 2 +- .../ui/components/EpisodesListPlayer.kt | 2 +- .../ui/components/LanguageSettingsPlayer.kt | 2 +- .../java/org/mosad/teapod/util/DataTypes.kt | 3 +- app/src/main/res/layout/activity_player.xml | 2 +- app/src/main/res/layout/fragment_about.xml | 2 +- app/src/main/res/layout/fragment_account.xml | 2 +- app/src/main/res/layout/fragment_home.xml | 2 +- app/src/main/res/layout/fragment_library.xml | 2 +- app/src/main/res/layout/fragment_media.xml | 2 +- .../res/layout/fragment_media_similar.xml | 23 +++++++---- app/src/main/res/layout/fragment_search.xml | 2 +- .../main/res/navigation/mobile_navigation.xml | 8 ++-- 31 files changed, 133 insertions(+), 83 deletions(-) delete mode 100644 app/src/main/java/org/mosad/teapod/activity/main/fragments/MediaSimilarFragment.kt rename app/src/main/java/org/mosad/teapod/{ => ui}/activity/SplashActivity.kt (80%) rename app/src/main/java/org/mosad/teapod/{ => ui}/activity/main/MainActivity.kt (93%) rename app/src/main/java/org/mosad/teapod/{ => ui}/activity/main/fragments/AboutFragment.kt (98%) rename app/src/main/java/org/mosad/teapod/{ => ui}/activity/main/fragments/AccountFragment.kt (97%) rename app/src/main/java/org/mosad/teapod/{ => ui}/activity/main/fragments/HomeFragment.kt (98%) rename app/src/main/java/org/mosad/teapod/{ => ui}/activity/main/fragments/LibraryFragment.kt (94%) rename app/src/main/java/org/mosad/teapod/{ => ui}/activity/main/fragments/MediaFragment.kt (91%) rename app/src/main/java/org/mosad/teapod/{ => ui}/activity/main/fragments/MediaFragmentEpisodes.kt (92%) create mode 100644 app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/MediaFragmentSimilar.kt rename app/src/main/java/org/mosad/teapod/{ => ui}/activity/main/fragments/SearchFragment.kt (95%) rename app/src/main/java/org/mosad/teapod/{ => ui}/activity/main/viewmodel/MediaFragmentViewModel.kt (93%) rename app/src/main/java/org/mosad/teapod/{ => ui}/activity/onboarding/OnLoginFragment.kt (97%) rename app/src/main/java/org/mosad/teapod/{ => ui}/activity/onboarding/OnWelcomeFragment.kt (95%) rename app/src/main/java/org/mosad/teapod/{ => ui}/activity/onboarding/OnboardingActivity.kt (95%) rename app/src/main/java/org/mosad/teapod/{ => ui}/activity/player/PlayerActivity.kt (99%) rename app/src/main/java/org/mosad/teapod/{ => ui}/activity/player/PlayerViewModel.kt (99%) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 11b032f..794a418 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -13,7 +13,7 @@ android:supportsRtl="true" android:theme="@style/AppTheme.Dark"> @@ -23,24 +23,24 @@ when (row.select("th").text().toLowerCase(Locale.ROOT)) { "produktionsjahr" -> media.info.year = row.select("td").text().toInt() @@ -337,7 +337,21 @@ object AoDParser { } } - // parse additional information for tv shows the episode title (description) is loaded from the "api" + // similar titles from media page + media.info.similar = res.select("h2:contains(Ähnliche Animes)").next().select("li").mapNotNull { + val mediaId = it.select("a.thumbs").attr("href") + .substringAfterLast("/").toIntOrNull() + val mediaImage = it.select("a.thumbs > img").attr("src") + val mediaTitle = it.select("a").text() + + if (mediaId != null) { + ItemMedia(mediaId, mediaTitle, mediaImage) + } else { + null + } + } + + // additional information for tv shows the episode title (description) is loaded from the "api" if (media.type == MediaType.TVSHOW) { res.select("div.three-box-container > div.episodebox").forEach { episodebox -> // make sure the episode has a streaming link diff --git a/app/src/main/java/org/mosad/teapod/activity/SplashActivity.kt b/app/src/main/java/org/mosad/teapod/ui/activity/SplashActivity.kt similarity index 80% rename from app/src/main/java/org/mosad/teapod/activity/SplashActivity.kt rename to app/src/main/java/org/mosad/teapod/ui/activity/SplashActivity.kt index 39b6744..c7dfa49 100644 --- a/app/src/main/java/org/mosad/teapod/activity/SplashActivity.kt +++ b/app/src/main/java/org/mosad/teapod/ui/activity/SplashActivity.kt @@ -1,9 +1,9 @@ -package org.mosad.teapod.activity +package org.mosad.teapod.ui.activity import android.content.Intent import android.os.Bundle import androidx.appcompat.app.AppCompatActivity -import org.mosad.teapod.activity.main.MainActivity +import org.mosad.teapod.ui.activity.main.MainActivity class SplashActivity : AppCompatActivity() { diff --git a/app/src/main/java/org/mosad/teapod/activity/main/MainActivity.kt b/app/src/main/java/org/mosad/teapod/ui/activity/main/MainActivity.kt similarity index 93% rename from app/src/main/java/org/mosad/teapod/activity/main/MainActivity.kt rename to app/src/main/java/org/mosad/teapod/ui/activity/main/MainActivity.kt index 1bd5b6d..19dd297 100644 --- a/app/src/main/java/org/mosad/teapod/activity/main/MainActivity.kt +++ b/app/src/main/java/org/mosad/teapod/ui/activity/main/MainActivity.kt @@ -20,7 +20,7 @@ * */ -package org.mosad.teapod.activity.main +package org.mosad.teapod.ui.activity.main import android.content.Intent import android.os.Bundle @@ -31,27 +31,25 @@ import androidx.fragment.app.Fragment import androidx.fragment.app.commit import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.callbacks.onDismiss -import com.afollestad.materialdialogs.utils.MDUtil.isLandscape import com.google.android.material.bottomnavigation.BottomNavigationView import kotlinx.coroutines.joinAll import kotlinx.coroutines.runBlocking import org.mosad.teapod.R import org.mosad.teapod.databinding.ActivityMainBinding import org.mosad.teapod.parser.AoDParser -import org.mosad.teapod.activity.player.PlayerActivity +import org.mosad.teapod.ui.activity.player.PlayerActivity import org.mosad.teapod.preferences.EncryptedPreferences import org.mosad.teapod.preferences.Preferences import org.mosad.teapod.ui.components.LoginDialog -import org.mosad.teapod.activity.main.fragments.AccountFragment -import org.mosad.teapod.activity.main.fragments.HomeFragment -import org.mosad.teapod.activity.main.fragments.LibraryFragment -import org.mosad.teapod.activity.main.fragments.SearchFragment -import org.mosad.teapod.activity.onboarding.OnboardingActivity +import org.mosad.teapod.ui.activity.main.fragments.AccountFragment +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.util.DataTypes import org.mosad.teapod.util.StorageController import org.mosad.teapod.util.exitAndRemoveTask import java.net.SocketTimeoutException -import kotlin.system.exitProcess import kotlin.system.measureTimeMillis class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemSelectedListener { diff --git a/app/src/main/java/org/mosad/teapod/activity/main/fragments/AboutFragment.kt b/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/AboutFragment.kt similarity index 98% rename from app/src/main/java/org/mosad/teapod/activity/main/fragments/AboutFragment.kt rename to app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/AboutFragment.kt index ddba535..a30d129 100644 --- a/app/src/main/java/org/mosad/teapod/activity/main/fragments/AboutFragment.kt +++ b/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/AboutFragment.kt @@ -1,4 +1,4 @@ -package org.mosad.teapod.activity.main.fragments +package org.mosad.teapod.ui.activity.main.fragments import android.content.Intent import android.net.Uri diff --git a/app/src/main/java/org/mosad/teapod/activity/main/fragments/AccountFragment.kt b/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/AccountFragment.kt similarity index 97% rename from app/src/main/java/org/mosad/teapod/activity/main/fragments/AccountFragment.kt rename to app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/AccountFragment.kt index 1561b1c..61ca637 100644 --- a/app/src/main/java/org/mosad/teapod/activity/main/fragments/AccountFragment.kt +++ b/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/AccountFragment.kt @@ -1,4 +1,4 @@ -package org.mosad.teapod.activity.main.fragments +package org.mosad.teapod.ui.activity.main.fragments import android.os.Bundle import android.util.Log @@ -9,7 +9,7 @@ import androidx.fragment.app.Fragment import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.list.listItemsSingleChoice import org.mosad.teapod.BuildConfig -import org.mosad.teapod.activity.main.MainActivity +import org.mosad.teapod.ui.activity.main.MainActivity import org.mosad.teapod.R import org.mosad.teapod.databinding.FragmentAccountBinding import org.mosad.teapod.parser.AoDParser diff --git a/app/src/main/java/org/mosad/teapod/activity/main/fragments/HomeFragment.kt b/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/HomeFragment.kt similarity index 98% rename from app/src/main/java/org/mosad/teapod/activity/main/fragments/HomeFragment.kt rename to app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/HomeFragment.kt index cf0fc0f..6e19d11 100644 --- a/app/src/main/java/org/mosad/teapod/activity/main/fragments/HomeFragment.kt +++ b/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/HomeFragment.kt @@ -1,4 +1,4 @@ -package org.mosad.teapod.activity.main.fragments +package org.mosad.teapod.ui.activity.main.fragments import android.os.Bundle import android.util.Log @@ -11,7 +11,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import org.mosad.teapod.R -import org.mosad.teapod.activity.main.MainActivity +import org.mosad.teapod.ui.activity.main.MainActivity import org.mosad.teapod.databinding.FragmentHomeBinding import org.mosad.teapod.parser.AoDParser import org.mosad.teapod.util.ItemMedia diff --git a/app/src/main/java/org/mosad/teapod/activity/main/fragments/LibraryFragment.kt b/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/LibraryFragment.kt similarity index 94% rename from app/src/main/java/org/mosad/teapod/activity/main/fragments/LibraryFragment.kt rename to app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/LibraryFragment.kt index 50ba7b9..01ab191 100644 --- a/app/src/main/java/org/mosad/teapod/activity/main/fragments/LibraryFragment.kt +++ b/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/LibraryFragment.kt @@ -1,4 +1,4 @@ -package org.mosad.teapod.activity.main.fragments +package org.mosad.teapod.ui.activity.main.fragments import android.os.Bundle import android.view.LayoutInflater @@ -9,7 +9,6 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import org.mosad.teapod.activity.main.MainActivity import org.mosad.teapod.databinding.FragmentLibraryBinding import org.mosad.teapod.parser.AoDParser import org.mosad.teapod.util.adapter.MediaItemAdapter diff --git a/app/src/main/java/org/mosad/teapod/activity/main/fragments/MediaFragment.kt b/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/MediaFragment.kt similarity index 91% rename from app/src/main/java/org/mosad/teapod/activity/main/fragments/MediaFragment.kt rename to app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/MediaFragment.kt index 6fda407..7fbfc64 100644 --- a/app/src/main/java/org/mosad/teapod/activity/main/fragments/MediaFragment.kt +++ b/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/MediaFragment.kt @@ -1,4 +1,4 @@ -package org.mosad.teapod.activity.main.fragments +package org.mosad.teapod.ui.activity.main.fragments import android.graphics.Color import android.graphics.drawable.ColorDrawable @@ -17,14 +17,16 @@ import com.google.android.material.tabs.TabLayoutMediator import jp.wasabeef.glide.transformations.BlurTransformation import kotlinx.coroutines.* import org.mosad.teapod.R -import org.mosad.teapod.activity.main.MainActivity -import org.mosad.teapod.activity.main.viewmodel.MediaFragmentViewModel +import org.mosad.teapod.ui.activity.main.MainActivity +import org.mosad.teapod.ui.activity.main.viewmodel.MediaFragmentViewModel import org.mosad.teapod.databinding.FragmentMediaBinding import org.mosad.teapod.util.* import org.mosad.teapod.util.DataTypes.MediaType /** - * TODO use a shared ViewModel for MediaFragment and it's sibling Fragments (episodes and similar) + * The media detail fragment. + * Note: the fragment is created only once, when selecting a similar title etc. + * therefore fragments may be not empty and model may be the old one */ class MediaFragment(private val mediaId: Int) : Fragment() { @@ -98,6 +100,10 @@ class MediaFragment(private val mediaId: Int) : Fragment() { Glide.with(requireContext()).load(R.drawable.ic_baseline_add_24).into(binding.imageMyListAction) } + // clear fragments, since it lives in onCreate scope (don't do this in onPause/onStop -> FragmentManager transaction) + fragments.clear() + pagerAdapter.notifyDataSetChanged() + // specific gui if (media.type == MediaType.TVSHOW) { // get next episode @@ -134,8 +140,10 @@ class MediaFragment(private val mediaId: Int) : Fragment() { } // if has similar titles - fragments.add(MediaSimilarFragment()) - pagerAdapter.notifyDataSetChanged() + if (media.info.similar.isNotEmpty()) { + fragments.add(MediaFragmentSimilar()) + pagerAdapter.notifyDataSetChanged() + } binding.frameLoading.visibility = View.GONE // hide loading indicator } diff --git a/app/src/main/java/org/mosad/teapod/activity/main/fragments/MediaFragmentEpisodes.kt b/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/MediaFragmentEpisodes.kt similarity index 92% rename from app/src/main/java/org/mosad/teapod/activity/main/fragments/MediaFragmentEpisodes.kt rename to app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/MediaFragmentEpisodes.kt index d16a50e..704610b 100644 --- a/app/src/main/java/org/mosad/teapod/activity/main/fragments/MediaFragmentEpisodes.kt +++ b/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/MediaFragmentEpisodes.kt @@ -1,4 +1,4 @@ -package org.mosad.teapod.activity.main.fragments +package org.mosad.teapod.ui.activity.main.fragments import android.os.Bundle import android.util.Log @@ -7,8 +7,8 @@ import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels -import org.mosad.teapod.activity.main.MainActivity -import org.mosad.teapod.activity.main.viewmodel.MediaFragmentViewModel +import org.mosad.teapod.ui.activity.main.MainActivity +import org.mosad.teapod.ui.activity.main.viewmodel.MediaFragmentViewModel import org.mosad.teapod.databinding.FragmentMediaEpisodesBinding import org.mosad.teapod.util.Episode import org.mosad.teapod.util.adapter.EpisodeItemAdapter diff --git a/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/MediaFragmentSimilar.kt b/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/MediaFragmentSimilar.kt new file mode 100644 index 0000000..8c8079c --- /dev/null +++ b/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/MediaFragmentSimilar.kt @@ -0,0 +1,39 @@ +package org.mosad.teapod.ui.activity.main.fragments + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import androidx.fragment.app.activityViewModels +import org.mosad.teapod.databinding.FragmentMediaSimilarBinding +import org.mosad.teapod.ui.activity.main.viewmodel.MediaFragmentViewModel +import org.mosad.teapod.util.adapter.MediaItemAdapter +import org.mosad.teapod.util.showFragment + +class MediaFragmentSimilar : Fragment() { + + private lateinit var binding: FragmentMediaSimilarBinding + private val model: MediaFragmentViewModel by activityViewModels() + + private lateinit var adapterSimilar: MediaItemAdapter + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { + binding = FragmentMediaSimilarBinding.inflate(inflater, container, false) + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + adapterSimilar = MediaItemAdapter(model.media.info.similar) + binding.recyclerMediaSimilar.adapter = adapterSimilar + + // set onItemClick only in adapter is initialized + if (this::adapterSimilar.isInitialized) { + adapterSimilar.onItemClick = { mediaId, _ -> + activity?.showFragment(MediaFragment(mediaId)) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/org/mosad/teapod/activity/main/fragments/SearchFragment.kt b/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/SearchFragment.kt similarity index 95% rename from app/src/main/java/org/mosad/teapod/activity/main/fragments/SearchFragment.kt rename to app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/SearchFragment.kt index 69ea9c4..57c43b1 100644 --- a/app/src/main/java/org/mosad/teapod/activity/main/fragments/SearchFragment.kt +++ b/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/SearchFragment.kt @@ -1,4 +1,4 @@ -package org.mosad.teapod.activity.main.fragments +package org.mosad.teapod.ui.activity.main.fragments import android.os.Bundle import android.view.LayoutInflater @@ -7,7 +7,6 @@ import android.view.ViewGroup import android.widget.SearchView import androidx.fragment.app.Fragment import kotlinx.coroutines.* -import org.mosad.teapod.activity.main.MainActivity import org.mosad.teapod.databinding.FragmentSearchBinding import org.mosad.teapod.parser.AoDParser import org.mosad.teapod.util.decoration.MediaItemDecoration diff --git a/app/src/main/java/org/mosad/teapod/activity/main/viewmodel/MediaFragmentViewModel.kt b/app/src/main/java/org/mosad/teapod/ui/activity/main/viewmodel/MediaFragmentViewModel.kt similarity index 93% rename from app/src/main/java/org/mosad/teapod/activity/main/viewmodel/MediaFragmentViewModel.kt rename to app/src/main/java/org/mosad/teapod/ui/activity/main/viewmodel/MediaFragmentViewModel.kt index 9352049..de0be69 100644 --- a/app/src/main/java/org/mosad/teapod/activity/main/viewmodel/MediaFragmentViewModel.kt +++ b/app/src/main/java/org/mosad/teapod/ui/activity/main/viewmodel/MediaFragmentViewModel.kt @@ -1,4 +1,4 @@ -package org.mosad.teapod.activity.main.viewmodel +package org.mosad.teapod.ui.activity.main.viewmodel import android.app.Application import androidx.lifecycle.AndroidViewModel @@ -18,6 +18,9 @@ class MediaFragmentViewModel(application: Application) : AndroidViewModel(applic var tmdb = TMDBResponse() internal set + /** + * set media, tmdb and nextEpisode + */ suspend fun load(mediaId: Int) { media = AoDParser.getMediaById(mediaId) tmdb = TMDBApiController().search(media.info.title, media.type) diff --git a/app/src/main/java/org/mosad/teapod/activity/onboarding/OnLoginFragment.kt b/app/src/main/java/org/mosad/teapod/ui/activity/onboarding/OnLoginFragment.kt similarity index 97% rename from app/src/main/java/org/mosad/teapod/activity/onboarding/OnLoginFragment.kt rename to app/src/main/java/org/mosad/teapod/ui/activity/onboarding/OnLoginFragment.kt index b60646e..f65ab30 100644 --- a/app/src/main/java/org/mosad/teapod/activity/onboarding/OnLoginFragment.kt +++ b/app/src/main/java/org/mosad/teapod/ui/activity/onboarding/OnLoginFragment.kt @@ -1,4 +1,4 @@ -package org.mosad.teapod.activity.onboarding +package org.mosad.teapod.ui.activity.onboarding import android.os.Bundle import android.view.LayoutInflater diff --git a/app/src/main/java/org/mosad/teapod/activity/onboarding/OnWelcomeFragment.kt b/app/src/main/java/org/mosad/teapod/ui/activity/onboarding/OnWelcomeFragment.kt similarity index 95% rename from app/src/main/java/org/mosad/teapod/activity/onboarding/OnWelcomeFragment.kt rename to app/src/main/java/org/mosad/teapod/ui/activity/onboarding/OnWelcomeFragment.kt index 28e221c..b51e6ed 100644 --- a/app/src/main/java/org/mosad/teapod/activity/onboarding/OnWelcomeFragment.kt +++ b/app/src/main/java/org/mosad/teapod/ui/activity/onboarding/OnWelcomeFragment.kt @@ -1,4 +1,4 @@ -package org.mosad.teapod.activity.onboarding +package org.mosad.teapod.ui.activity.onboarding import android.os.Bundle import android.view.LayoutInflater diff --git a/app/src/main/java/org/mosad/teapod/activity/onboarding/OnboardingActivity.kt b/app/src/main/java/org/mosad/teapod/ui/activity/onboarding/OnboardingActivity.kt similarity index 95% rename from app/src/main/java/org/mosad/teapod/activity/onboarding/OnboardingActivity.kt rename to app/src/main/java/org/mosad/teapod/ui/activity/onboarding/OnboardingActivity.kt index 3c4488b..8087e98 100644 --- a/app/src/main/java/org/mosad/teapod/activity/onboarding/OnboardingActivity.kt +++ b/app/src/main/java/org/mosad/teapod/ui/activity/onboarding/OnboardingActivity.kt @@ -1,4 +1,4 @@ -package org.mosad.teapod.activity.onboarding +package org.mosad.teapod.ui.activity.onboarding import android.content.Intent import android.os.Bundle @@ -8,7 +8,7 @@ import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentActivity import androidx.viewpager2.adapter.FragmentStateAdapter import com.google.android.material.tabs.TabLayoutMediator -import org.mosad.teapod.activity.main.MainActivity +import org.mosad.teapod.ui.activity.main.MainActivity import org.mosad.teapod.databinding.ActivityOnboardingBinding class OnboardingActivity : AppCompatActivity() { diff --git a/app/src/main/java/org/mosad/teapod/activity/player/PlayerActivity.kt b/app/src/main/java/org/mosad/teapod/ui/activity/player/PlayerActivity.kt similarity index 99% rename from app/src/main/java/org/mosad/teapod/activity/player/PlayerActivity.kt rename to app/src/main/java/org/mosad/teapod/ui/activity/player/PlayerActivity.kt index d3e66ec..0999106 100644 --- a/app/src/main/java/org/mosad/teapod/activity/player/PlayerActivity.kt +++ b/app/src/main/java/org/mosad/teapod/ui/activity/player/PlayerActivity.kt @@ -1,4 +1,4 @@ -package org.mosad.teapod.activity.player +package org.mosad.teapod.ui.activity.player import android.animation.Animator import android.animation.AnimatorListenerAdapter diff --git a/app/src/main/java/org/mosad/teapod/activity/player/PlayerViewModel.kt b/app/src/main/java/org/mosad/teapod/ui/activity/player/PlayerViewModel.kt similarity index 99% rename from app/src/main/java/org/mosad/teapod/activity/player/PlayerViewModel.kt rename to app/src/main/java/org/mosad/teapod/ui/activity/player/PlayerViewModel.kt index 8a1eb89..4efb7c4 100644 --- a/app/src/main/java/org/mosad/teapod/activity/player/PlayerViewModel.kt +++ b/app/src/main/java/org/mosad/teapod/ui/activity/player/PlayerViewModel.kt @@ -1,4 +1,4 @@ -package org.mosad.teapod.activity.player +package org.mosad.teapod.ui.activity.player import android.app.Application import android.net.Uri diff --git a/app/src/main/java/org/mosad/teapod/ui/components/EpisodesListPlayer.kt b/app/src/main/java/org/mosad/teapod/ui/components/EpisodesListPlayer.kt index 259305f..cb51deb 100644 --- a/app/src/main/java/org/mosad/teapod/ui/components/EpisodesListPlayer.kt +++ b/app/src/main/java/org/mosad/teapod/ui/components/EpisodesListPlayer.kt @@ -6,7 +6,7 @@ import android.view.LayoutInflater import android.view.ViewGroup import android.widget.LinearLayout import org.mosad.teapod.databinding.PlayerEpisodesListBinding -import org.mosad.teapod.activity.player.PlayerViewModel +import org.mosad.teapod.ui.activity.player.PlayerViewModel import org.mosad.teapod.util.adapter.PlayerEpisodeItemAdapter class EpisodesListPlayer @JvmOverloads constructor( diff --git a/app/src/main/java/org/mosad/teapod/ui/components/LanguageSettingsPlayer.kt b/app/src/main/java/org/mosad/teapod/ui/components/LanguageSettingsPlayer.kt index a1b1d92..404ba7e 100644 --- a/app/src/main/java/org/mosad/teapod/ui/components/LanguageSettingsPlayer.kt +++ b/app/src/main/java/org/mosad/teapod/ui/components/LanguageSettingsPlayer.kt @@ -13,7 +13,7 @@ import android.widget.TextView import androidx.core.view.children import org.mosad.teapod.R import org.mosad.teapod.databinding.PlayerLanguageSettingsBinding -import org.mosad.teapod.activity.player.PlayerViewModel +import org.mosad.teapod.ui.activity.player.PlayerViewModel import java.util.* class LanguageSettingsPlayer @JvmOverloads constructor( diff --git a/app/src/main/java/org/mosad/teapod/util/DataTypes.kt b/app/src/main/java/org/mosad/teapod/util/DataTypes.kt index bc27719..ea6e59e 100644 --- a/app/src/main/java/org/mosad/teapod/util/DataTypes.kt +++ b/app/src/main/java/org/mosad/teapod/util/DataTypes.kt @@ -62,7 +62,8 @@ data class Info( var description: String = "", var year: Int = 0, var age: Int = 0, - var episodesCount: Int = 0 + var episodesCount: Int = 0, + var similar: List = listOf() ) /** diff --git a/app/src/main/res/layout/activity_player.xml b/app/src/main/res/layout/activity_player.xml index 050d442..5a8f6bd 100644 --- a/app/src/main/res/layout/activity_player.xml +++ b/app/src/main/res/layout/activity_player.xml @@ -7,7 +7,7 @@ android:layout_height="match_parent" android:background="#000000" android:keepScreenOn="true" - tools:context=".activity.player.PlayerActivity"> + tools:context=".ui.activity.player.PlayerActivity"> + tools:context=".ui.activity.main.fragments.AboutFragment"> + tools:context=".ui.activity.main.fragments.AccountFragment"> + tools:context=".ui.activity.main.fragments.HomeFragment"> + tools:context=".ui.activity.main.fragments.LibraryFragment"> + tools:context=".ui.activity.main.fragments.MediaFragment"> - + app:layout_constraintTop_toTopOf="parent" + app:spanCount="2" + tools:listitem="@layout/item_media" /> + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_search.xml b/app/src/main/res/layout/fragment_search.xml index 02fd428..6427560 100644 --- a/app/src/main/res/layout/fragment_search.xml +++ b/app/src/main/res/layout/fragment_search.xml @@ -5,7 +5,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:background="?themePrimary" - tools:context=".activity.main.fragments.SearchFragment"> + tools:context=".ui.activity.main.fragments.SearchFragment"> -- 2.44.0 From d6b775d1130a209334d49cb977bc92e680ef47e5 Mon Sep 17 00:00:00 2001 From: Jannik Date: Sun, 31 Jan 2021 23:15:18 +0100 Subject: [PATCH 4/7] minor clean up --- app/src/main/res/layout/fragment_media.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/layout/fragment_media.xml b/app/src/main/res/layout/fragment_media.xml index a22d134..819cde1 100644 --- a/app/src/main/res/layout/fragment_media.xml +++ b/app/src/main/res/layout/fragment_media.xml @@ -164,7 +164,7 @@ + android:layout_height="wrap_content" /> -- 2.44.0 From 3efb9fdce9ab941ed8ba496f0fe1e54da08b2207 Mon Sep 17 00:00:00 2001 From: Jannik Date: Mon, 1 Feb 2021 00:09:44 +0100 Subject: [PATCH 5/7] update androidx navigation libraries --- app/build.gradle | 4 ++-- .../res/layout/fragment_media_episodes.xml | 6 +++--- .../res/layout/fragment_media_similar.xml | 19 ++++++++----------- 3 files changed, 13 insertions(+), 16 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 218155c..cae0d62 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -46,8 +46,8 @@ dependencies { implementation 'androidx.core:core-ktx:1.3.2' implementation 'androidx.appcompat:appcompat:1.2.0' implementation 'androidx.constraintlayout:constraintlayout:2.0.4' - implementation 'androidx.navigation:navigation-fragment-ktx:2.3.2' - implementation 'androidx.navigation:navigation-ui-ktx:2.3.2' + implementation 'androidx.navigation:navigation-fragment-ktx:2.3.3' + implementation 'androidx.navigation:navigation-ui-ktx:2.3.3' implementation 'androidx.security:security-crypto:1.1.0-alpha03' implementation 'androidx.legacy:legacy-support-v4:1.0.0' diff --git a/app/src/main/res/layout/fragment_media_episodes.xml b/app/src/main/res/layout/fragment_media_episodes.xml index 21453fc..89b3e68 100644 --- a/app/src/main/res/layout/fragment_media_episodes.xml +++ b/app/src/main/res/layout/fragment_media_episodes.xml @@ -4,15 +4,15 @@ xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" - android:layout_height="match_parent"> + android:layout_height="wrap_content"> diff --git a/app/src/main/res/layout/fragment_media_similar.xml b/app/src/main/res/layout/fragment_media_similar.xml index 37d5b92..67399e4 100644 --- a/app/src/main/res/layout/fragment_media_similar.xml +++ b/app/src/main/res/layout/fragment_media_similar.xml @@ -1,25 +1,22 @@ - + android:layout_height="wrap_content"> - \ No newline at end of file + \ No newline at end of file -- 2.44.0 From e650dc3d13da892a35bcb9c1a1e9002c3e9d98d5 Mon Sep 17 00:00:00 2001 From: Jannik Date: Mon, 1 Feb 2021 12:55:48 +0100 Subject: [PATCH 6/7] add item decoration to recyclerMediaSImilar --- .../teapod/ui/activity/main/fragments/MediaFragmentSimilar.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/MediaFragmentSimilar.kt b/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/MediaFragmentSimilar.kt index 8c8079c..db6d519 100644 --- a/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/MediaFragmentSimilar.kt +++ b/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/MediaFragmentSimilar.kt @@ -9,6 +9,7 @@ import androidx.fragment.app.activityViewModels import org.mosad.teapod.databinding.FragmentMediaSimilarBinding import org.mosad.teapod.ui.activity.main.viewmodel.MediaFragmentViewModel import org.mosad.teapod.util.adapter.MediaItemAdapter +import org.mosad.teapod.util.decoration.MediaItemDecoration import org.mosad.teapod.util.showFragment class MediaFragmentSimilar : Fragment() { @@ -28,6 +29,7 @@ class MediaFragmentSimilar : Fragment() { adapterSimilar = MediaItemAdapter(model.media.info.similar) binding.recyclerMediaSimilar.adapter = adapterSimilar + binding.recyclerMediaSimilar.addItemDecoration(MediaItemDecoration(9)) // set onItemClick only in adapter is initialized if (this::adapterSimilar.isInitialized) { -- 2.44.0 From 25294c2d87fc8667dedb0e612589e566193a0204 Mon Sep 17 00:00:00 2001 From: Jannik Date: Tue, 2 Feb 2021 23:50:43 +0100 Subject: [PATCH 7/7] fix updateNextEpisode() the function could crash, if no matching episode was found, if that's the case now, it returns the first episode --- .../ui/activity/main/fragments/MediaFragment.kt | 2 +- .../activity/main/fragments/MediaFragmentEpisodes.kt | 2 +- .../main/viewmodel/MediaFragmentViewModel.kt | 12 ++++-------- app/src/main/java/org/mosad/teapod/util/DataTypes.kt | 2 ++ 4 files changed, 8 insertions(+), 10 deletions(-) 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 7fbfc64..47d9067 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 @@ -183,7 +183,7 @@ class MediaFragment(private val mediaId: Int) : Fragment() { (activity as MainActivity).startPlayer(model.media.id, ep.id) Log.d(javaClass.name, "Started Player with episodeId: ${ep.id}") - model.updateNextEpisode() // set the correct next episode + model.updateNextEpisode(ep) // set the correct next episode } /** 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 704610b..78f480f 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 @@ -55,7 +55,7 @@ class MediaFragmentEpisodes : Fragment() { (activity as MainActivity).startPlayer(model.media.id, ep.id) Log.d(javaClass.name, "Started Player with episodeId: ${ep.id}") - model.updateNextEpisode() // set the correct next episode + model.updateNextEpisode(ep) // 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/MediaFragmentViewModel.kt b/app/src/main/java/org/mosad/teapod/ui/activity/main/viewmodel/MediaFragmentViewModel.kt index de0be69..c2ba21d 100644 --- a/app/src/main/java/org/mosad/teapod/ui/activity/main/viewmodel/MediaFragmentViewModel.kt +++ b/app/src/main/java/org/mosad/teapod/ui/activity/main/viewmodel/MediaFragmentViewModel.kt @@ -35,18 +35,14 @@ class MediaFragmentViewModel(application: Application) : AndroidViewModel(applic } /** - * based on watched state and current episode number set the next episode + * get the next episode based on episode number (the true next episode) * if no matching is found, use first episode */ - fun updateNextEpisode() { + fun updateNextEpisode(currentEp: Episode) { if (media.type == MediaType.MOVIE) return // return if movie - val currentEpNumber = nextEpisode.number - nextEpisode = if (media.episodes.firstOrNull{ !it.watched } != null) { - media.episodes.first{ !it.watched && it.number > currentEpNumber } - } else { - media.episodes.first() - } + nextEpisode = media.episodes.firstOrNull{ it.number > currentEp.number } + ?: media.episodes.first() } } \ No newline at end of file diff --git a/app/src/main/java/org/mosad/teapod/util/DataTypes.kt b/app/src/main/java/org/mosad/teapod/util/DataTypes.kt index ea6e59e..cf936bd 100644 --- a/app/src/main/java/org/mosad/teapod/util/DataTypes.kt +++ b/app/src/main/java/org/mosad/teapod/util/DataTypes.kt @@ -55,6 +55,7 @@ data class Media( fun getEpisodeById(id: Int) = episodes.first { it.id == id } } +// TODO all val? data class Info( var title: String = "", var posterUrl: String = "", @@ -97,6 +98,7 @@ data class Stream( /** * this class is used for tmdb responses + * TODO why is runtime var? */ data class TMDBResponse( val id: Int = 0, -- 2.44.0