package ani.dantotsu.media import android.annotation.SuppressLint import android.content.Intent import android.graphics.Bitmap import android.graphics.Canvas import android.graphics.drawable.BitmapDrawable import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.view.animation.AccelerateDecelerateInterpolator import android.widget.ImageView import androidx.appcompat.content.res.AppCompatResources import androidx.core.app.ActivityOptionsCompat import androidx.core.content.ContextCompat import androidx.core.view.ViewCompat import androidx.core.view.isVisible import androidx.core.view.updateLayoutParams import androidx.fragment.app.FragmentActivity import androidx.recyclerview.widget.RecyclerView import androidx.viewpager2.widget.ViewPager2 import ani.dantotsu.R import ani.dantotsu.blurImage import ani.dantotsu.currActivity import ani.dantotsu.databinding.ItemMediaCompactBinding import ani.dantotsu.databinding.ItemMediaLargeBinding import ani.dantotsu.databinding.ItemMediaPageBinding import ani.dantotsu.databinding.ItemMediaPageSmallBinding import ani.dantotsu.loadImage import ani.dantotsu.setAnimation import ani.dantotsu.setSafeOnClickListener import ani.dantotsu.settings.saving.PrefManager import ani.dantotsu.settings.saving.PrefName import com.flaviofaria.kenburnsview.RandomTransitionGenerator import java.io.Serializable class MediaAdaptor( var type: Int, private val mediaList: MutableList?, private val activity: FragmentActivity, private val matchParent: Boolean = false, private val viewPager: ViewPager2? = null, private val fav: Boolean = false, ) : RecyclerView.Adapter() { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { return when (type) { 0 -> MediaViewHolder( ItemMediaCompactBinding.inflate( LayoutInflater.from(parent.context), parent, false ) ) 1 -> MediaLargeViewHolder( ItemMediaLargeBinding.inflate( LayoutInflater.from(parent.context), parent, false ) ) 2 -> MediaPageViewHolder( ItemMediaPageBinding.inflate( LayoutInflater.from(parent.context), parent, false ) ) 3 -> MediaPageSmallViewHolder( ItemMediaPageSmallBinding.inflate( LayoutInflater.from(parent.context), parent, false ) ) else -> throw IllegalArgumentException() } } @SuppressLint("ClickableViewAccessibility") override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { when (type) { 0 -> { val b = (holder as MediaViewHolder).binding setAnimation(activity, b.root) val media = mediaList?.getOrNull(position) if (media != null) { b.itemCompactImage.loadImage(media.cover) b.itemCompactOngoing.isVisible = media.status == currActivity()!!.getString(R.string.status_releasing) b.itemCompactTitle.text = media.userPreferredName b.itemCompactScore.text = ((if (media.userScore == 0) (media.meanScore ?: 0) else media.userScore) / 10.0).toString() b.itemCompactScoreBG.background = ContextCompat.getDrawable( b.root.context, (if (media.userScore != 0) R.drawable.item_user_score else R.drawable.item_score) ) b.itemCompactUserProgress.text = (media.userProgress ?: "~").toString() if (media.relation != null) { b.itemCompactRelation.text = "${media.relation} " b.itemCompactType.visibility = View.VISIBLE } else { b.itemCompactType.visibility = View.GONE } if (media.anime != null) { if (media.relation != null) b.itemCompactTypeImage.setImageDrawable( AppCompatResources.getDrawable( activity, R.drawable.ic_round_movie_filter_24 ) ) b.itemCompactTotal.text = " | ${if (media.anime.nextAiringEpisode != null) (media.anime.nextAiringEpisode.toString() + " | " + (media.anime.totalEpisodes ?: "~").toString()) else (media.anime.totalEpisodes ?: "~").toString()}" } else if (media.manga != null) { if (media.relation != null) b.itemCompactTypeImage.setImageDrawable( AppCompatResources.getDrawable( activity, R.drawable.ic_round_import_contacts_24 ) ) b.itemCompactTotal.text = " | ${media.manga.totalChapters ?: "~"}" } b.itemCompactProgressContainer.visibility = if (fav) View.GONE else View.VISIBLE } } 1 -> { val b = (holder as MediaLargeViewHolder).binding setAnimation(activity, b.root) val media = mediaList?.get(position) if (media != null) { b.itemCompactImage.loadImage(media.cover) blurImage(b.itemCompactBanner, media.banner ?: media.cover) b.itemCompactOngoing.isVisible = media.status == currActivity()!!.getString(R.string.status_releasing) b.itemCompactTitle.text = media.userPreferredName b.itemCompactScore.text = ((if (media.userScore == 0) (media.meanScore ?: 0) else media.userScore) / 10.0).toString() b.itemCompactScoreBG.background = ContextCompat.getDrawable( b.root.context, (if (media.userScore != 0) R.drawable.item_user_score else R.drawable.item_score) ) if (media.anime != null) { val itemTotal = " " + if ((media.anime.totalEpisodes ?: 0) != 1) currActivity()!!.getString(R.string.episode_plural) else currActivity()!!.getString(R.string.episode_singular) b.itemTotal.text = itemTotal b.itemCompactTotal.text = if (media.anime.nextAiringEpisode != null) (media.anime.nextAiringEpisode.toString() + " / " + (media.anime.totalEpisodes ?: "??").toString()) else (media.anime.totalEpisodes ?: "??").toString() } else if (media.manga != null) { val itemTotal = " " + if ((media.manga.totalChapters ?: 0) != 1) currActivity()!!.getString(R.string.chapter_plural) else currActivity()!!.getString(R.string.chapter_singular) b.itemTotal.text = itemTotal b.itemCompactTotal.text = "${media.manga.totalChapters ?: "??"}" } if (position == mediaList!!.size - 2 && viewPager != null) viewPager.post { val start = mediaList.size mediaList.addAll(mediaList) val end = mediaList.size - start notifyItemRangeInserted(start, end) } } } 2 -> { val b = (holder as MediaPageViewHolder).binding val media = mediaList?.get(position) if (media != null) { val bannerAnimations: Boolean = PrefManager.getVal(PrefName.BannerAnimations) b.itemCompactImage.loadImage(media.cover) if (bannerAnimations) b.itemCompactBanner.setTransitionGenerator( RandomTransitionGenerator( (10000 + 15000 * ((PrefManager.getVal(PrefName.AnimationSpeed)) as Float)).toLong(), AccelerateDecelerateInterpolator() ) ) blurImage(if (bannerAnimations) b.itemCompactBanner else b.itemCompactBannerNoKen , media.banner ?: media.cover) b.itemCompactOngoing.isVisible = media.status == currActivity()!!.getString(R.string.status_releasing) b.itemCompactTitle.text = media.userPreferredName b.itemCompactScore.text = ((if (media.userScore == 0) (media.meanScore ?: 0) else media.userScore) / 10.0).toString() b.itemCompactScoreBG.background = ContextCompat.getDrawable( b.root.context, (if (media.userScore != 0) R.drawable.item_user_score else R.drawable.item_score) ) if (media.anime != null) { b.itemTotal.text = " " + if ((media.anime.totalEpisodes ?: 0) != 1 ) currActivity()!!.getString(R.string.episode_plural) else currActivity()!!.getString(R.string.episode_singular) b.itemCompactTotal.text = if (media.anime.nextAiringEpisode != null) (media.anime.nextAiringEpisode.toString() + " / " + (media.anime.totalEpisodes ?: "??").toString()) else (media.anime.totalEpisodes ?: "??").toString() } else if (media.manga != null) { b.itemTotal.text = " " + if ((media.manga.totalChapters ?: 0) != 1 ) currActivity()!!.getString(R.string.chapter_plural) else currActivity()!!.getString(R.string.chapter_singular) b.itemCompactTotal.text = "${media.manga.totalChapters ?: "??"}" } @SuppressLint("NotifyDataSetChanged") if (position == mediaList!!.size - 2 && viewPager != null) viewPager.post { val size = mediaList.size mediaList.addAll(mediaList) notifyItemRangeInserted(size - 1, mediaList.size) } } } 3 -> { val b = (holder as MediaPageSmallViewHolder).binding val media = mediaList?.get(position) if (media != null) { val bannerAnimations: Boolean = PrefManager.getVal(PrefName.BannerAnimations) b.itemCompactImage.loadImage(media.cover) if (bannerAnimations) b.itemCompactBanner.setTransitionGenerator( RandomTransitionGenerator( (10000 + 15000 * ((PrefManager.getVal(PrefName.AnimationSpeed) as Float))).toLong(), AccelerateDecelerateInterpolator() ) ) blurImage(if (bannerAnimations) b.itemCompactBanner else b.itemCompactBannerNoKen , media.banner ?: media.cover) b.itemCompactOngoing.isVisible = media.status == currActivity()!!.getString(R.string.status_releasing) b.itemCompactTitle.text = media.userPreferredName b.itemCompactScore.text = ((if (media.userScore == 0) (media.meanScore ?: 0) else media.userScore) / 10.0).toString() b.itemCompactScoreBG.background = ContextCompat.getDrawable( b.root.context, (if (media.userScore != 0) R.drawable.item_user_score else R.drawable.item_score) ) media.genres.apply { if (isNotEmpty()) { var genres = "" forEach { genres += "$it • " } genres = genres.removeSuffix(" • ") b.itemCompactGenres.text = genres } } b.itemCompactStatus.text = media.status ?: "" if (media.anime != null) { b.itemTotal.text = " " + if ((media.anime.totalEpisodes ?: 0) != 1 ) currActivity()!!.getString(R.string.episode_plural) else currActivity()!!.getString(R.string.episode_singular) b.itemCompactTotal.text = if (media.anime.nextAiringEpisode != null) (media.anime.nextAiringEpisode.toString() + " / " + (media.anime.totalEpisodes ?: "??").toString()) else (media.anime.totalEpisodes ?: "??").toString() } else if (media.manga != null) { b.itemTotal.text = " " + if ((media.manga.totalChapters ?: 0) != 1 ) currActivity()!!.getString(R.string.chapter_plural) else currActivity()!!.getString(R.string.chapter_singular) b.itemCompactTotal.text = "${media.manga.totalChapters ?: "??"}" } @SuppressLint("NotifyDataSetChanged") if (position == mediaList!!.size - 2 && viewPager != null) viewPager.post { val size = mediaList.size mediaList.addAll(mediaList) notifyItemRangeInserted(size - 1, mediaList.size) } } } } } override fun getItemCount() = mediaList!!.size override fun getItemViewType(position: Int): Int { return type } fun randomOptionClick() { val media = if (!mediaList.isNullOrEmpty()) { mediaList.random() } else { null } media?.let { val index = mediaList?.indexOf(it) ?: -1 clicked(index, null) } } inner class MediaViewHolder(val binding: ItemMediaCompactBinding) : RecyclerView.ViewHolder(binding.root) { init { if (matchParent) itemView.updateLayoutParams { width = -1 } itemView.setSafeOnClickListener { clicked( bindingAdapterPosition, binding.itemCompactImage, resizeBitmap(getBitmapFromImageView(binding.itemCompactImage), 100) ) } itemView.setOnLongClickListener { longClicked(bindingAdapterPosition) } } } inner class MediaLargeViewHolder(val binding: ItemMediaLargeBinding) : RecyclerView.ViewHolder(binding.root) { init { itemView.setSafeOnClickListener { clicked( bindingAdapterPosition, binding.itemCompactImage, resizeBitmap(getBitmapFromImageView(binding.itemCompactImage), 100) ) } itemView.setOnLongClickListener { longClicked(bindingAdapterPosition) } } } @SuppressLint("ClickableViewAccessibility") inner class MediaPageViewHolder(val binding: ItemMediaPageBinding) : RecyclerView.ViewHolder(binding.root) { init { binding.itemCompactImage.setSafeOnClickListener { clicked( bindingAdapterPosition, binding.itemCompactImage, resizeBitmap(getBitmapFromImageView(binding.itemCompactImage), 100) ) } itemView.setOnTouchListener { _, _ -> true } binding.itemCompactImage.setOnLongClickListener { longClicked(bindingAdapterPosition) } } } @SuppressLint("ClickableViewAccessibility") inner class MediaPageSmallViewHolder(val binding: ItemMediaPageSmallBinding) : RecyclerView.ViewHolder(binding.root) { init { binding.itemCompactImage.setSafeOnClickListener { clicked( bindingAdapterPosition, binding.itemCompactImage, resizeBitmap(getBitmapFromImageView(binding.itemCompactImage), 100) ) } binding.itemCompactTitleContainer.setSafeOnClickListener { clicked( bindingAdapterPosition, binding.itemCompactImage, resizeBitmap(getBitmapFromImageView(binding.itemCompactImage), 100) ) } itemView.setOnTouchListener { _, _ -> true } binding.itemCompactImage.setOnLongClickListener { longClicked(bindingAdapterPosition) } } } fun clicked(position: Int, itemCompactImage: ImageView?, bitmap: Bitmap? = null) { if ((mediaList?.size ?: 0) > position && position != -1) { val media = mediaList?.get(position) if (bitmap != null) MediaSingleton.bitmap = bitmap ContextCompat.startActivity( activity, Intent(activity, MediaDetailsActivity::class.java).putExtra( "media", media as Serializable ), if (itemCompactImage != null) { ActivityOptionsCompat.makeSceneTransitionAnimation( activity, itemCompactImage, ViewCompat.getTransitionName(itemCompactImage)!! ).toBundle() } else { null } ) } } fun longClicked(position: Int): Boolean { if ((mediaList?.size ?: 0) > position && position != -1) { val media = mediaList?.get(position) ?: return false if (activity.supportFragmentManager.findFragmentByTag("list") == null) { MediaListDialogSmallFragment.newInstance(media) .show(activity.supportFragmentManager, "list") return true } } return false } fun getBitmapFromImageView(imageView: ImageView): Bitmap? { val drawable = imageView.drawable ?: return null // If the drawable is a BitmapDrawable, then just get the bitmap if (drawable is BitmapDrawable) { return drawable.bitmap } // Create a bitmap with the same dimensions as the drawable val bitmap = Bitmap.createBitmap( drawable.intrinsicWidth, drawable.intrinsicHeight, Bitmap.Config.ARGB_8888 ) // Draw the drawable onto the bitmap val canvas = Canvas(bitmap) drawable.setBounds(0, 0, canvas.width, canvas.height) drawable.draw(canvas) return bitmap } fun resizeBitmap(source: Bitmap?, maxDimension: Int): Bitmap? { if (source == null) return null val width = source.width val height = source.height val newWidth: Int val newHeight: Int if (width > height) { newWidth = maxDimension newHeight = (height * (maxDimension.toFloat() / width)).toInt() } else { newHeight = maxDimension newWidth = (width * (maxDimension.toFloat() / height)).toInt() } return Bitmap.createScaledBitmap(source, newWidth, newHeight, true) } }