add episodes list to player [Part 1]
This commit is contained in:
		| @ -29,6 +29,7 @@ import kotlinx.coroutines.launch | ||||
| import kotlinx.coroutines.withContext | ||||
| import org.mosad.teapod.R | ||||
| import org.mosad.teapod.preferences.Preferences | ||||
| import org.mosad.teapod.ui.components.EpisodesPlayer | ||||
| import org.mosad.teapod.util.DataTypes | ||||
| import org.mosad.teapod.util.Episode | ||||
| import java.util.* | ||||
| @ -151,6 +152,7 @@ class PlayerActivity : AppCompatActivity() { | ||||
|                 } | ||||
|  | ||||
|                 if (state == ExoPlayer.STATE_ENDED && model.nextEpisode != null && Preferences.autoplay) { | ||||
|                     // if next episode btn was clicked, skipp playNextEpisode() on STATE_ENDED | ||||
|                     if (nextEpManually) { | ||||
|                         nextEpManually = false | ||||
|                     } else { | ||||
| @ -187,6 +189,7 @@ class PlayerActivity : AppCompatActivity() { | ||||
|         ffwd_10.setOnButtonClickListener { fastForward() } | ||||
|         button_next_ep.setOnClickListener { playNextEpisode() } | ||||
|         button_next_ep_c.setOnClickListener { playNextEpisode() } | ||||
|         button_episodes.setOnClickListener { showEpisodesList() } | ||||
|     } | ||||
|  | ||||
|     private fun initTimeUpdates() { | ||||
| @ -314,7 +317,11 @@ class PlayerActivity : AppCompatActivity() { | ||||
|     private fun playCurrentMedia(seekToPosition: Boolean) { | ||||
|         // update the gui | ||||
|         exo_text_title.text = if (model.media.type == DataTypes.MediaType.TVSHOW) { | ||||
|             getString(R.string.component_episode_title, model.currentEpisode.number, model.currentEpisode.description) | ||||
|             getString( | ||||
|                 R.string.component_episode_title, | ||||
|                 model.currentEpisode.number, | ||||
|                 model.currentEpisode.description | ||||
|             ) | ||||
|         } else { | ||||
|             model.currentEpisode.title | ||||
|         } | ||||
| @ -401,6 +408,11 @@ class PlayerActivity : AppCompatActivity() { | ||||
|  | ||||
|     } | ||||
|  | ||||
|     private fun showEpisodesList() { | ||||
|         val rootView = window.decorView.rootView as ViewGroup | ||||
|         EpisodesPlayer(rootView, model) | ||||
|     } | ||||
|  | ||||
|     inner class PlayerGestureListener : GestureDetector.SimpleOnGestureListener() { | ||||
|  | ||||
|         /** | ||||
|  | ||||
| @ -0,0 +1,37 @@ | ||||
| package org.mosad.teapod.ui.components | ||||
|  | ||||
| import android.view.LayoutInflater | ||||
| import android.view.ViewGroup | ||||
| import org.mosad.teapod.databinding.PlayerEpisodesBinding | ||||
| import org.mosad.teapod.player.PlayerViewModel | ||||
| import org.mosad.teapod.util.adapter.PlayerEpisodeItemAdapter | ||||
|  | ||||
| /** | ||||
|  * TODO toggle play/pause on close/open | ||||
|  * TODO play selected episode | ||||
|  * TODO scroll to current episode | ||||
|  */ | ||||
| class EpisodesPlayer(val parent: ViewGroup, private val model: PlayerViewModel) { | ||||
|  | ||||
|     private val binding = PlayerEpisodesBinding.inflate(LayoutInflater.from(parent.context), parent, true) | ||||
|     private var adapterRecEpisodes = PlayerEpisodeItemAdapter(model.media.episodes) | ||||
|  | ||||
|     init { | ||||
|         binding.recyclerEpisodesPlayer.adapter = adapterRecEpisodes | ||||
|  | ||||
|         initActions() | ||||
|     } | ||||
|  | ||||
|     private fun initActions() { | ||||
|         binding.buttonCloseEpisodesList.setOnClickListener { | ||||
|             parent.removeView(binding.root) | ||||
|         } | ||||
|  | ||||
|         adapterRecEpisodes.onImageClick = { _, position -> | ||||
|             println(model.media.episodes[position]) | ||||
|             //playEpisode(media.episodes[position]) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
| @ -0,0 +1,52 @@ | ||||
| package org.mosad.teapod.util.adapter | ||||
|  | ||||
| import android.view.LayoutInflater | ||||
| import android.view.ViewGroup | ||||
| import androidx.recyclerview.widget.RecyclerView | ||||
| import com.bumptech.glide.Glide | ||||
| import com.bumptech.glide.request.RequestOptions | ||||
| import jp.wasabeef.glide.transformations.RoundedCornersTransformation | ||||
| import org.mosad.teapod.R | ||||
| import org.mosad.teapod.databinding.ItemEpisodePlayerBinding | ||||
| import org.mosad.teapod.util.Episode | ||||
|  | ||||
| class PlayerEpisodeItemAdapter(private val episodes: List<Episode>) : RecyclerView.Adapter<PlayerEpisodeItemAdapter.EpisodeViewHolder>() { | ||||
|  | ||||
|     var onImageClick: ((String, Int) -> Unit)? = null | ||||
|  | ||||
|     override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): EpisodeViewHolder { | ||||
|         return EpisodeViewHolder(ItemEpisodePlayerBinding.inflate(LayoutInflater.from(parent.context), parent, false)) | ||||
|     } | ||||
|  | ||||
|     override fun onBindViewHolder(holder: EpisodeViewHolder, position: Int) { | ||||
|         val context = holder.binding.root.context | ||||
|         val ep = episodes[position] | ||||
|  | ||||
|         val titleText = if (ep.priStreamUrl.isEmpty() && ep.secStreamOmU) { | ||||
|             context.getString(R.string.component_episode_title_sub, ep.number, ep.description) | ||||
|         } else { | ||||
|             context.getString(R.string.component_episode_title, ep.number, ep.description) | ||||
|         } | ||||
|  | ||||
|         holder.binding.textEpisodeTitle2.text = titleText | ||||
|         holder.binding.textEpisodeDesc2.text = ep.shortDesc | ||||
|  | ||||
|         if (episodes[position].posterUrl.isNotEmpty()) { | ||||
|             Glide.with(context).load(ep.posterUrl) | ||||
|                 .apply(RequestOptions.bitmapTransform(RoundedCornersTransformation(10, 0))) | ||||
|                 .into(holder.binding.imageEpisode) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     override fun getItemCount(): Int { | ||||
|         return episodes.size | ||||
|     } | ||||
|  | ||||
|     inner class EpisodeViewHolder(val binding: ItemEpisodePlayerBinding) : RecyclerView.ViewHolder(binding.root) { | ||||
|         init { | ||||
|             binding.imageEpisode.setOnClickListener { | ||||
|                 onImageClick?.invoke(episodes[adapterPosition].title, adapterPosition) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -1,6 +1,5 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     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" | ||||
|  | ||||
							
								
								
									
										50
									
								
								app/src/main/res/layout/item_episode_player.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								app/src/main/res/layout/item_episode_player.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,50 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     xmlns:app="http://schemas.android.com/apk/res-auto" | ||||
|     xmlns:tools="http://schemas.android.com/tools" | ||||
|     android:layout_width="wrap_content" | ||||
|     android:layout_height="match_parent" | ||||
|     android:orientation="vertical" | ||||
|     android:padding="7dp" > | ||||
|  | ||||
|     <FrameLayout | ||||
|         android:layout_width="wrap_content" | ||||
|         android:layout_height="wrap_content"> | ||||
|  | ||||
|         <com.google.android.material.imageview.ShapeableImageView | ||||
|             android:id="@+id/image_episode" | ||||
|             android:layout_width="192dp" | ||||
|             android:layout_height="108dp" | ||||
|             android:contentDescription="@string/component_poster_desc" | ||||
|             app:shapeAppearance="@style/ShapeAppearance.Teapod.RoundedPoster" | ||||
|             app:srcCompat="@color/md_disabled_text_dark_theme" /> | ||||
|  | ||||
|         <ImageView | ||||
|             android:id="@+id/image_episode_play" | ||||
|             android:layout_width="wrap_content" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:layout_gravity="center" | ||||
|             android:background="@drawable/bg_circle__black_transparent_24dp" | ||||
|             android:contentDescription="@string/button_play" | ||||
|             app:srcCompat="@drawable/ic_baseline_play_arrow_24" | ||||
|             app:tint="#FFFFFF" /> | ||||
|     </FrameLayout> | ||||
|  | ||||
|     <TextView | ||||
|         android:id="@+id/text_episode_title2" | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_marginTop="7dp" | ||||
|         android:text="@string/component_episode_title" | ||||
|         android:textColor="@color/textPrimaryDark" | ||||
|         android:textSize="16sp" /> | ||||
|  | ||||
|     <TextView | ||||
|         android:id="@+id/text_episode_desc2" | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="match_parent" | ||||
|         android:layout_marginTop="5dp" | ||||
|         android:text="@string/text_overview_ex" | ||||
|         android:textColor="@color/textPrimaryDark"/> | ||||
|  | ||||
| </LinearLayout> | ||||
							
								
								
									
										43
									
								
								app/src/main/res/layout/player_episodes.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								app/src/main/res/layout/player_episodes.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,43 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     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:background="#73000000"> | ||||
|  | ||||
|     <LinearLayout | ||||
|         android:id="@+id/linearLayout3" | ||||
|         android:layout_width="0dp" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_marginStart="12dp" | ||||
|         android:layout_marginTop="7dp" | ||||
|         android:layout_marginEnd="12dp" | ||||
|         android:orientation="horizontal" | ||||
|         app:layout_constraintEnd_toEndOf="parent" | ||||
|         app:layout_constraintStart_toStartOf="parent" | ||||
|         app:layout_constraintTop_toTopOf="parent"> | ||||
|  | ||||
|         <ImageButton | ||||
|             android:id="@+id/button_close_episodes_list" | ||||
|             style="@style/ExoStyledControls.Button.Center" | ||||
|             android:layout_width="44dp" | ||||
|             android:layout_height="44dp" | ||||
|             android:contentDescription="@string/close_player" | ||||
|             android:padding="10dp" | ||||
|             app:srcCompat="@drawable/ic_baseline_arrow_back_24" /> | ||||
|     </LinearLayout> | ||||
|  | ||||
|     <androidx.recyclerview.widget.RecyclerView | ||||
|         android:id="@+id/recycler_episodes_player" | ||||
|         android:layout_width="0dp" | ||||
|         android:layout_height="0dp" | ||||
|         android:orientation="horizontal" | ||||
|         app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" | ||||
|         app:layout_constraintBottom_toBottomOf="parent" | ||||
|         app:layout_constraintEnd_toEndOf="parent" | ||||
|         app:layout_constraintStart_toStartOf="parent" | ||||
|         app:layout_constraintTop_toBottomOf="@+id/linearLayout3" | ||||
|         tools:listitem="@layout/item_episode_player" /> | ||||
|  | ||||
| </androidx.constraintlayout.widget.ConstraintLayout> | ||||
		Reference in New Issue
	
	Block a user