/** * Teapod * * Copyright 2020-2022 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301, USA. * */ package org.mosad.teapod.ui.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.core.view.children import androidx.core.view.isVisible import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels import androidx.lifecycle.Lifecycle import androidx.lifecycle.lifecycleScope import androidx.lifecycle.repeatOnLifecycle import com.bumptech.glide.Glide import com.facebook.shimmer.ShimmerFrameLayout 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.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() { private val classTag = javaClass.name private val model: HomeViewModel by viewModels() private lateinit var binding: FragmentHomeBinding override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { binding = FragmentHomeBinding.inflate(inflater, container, false) return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) binding.recyclerUpNext.addItemDecoration(MediaItemDecoration(9)) binding.recyclerWatchlist.addItemDecoration(MediaItemDecoration(9)) binding.recyclerRecommendations.addItemDecoration(MediaItemDecoration(9)) binding.recyclerNewTitles.addItemDecoration(MediaItemDecoration(9)) binding.recyclerTopTen.addItemDecoration(MediaItemDecoration(9)) binding.recyclerUpNext.adapter = MediaEpisodeListAdapter( MediaEpisodeListAdapter.OnClickListener { activity?.startPlayer(it.panel.episodeMetadata.seasonId, it.panel.id) } ) binding.recyclerWatchlist.adapter = MediaItemListAdapter( MediaItemListAdapter.OnClickListener { activity?.showFragment(MediaFragment(it.id)) } ) binding.recyclerRecommendations.adapter = MediaItemListAdapter( MediaItemListAdapter.OnClickListener { activity?.showFragment(MediaFragment(it.id)) } ) binding.recyclerNewTitles.adapter = MediaItemListAdapter( MediaItemListAdapter.OnClickListener { activity?.showFragment(MediaFragment(it.id)) } ) binding.recyclerTopTen.adapter = MediaItemListAdapter( MediaItemListAdapter.OnClickListener { activity?.showFragment(MediaFragment(it.id)) } ) binding.textHighlightMyList.setOnClickListener { model.toggleHighlightWatchlist() // disable the watchlist button until the result has been loaded binding.textHighlightMyList.isClickable = false // TODO since this might take a few seconds show a loading animation for the watchlist button } viewLifecycleOwner.lifecycleScope.launch { viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) { model.onUiState(viewLifecycleOwner.lifecycleScope) { uiState -> when (uiState) { is HomeViewModel.UiState.Normal -> bindUiStateNormal(uiState) is HomeViewModel.UiState.Loading -> bindUiStateLoading() is HomeViewModel.UiState.Error -> bindUiStateError(uiState) } } } } } private fun bindUiStateNormal(uiState: HomeViewModel.UiState.Normal) { val adapterUpNext = binding.recyclerUpNext.adapter as MediaEpisodeListAdapter adapterUpNext.submitList(uiState.upNextItems.filter { !it.fullyWatched }) val adapterWatchlist = binding.recyclerWatchlist.adapter as MediaItemListAdapter adapterWatchlist.submitList(uiState.watchlistItems.toItemMediaList()) val adapterRecommendations = binding.recyclerRecommendations.adapter as MediaItemListAdapter adapterRecommendations.submitList(uiState.recommendationsItems.toItemMediaList()) val adapterNewTitles = binding.recyclerNewTitles.adapter as MediaItemListAdapter adapterNewTitles.submitList(uiState.recentlyAddedItems.toItemMediaList()) val adapterTopTen = binding.recyclerTopTen.adapter as MediaItemListAdapter adapterTopTen.submitList(uiState.topTenItems.toItemMediaList()) // highlight item binding.textHighlightTitle.text = uiState.highlightItem.title Glide.with(requireContext()).load(uiState.highlightItem.images.poster_wide[0][3].source) .into(binding.imageHighlight) val iconHighlightWatchlist = if (uiState.highlightIsWatchlist) { R.drawable.ic_baseline_check_24 } else { R.drawable.ic_baseline_add_24 } binding.textHighlightMyList.setDrawableTop(iconHighlightWatchlist) binding.textHighlightMyList.isClickable = true binding.textHighlightInfo.setOnClickListener { activity?.showFragment(MediaFragment(uiState.highlightItem.id)) } binding.buttonPlayHighlight.setOnClickListener { val panel = uiState.highlightItemUpNext.panel activity?.startPlayer(panel.episodeMetadata.seasonId, panel.id) } // disable the shimmer effect disableShimmer() // make highlights layout visible again binding.linearHighlight.isVisible = true } private fun bindUiStateLoading() { // hide highlights layout binding.linearHighlight.isVisible = false println(binding.root.childCount) binding.root.children.filter { it is ShimmerFrameLayout }.forEach { it as ShimmerFrameLayout it.startShimmer() } } private fun bindUiStateError(uiState: HomeViewModel.UiState.Error) { // currently not used Log.e(classTag, "A error occurred while loading a UiState: ${uiState.message}") } /** * Disable the shimmer effect for all shimmer layouts and hide them. */ private fun disableShimmer() { binding.shimmerLayoutHighlight.apply { stopShimmer() isVisible = false } binding.shimmerLayoutUpNext.apply { stopShimmer() isVisible = false } binding.shimmerLayoutWatchlist.apply { stopShimmer() isVisible = false } binding.shimmerLayoutRecommendations.apply { stopShimmer() isVisible = false } binding.shimmerLayoutNewTitles.apply { stopShimmer() isVisible = false } binding.shimmerLayoutTopTen.apply { stopShimmer() isVisible = false } } }