2020-10-14 20:22:20 +02:00
package org.mosad.teapod.util.adapter
2020-10-12 09:54:32 +02:00
2021-01-11 22:12:21 +01:00
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
2022-01-05 01:28:39 +01:00
import android.graphics.drawable.Drawable
2020-10-12 09:54:32 +02:00
import android.view.LayoutInflater
2022-04-03 14:57:14 +02:00
import android.view.View
2020-10-12 09:54:32 +02:00
import android.view.ViewGroup
2022-01-05 01:28:39 +01:00
import androidx.core.content.ContextCompat
2020-10-12 09:54:32 +02:00
import androidx.recyclerview.widget.RecyclerView
2020-10-13 15:56:07 +02:00
import com.bumptech.glide.Glide
2020-10-14 18:33:02 +02:00
import com.bumptech.glide.request.RequestOptions
import jp.wasabeef.glide.transformations.RoundedCornersTransformation
2020-10-12 09:54:32 +02:00
import org.mosad.teapod.R
2020-11-25 22:35:55 +01:00
import org.mosad.teapod.databinding.ItemEpisodeBinding
2022-04-10 21:24:09 +02:00
import org.mosad.teapod.databinding.ItemEpisodePlayerBinding
2021-12-29 19:36:33 +01:00
import org.mosad.teapod.parser.crunchyroll.Episode
2022-04-10 21:24:09 +02:00
import org.mosad.teapod.parser.crunchyroll.PlayheadObject
2022-01-05 01:28:39 +01:00
import org.mosad.teapod.parser.crunchyroll.PlayheadsMap
2021-07-25 19:15:31 +02:00
import org.mosad.teapod.util.tmdb.TMDBTVEpisode
2020-10-12 09:54:32 +02:00
2022-01-05 01:28:39 +01:00
class EpisodeItemAdapter (
private val episodes : List < Episode > ,
private val tmdbEpisodes : List < TMDBTVEpisode > ? ,
2022-04-10 21:24:09 +02:00
private val playheads : PlayheadsMap ,
private val onClickListener : OnClickListener ,
private val viewType : ViewType
) : RecyclerView . Adapter < RecyclerView . ViewHolder > ( ) {
2020-10-12 09:54:32 +02:00
2022-04-10 21:24:09 +02:00
var currentSelected : Int = - 1 // -1, since position should never be < 0
2020-10-12 09:54:32 +02:00
2022-04-10 21:24:09 +02:00
override fun onCreateViewHolder ( parent : ViewGroup , viewType : Int ) : RecyclerView . ViewHolder {
return when ( viewType ) {
ViewType . PLAYER . ordinal -> {
PlayerEpisodeViewHolder ( ( ItemEpisodePlayerBinding . inflate ( LayoutInflater . from ( parent . context ) , parent , false ) ) )
}
else -> {
// media fragment episode list is default
EpisodeViewHolder ( ItemEpisodeBinding . inflate ( LayoutInflater . from ( parent . context ) , parent , false ) )
2021-12-29 20:51:53 +01:00
}
2020-10-19 21:57:02 +02:00
}
2022-04-10 21:24:09 +02:00
}
2020-10-19 21:57:02 +02:00
2022-04-10 21:24:09 +02:00
override fun onBindViewHolder ( holder : RecyclerView . ViewHolder , position : Int ) {
val episode = episodes [ position ]
val playhead = playheads [ episode . id ]
val tmdbEpisode = tmdbEpisodes ?. getOrNull ( position )
2020-10-13 20:23:55 +02:00
2022-04-10 21:24:09 +02:00
when ( holder . itemViewType ) {
ViewType . MEDIA_FRAGMENT . ordinal -> {
( holder as EpisodeViewHolder ) . bind ( episode , playhead , tmdbEpisode )
}
ViewType . PLAYER . ordinal -> {
2022-04-15 17:47:17 +02:00
( holder as PlayerEpisodeViewHolder ) . bind ( episode , playhead , currentSelected )
2022-04-10 21:24:09 +02:00
}
2020-10-13 20:23:55 +02:00
}
2022-04-10 21:24:09 +02:00
}
2020-10-13 15:56:07 +02:00
2022-04-10 21:24:09 +02:00
override fun getItemViewType ( position : Int ) : Int {
return when ( viewType ) {
ViewType . MEDIA _FRAGMENT -> ViewType . MEDIA_FRAGMENT . ordinal
ViewType . PLAYER -> ViewType . PLAYER . ordinal
2022-01-05 01:28:39 +01:00
}
2020-10-12 09:54:32 +02:00
}
override fun getItemCount ( ) : Int {
2021-12-29 19:36:33 +01:00
return episodes . size
2020-10-12 09:54:32 +02:00
}
2021-12-20 22:14:58 +01:00
inner class EpisodeViewHolder ( val binding : ItemEpisodeBinding ) :
RecyclerView . ViewHolder ( binding . root ) {
2022-04-10 21:24:09 +02:00
fun bind ( episode : Episode , playhead : PlayheadObject ? , tmdbEpisode : TMDBTVEpisode ? ) {
val context = binding . root . context
val titleText = if ( episode . episodeNumber != null ) {
// for tv shows add ep prefix and episode number
if ( episode . isDubbed ) {
context . getString ( R . string . component _episode _title , episode . episode , episode . title )
} else {
context . getString ( R . string . component _episode _title _sub , episode . episode , episode . title )
}
} else {
episode . title
}
binding . textEpisodeTitle . text = titleText
binding . textEpisodeDesc . text = episode . description . ifEmpty {
tmdbEpisode ?. overview ?: " "
}
if ( episode . images . thumbnail [ 0 ] [ 0 ] . source . isNotEmpty ( ) ) {
Glide . with ( context ) . load ( episode . images . thumbnail [ 0 ] [ 0 ] . source )
. apply ( RequestOptions . placeholderOf ( ColorDrawable ( Color . DKGRAY ) ) )
. apply ( RequestOptions . bitmapTransform ( RoundedCornersTransformation ( 10 , 0 ) ) )
. into ( binding . imageEpisode )
}
// add watched progress
val playheadProgress = playhead ?. playhead ?. let {
( ( it . toFloat ( ) / ( episode . durationMs / 1000 ) ) * 100 ) . toInt ( )
} ?: 0
binding . progressPlayhead . setProgressCompat ( playheadProgress , false )
binding . progressPlayhead . visibility = if ( playheadProgress <= 0 )
View . GONE else View . VISIBLE
// add watched icon to episode, if the episode id is present in playheads and fullyWatched
val watchedImage : Drawable ? = if ( playhead ?. fullyWatched == true ) {
ContextCompat . getDrawable ( context , R . drawable . ic _baseline _check _circle _24 )
} else {
null
}
binding . imageWatched . setImageDrawable ( watchedImage )
2020-11-25 22:35:55 +01:00
binding . imageEpisode . setOnClickListener {
2022-04-10 21:24:09 +02:00
onClickListener . onClick ( episode )
2020-10-16 10:05:11 +02:00
}
2020-10-12 09:54:32 +02:00
}
}
2022-04-10 21:24:09 +02:00
inner class PlayerEpisodeViewHolder ( val binding : ItemEpisodePlayerBinding ) :
RecyclerView . ViewHolder ( binding . root ) {
// -1, since position should never be < 0
2022-04-15 17:47:17 +02:00
fun bind ( episode : Episode , playhead : PlayheadObject ? , currentSelected : Int ) {
2022-04-10 21:24:09 +02:00
val context = binding . root . context
val titleText = if ( episode . episodeNumber != null ) {
// for tv shows add ep prefix and episode number
if ( episode . isDubbed ) {
context . getString ( R . string . component _episode _title , episode . episode , episode . title )
} else {
context . getString ( R . string . component _episode _title _sub , episode . episode , episode . title )
}
} else {
episode . title
}
binding . textEpisodeTitle2 . text = titleText
binding . textEpisodeDesc2 . text = episode . description . ifEmpty { " " }
if ( episode . images . thumbnail [ 0 ] [ 0 ] . source . isNotEmpty ( ) ) {
Glide . with ( context ) . load ( episode . images . thumbnail [ 0 ] [ 0 ] . source )
. apply ( RequestOptions . bitmapTransform ( RoundedCornersTransformation ( 10 , 0 ) ) )
. into ( binding . imageEpisode )
}
2022-04-15 17:47:17 +02:00
// add watched progress
val playheadProgress = playhead ?. playhead ?. let {
( ( it . toFloat ( ) / ( episode . durationMs / 1000 ) ) * 100 ) . toInt ( )
} ?: 0
binding . progressPlayhead . setProgressCompat ( playheadProgress , false )
binding . progressPlayhead . visibility = if ( playheadProgress <= 0 )
View . GONE else View . VISIBLE
2022-04-10 21:24:09 +02:00
// hide the play icon, if it's the current episode
binding . imageEpisodePlay . visibility = if ( currentSelected == bindingAdapterPosition ) {
View . GONE
} else {
View . VISIBLE
}
if ( currentSelected != bindingAdapterPosition ) {
binding . imageEpisode . setOnClickListener {
onClickListener . onClick ( episode )
}
}
}
}
class OnClickListener ( val clickListener : ( episode : Episode ) -> Unit ) {
fun onClick ( episode : Episode ) = clickListener ( episode )
}
enum class ViewType {
MEDIA _FRAGMENT ,
PLAYER
}
2020-10-12 09:54:32 +02:00
}