refactor: make item actions material buttons

Also fixes the buttons being clickable when the content has not loaded yet
This commit is contained in:
Jarne Demeulemeester 2023-05-20 20:32:03 +02:00
parent d6810c0f42
commit 36f07ad1c7
No known key found for this signature in database
GPG key ID: 1E5C6AFBD622E9F5
10 changed files with 145 additions and 188 deletions

View file

@ -8,7 +8,6 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
@ -34,8 +33,7 @@ import dev.jdtech.jellyfin.models.PlayerItem
import dev.jdtech.jellyfin.models.UiText import dev.jdtech.jellyfin.models.UiText
import dev.jdtech.jellyfin.models.isDownloaded import dev.jdtech.jellyfin.models.isDownloaded
import dev.jdtech.jellyfin.models.isDownloading import dev.jdtech.jellyfin.models.isDownloading
import dev.jdtech.jellyfin.utils.setTintColor import dev.jdtech.jellyfin.utils.setIconTintColorAttribute
import dev.jdtech.jellyfin.utils.setTintColorAttribute
import dev.jdtech.jellyfin.viewmodels.EpisodeBottomSheetViewModel import dev.jdtech.jellyfin.viewmodels.EpisodeBottomSheetViewModel
import dev.jdtech.jellyfin.viewmodels.PlayerViewModel import dev.jdtech.jellyfin.viewmodels.PlayerViewModel
import java.text.DateFormat import java.text.DateFormat
@ -64,8 +62,9 @@ class EpisodeBottomSheetFragment : BottomSheetDialogFragment() {
binding = EpisodeBottomSheetBinding.inflate(inflater, container, false) binding = EpisodeBottomSheetBinding.inflate(inflater, container, false)
binding.itemActions.playButton.setOnClickListener { binding.itemActions.playButton.setOnClickListener {
binding.itemActions.playButton.setImageResource(AndroidR.color.transparent) binding.itemActions.playButton.isEnabled = false
binding.itemActions.progressCircular.isVisible = true binding.itemActions.playButton.setIconResource(AndroidR.color.transparent)
binding.itemActions.progressPlay.isVisible = true
playerViewModel.loadPlayerItems(viewModel.item) playerViewModel.loadPlayerItems(viewModel.item)
} }
@ -89,12 +88,13 @@ class EpisodeBottomSheetFragment : BottomSheetDialogFragment() {
downloadPreparingDialog.dismiss() downloadPreparingDialog.dismiss()
} }
DownloadManager.STATUS_PENDING -> { DownloadManager.STATUS_PENDING -> {
binding.itemActions.downloadButton.setImageResource(AndroidR.color.transparent) binding.itemActions.downloadButton.setIconResource(AndroidR.color.transparent)
binding.itemActions.progressDownload.isIndeterminate = true binding.itemActions.progressDownload.isIndeterminate = true
binding.itemActions.progressDownload.isVisible = true binding.itemActions.progressDownload.isVisible = true
} }
DownloadManager.STATUS_RUNNING -> { DownloadManager.STATUS_RUNNING -> {
binding.itemActions.downloadButton.setImageResource(AndroidR.color.transparent) binding.itemActions.downloadButton.setIconResource(AndroidR.color.transparent)
binding.itemActions.progressDownload.isVisible = true binding.itemActions.progressDownload.isVisible = true
if (progress < 5) { if (progress < 5) {
binding.itemActions.progressDownload.isIndeterminate = true binding.itemActions.progressDownload.isIndeterminate = true
@ -104,12 +104,12 @@ class EpisodeBottomSheetFragment : BottomSheetDialogFragment() {
} }
} }
DownloadManager.STATUS_SUCCESSFUL -> { DownloadManager.STATUS_SUCCESSFUL -> {
binding.itemActions.downloadButton.setImageResource(CoreR.drawable.ic_trash) binding.itemActions.downloadButton.setIconResource(CoreR.drawable.ic_trash)
binding.itemActions.progressDownload.isVisible = false binding.itemActions.progressDownload.isVisible = false
} }
else -> { else -> {
binding.itemActions.progressDownload.isVisible = false binding.itemActions.progressDownload.isVisible = false
binding.itemActions.downloadButton.setImageResource(CoreR.drawable.ic_download) binding.itemActions.downloadButton.setIconResource(CoreR.drawable.ic_download)
} }
} }
} }
@ -153,11 +153,11 @@ class EpisodeBottomSheetFragment : BottomSheetDialogFragment() {
binding.itemActions.downloadButton.setOnClickListener { binding.itemActions.downloadButton.setOnClickListener {
if (viewModel.item.isDownloaded()) { if (viewModel.item.isDownloaded()) {
viewModel.deleteEpisode() viewModel.deleteEpisode()
binding.itemActions.downloadButton.setImageResource(CoreR.drawable.ic_download) binding.itemActions.downloadButton.setIconResource(CoreR.drawable.ic_download)
} else if (viewModel.item.isDownloading()) { } else if (viewModel.item.isDownloading()) {
createCancelDialog() createCancelDialog()
} else { } else {
binding.itemActions.downloadButton.setImageResource(android.R.color.transparent) binding.itemActions.downloadButton.setIconResource(AndroidR.color.transparent)
binding.itemActions.progressDownload.isIndeterminate = true binding.itemActions.progressDownload.isIndeterminate = true
binding.itemActions.progressDownload.isVisible = true binding.itemActions.progressDownload.isVisible = true
if (requireContext().getExternalFilesDirs(null).filterNotNull().size > 1) { if (requireContext().getExternalFilesDirs(null).filterNotNull().size > 1) {
@ -174,7 +174,7 @@ class EpisodeBottomSheetFragment : BottomSheetDialogFragment() {
}, },
onCancel = { onCancel = {
binding.itemActions.progressDownload.isVisible = false binding.itemActions.progressDownload.isVisible = false
binding.itemActions.downloadButton.setImageResource(CoreR.drawable.ic_download) binding.itemActions.downloadButton.setIconResource(CoreR.drawable.ic_download)
} }
) )
dialog.show() dialog.show()
@ -185,7 +185,7 @@ class EpisodeBottomSheetFragment : BottomSheetDialogFragment() {
}, },
onCancel = { onCancel = {
binding.itemActions.progressDownload.isVisible = false binding.itemActions.progressDownload.isVisible = false
binding.itemActions.downloadButton.setImageResource(CoreR.drawable.ic_download) binding.itemActions.downloadButton.setIconResource(CoreR.drawable.ic_download)
} }
) )
storageDialog.show() storageDialog.show()
@ -201,7 +201,7 @@ class EpisodeBottomSheetFragment : BottomSheetDialogFragment() {
}, },
onCancel = { onCancel = {
binding.itemActions.progressDownload.isVisible = false binding.itemActions.progressDownload.isVisible = false
binding.itemActions.downloadButton.setImageResource(CoreR.drawable.ic_download) binding.itemActions.downloadButton.setIconResource(CoreR.drawable.ic_download)
} }
) )
dialog.show() dialog.show()
@ -242,16 +242,16 @@ class EpisodeBottomSheetFragment : BottomSheetDialogFragment() {
binding.progressBar.isVisible = true binding.progressBar.isVisible = true
} }
val canPlay = episode.canPlay && episode.sources.isNotEmpty() binding.itemActions.playButton.isEnabled = episode.canPlay && episode.sources.isNotEmpty()
binding.itemActions.playButton.isEnabled = canPlay binding.itemActions.checkButton.isEnabled = true
binding.itemActions.playButton.alpha = if (!canPlay) 0.5F else 1.0F binding.itemActions.favoriteButton.isEnabled = true
bindCheckButtonState(episode.played) bindCheckButtonState(episode.played)
bindFavoriteButtonState(episode.favorite) bindFavoriteButtonState(episode.favorite)
if (episode.isDownloaded()) { if (episode.isDownloaded()) {
binding.itemActions.downloadButton.setImageResource(CoreR.drawable.ic_trash) binding.itemActions.downloadButton.setIconResource(CoreR.drawable.ic_trash)
} }
when (canDownload || canDelete) { when (canDownload || canDelete) {
@ -300,19 +300,17 @@ class EpisodeBottomSheetFragment : BottomSheetDialogFragment() {
private fun bindPlayerItems(items: PlayerViewModel.PlayerItems) { private fun bindPlayerItems(items: PlayerViewModel.PlayerItems) {
navigateToPlayerActivity(items.items.toTypedArray()) navigateToPlayerActivity(items.items.toTypedArray())
binding.itemActions.playButton.setImageDrawable( binding.itemActions.playButton.setIconResource(CoreR.drawable.ic_play)
ContextCompat.getDrawable( binding.itemActions.progressPlay.visibility = View.INVISIBLE
requireActivity(),
CoreR.drawable.ic_play
)
)
binding.itemActions.progressCircular.visibility = View.INVISIBLE
} }
private fun bindCheckButtonState(played: Boolean) { private fun bindCheckButtonState(played: Boolean) {
when (played) { when (played) {
true -> binding.itemActions.checkButton.setTintColor(CoreR.color.red, requireActivity().theme) true -> binding.itemActions.checkButton.setIconTintResource(
false -> binding.itemActions.checkButton.setTintColorAttribute( CoreR.color.red
)
false -> binding.itemActions.checkButton.setIconTintColorAttribute(
MaterialR.attr.colorOnSecondaryContainer, MaterialR.attr.colorOnSecondaryContainer,
requireActivity().theme requireActivity().theme
) )
@ -324,10 +322,13 @@ class EpisodeBottomSheetFragment : BottomSheetDialogFragment() {
true -> CoreR.drawable.ic_heart_filled true -> CoreR.drawable.ic_heart_filled
false -> CoreR.drawable.ic_heart false -> CoreR.drawable.ic_heart
} }
binding.itemActions.favoriteButton.setImageResource(favoriteDrawable) binding.itemActions.favoriteButton.setIconResource(favoriteDrawable)
when (favorite) { when (favorite) {
true -> binding.itemActions.favoriteButton.setTintColor(CoreR.color.red, requireActivity().theme) true -> binding.itemActions.favoriteButton.setIconTintResource(
false -> binding.itemActions.favoriteButton.setTintColorAttribute( CoreR.color.red
)
false -> binding.itemActions.favoriteButton.setIconTintColorAttribute(
MaterialR.attr.colorOnSecondaryContainer, MaterialR.attr.colorOnSecondaryContainer,
requireActivity().theme requireActivity().theme
) )
@ -336,20 +337,19 @@ class EpisodeBottomSheetFragment : BottomSheetDialogFragment() {
private fun bindPlayerItemsError(error: PlayerViewModel.PlayerItemError) { private fun bindPlayerItemsError(error: PlayerViewModel.PlayerItemError) {
Timber.e(error.error.message) Timber.e(error.error.message)
binding.playerItemsError.isVisible = true binding.playerItemsError.isVisible = true
binding.itemActions.playButton.setImageDrawable( playButtonNormal()
ContextCompat.getDrawable(
requireActivity(),
CoreR.drawable.ic_play
)
)
binding.itemActions.progressCircular.visibility = View.INVISIBLE
binding.playerItemsErrorDetails.setOnClickListener { binding.playerItemsErrorDetails.setOnClickListener {
ErrorDialogFragment.newInstance(error.error).show(parentFragmentManager, ErrorDialogFragment.TAG) ErrorDialogFragment.newInstance(error.error).show(parentFragmentManager, ErrorDialogFragment.TAG)
} }
} }
private fun playButtonNormal() {
binding.itemActions.playButton.isEnabled = true
binding.itemActions.playButton.setIconResource(CoreR.drawable.ic_play)
binding.itemActions.progressPlay.visibility = View.INVISIBLE
}
private fun createErrorDialog(uiText: UiText) { private fun createErrorDialog(uiText: UiText) {
val builder = MaterialAlertDialogBuilder(requireContext()) val builder = MaterialAlertDialogBuilder(requireContext())
builder builder
@ -359,7 +359,7 @@ class EpisodeBottomSheetFragment : BottomSheetDialogFragment() {
} }
builder.show() builder.show()
binding.itemActions.progressDownload.isVisible = false binding.itemActions.progressDownload.isVisible = false
binding.itemActions.downloadButton.setImageResource(CoreR.drawable.ic_download) binding.itemActions.downloadButton.setIconResource(CoreR.drawable.ic_download)
} }
private fun createDownloadPreparingDialog() { private fun createDownloadPreparingDialog() {

View file

@ -10,7 +10,6 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
@ -19,7 +18,6 @@ import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle import androidx.lifecycle.repeatOnLifecycle
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs import androidx.navigation.fragment.navArgs
import com.google.android.material.R as MaterialR
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import dev.jdtech.jellyfin.AppPreferences import dev.jdtech.jellyfin.AppPreferences
@ -39,8 +37,7 @@ import dev.jdtech.jellyfin.models.UiText
import dev.jdtech.jellyfin.models.isDownloaded import dev.jdtech.jellyfin.models.isDownloaded
import dev.jdtech.jellyfin.models.isDownloading import dev.jdtech.jellyfin.models.isDownloading
import dev.jdtech.jellyfin.utils.checkIfLoginRequired import dev.jdtech.jellyfin.utils.checkIfLoginRequired
import dev.jdtech.jellyfin.utils.setTintColor import dev.jdtech.jellyfin.utils.setIconTintColorAttribute
import dev.jdtech.jellyfin.utils.setTintColorAttribute
import dev.jdtech.jellyfin.viewmodels.MovieViewModel import dev.jdtech.jellyfin.viewmodels.MovieViewModel
import dev.jdtech.jellyfin.viewmodels.PlayerViewModel import dev.jdtech.jellyfin.viewmodels.PlayerViewModel
import java.util.UUID import java.util.UUID
@ -94,12 +91,12 @@ class MovieFragment : Fragment() {
downloadPreparingDialog.dismiss() downloadPreparingDialog.dismiss()
} }
DownloadManager.STATUS_PENDING -> { DownloadManager.STATUS_PENDING -> {
binding.itemActions.downloadButton.setImageResource(android.R.color.transparent) binding.itemActions.downloadButton.setIconResource(android.R.color.transparent)
binding.itemActions.progressDownload.isIndeterminate = true binding.itemActions.progressDownload.isIndeterminate = true
binding.itemActions.progressDownload.isVisible = true binding.itemActions.progressDownload.isVisible = true
} }
DownloadManager.STATUS_RUNNING -> { DownloadManager.STATUS_RUNNING -> {
binding.itemActions.downloadButton.setImageResource(android.R.color.transparent) binding.itemActions.downloadButton.setIconResource(android.R.color.transparent)
binding.itemActions.progressDownload.isVisible = true binding.itemActions.progressDownload.isVisible = true
if (progress < 5) { if (progress < 5) {
binding.itemActions.progressDownload.isIndeterminate = true binding.itemActions.progressDownload.isIndeterminate = true
@ -109,12 +106,12 @@ class MovieFragment : Fragment() {
} }
} }
DownloadManager.STATUS_SUCCESSFUL -> { DownloadManager.STATUS_SUCCESSFUL -> {
binding.itemActions.downloadButton.setImageResource(CoreR.drawable.ic_trash) binding.itemActions.downloadButton.setIconResource(CoreR.drawable.ic_trash)
binding.itemActions.progressDownload.isVisible = false binding.itemActions.progressDownload.isVisible = false
} }
else -> { else -> {
binding.itemActions.progressDownload.isVisible = false binding.itemActions.progressDownload.isVisible = false
binding.itemActions.downloadButton.setImageResource(CoreR.drawable.ic_download) binding.itemActions.downloadButton.setIconResource(CoreR.drawable.ic_download)
} }
} }
} }
@ -151,8 +148,8 @@ class MovieFragment : Fragment() {
binding.itemActions.playButton.setOnClickListener { binding.itemActions.playButton.setOnClickListener {
binding.itemActions.playButton.isEnabled = false binding.itemActions.playButton.isEnabled = false
binding.itemActions.playButton.setImageResource(android.R.color.transparent) binding.itemActions.playButton.setIconResource(android.R.color.transparent)
binding.itemActions.progressCircular.isVisible = true binding.itemActions.progressPlay.isVisible = true
if (viewModel.item.sources.size > 1) { if (viewModel.item.sources.size > 1) {
val dialog = getVideoVersionDialog( val dialog = getVideoVersionDialog(
requireContext(), viewModel.item, requireContext(), viewModel.item,
@ -196,11 +193,11 @@ class MovieFragment : Fragment() {
binding.itemActions.downloadButton.setOnClickListener { binding.itemActions.downloadButton.setOnClickListener {
if (viewModel.item.isDownloaded()) { if (viewModel.item.isDownloaded()) {
viewModel.deleteItem() viewModel.deleteItem()
binding.itemActions.downloadButton.setImageResource(CoreR.drawable.ic_download) binding.itemActions.downloadButton.setIconResource(CoreR.drawable.ic_download)
} else if (viewModel.item.isDownloading()) { } else if (viewModel.item.isDownloading()) {
createCancelDialog() createCancelDialog()
} else { } else {
binding.itemActions.downloadButton.setImageResource(android.R.color.transparent) binding.itemActions.downloadButton.setIconResource(android.R.color.transparent)
binding.itemActions.progressDownload.isIndeterminate = true binding.itemActions.progressDownload.isIndeterminate = true
binding.itemActions.progressDownload.isVisible = true binding.itemActions.progressDownload.isVisible = true
if (requireContext().getExternalFilesDirs(null).filterNotNull().size > 1) { if (requireContext().getExternalFilesDirs(null).filterNotNull().size > 1) {
@ -217,7 +214,7 @@ class MovieFragment : Fragment() {
}, },
onCancel = { onCancel = {
binding.itemActions.progressDownload.isVisible = false binding.itemActions.progressDownload.isVisible = false
binding.itemActions.downloadButton.setImageResource(CoreR.drawable.ic_download) binding.itemActions.downloadButton.setIconResource(CoreR.drawable.ic_download)
} }
) )
dialog.show() dialog.show()
@ -228,7 +225,7 @@ class MovieFragment : Fragment() {
}, },
onCancel = { onCancel = {
binding.itemActions.progressDownload.isVisible = false binding.itemActions.progressDownload.isVisible = false
binding.itemActions.downloadButton.setImageResource(CoreR.drawable.ic_download) binding.itemActions.downloadButton.setIconResource(CoreR.drawable.ic_download)
} }
) )
storageDialog.show() storageDialog.show()
@ -244,7 +241,7 @@ class MovieFragment : Fragment() {
}, },
onCancel = { onCancel = {
binding.itemActions.progressDownload.isVisible = false binding.itemActions.progressDownload.isVisible = false
binding.itemActions.downloadButton.setImageResource(CoreR.drawable.ic_download) binding.itemActions.downloadButton.setIconResource(CoreR.drawable.ic_download)
} }
) )
dialog.show() dialog.show()
@ -282,16 +279,16 @@ class MovieFragment : Fragment() {
binding.communityRating.isVisible = item.communityRating != null binding.communityRating.isVisible = item.communityRating != null
binding.actors.isVisible = actors.isNotEmpty() binding.actors.isVisible = actors.isNotEmpty()
val canPlay = item.canPlay && item.sources.isNotEmpty() binding.itemActions.playButton.isEnabled = item.canPlay && item.sources.isNotEmpty()
binding.itemActions.playButton.isEnabled = canPlay binding.itemActions.checkButton.isEnabled = true
binding.itemActions.playButton.alpha = if (!canPlay) 0.5F else 1.0F binding.itemActions.favoriteButton.isEnabled = true
bindCheckButtonState(item.played) bindCheckButtonState(item.played)
bindFavoriteButtonState(item.favorite) bindFavoriteButtonState(item.favorite)
if (item.isDownloaded()) { if (item.isDownloaded()) {
binding.itemActions.downloadButton.setImageResource(CoreR.drawable.ic_trash) binding.itemActions.downloadButton.setIconResource(CoreR.drawable.ic_trash)
} }
when (canDownload || canDelete) { when (canDownload || canDelete) {
@ -411,9 +408,9 @@ class MovieFragment : Fragment() {
private fun bindCheckButtonState(played: Boolean) { private fun bindCheckButtonState(played: Boolean) {
when (played) { when (played) {
true -> binding.itemActions.checkButton.setTintColor(CoreR.color.red, requireActivity().theme) true -> binding.itemActions.checkButton.setIconTintResource(CoreR.color.red)
false -> binding.itemActions.checkButton.setTintColorAttribute( false -> binding.itemActions.checkButton.setIconTintColorAttribute(
MaterialR.attr.colorOnSecondaryContainer, com.google.android.material.R.attr.colorOnSecondaryContainer,
requireActivity().theme requireActivity().theme
) )
} }
@ -424,11 +421,11 @@ class MovieFragment : Fragment() {
true -> CoreR.drawable.ic_heart_filled true -> CoreR.drawable.ic_heart_filled
false -> CoreR.drawable.ic_heart false -> CoreR.drawable.ic_heart
} }
binding.itemActions.favoriteButton.setImageResource(favoriteDrawable) binding.itemActions.favoriteButton.setIconResource(favoriteDrawable)
when (favorite) { when (favorite) {
true -> binding.itemActions.favoriteButton.setTintColor(CoreR.color.red, requireActivity().theme) true -> binding.itemActions.favoriteButton.setIconTintResource(CoreR.color.red)
false -> binding.itemActions.favoriteButton.setTintColorAttribute( false -> binding.itemActions.favoriteButton.setIconTintColorAttribute(
MaterialR.attr.colorOnSecondaryContainer, com.google.android.material.R.attr.colorOnSecondaryContainer,
requireActivity().theme requireActivity().theme
) )
} }
@ -436,13 +433,8 @@ class MovieFragment : Fragment() {
private fun bindPlayerItems(items: PlayerViewModel.PlayerItems) { private fun bindPlayerItems(items: PlayerViewModel.PlayerItems) {
navigateToPlayerActivity(items.items.toTypedArray()) navigateToPlayerActivity(items.items.toTypedArray())
binding.itemActions.playButton.setImageDrawable( binding.itemActions.playButton.setIconResource(CoreR.drawable.ic_play)
ContextCompat.getDrawable( binding.itemActions.progressPlay.visibility = View.INVISIBLE
requireActivity(),
CoreR.drawable.ic_play
)
)
binding.itemActions.progressCircular.visibility = View.INVISIBLE
} }
private fun bindPlayerItemsError(error: PlayerViewModel.PlayerItemError) { private fun bindPlayerItemsError(error: PlayerViewModel.PlayerItemError) {
@ -457,13 +449,8 @@ class MovieFragment : Fragment() {
private fun playButtonNormal() { private fun playButtonNormal() {
binding.itemActions.playButton.isEnabled = true binding.itemActions.playButton.isEnabled = true
binding.itemActions.playButton.setImageDrawable( binding.itemActions.playButton.setIconResource(CoreR.drawable.ic_play)
ContextCompat.getDrawable( binding.itemActions.progressPlay.visibility = View.INVISIBLE
requireActivity(),
CoreR.drawable.ic_play
)
)
binding.itemActions.progressCircular.visibility = View.INVISIBLE
} }
private fun createErrorDialog(uiText: UiText) { private fun createErrorDialog(uiText: UiText) {
@ -475,7 +462,7 @@ class MovieFragment : Fragment() {
} }
builder.show() builder.show()
binding.itemActions.progressDownload.isVisible = false binding.itemActions.progressDownload.isVisible = false
binding.itemActions.downloadButton.setImageResource(CoreR.drawable.ic_download) binding.itemActions.downloadButton.setIconResource(CoreR.drawable.ic_download)
} }
private fun createDownloadPreparingDialog() { private fun createDownloadPreparingDialog() {

View file

@ -7,7 +7,6 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.Toast import android.widget.Toast
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
@ -16,7 +15,7 @@ import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle import androidx.lifecycle.repeatOnLifecycle
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs import androidx.navigation.fragment.navArgs
import com.google.android.material.R as MaterialR import com.google.android.material.R
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import dev.jdtech.jellyfin.AppPreferences import dev.jdtech.jellyfin.AppPreferences
import dev.jdtech.jellyfin.adapters.PersonListAdapter import dev.jdtech.jellyfin.adapters.PersonListAdapter
@ -32,8 +31,7 @@ import dev.jdtech.jellyfin.models.FindroidSourceType
import dev.jdtech.jellyfin.models.PlayerItem import dev.jdtech.jellyfin.models.PlayerItem
import dev.jdtech.jellyfin.models.isDownloaded import dev.jdtech.jellyfin.models.isDownloaded
import dev.jdtech.jellyfin.utils.checkIfLoginRequired import dev.jdtech.jellyfin.utils.checkIfLoginRequired
import dev.jdtech.jellyfin.utils.setTintColor import dev.jdtech.jellyfin.utils.setIconTintColorAttribute
import dev.jdtech.jellyfin.utils.setTintColorAttribute
import dev.jdtech.jellyfin.viewmodels.PlayerViewModel import dev.jdtech.jellyfin.viewmodels.PlayerViewModel
import dev.jdtech.jellyfin.viewmodels.ShowViewModel import dev.jdtech.jellyfin.viewmodels.ShowViewModel
import java.util.UUID import java.util.UUID
@ -132,8 +130,9 @@ class ShowFragment : Fragment() {
} }
binding.itemActions.playButton.setOnClickListener { binding.itemActions.playButton.setOnClickListener {
binding.itemActions.playButton.setImageResource(android.R.color.transparent) binding.itemActions.playButton.isEnabled = false
binding.itemActions.progressCircular.isVisible = true binding.itemActions.playButton.setIconResource(android.R.color.transparent)
binding.itemActions.progressPlay.isVisible = true
playerViewModel.loadPlayerItems(viewModel.item) playerViewModel.loadPlayerItems(viewModel.item)
} }
@ -170,9 +169,10 @@ class ShowFragment : Fragment() {
binding.communityRating.isVisible = item.communityRating != null binding.communityRating.isVisible = item.communityRating != null
binding.actors.isVisible = actors.isNotEmpty() binding.actors.isVisible = actors.isNotEmpty()
val canPlay = item.canPlay /*&& item.sources.isNotEmpty()*/ // TODO currently the sources of a show is always empty, we need a way to check if sources are available // TODO currently the sources of a show is always empty, we need a way to check if sources are available
binding.itemActions.playButton.isEnabled = canPlay binding.itemActions.playButton.isEnabled = item.canPlay
binding.itemActions.playButton.alpha = if (!canPlay) 0.5F else 1.0F binding.itemActions.checkButton.isEnabled = true
binding.itemActions.favoriteButton.isEnabled = true
bindCheckButtonState(item.played) bindCheckButtonState(item.played)
@ -183,9 +183,8 @@ class ShowFragment : Fragment() {
binding.itemActions.downloadButton.isVisible = true binding.itemActions.downloadButton.isVisible = true
binding.itemActions.downloadButton.isEnabled = !downloaded binding.itemActions.downloadButton.isEnabled = !downloaded
if (downloaded) binding.itemActions.downloadButton.setTintColor( if (downloaded) binding.itemActions.downloadButton.setIconTintResource(
CoreR.color.red, CoreR.color.red
requireActivity().theme
) )
} }
@ -263,9 +262,9 @@ class ShowFragment : Fragment() {
private fun bindCheckButtonState(played: Boolean) { private fun bindCheckButtonState(played: Boolean) {
when (played) { when (played) {
true -> binding.itemActions.checkButton.setTintColor(CoreR.color.red, requireActivity().theme) true -> binding.itemActions.checkButton.setIconTintResource(CoreR.color.red)
false -> binding.itemActions.checkButton.setTintColorAttribute( false -> binding.itemActions.checkButton.setIconTintColorAttribute(
MaterialR.attr.colorOnSecondaryContainer, R.attr.colorOnSecondaryContainer,
requireActivity().theme requireActivity().theme
) )
} }
@ -276,11 +275,11 @@ class ShowFragment : Fragment() {
true -> CoreR.drawable.ic_heart_filled true -> CoreR.drawable.ic_heart_filled
false -> CoreR.drawable.ic_heart false -> CoreR.drawable.ic_heart
} }
binding.itemActions.favoriteButton.setImageResource(favoriteDrawable) binding.itemActions.favoriteButton.setIconResource(favoriteDrawable)
when (favorite) { when (favorite) {
true -> binding.itemActions.favoriteButton.setTintColor(CoreR.color.red, requireActivity().theme) true -> binding.itemActions.favoriteButton.setIconTintResource(CoreR.color.red)
false -> binding.itemActions.favoriteButton.setTintColorAttribute( false -> binding.itemActions.favoriteButton.setIconTintColorAttribute(
MaterialR.attr.colorOnSecondaryContainer, R.attr.colorOnSecondaryContainer,
requireActivity().theme requireActivity().theme
) )
} }
@ -288,31 +287,26 @@ class ShowFragment : Fragment() {
private fun bindPlayerItems(items: PlayerViewModel.PlayerItems) { private fun bindPlayerItems(items: PlayerViewModel.PlayerItems) {
navigateToPlayerActivity(items.items.toTypedArray()) navigateToPlayerActivity(items.items.toTypedArray())
binding.itemActions.playButton.setImageDrawable( binding.itemActions.playButton.setIconResource(CoreR.drawable.ic_play)
ContextCompat.getDrawable( binding.itemActions.progressPlay.visibility = View.INVISIBLE
requireActivity(),
CoreR.drawable.ic_play
)
)
binding.itemActions.progressCircular.visibility = View.INVISIBLE
} }
private fun bindPlayerItemsError(error: PlayerViewModel.PlayerItemError) { private fun bindPlayerItemsError(error: PlayerViewModel.PlayerItemError) {
Timber.e(error.error.message) Timber.e(error.error.message)
binding.playerItemsError.visibility = View.VISIBLE binding.playerItemsError.visibility = View.VISIBLE
binding.itemActions.playButton.setImageDrawable( playButtonNormal()
ContextCompat.getDrawable(
requireActivity(),
CoreR.drawable.ic_play
)
)
binding.itemActions.progressCircular.visibility = View.INVISIBLE
binding.playerItemsErrorDetails.setOnClickListener { binding.playerItemsErrorDetails.setOnClickListener {
ErrorDialogFragment.newInstance(error.error) ErrorDialogFragment.newInstance(error.error)
.show(parentFragmentManager, ErrorDialogFragment.TAG) .show(parentFragmentManager, ErrorDialogFragment.TAG)
} }
} }
private fun playButtonNormal() {
binding.itemActions.playButton.isEnabled = true
binding.itemActions.playButton.setIconResource(CoreR.drawable.ic_play)
binding.itemActions.progressPlay.visibility = View.INVISIBLE
}
private fun navigateToEpisodeBottomSheetFragment(episode: FindroidItem) { private fun navigateToEpisodeBottomSheetFragment(episode: FindroidItem) {
findNavController().navigate( findNavController().navigate(
ShowFragmentDirections.actionShowFragmentToEpisodeBottomSheetFragment( ShowFragmentDirections.actionShowFragmentToEpisodeBottomSheetFragment(

View file

@ -132,14 +132,13 @@
layout="@layout/item_actions" layout="@layout/item_actions"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp" /> android:layout_marginHorizontal="20dp" />
<LinearLayout <LinearLayout
android:id="@+id/player_items_error" android:id="@+id/player_items_error"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp" android:layout_marginHorizontal="24dp"
android:layout_marginTop="4dp"
android:orientation="vertical" android:orientation="vertical"
android:visibility="gone" android:visibility="gone"
tools:visibility="visible"> tools:visibility="visible">

View file

@ -166,8 +166,8 @@
layout="@layout/item_actions" layout="@layout/item_actions"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp" android:layout_marginHorizontal="20dp"
android:layout_marginTop="12dp" android:layout_marginTop="8dp"
android:layout_marginBottom="24dp" android:layout_marginBottom="24dp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
@ -179,7 +179,6 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp" android:layout_marginHorizontal="24dp"
android:layout_marginTop="12dp"
android:layout_marginBottom="12dp" android:layout_marginBottom="12dp"
android:orientation="vertical" android:orientation="vertical"
android:visibility="gone" android:visibility="gone"
@ -211,7 +210,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp" android:layout_marginHorizontal="24dp"
android:layout_marginTop="12dp" android:layout_marginTop="8dp"
android:textAppearance="@style/TextAppearance.Material3.BodyMedium" android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"

View file

@ -126,7 +126,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="start" android:layout_gravity="start"
android:layout_marginTop="10dp" android:layout_marginTop="10dp"
android:layout_marginBottom="16dp" android:layout_marginBottom="12dp"
app:singleLine="true"> app:singleLine="true">
<com.google.android.material.chip.Chip <com.google.android.material.chip.Chip
@ -198,14 +198,13 @@
layout="@layout/item_actions" layout="@layout/item_actions"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp" /> android:layout_marginHorizontal="20dp" />
<LinearLayout <LinearLayout
android:id="@+id/player_items_error" android:id="@+id/player_items_error"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp" android:layout_marginHorizontal="24dp"
android:layout_marginTop="4dp"
android:orientation="vertical" android:orientation="vertical"
android:visibility="gone" android:visibility="gone"
tools:visibility="visible"> tools:visibility="visible">

View file

@ -72,7 +72,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp" android:layout_marginHorizontal="24dp"
android:layout_marginBottom="12dp"> android:layout_marginBottom="8dp">
<TextView <TextView
android:id="@+id/year" android:id="@+id/year"
@ -119,14 +119,13 @@
layout="@layout/item_actions" layout="@layout/item_actions"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp" /> android:layout_marginHorizontal="20dp" />
<LinearLayout <LinearLayout
android:id="@+id/player_items_error" android:id="@+id/player_items_error"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp" android:layout_marginHorizontal="24dp"
android:layout_marginTop="4dp"
android:orientation="vertical" android:orientation="vertical"
android:visibility="gone" android:visibility="gone"
tools:visibility="visible"> tools:visibility="visible">

View file

@ -3,88 +3,78 @@
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content">
android:layout_marginHorizontal="24dp"
android:layout_marginBottom="24dp">
<RelativeLayout <RelativeLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content">
android:layout_marginEnd="12dp">
<ImageButton <com.google.android.material.button.MaterialButton
android:id="@+id/play_button" android:id="@+id/play_button"
android:layout_width="72dp" style="?attr/materialIconButtonFilledStyle"
android:layout_height="48dp" android:layout_width="wrap_content"
android:background="@drawable/button_setup_background" android:layout_height="wrap_content"
android:contentDescription="@string/play_button_description" android:contentDescription="@string/play_button_description"
android:foreground="@drawable/ripple_background" android:enabled="false"
android:paddingHorizontal="24dp" android:paddingHorizontal="24dp"
android:paddingVertical="12dp" app:icon="@drawable/ic_play"
android:src="@drawable/ic_play" tools:enabled="true" />
app:tint="?attr/colorOnPrimary" />
<ProgressBar <com.google.android.material.progressindicator.CircularProgressIndicator
android:id="@+id/progress_circular" android:id="@+id/progress_play"
android:layout_width="48dp" android:layout_width="48dp"
android:layout_height="48dp" android:layout_height="48dp"
android:layout_centerHorizontal="true" android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:elevation="8dp" android:elevation="8dp"
android:indeterminateTint="?attr/colorOnPrimary" android:indeterminate="true"
android:padding="8dp" android:visibility="invisible"
android:visibility="invisible" /> app:indicatorSize="24dp"
app:trackCornerRadius="2dp" />
</RelativeLayout> </RelativeLayout>
<ImageButton <com.google.android.material.button.MaterialButton
android:id="@+id/trailer_button" android:id="@+id/trailer_button"
style="?attr/materialIconButtonFilledTonalStyle"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="12dp"
android:background="@drawable/button_accent_background"
android:contentDescription="@string/trailer_button_description" android:contentDescription="@string/trailer_button_description"
android:padding="12dp"
android:src="@drawable/ic_film"
android:visibility="gone" android:visibility="gone"
tools:visibility="visible" app:icon="@drawable/ic_film"
app:tint="?attr/colorOnSecondaryContainer" /> tools:visibility="visible" />
<ImageButton <com.google.android.material.button.MaterialButton
android:id="@+id/check_button" android:id="@+id/check_button"
style="?attr/materialIconButtonFilledTonalStyle"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="12dp"
android:background="@drawable/button_accent_background"
android:contentDescription="@string/check_button_description" android:contentDescription="@string/check_button_description"
android:padding="12dp" android:enabled="false"
android:src="@drawable/ic_check" app:icon="@drawable/ic_check"
app:tint="?attr/colorOnSecondaryContainer" /> tools:enabled="true" />
<ImageButton <com.google.android.material.button.MaterialButton
android:id="@+id/favorite_button" android:id="@+id/favorite_button"
style="?attr/materialIconButtonFilledTonalStyle"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="12dp"
android:background="@drawable/button_accent_background"
android:contentDescription="@string/favorite_button_description" android:contentDescription="@string/favorite_button_description"
android:padding="12dp" android:enabled="false"
android:src="@drawable/ic_heart" app:icon="@drawable/ic_heart"
app:tint="?attr/colorOnSecondaryContainer" /> tools:enabled="true" />
<RelativeLayout <RelativeLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content">
android:layout_marginEnd="12dp">
<ImageButton <com.google.android.material.button.MaterialButton
android:id="@+id/download_button" android:id="@+id/download_button"
android:layout_width="48dp" style="?attr/materialIconButtonFilledTonalStyle"
android:layout_height="48dp" android:layout_width="wrap_content"
android:background="@drawable/button_accent_background" android:layout_height="wrap_content"
android:contentDescription="@string/download_button_description" android:contentDescription="@string/download_button_description"
android:padding="12dp"
android:src="@drawable/ic_download"
android:visibility="gone" android:visibility="gone"
app:tint="?attr/colorOnSecondaryContainer" app:icon="@drawable/ic_download"
tools:visibility="visible" /> tools:visibility="visible" />
<com.google.android.material.progressindicator.CircularProgressIndicator <com.google.android.material.progressindicator.CircularProgressIndicator
@ -97,7 +87,7 @@
android:progress="0" android:progress="0"
android:progressTint="?attr/colorOnSecondary" android:progressTint="?attr/colorOnSecondary"
android:visibility="invisible" android:visibility="invisible"
app:indicatorSize="32dp" app:indicatorSize="24dp"
app:trackCornerRadius="2dp" /> app:trackCornerRadius="2dp" />
</RelativeLayout> </RelativeLayout>

View file

@ -12,7 +12,7 @@
android:id="@+id/size_title" android:id="@+id/size_title"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="12dp" android:layout_marginTop="8dp"
android:text="@string/size" android:text="@string/size"
android:textAppearance="@style/TextAppearance.Material3.BodyMedium" android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
android:visibility="gone" android:visibility="gone"
@ -108,7 +108,7 @@
android:id="@+id/description" android:id="@+id/description"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="16dp" android:layout_marginTop="12dp"
android:textAppearance="@style/TextAppearance.Material3.BodyMedium" android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
@ -119,7 +119,7 @@
android:id="@+id/genres_title" android:id="@+id/genres_title"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="16dp" android:layout_marginTop="12dp"
android:text="@string/genres" android:text="@string/genres"
android:textAppearance="@style/TextAppearance.Material3.BodyMedium" android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"

View file

@ -7,9 +7,8 @@ import android.content.res.Resources
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.util.TypedValue import android.util.TypedValue
import android.widget.ImageButton
import androidx.annotation.AttrRes import androidx.annotation.AttrRes
import androidx.annotation.ColorRes import com.google.android.material.button.MaterialButton
import dev.jdtech.jellyfin.models.View import dev.jdtech.jellyfin.models.View
import java.io.Serializable import java.io.Serializable
import org.jellyfin.sdk.model.api.BaseItemDto import org.jellyfin.sdk.model.api.BaseItemDto
@ -24,19 +23,10 @@ fun BaseItemDto.toView(): View {
fun Resources.dip(px: Int) = (px * displayMetrics.density).toInt() fun Resources.dip(px: Int) = (px * displayMetrics.density).toInt()
fun ImageButton.setTintColor(@ColorRes colorId: Int, theme: Resources.Theme) { fun MaterialButton.setIconTintColorAttribute(@AttrRes attributeId: Int, theme: Resources.Theme) {
this.imageTintList = ColorStateList.valueOf(
resources.getColor(
colorId,
theme
)
)
}
fun ImageButton.setTintColorAttribute(@AttrRes attributeId: Int, theme: Resources.Theme) {
val typedValue = TypedValue() val typedValue = TypedValue()
theme.resolveAttribute(attributeId, typedValue, true) theme.resolveAttribute(attributeId, typedValue, true)
this.imageTintList = ColorStateList.valueOf( this.iconTint = ColorStateList.valueOf(
resources.getColor( resources.getColor(
typedValue.resourceId, typedValue.resourceId,
theme theme