tv layout stuff

This commit is contained in:
reduplicated 2022-08-06 01:41:35 +02:00
parent 33045c9115
commit fdaeffed0c
25 changed files with 710 additions and 188 deletions

View File

@ -260,10 +260,10 @@ object CommonActivity {
KeyEvent.KEYCODE_A, KeyEvent.KEYCODE_MEDIA_SKIP_BACKWARD, KeyEvent.KEYCODE_MEDIA_REWIND -> { KeyEvent.KEYCODE_A, KeyEvent.KEYCODE_MEDIA_SKIP_BACKWARD, KeyEvent.KEYCODE_MEDIA_REWIND -> {
PlayerEventType.SeekBack PlayerEventType.SeekBack
} }
KeyEvent.KEYCODE_MEDIA_NEXT, KeyEvent.KEYCODE_BUTTON_R1 -> { KeyEvent.KEYCODE_MEDIA_NEXT, KeyEvent.KEYCODE_BUTTON_R1, KeyEvent.KEYCODE_N -> {
PlayerEventType.NextEpisode PlayerEventType.NextEpisode
} }
KeyEvent.KEYCODE_MEDIA_PREVIOUS, KeyEvent.KEYCODE_BUTTON_L1 -> { KeyEvent.KEYCODE_MEDIA_PREVIOUS, KeyEvent.KEYCODE_BUTTON_L1, KeyEvent.KEYCODE_B -> {
PlayerEventType.PrevEpisode PlayerEventType.PrevEpisode
} }
KeyEvent.KEYCODE_MEDIA_PAUSE -> { KeyEvent.KEYCODE_MEDIA_PAUSE -> {
@ -294,6 +294,9 @@ object CommonActivity {
KeyEvent.KEYCODE_R, KeyEvent.KEYCODE_NUMPAD_0 -> { KeyEvent.KEYCODE_R, KeyEvent.KEYCODE_NUMPAD_0 -> {
PlayerEventType.Resize PlayerEventType.Resize
} }
KeyEvent.KEYCODE_C, KeyEvent.KEYCODE_NUMPAD_4 -> {
PlayerEventType.SkipOp
}
KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, KeyEvent.KEYCODE_P, KeyEvent.KEYCODE_SPACE, KeyEvent.KEYCODE_NUMPAD_ENTER, KeyEvent.KEYCODE_ENTER -> { // space is not captured due to navigation KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, KeyEvent.KEYCODE_P, KeyEvent.KEYCODE_SPACE, KeyEvent.KEYCODE_NUMPAD_ENTER, KeyEvent.KEYCODE_ENTER -> { // space is not captured due to navigation
PlayerEventType.PlayPauseToggle PlayerEventType.PlayPauseToggle
} }

View File

@ -98,7 +98,7 @@ class ParentItemAdapter(
recyclerView?.apply { recyclerView?.apply {
// this loops every viewHolder in the recycle view and checks the position to see if it is within the update range // this loops every viewHolder in the recycle view and checks the position to see if it is within the update range
val missingUpdates = (position until (position + count)).toMutableSet() val missingUpdates = (position until (position + count)).toMutableSet()
for (i in 0 until mAdapter.itemCount) { for (i in 0 until itemCount) {
val viewHolder = getChildViewHolder(getChildAt(i)) val viewHolder = getChildViewHolder(getChildAt(i))
val absolutePosition = viewHolder.absoluteAdapterPosition val absolutePosition = viewHolder.absoluteAdapterPosition
if (absolutePosition >= position && absolutePosition < position + count) { if (absolutePosition >= position && absolutePosition < position + count) {

View File

@ -1164,6 +1164,9 @@ open class FullScreenPlayer : AbstractPlayerFragment() {
openOnlineSubPicker(view.context, null) {} openOnlineSubPicker(view.context, null) {}
} }
} }
PlayerEventType.SkipOp -> {
skipOp()
}
} }
} }

View File

@ -23,6 +23,7 @@ enum class PlayerEventType(val value: Int) {
ShowMirrors(12), ShowMirrors(12),
Resize(13), Resize(13),
SearchSubtitlesOnline(14), SearchSubtitlesOnline(14),
SkipOp(15),
} }
enum class CSPlayerEvent(val value: Int) { enum class CSPlayerEvent(val value: Int) {

View File

@ -57,11 +57,11 @@ const val ACTION_DOWNLOAD_EPISODE_SUBTITLE_MIRROR = 14
data class EpisodeClickEvent(val action: Int, val data: ResultEpisode) data class EpisodeClickEvent(val action: Int, val data: ResultEpisode)
class EpisodeAdapter( class EpisodeAdapter(
private var cardList: MutableList<ResultEpisode>,
private val hasDownloadSupport: Boolean, private val hasDownloadSupport: Boolean,
private val clickCallback: (EpisodeClickEvent) -> Unit, private val clickCallback: (EpisodeClickEvent) -> Unit,
private val downloadClickCallback: (DownloadClickEvent) -> Unit, private val downloadClickCallback: (DownloadClickEvent) -> Unit,
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() { ) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private var cardList: MutableList<ResultEpisode> = mutableListOf()
private val mBoundViewHolders: HashSet<DownloadButtonViewHolder> = HashSet() private val mBoundViewHolders: HashSet<DownloadButtonViewHolder> = HashSet()
private fun getAllBoundViewHolders(): Set<DownloadButtonViewHolder?>? { private fun getAllBoundViewHolders(): Set<DownloadButtonViewHolder?>? {
@ -104,6 +104,8 @@ class EpisodeAdapter(
diffResult.dispatchUpdatesTo(this) diffResult.dispatchUpdatesTo(this)
} }
var layout = R.layout.result_episode_both
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
/*val layout = if (cardList.filter { it.poster != null }.size >= cardList.size / 2) /*val layout = if (cardList.filter { it.poster != null }.size >= cardList.size / 2)
R.layout.result_episode_large R.layout.result_episode_large
@ -111,7 +113,7 @@ class EpisodeAdapter(
return EpisodeCardViewHolder( return EpisodeCardViewHolder(
LayoutInflater.from(parent.context) LayoutInflater.from(parent.context)
.inflate(R.layout.result_episode_both, parent, false), .inflate(layout, parent, false),
hasDownloadSupport, hasDownloadSupport,
clickCallback, clickCallback,
downloadClickCallback downloadClickCallback
@ -149,6 +151,8 @@ class EpisodeAdapter(
fun bind(card: ResultEpisode) { fun bind(card: ResultEpisode) {
localCard = card localCard = card
val isTrueTv = itemView.context?.isTrueTvSettings() == true
val (parentView, otherView) = if (card.poster == null) { val (parentView, otherView) = if (card.poster == null) {
itemView.episode_holder to itemView.episode_holder_large itemView.episode_holder to itemView.episode_holder_large
} else { } else {
@ -199,20 +203,22 @@ class EpisodeAdapter(
} }
} }
episodePoster?.setOnClickListener { if (!isTrueTv) {
clickCallback.invoke(EpisodeClickEvent(ACTION_CLICK_DEFAULT, card)) episodePoster?.setOnClickListener {
} clickCallback.invoke(EpisodeClickEvent(ACTION_CLICK_DEFAULT, card))
}
episodePoster?.setOnLongClickListener { episodePoster?.setOnLongClickListener {
clickCallback.invoke(EpisodeClickEvent(ACTION_SHOW_TOAST, card)) clickCallback.invoke(EpisodeClickEvent(ACTION_SHOW_TOAST, card))
return@setOnLongClickListener true return@setOnLongClickListener true
}
} }
parentView.setOnClickListener { parentView.setOnClickListener {
clickCallback.invoke(EpisodeClickEvent(ACTION_CLICK_DEFAULT, card)) clickCallback.invoke(EpisodeClickEvent(ACTION_CLICK_DEFAULT, card))
} }
if (parentView.context.isTrueTvSettings()) { if (isTrueTv) {
parentView.isFocusable = true parentView.isFocusable = true
parentView.isFocusableInTouchMode = true parentView.isFocusableInTouchMode = true
parentView.touchscreenBlocksFocus = false parentView.touchscreenBlocksFocus = false

View File

@ -328,6 +328,98 @@ open class ResultFragment : ResultTrailerPlayer() {
viewModel.reloadEpisodes() viewModel.reloadEpisodes()
} }
open fun updateMovie(data : ResourceSome<Pair<UiText, ResultEpisode>>) {
when (data) {
is ResourceSome.Success -> {
data.value.let { (text, ep) ->
result_play_movie.setText(text)
result_play_movie?.setOnClickListener {
viewModel.handleAction(
activity,
EpisodeClickEvent(ACTION_CLICK_DEFAULT, ep)
)
}
result_play_movie?.setOnLongClickListener {
viewModel.handleAction(
activity,
EpisodeClickEvent(ACTION_SHOW_OPTIONS, ep)
)
return@setOnLongClickListener true
}
main {
val file =
ioWork {
context?.let {
VideoDownloadManager.getDownloadFileInfoAndUpdateSettings(
it,
ep.id
)
}
}
downloadButton?.dispose()
downloadButton = EasyDownloadButton()
downloadButton?.setUpMoreButton(
file?.fileLength,
file?.totalBytes,
result_movie_progress_downloaded,
result_movie_download_icon,
result_movie_download_text,
result_movie_download_text_precentage,
result_download_movie,
true,
VideoDownloadHelper.DownloadEpisodeCached(
ep.name,
ep.poster,
0,
null,
ep.id,
ep.id,
null,
null,
System.currentTimeMillis(),
)
) { click ->
when(click.action) {
DOWNLOAD_ACTION_DOWNLOAD -> {
viewModel.handleAction(
activity,
EpisodeClickEvent(ACTION_DOWNLOAD_EPISODE, ep)
)
}
else -> handleDownloadClick(activity, click)
}
}
result_movie_progress_downloaded_holder?.isVisible = true
}
}
}
else -> {
result_movie_progress_downloaded_holder?.isVisible = false
result_play_movie?.isVisible = false
}
}
}
open fun updateEpisodes(episodes : ResourceSome<List<ResultEpisode>>) {
when (episodes) {
is ResourceSome.None -> {
result_episode_loading?.isVisible = false
result_episodes?.isVisible = false
}
is ResourceSome.Loading -> {
result_episode_loading?.isVisible = true
result_episodes?.isVisible = false
}
is ResourceSome.Success -> {
result_episodes?.isVisible = true
result_episode_loading?.isVisible = false
(result_episodes?.adapter as? EpisodeAdapter?)?.updateList(episodes.value)
}
}
}
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
@ -401,24 +493,8 @@ open class ResultFragment : ResultTrailerPlayer() {
} }
} }
result_scroll.setOnScrollChangeListener(NestedScrollView.OnScrollChangeListener { _, _, scrollY, _, oldScrollY ->
val dy = scrollY - oldScrollY
if (dy > 0) { //check for scroll down
result_bookmark_fab?.shrink()
} else if (dy < -5) {
result_bookmark_fab?.extend()
}
if (!isFullScreenPlayer && player.getIsPlaying()) {
if (scrollY > (player_background?.height ?: scrollY)) {
player.handleEvent(CSPlayerEvent.Pause)
}
}
//result_poster_blur_holder?.translationY = -scrollY.toFloat()
})
result_episodes.adapter = result_episodes.adapter =
EpisodeAdapter( EpisodeAdapter(
ArrayList(),
api.hasDownloadSupport, api.hasDownloadSupport,
{ episodeClick -> { episodeClick ->
viewModel.handleAction(activity, episodeClick) viewModel.handleAction(activity, episodeClick)
@ -456,9 +532,10 @@ open class ResultFragment : ResultTrailerPlayer() {
} }
// This is to band-aid FireTV navigation // This is to band-aid FireTV navigation
result_season_button?.isFocusableInTouchMode = context?.isTvSettings() == true val isTv = context?.isTvSettings() == true
result_episode_select?.isFocusableInTouchMode = context?.isTvSettings() == true result_season_button?.isFocusableInTouchMode = isTv
result_dub_select?.isFocusableInTouchMode = context?.isTvSettings() == true result_episode_select?.isFocusableInTouchMode = isTv
result_dub_select?.isFocusableInTouchMode = isTv
context?.let { ctx -> context?.let { ctx ->
val arrayAdapter = ArrayAdapter<String>(ctx, R.layout.sort_bottom_single_choice) val arrayAdapter = ArrayAdapter<String>(ctx, R.layout.sort_bottom_single_choice)
@ -653,21 +730,7 @@ open class ResultFragment : ResultTrailerPlayer() {
} }
observe(viewModel.episodes) { episodes -> observe(viewModel.episodes) { episodes ->
when (episodes) { updateEpisodes(episodes)
is ResourceSome.None -> {
result_episode_loading?.isVisible = false
result_episodes?.isVisible = false
}
is ResourceSome.Loading -> {
result_episode_loading?.isVisible = true
result_episodes?.isVisible = false
}
is ResourceSome.Success -> {
result_episodes?.isVisible = true
result_episode_loading?.isVisible = false
(result_episodes?.adapter as? EpisodeAdapter?)?.updateList(episodes.value)
}
}
} }
result_cast_items?.setOnFocusChangeListener { _, hasFocus -> result_cast_items?.setOnFocusChangeListener { _, hasFocus ->
@ -692,77 +755,7 @@ open class ResultFragment : ResultTrailerPlayer() {
} }
observe(viewModel.movie) { data -> observe(viewModel.movie) { data ->
when (data) { updateMovie(data)
is ResourceSome.Success -> {
data.value.let { (text, ep) ->
result_play_movie.setText(text)
result_play_movie?.setOnClickListener {
viewModel.handleAction(
activity,
EpisodeClickEvent(ACTION_CLICK_DEFAULT, ep)
)
}
result_play_movie?.setOnLongClickListener {
viewModel.handleAction(
activity,
EpisodeClickEvent(ACTION_SHOW_OPTIONS, ep)
)
return@setOnLongClickListener true
}
main {
val file =
ioWork {
context?.let {
VideoDownloadManager.getDownloadFileInfoAndUpdateSettings(
it,
ep.id
)
}
}
downloadButton?.dispose()
downloadButton = EasyDownloadButton()
downloadButton?.setUpMoreButton(
file?.fileLength,
file?.totalBytes,
result_movie_progress_downloaded,
result_movie_download_icon,
result_movie_download_text,
result_movie_download_text_precentage,
result_download_movie,
true,
VideoDownloadHelper.DownloadEpisodeCached(
ep.name,
ep.poster,
0,
null,
ep.id,
ep.id,
null,
null,
System.currentTimeMillis(),
)
) { click ->
when(click.action) {
DOWNLOAD_ACTION_DOWNLOAD -> {
viewModel.handleAction(
activity,
EpisodeClickEvent(ACTION_DOWNLOAD_EPISODE, ep)
)
}
else -> handleDownloadClick(activity, click)
}
}
result_movie_progress_downloaded_holder?.isVisible = true
}
}
}
else -> {
result_movie_progress_downloaded_holder?.isVisible = false
result_play_movie?.isVisible = false
}
}
} }
observe(viewModel.page) { data -> observe(viewModel.page) { data ->

View File

@ -7,6 +7,7 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.view.isGone import androidx.core.view.isGone
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.core.widget.NestedScrollView
import com.discord.panels.OverlappingPanelsLayout import com.discord.panels.OverlappingPanelsLayout
import com.discord.panels.PanelsChildGestureRegionObserver import com.discord.panels.PanelsChildGestureRegionObserver
import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.bottomsheet.BottomSheetDialog
@ -18,6 +19,7 @@ import com.lagradost.cloudstream3.SearchResponse
import com.lagradost.cloudstream3.mvvm.Some import com.lagradost.cloudstream3.mvvm.Some
import com.lagradost.cloudstream3.mvvm.observe import com.lagradost.cloudstream3.mvvm.observe
import com.lagradost.cloudstream3.ui.WatchType import com.lagradost.cloudstream3.ui.WatchType
import com.lagradost.cloudstream3.ui.player.CSPlayerEvent
import com.lagradost.cloudstream3.ui.search.SearchAdapter import com.lagradost.cloudstream3.ui.search.SearchAdapter
import com.lagradost.cloudstream3.ui.search.SearchHelper import com.lagradost.cloudstream3.ui.search.SearchHelper
import com.lagradost.cloudstream3.utils.AppUtils.openBrowser import com.lagradost.cloudstream3.utils.AppUtils.openBrowser
@ -30,6 +32,7 @@ import com.lagradost.cloudstream3.utils.UIHelper.popupMenuNoIcons
import com.lagradost.cloudstream3.utils.UIHelper.popupMenuNoIconsAndNoStringRes import com.lagradost.cloudstream3.utils.UIHelper.popupMenuNoIconsAndNoStringRes
import kotlinx.android.synthetic.main.fragment_result.* import kotlinx.android.synthetic.main.fragment_result.*
import kotlinx.android.synthetic.main.fragment_result_swipe.* import kotlinx.android.synthetic.main.fragment_result_swipe.*
import kotlinx.android.synthetic.main.fragment_trailer.*
import kotlinx.android.synthetic.main.result_recommendations.* import kotlinx.android.synthetic.main.result_recommendations.*
import kotlinx.android.synthetic.main.trailer_custom_layout.* import kotlinx.android.synthetic.main.trailer_custom_layout.*
@ -129,10 +132,10 @@ class ResultFragmentPhone : ResultFragment() {
context?.openBrowser(it.url) context?.openBrowser(it.url)
} }
} }
result_recommendations?.spanCount = 3
result_overlapping_panels?.setStartPanelLockState(OverlappingPanelsLayout.LockState.CLOSE) result_overlapping_panels?.setStartPanelLockState(OverlappingPanelsLayout.LockState.CLOSE)
result_overlapping_panels?.setEndPanelLockState(OverlappingPanelsLayout.LockState.CLOSE) result_overlapping_panels?.setEndPanelLockState(OverlappingPanelsLayout.LockState.CLOSE)
result_recommendations?.spanCount = 3
result_recommendations?.adapter = result_recommendations?.adapter =
SearchAdapter( SearchAdapter(
ArrayList(), ArrayList(),
@ -175,6 +178,21 @@ class ResultFragmentPhone : ResultFragment() {
}) })
result_scroll?.setOnScrollChangeListener(NestedScrollView.OnScrollChangeListener { _, _, scrollY, _, oldScrollY ->
val dy = scrollY - oldScrollY
if (dy > 0) { //check for scroll down
result_bookmark_fab?.shrink()
} else if (dy < -5) {
result_bookmark_fab?.extend()
}
if (!isFullScreenPlayer && player.getIsPlaying()) {
if (scrollY > (player_background?.height ?: scrollY)) {
player.handleEvent(CSPlayerEvent.Pause)
}
}
//result_poster_blur_holder?.translationY = -scrollY.toFloat()
})
observe(viewModel.selectPopup) { popup -> observe(viewModel.selectPopup) { popup ->
when (popup) { when (popup) {
is Some.Success -> { is Some.Success -> {

View File

@ -1,11 +1,129 @@
package com.lagradost.cloudstream3.ui.result package com.lagradost.cloudstream3.ui.result
import android.os.Bundle
import android.view.View
import androidx.core.view.children
import androidx.core.view.isGone
import androidx.core.view.isVisible
import androidx.recyclerview.widget.RecyclerView
import com.discord.panels.OverlappingPanelsLayout
import com.lagradost.cloudstream3.DubStatus
import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.SearchResponse import com.lagradost.cloudstream3.SearchResponse
import com.lagradost.cloudstream3.mvvm.ResourceSome
import com.lagradost.cloudstream3.mvvm.observe
import com.lagradost.cloudstream3.ui.search.SearchAdapter
import com.lagradost.cloudstream3.ui.search.SearchHelper
import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showBottomDialog
import kotlinx.android.synthetic.main.fragment_result_swipe.*
import kotlinx.android.synthetic.main.fragment_result_tv.*
import kotlinx.android.synthetic.main.result_recommendations.*
class ResultFragmentTv : ResultFragment() { class ResultFragmentTv : ResultFragment() {
override val resultLayout = R.layout.fragment_result_tv override val resultLayout = R.layout.fragment_result_tv
override fun setRecommendations(rec: List<SearchResponse>?, validApiName: String?) {
private fun handleSelection(data: Any) {
when (data) {
is EpisodeRange -> {
viewModel.changeRange(data)
}
is Int -> {
viewModel.changeSeason(data)
}
is DubStatus -> {
viewModel.changeDubStatus(data)
}
}
}
private fun RecyclerView?.select(index: Int) {
(this?.adapter as? SelectAdaptor?)?.select(index, this)
}
private fun RecyclerView?.update(data: List<SelectData>) {
(this?.adapter as? SelectAdaptor?)?.updateSelectionList(data)
this?.isVisible = data.size > 1
}
private fun RecyclerView?.setAdapter() {
this?.adapter = SelectAdaptor { data ->
handleSelection(data)
}
}
private fun hasNoFocus(): Boolean {
val focus = activity?.currentFocus
if (focus == null || !focus.isVisible) return true
return focus == this.result_root
}
override fun updateEpisodes(episodes: ResourceSome<List<ResultEpisode>>) {
super.updateEpisodes(episodes)
if (episodes is ResourceSome.Success && hasNoFocus()) {
result_episodes?.requestFocus()
}
}
override fun updateMovie(data: ResourceSome<Pair<UiText, ResultEpisode>>) {
super.updateMovie(data)
if (data is ResourceSome.Success && hasNoFocus()) {
result_play_movie?.requestFocus()
}
}
override fun setRecommendations(rec: List<SearchResponse>?, validApiName: String?) {
val isInvalid = rec.isNullOrEmpty()
result_recommendations?.isGone = isInvalid
result_recommendations_btt?.isGone = isInvalid
val matchAgainst = validApiName ?: rec?.firstOrNull()?.apiName
(result_recommendations?.adapter as SearchAdapter?)?.updateList(rec?.filter { it.apiName == matchAgainst } ?: emptyList())
rec?.map { it.apiName }?.distinct()?.let { apiNames ->
// very dirty selection
result_recommendations_filter_button?.isVisible = apiNames.size > 1
result_recommendations_filter_button?.text = matchAgainst
} ?: run {
result_recommendations_filter_button?.isVisible = false
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
(result_episodes?.adapter as EpisodeAdapter?)?.apply {
layout = R.layout.result_episode_both_tv
}
result_season_selection.setAdapter()
result_range_selection.setAdapter()
result_dub_selection.setAdapter()
observe(viewModel.selectedRangeIndex) { selected ->
result_range_selection.select(selected)
}
observe(viewModel.selectedSeasonIndex) { selected ->
result_season_selection.select(selected)
}
observe(viewModel.selectedDubStatusIndex) { selected ->
result_dub_selection.select(selected)
}
observe(viewModel.rangeSelections) {
result_range_selection.update(it)
}
observe(viewModel.dubSubSelections) {
result_dub_selection.update(it)
}
observe(viewModel.seasonSelections) {
result_season_selection.update(it)
}
result_recommendations?.spanCount = 8
result_recommendations?.adapter =
SearchAdapter(
ArrayList(),
result_recommendations,
) { callback ->
SearchHelper.handleSearchClickCallback(activity, callback)
}
} }
} }

View File

@ -57,6 +57,7 @@ import com.lagradost.cloudstream3.utils.UIHelper.navigate
import com.lagradost.cloudstream3.utils.UIHelper.requestRW import com.lagradost.cloudstream3.utils.UIHelper.requestRW
import kotlinx.coroutines.* import kotlinx.coroutines.*
import java.io.File import java.io.File
import java.lang.Math.abs
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
@ -311,8 +312,8 @@ class ResultViewModel2 : ViewModel() {
/** map<dub, map<season, List<episode>>> */ /** map<dub, map<season, List<episode>>> */
private var currentEpisodes: Map<EpisodeIndexer, List<ResultEpisode>> = mapOf() private var currentEpisodes: Map<EpisodeIndexer, List<ResultEpisode>> = mapOf()
private var currentRanges: Map<EpisodeIndexer, List<EpisodeRange>> = mapOf() private var currentRanges: Map<EpisodeIndexer, List<EpisodeRange>> = mapOf()
private var currentSeasons: Set<Int> = setOf() private var currentSeasons: List<Int> = listOf()
private var currentDubStatus: Set<DubStatus> = setOf() private var currentDubStatus: List<DubStatus> = listOf()
private var currentMeta: SyncAPI.SyncResult? = null private var currentMeta: SyncAPI.SyncResult? = null
private var currentSync: Map<String, String>? = null private var currentSync: Map<String, String>? = null
private var currentIndex: EpisodeIndexer? = null private var currentIndex: EpisodeIndexer? = null
@ -376,6 +377,18 @@ class ResultViewModel2 : ViewModel() {
private val _selectedDubStatus: MutableLiveData<Some<UiText>> = MutableLiveData(Some.None) private val _selectedDubStatus: MutableLiveData<Some<UiText>> = MutableLiveData(Some.None)
val selectedDubStatus: LiveData<Some<UiText>> = _selectedDubStatus val selectedDubStatus: LiveData<Some<UiText>> = _selectedDubStatus
private val _selectedRangeIndex: MutableLiveData<Int> =
MutableLiveData(-1)
val selectedRangeIndex: LiveData<Int> = _selectedRangeIndex
private val _selectedSeasonIndex: MutableLiveData<Int> =
MutableLiveData(-1)
val selectedSeasonIndex: LiveData<Int> = _selectedSeasonIndex
private val _selectedDubStatusIndex: MutableLiveData<Int> = MutableLiveData(-1)
val selectedDubStatusIndex: LiveData<Int> = _selectedDubStatusIndex
private val _loadedLinks: MutableLiveData<Some<LinkProgress>> = MutableLiveData(Some.None) private val _loadedLinks: MutableLiveData<Some<LinkProgress>> = MutableLiveData(Some.None)
val loadedLinks: LiveData<Some<LinkProgress>> = _loadedLinks val loadedLinks: LiveData<Some<LinkProgress>> = _loadedLinks
@ -1414,6 +1427,16 @@ class ResultViewModel2 : ViewModel() {
val episodes = currentEpisodes[indexer] val episodes = currentEpisodes[indexer]
val ranges = currentRanges[indexer] val ranges = currentRanges[indexer]
if (ranges?.contains(range) != true) {
// if the current ranges does not include the range then select the range with the closest matching start episode
// this usually happends when dub has less episodes then sub -> the range does not exist
ranges?.minByOrNull { abs(it.startEpisode - range.startEpisode) }?.let { r ->
postEpisodeRange(indexer, r)
return
}
}
val size = episodes?.size val size = episodes?.size
val isMovie = currentResponse?.isMovie() == true val isMovie = currentResponse?.isMovie() == true
currentIndex = indexer currentIndex = indexer
@ -1435,6 +1458,10 @@ class ResultViewModel2 : ViewModel() {
) )
) )
_selectedSeasonIndex.postValue(
currentSeasons.indexOf(indexer.season)
)
_selectedSeason.postValue( _selectedSeason.postValue(
some( some(
if (isMovie || currentSeasons.size <= 1) null else if (isMovie || currentSeasons.size <= 1) null else
@ -1449,6 +1476,10 @@ class ResultViewModel2 : ViewModel() {
) )
) )
_selectedRangeIndex.postValue(
ranges?.indexOf(range) ?: -1
)
_selectedRange.postValue( _selectedRange.postValue(
some( some(
if (isMovie) null else if ((currentRanges[indexer]?.size ?: 0) > 1) { if (isMovie) null else if ((currentRanges[indexer]?.size ?: 0) > 1) {
@ -1458,6 +1489,11 @@ class ResultViewModel2 : ViewModel() {
} }
) )
) )
_selectedDubStatusIndex.postValue(
currentDubStatus.indexOf(indexer.dubStatus)
)
_selectedDubStatus.postValue( _selectedDubStatus.postValue(
some( some(
if (isMovie || currentDubStatus.size <= 1) null else if (isMovie || currentDubStatus.size <= 1) null else
@ -1487,6 +1523,12 @@ class ResultViewModel2 : ViewModel() {
postMovie() postMovie()
} else { } else {
val ret = getEpisodes(indexer, range) val ret = getEpisodes(indexer, range)
/*if (ret.isEmpty()) {
val index = ranges?.indexOf(range)
if(index != null && index > 0) {
}
}*/
_episodes.postValue(ResourceSome.Success(ret)) _episodes.postValue(ResourceSome.Success(ret))
} }
} }
@ -1675,8 +1717,8 @@ class ResultViewModel2 : ViewModel() {
seasonsSelection += key.season seasonsSelection += key.season
dubSelection += key.dubStatus dubSelection += key.dubStatus
} }
currentDubStatus = dubSelection currentDubStatus = dubSelection.toList()
currentSeasons = seasonsSelection currentSeasons = seasonsSelection.toList()
_dubSubSelections.postValue(dubSelection.map { txt(it) to it }) _dubSubSelections.postValue(dubSelection.map { txt(it) to it })
if (loadResponse is EpisodeResponse) { if (loadResponse is EpisodeResponse) {
_seasonSelections.postValue(seasonsSelection.map { seasonNumber -> _seasonSelections.postValue(seasonsSelection.map { seasonNumber ->

View File

@ -0,0 +1,121 @@
package com.lagradost.cloudstream3.ui.result
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.core.view.isVisible
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.button.MaterialButton
import com.lagradost.cloudstream3.ActorData
import com.lagradost.cloudstream3.ActorRole
import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.ui.home.ParentItemAdapter
import com.lagradost.cloudstream3.ui.settings.AccountAdapter
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings
import com.lagradost.cloudstream3.utils.UIHelper.setImage
import kotlinx.android.synthetic.main.cast_item.view.*
import org.schabi.newpipe.extractor.timeago.patterns.it
typealias SelectData = Pair<UiText?, Any>
class SelectAdaptor(val callback: (Any) -> Unit) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private val selection: MutableList<SelectData> = mutableListOf()
private var selectedIndex: Int = -1
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return SelectViewHolder(
LayoutInflater.from(parent.context).inflate(R.layout.result_selection, parent, false),
)
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when (holder) {
is SelectViewHolder -> {
holder.bind(selection[position], position == selectedIndex, callback)
}
}
}
override fun getItemCount(): Int {
return selection.size
}
fun select(newIndex: Int, recyclerView: RecyclerView?) {
if(recyclerView == null) return
if(newIndex == selectedIndex) return
val oldIndex = selectedIndex
selectedIndex = newIndex
recyclerView.apply {
for (i in 0 until itemCount) {
val viewHolder = getChildViewHolder( getChildAt(i) ?: continue) ?: continue
val pos = viewHolder.absoluteAdapterPosition
if (viewHolder is SelectViewHolder) {
if (pos == oldIndex) {
viewHolder.update(false)
} else if (pos == newIndex) {
viewHolder.update(true)
}
}
}
}
}
fun updateSelectionList(newList: List<SelectData>) {
val diffResult = DiffUtil.calculateDiff(
SelectDataCallback(this.selection, newList)
)
selection.clear()
selection.addAll(newList)
diffResult.dispatchUpdatesTo(this)
}
private class SelectViewHolder
constructor(
itemView: View,
) :
RecyclerView.ViewHolder(itemView) {
private val item: MaterialButton = itemView as MaterialButton
fun update(isSelected: Boolean) {
item.isSelected = isSelected
}
fun bind(
data: SelectData, isSelected: Boolean, callback: (Any) -> Unit
) {
val isTrueTv = itemView.context?.isTrueTvSettings() == true
if (isTrueTv) {
item.isFocusable = true
item.isFocusableInTouchMode = true
}
item.isSelected = isSelected
item.setText(data.first)
item.setOnClickListener {
callback.invoke(data.second)
}
}
}
}
class SelectDataCallback(
private val oldList: List<SelectData>,
private val newList: List<SelectData>
) :
DiffUtil.Callback() {
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int) =
oldList[oldItemPosition].second == newList[newItemPosition].second
override fun getOldListSize() = oldList.size
override fun getNewListSize() = newList.size
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int) =
oldList[oldItemPosition] == newList[newItemPosition]
}

View File

@ -44,6 +44,7 @@ import com.lagradost.cloudstream3.isMovieType
import com.lagradost.cloudstream3.mapper import com.lagradost.cloudstream3.mapper
import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.mvvm.logError
import com.lagradost.cloudstream3.ui.result.ResultFragment import com.lagradost.cloudstream3.ui.result.ResultFragment
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings
import com.lagradost.cloudstream3.utils.AppUtils.loadResult import com.lagradost.cloudstream3.utils.AppUtils.loadResult
import com.lagradost.cloudstream3.utils.Coroutines.ioSafe import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
@ -316,12 +317,11 @@ object AppUtils {
//private val viewModel: ResultViewModel by activityViewModels() //private val viewModel: ResultViewModel by activityViewModels()
private fun getResultsId(context: Context) : Int { private fun getResultsId(context: Context) : Int {
return R.id.global_to_navigation_results_phone return if(context.isTrueTvSettings()) {
//return if(context.isTvSettings()) { R.id.global_to_navigation_results_tv
// R.id.global_to_navigation_results_tv } else {
//} else { R.id.global_to_navigation_results_phone
// R.id.global_to_navigation_results_phone }
//}
} }
fun AppCompatActivity.loadResult( fun AppCompatActivity.loadResult(

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="?attr/textColor"/> <item android:state_selected="true" android:color="?attr/iconGrayBackground" />
<item android:state_focused="true" android:color="?attr/iconGrayBackground"/> <item android:color="?attr/textColor" />
</selector> </selector>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true" android:color="?attr/textColor"/> <item android:state_selected="true" android:color="?attr/textColor"/>
<item android:color="?attr/iconGrayBackground"/> <item android:color="?attr/iconGrayBackground"/>
</selector> </selector>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true" android:drawable="@drawable/outline_less" /> <!-- focused -->
</selector>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<stroke android:width="2dp"
android:color="?attr/white"/>
<corners
android:bottomLeftRadius="@dimen/rounded_button_radius"
android:bottomRightRadius="@dimen/rounded_button_radius"
android:topLeftRadius="@dimen/rounded_button_radius"
android:topRightRadius="@dimen/rounded_button_radius" />
</shape>

View File

@ -6,9 +6,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
style="@style/DarkFragment" style="@style/DarkFragment"
android:background="?attr/primaryBlackBackground" android:background="?attr/primaryBlackBackground">
android:clickable="true"
android:focusable="true">
<com.facebook.shimmer.ShimmerFrameLayout <com.facebook.shimmer.ShimmerFrameLayout
android:id="@+id/result_loading" android:id="@+id/result_loading"
@ -271,7 +269,7 @@
tools:text="Cast: Joe Ligma" /> tools:text="Cast: Joe Ligma" />
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
tools:visibility="gone" tools:visibility="visible"
android:nextFocusUp="@id/result_bookmark_button" android:nextFocusUp="@id/result_bookmark_button"
android:nextFocusDown="@id/result_play_movie" android:nextFocusDown="@id/result_play_movie"
@ -305,6 +303,7 @@
android:textColor="?attr/grayTextColor" android:textColor="?attr/grayTextColor"
android:textSize="15sp" android:textSize="15sp"
tools:text="@string/provider_info_meta" /> tools:text="@string/provider_info_meta" />
<TextView <TextView
android:id="@+id/result_no_episodes" android:id="@+id/result_no_episodes"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -373,6 +372,10 @@
tools:visibility="visible"> tools:visibility="visible">
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:nextFocusRight="@id/result_download_movie"
android:nextFocusUp="@id/result_cast_items"
android:nextFocusDown="@id/result_resume_series_button_play"
android:id="@+id/result_play_movie" android:id="@+id/result_play_movie"
style="@style/WhiteButton" style="@style/WhiteButton"
android:layout_width="0dp" android:layout_width="0dp"
@ -381,14 +384,10 @@
android:layout_marginStart="0dp" android:layout_marginStart="0dp"
android:layout_marginEnd="5dp" android:layout_marginEnd="5dp"
android:layout_marginBottom="10dp" android:layout_marginBottom="10dp"
android:nextFocusUp="@id/result_bookmark_button"
android:nextFocusDown="@id/result_download_movie"
android:text="@string/play_movie_button" android:text="@string/play_movie_button"
android:visibility="visible" android:visibility="visible"
app:icon="@drawable/ic_baseline_play_arrow_24"> app:icon="@drawable/ic_baseline_play_arrow_24">
<requestFocus />
</com.google.android.material.button.MaterialButton> </com.google.android.material.button.MaterialButton>
@ -400,6 +399,10 @@
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:nextFocusLeft="@id/result_play_movie"
android:nextFocusUp="@id/result_cast_items"
android:nextFocusDown="@id/result_resume_series_button_play"
android:id="@+id/result_download_movie" android:id="@+id/result_download_movie"
style="@style/BlackButton" style="@style/BlackButton"
@ -410,8 +413,6 @@
android:clickable="true" android:clickable="true"
android:focusable="true" android:focusable="true"
android:nextFocusUp="@id/result_play_movie"
android:nextFocusDown="@id/result_season_button"
android:visibility="visible" /> android:visibility="visible" />
<LinearLayout <LinearLayout
@ -508,8 +509,10 @@
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<ImageView <ImageView
android:layout_marginEnd="10dp"
android:id="@+id/result_resume_series_button_play" android:id="@+id/result_resume_series_button_play"
android:nextFocusUp="@id/result_play_movie"
android:nextFocusDown="@id/result_season_selection"
android:layout_width="30dp" android:layout_width="30dp"
android:layout_height="30dp" android:layout_height="30dp"
android:layout_gravity="center" android:layout_gravity="center"
@ -522,6 +525,8 @@
<TextView <TextView
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:layout_gravity="center" android:layout_gravity="center"
android:gravity="center" android:gravity="center"
android:id="@+id/result_resume_series_title" android:id="@+id/result_resume_series_title"
@ -540,7 +545,6 @@
android:layout_gravity="center" android:layout_gravity="center"
android:layout_weight="0" android:layout_weight="0"
android:gravity="center" android:gravity="center"
android:paddingStart="10dp"
android:textColor="?attr/grayTextColor" android:textColor="?attr/grayTextColor"
tools:ignore="RtlSymmetry" tools:ignore="RtlSymmetry"
tools:text="69m remaining" /> tools:text="69m remaining" />
@ -574,42 +578,46 @@
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:id="@+id/result_episodes_tab"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:paddingBottom="10dp" android:nextFocusUp="@id/result_resume_series_button_play"
android:nextFocusDown="@id/result_range_selection"
android:id="@+id/result_season_selection" android:id="@+id/result_season_selection"
android:paddingBottom="10dp"
tools:listitem="@layout/result_selection" tools:listitem="@layout/result_selection"
android:orientation="horizontal" android:orientation="horizontal"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content"> android:layout_height="wrap_content" />
</androidx.recyclerview.widget.RecyclerView>
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:paddingBottom="10dp" android:nextFocusUp="@id/result_season_selection"
android:nextFocusDown="@id/result_dub_selection"
android:id="@+id/result_range_selection" android:id="@+id/result_range_selection"
tools:listitem="@layout/result_selection"
android:orientation="horizontal"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</androidx.recyclerview.widget.RecyclerView>
<androidx.recyclerview.widget.RecyclerView
android:paddingBottom="10dp"
android:id="@+id/result_dub_selection"
tools:listitem="@layout/result_selection"
android:orientation="horizontal"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</androidx.recyclerview.widget.RecyclerView> android:paddingBottom="10dp"
tools:listitem="@layout/result_selection"
android:orientation="horizontal"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<androidx.recyclerview.widget.RecyclerView
android:nextFocusUp="@id/result_range_selection"
android:nextFocusDown="@id/result_episodes"
android:id="@+id/result_dub_selection"
android:paddingBottom="10dp"
tools:listitem="@layout/result_selection"
android:orientation="horizontal"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<LinearLayout <LinearLayout
android:id="@+id/result_next_airing_holder" android:id="@+id/result_next_airing_holder"
@ -643,6 +651,7 @@
</LinearLayout> </LinearLayout>
<com.facebook.shimmer.ShimmerFrameLayout <com.facebook.shimmer.ShimmerFrameLayout
tools:visibility="gone"
android:id="@+id/result_episode_loading" android:id="@+id/result_episode_loading"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
@ -652,8 +661,7 @@
app:shimmer_auto_start="true" app:shimmer_auto_start="true"
app:shimmer_base_alpha="0.2" app:shimmer_base_alpha="0.2"
app:shimmer_duration="@integer/loading_time" app:shimmer_duration="@integer/loading_time"
app:shimmer_highlight_alpha="0.3" app:shimmer_highlight_alpha="0.3">
tools:visibility="visible">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@ -678,22 +686,21 @@
android:layout_height="50dp" />--> android:layout_height="50dp" />-->
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:nextFocusUp="@id/result_dub_selection"
android:id="@+id/result_episodes" android:id="@+id/result_episodes"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="0dp"
android:clipToPadding="false" android:clipToPadding="false"
android:orientation="horizontal"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
android:descendantFocusability="afterDescendants"
android:paddingBottom="100dp"
tools:listitem="@layout/result_episode" /> tools:listitem="@layout/result_episode" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
<include layout="@layout/result_recommendations" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
</androidx.core.widget.NestedScrollView> </androidx.core.widget.NestedScrollView>
</LinearLayout> </LinearLayout>
</FrameLayout> </FrameLayout>

View File

@ -2,8 +2,6 @@
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" <androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
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:nextFocusLeft="@id/result_episode_download"
android:nextFocusRight="@id/result_episode_download" android:nextFocusRight="@id/result_episode_download"
android:id="@+id/episode_holder" android:id="@+id/episode_holder"
@ -15,6 +13,10 @@
app:cardElevation="0dp" app:cardElevation="0dp"
android:foreground="@drawable/outline_drawable" android:foreground="@drawable/outline_drawable"
android:layout_marginBottom="5dp"> android:layout_marginBottom="5dp">
<!--
android:nextFocusLeft="@id/result_episode_download"
-->
<!-- IDK BUT THIS DOES NOT SEAM LIKE A GOOD WAY OF DOING IT --> <!-- IDK BUT THIS DOES NOT SEAM LIKE A GOOD WAY OF DOING IT -->
<!--<LinearLayout <!--<LinearLayout
android:layout_width="fill_parent" android:layout_width="fill_parent"
@ -110,9 +112,10 @@
android:progress="0" android:progress="0"
android:visibility="visible" /> android:visibility="visible" />
<!--
android:nextFocusRight="@id/episode_holder"-->
<ImageView <ImageView
android:nextFocusLeft="@id/episode_holder" android:nextFocusLeft="@id/episode_holder"
android:nextFocusRight="@id/episode_holder"
app:tint="?attr/white" app:tint="?attr/white"
android:id="@+id/result_episode_download" android:id="@+id/result_episode_download"
android:visibility="visible" android:visibility="visible"

View File

@ -4,5 +4,5 @@
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<include android:visibility="gone" layout="@layout/result_episode" /> <include android:visibility="gone" layout="@layout/result_episode" />
<include android:visibility="gone" layout="@layout/result_episode_large" /> <include android:visibility="visible" layout="@layout/result_episode_large" />
</FrameLayout> </FrameLayout>

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
xmlns:tools="http://schemas.android.com/tools">
<include
tools:visibility="visible"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="50dp"
layout="@layout/result_episode_tv" />
<include
tools:visibility="gone"
android:visibility="gone"
android:layout_width="450dp"
android:layout_height="wrap_content"
layout="@layout/result_episode_large_tv" />
</FrameLayout>

View File

@ -3,11 +3,10 @@
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:nextFocusLeft="@id/episode_poster"
android:nextFocusRight="@id/result_episode_download" android:nextFocusRight="@id/result_episode_download"
android:id="@+id/episode_holder_large" android:id="@+id/episode_holder_large"
android:layout_width="match_parent" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:cardCornerRadius="@dimen/rounded_image_radius" app:cardCornerRadius="@dimen/rounded_image_radius"
app:cardBackgroundColor="?attr/boxItemBackground" app:cardBackgroundColor="?attr/boxItemBackground"
@ -19,7 +18,7 @@
android:foreground="?android:attr/selectableItemBackgroundBorderless" android:foreground="?android:attr/selectableItemBackgroundBorderless"
android:padding="10dp" android:padding="10dp"
android:orientation="vertical" android:orientation="vertical"
android:layout_width="match_parent" android:layout_width="wrap_content"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<LinearLayout <LinearLayout
@ -33,8 +32,7 @@
android:foreground="@drawable/outline_drawable"> android:foreground="@drawable/outline_drawable">
<ImageView <ImageView
android:nextFocusLeft="@id/result_episode_download" android:nextFocusRight="@id/result_episode_download"
android:nextFocusRight="@id/episode_holder"
android:id="@+id/episode_poster" android:id="@+id/episode_poster"
tools:src="@drawable/example_poster" tools:src="@drawable/example_poster"
@ -126,7 +124,6 @@
<ImageView <ImageView
android:nextFocusLeft="@id/episode_poster" android:nextFocusLeft="@id/episode_poster"
android:nextFocusRight="@id/episode_holder"
android:id="@+id/result_episode_download" android:id="@+id/result_episode_download"
android:visibility="visible" android:visibility="visible"

View File

@ -0,0 +1,113 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView 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:nextFocusRight="@id/result_episode_download"
android:id="@+id/episode_holder_large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:cardCornerRadius="@dimen/rounded_image_radius"
app:cardBackgroundColor="?attr/boxItemBackground"
android:foreground="@drawable/outline_drawable"
android:layout_marginBottom="10dp">
<LinearLayout
android:foreground="?android:attr/selectableItemBackgroundBorderless"
android:padding="10dp"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:orientation="horizontal"
android:layout_height="wrap_content">
<!--app:cardCornerRadius="@dimen/roundedImageRadius"-->
<androidx.cardview.widget.CardView
android:layout_width="126dp"
android:layout_height="72dp"
android:foreground="@drawable/outline_drawable">
<ImageView
android:id="@+id/episode_poster"
tools:src="@drawable/example_poster"
android:foreground="?android:attr/selectableItemBackgroundBorderless"
android:scaleType="centerCrop"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="@string/episode_poster_img_des" />
<ImageView
android:src="@drawable/play_button"
android:layout_gravity="center"
android:layout_width="36dp"
android:layout_height="36dp"
android:contentDescription="@string/play_episode" />
<androidx.core.widget.ContentLoadingProgressBar
android:layout_marginBottom="-1.5dp"
android:id="@+id/episode_progress"
android:progressTint="?attr/colorPrimary"
android:progressBackgroundTint="?attr/colorPrimary"
style="@android:style/Widget.Material.ProgressBar.Horizontal"
android:layout_width="match_parent"
tools:progress="50"
android:layout_gravity="bottom"
android:layout_height="5dp" />
</androidx.cardview.widget.CardView>
<LinearLayout
android:layout_marginStart="15dp"
android:orientation="vertical"
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_marginEnd="50dp"
android:layout_height="wrap_content">
<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<com.google.android.material.button.MaterialButton
android:layout_gravity="start"
style="@style/SmallBlackButton"
android:layout_marginEnd="10dp"
android:text="@string/filler"
android:id="@+id/episode_filler" />
<TextView
android:layout_gravity="center_vertical"
android:id="@+id/episode_text"
tools:text="1. Jobless"
android:textStyle="bold"
android:textColor="?attr/textColor"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<TextView
android:id="@+id/episode_rating"
tools:text="Rated: 8.8"
android:textColor="?attr/grayTextColor"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
<TextView
android:maxLines="4"
android:ellipsize="end"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:id="@+id/episode_descript"
android:textColor="?attr/grayTextColor"
tools:text="Jon and Daenerys arrive in Winterfell and are met with skepticism. Sam learns about the fate of his family. Cersei gives Euron the reward he aims for. Theon follows his heart. Jon and Daenerys arrive in Winterfell and are met with skepticism. Sam learns about the fate of his family. Cersei gives Euron the reward he aims for. Theon follows his heart."
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</androidx.cardview.widget.CardView>

View File

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView 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:nextFocusRight="@id/result_episode_download"
android:id="@+id/episode_holder"
android:layout_width="wrap_content"
android:layout_height="50dp"
app:cardCornerRadius="@dimen/rounded_image_radius"
app:cardBackgroundColor="@color/transparent"
app:cardElevation="0dp"
android:foreground="@drawable/outline_drawable"
android:layout_marginBottom="5dp">
<androidx.core.widget.ContentLoadingProgressBar
android:layout_marginBottom="-1.5dp"
android:id="@+id/episode_progress"
android:progressTint="?attr/colorPrimary"
android:progressBackgroundTint="?attr/colorPrimary"
style="@android:style/Widget.Material.ProgressBar.Horizontal"
android:layout_width="match_parent"
tools:progress="50"
android:layout_gravity="bottom"
android:layout_height="5dp" />
<LinearLayout
android:paddingStart="20dp"
android:paddingEnd="20dp"
android:gravity="center"
android:foreground="?android:attr/selectableItemBackgroundBorderless"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--marquee_forever-->
<com.google.android.material.button.MaterialButton
android:layout_marginEnd="10dp"
tools:visibility="visible"
android:gravity="center"
android:layout_gravity="center"
style="@style/SmallBlackButton"
android:text="@string/filler"
android:id="@+id/episode_filler" />
<TextView
android:id="@+id/episode_text"
android:layout_gravity="center_vertical"
android:gravity="center"
tools:text="Episode 1"
android:textColor="?attr/textColor"
android:scrollHorizontally="true"
android:ellipsize="marquee"
android:marqueeRepeatLimit="0"
android:singleLine="true"
android:layout_width="wrap_content"
android:layout_height="match_parent" />
</LinearLayout>
</androidx.cardview.widget.CardView>

View File

@ -1,8 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.button.MaterialButton android:id="@+id/result_season_button" <com.google.android.material.button.MaterialButton xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
style="@style/SelectableButton" style="@style/SelectableButton"
android:layout_marginStart="0dp" android:layout_marginStart="0dp"
android:layout_marginEnd="10dp" android:layout_marginEnd="10dp"
tools:text="Season 1" tools:text="Season 1" />
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" />

View File

@ -3,6 +3,8 @@
<dimen name="activity_horizontal_margin">16dp</dimen> <dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen> <dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="rounded_image_radius">10dp</dimen> <dimen name="rounded_image_radius">10dp</dimen>
<dimen name="rounded_button_radius">4dp</dimen>
<dimen name="navbar_height">0dp</dimen> <dimen name="navbar_height">0dp</dimen>
<dimen name="card_corner_radius">2dp</dimen> <dimen name="card_corner_radius">2dp</dimen>
<dimen name="result_padding">15dp</dimen> <dimen name="result_padding">15dp</dimen>

View File

@ -432,12 +432,12 @@
<item name="android:textAllCaps">false</item> <item name="android:textAllCaps">false</item>
<item name="iconGravity">textStart</item> <item name="iconGravity">textStart</item>
<item name="iconSize">20dp</item> <item name="iconSize">20dp</item>
<item name="cornerRadius">4dp</item> <item name="cornerRadius">@dimen/rounded_button_radius</item>
<item name="android:textSize">15sp</item> <item name="android:textSize">15sp</item>
<item name="android:insetTop">0dp</item> <item name="android:insetTop">0dp</item>
<item name="android:insetBottom">0dp</item> <item name="android:insetBottom">0dp</item>
<item name="android:foreground">@drawable/outline_drawable</item> <item name="android:foreground">@drawable/outline_drawable_less</item>
</style> </style>
<style name="WhiteButton" parent="NiceButton"> <style name="WhiteButton" parent="NiceButton">